View unanswered posts | View active topics It is currently 20 Dec 2014 23:26



Post new topic Reply to topic  [ 8 posts ] 
[Solved] Return ANY string across ENDLOCAL boundry - BUG! 
Author Message
Online
Expert

Joined: 12 Feb 2011 21:02
Posts: 1313
Location: United States (east coast)
Post [Solved] Return ANY string across ENDLOCAL boundry - BUG!
Noooooooo! :x :cry:

I just discovered a serious bug in the "magic" code that Jeb developed here :chr, :asc, :str2hex, :hex2str

The code is intended to return any string across an ENDLOCAL boundry, whether or not delayed expansion is enabled or disabled. But it doesn't work if the string contains any of the following: %A, %B, %C, %L.

The results are weird, especially for %B. :shock: I am mystified why those strings don't work, yet %~A, %~B, %~C and %~L work perfectly.

I have been lovin' the technique and have used it in a number of functions. I hope this doesn't mean the whole house of cards is collapsing :!:

Jeb - do you see a way to fix this :?:

Here is Jeb's original test code, with the failing new test cases appended to the "zero" line.
Code:
@echo off
setlocal EnableDelayedExpansion
cls
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set LF=^


rem TWO Empty lines are neccessary
set "original=zero*? %%~A%%~B%%~C%%~L :%%A:%%B:%%C:%%L:!LF!one&line!LF!two with exclam^! !LF!three with "quotes^&"&"!LF!four with ^^^^ ^| ^< ^> ( ) ^& ^^^! ^"!LF!xxxxxwith CR!CR!five !LF!six with ^"^"Q ^"^"L still six "

setlocal DisableDelayedExpansion
call :lfTest result original

setlocal EnableDelayedExpansion
echo The result with disabled delayed expansion is:
if !original! == !result! (echo OK) ELSE echo !result!

call :lfTest result original
echo The result with enabled delayed expansion is:
if !original! == !result! (echo OK) ELSE echo !result!
echo !lf!------------------!lf!original:
echo !original!

goto :eof

::::::::::::::::::::
:lfTest
setlocal
set "NotDelayedFlag=!"
echo(
if defined NotDelayedFlag (echo lfTest was called with Delayed Expansion DISABLED) else echo lfTest was called with Delayed Expansion ENABLED
setlocal EnableDelayedExpansion
set "var=!%~2!"

rem echo the input is:
rem echo !var!
echo(

rem ** Prepare for return
set "var=!var:%%=%%~A!"
set "var=!var:"=%%~B!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~C!"

rem ** It is neccessary to use two IF's else the %var% expansion doesn't work as expected
if not defined NotDelayedFlag set "var=!var:^=^^^^!"
if not defined NotDelayedFlag set "var=%var:!=^^^!%" !

set "replace=%% """ !CR!!CR!"
for %%L in ("!LF!") do (
   for /F "tokens=1,2,3" %%A in ("!replace!") DO (
     ENDLOCAL
     ENDLOCAL
     set "%~1=%var%" !
     @echo off
      goto :eof
   )
)

and the unfortunate results are:
Code:

lfTest was called with Delayed Expansion DISABLED

The result with disabled delayed expansion is:
zero*? %~A%~B%~C%~L ::d--------:::
one&line
two with exclam!
three with "quotes&"&"
four with ^ | < > ( ) & ! "
five with CR
six with ""Q ""L still six

lfTest was called with Delayed Expansion ENABLED

The result with enabled delayed expansion is:
zero*? %~A%~B%~C%~L ::d--------:::
one&line
two with exclam!
three with "quotes&"&"
four with ^ | < > ( ) & ! "
five with CR
six with ""Q ""L still six

------------------
original:
zero*? %~A%~B%~C%~L :%A:%B:%C:%L:
one&line
two with exclam!
three with "quotes&"&"
four with ^ | < > ( ) & ! "
five with CR
six with ""Q ""L still six


Dave Benham


Last edited by dbenham on 23 May 2011 09:51, edited 1 time in total.



22 May 2011 20:11
Profile
Expert

Joined: 16 May 2011 08:21
Posts: 1275
Location: Flanders_(Belgium)
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
I can't follow this bit of code :
Code:
set "var=!var:%%=%%~A!"
set "var=!var:"=%%~B!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~C!"

Would you explain it for me :shock: I'm not at your level :?


22 May 2011 20:29
Profile WWW
Expert

Joined: 30 Aug 2007 08:05
Posts: 679
Location: Germany
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
Hi Ed,

Ed Dyreen wrote:
I can't follow this bit of code :
Code:
set "var=!var:%%=%%~A!"
set "var=!var:"=%%~B!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~C!"

Would you explain it for me :shock: I'm not at your level :?


First, all (single) percents are replaces with %~A
All quotes are replaced with %~B
All <LF> are replaced with %~L
All <CR> are replaced with %~C
The <LF> and <CR> need a FOR-Loop-Var, to replace the character, as you can't place it directly between !..!

But why :?:
Because at the end, all these replacements are replaced to their original values,
this is neccessary, as they can't stay int the return statement without this trick.
Code:
set "%~1=%var%" !


@dbenham
dbenham wrote:
Noooooooo! :x :cry:

I just discovered a serious bug in the "magic" code that Jeb developed here


Ok there is a bug, but it's not a problem :wink:
Simply replace the %~A, %~B %~C (and perhaps %~L) with
%~2, %~3, %~4, %~9 and change the For-Loop to %%2 (%%1 could collide with the set %~1)

Code:
rem ** Prepare for return
set "var=!var:%%=%%~2!"
set "var=!var:"=%%~3!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~9!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~4!"

rem ** It is neccessary to use two IF's else the %var% expansion doesn't work as expected
if not defined NotDelayedFlag set "var=!var:^=^^^^!"
if not defined NotDelayedFlag set "var=%var:!=^^^!%" !

set "replace=%% """ !CR!!CR!"
for %%9 in ("!LF!") do (
   for /F "tokens=1,2,3" %%2 in ("!replace!") DO (
     ENDLOCAL
     ENDLOCAL
     set "%~1=%var%" !
     @echo off
      goto :eof
   )
)


The problem seems to be the characters, they are interpreted as flags A=a=file attributes...

jeb


23 May 2011 03:53
Profile
Online
Expert

Joined: 12 Feb 2011 21:02
Posts: 1313
Location: United States (east coast)
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
:D :D :D Thank you Jeb :!:

I replaced the zero line characters ABCL with 2349 in the original test string, and everything works perfectly!

Jeb wrote:
The problem seems to be the characters, they are interpreted as flags A=a=file attributes...

:shock: Where does that come from? Can you explain that a bit more?

Dave Benham


23 May 2011 05:36
Profile
Expert

Joined: 30 Aug 2007 08:05
Posts: 679
Location: Germany
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
From the For /? help
Code:
    %~I
    %~fI
    %~dI
    %~pI
    %~nI
    %~xI
    %~sI
    %~aI  - file attributes
    %~tI
    %~zI
    %~$PATH:I


The flags aren't case sensitive, and the flags can be combined.

So the %%~AAAAAB are all interpreted as file attributes for %%B.

jeb


23 May 2011 05:49
Profile
Online
Expert

Joined: 12 Feb 2011 21:02
Posts: 1313
Location: United States (east coast)
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
Hi Jeb

That doesn't make sense to me. Why would each of the following strings fail with the original code?
%%B
%%C
%%L

They don't have an A, so where do the attributes come in to the picture?

or why would %%A imply file attributes when there is no ~?

It seems like there must be some other mechanism.

Dave


23 May 2011 06:47
Profile
Expert

Joined: 30 Aug 2007 08:05
Posts: 679
Location: Germany
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
dbenham wrote:
That doesn't make sense to me. Why would each of the following strings fail with the original code?
%%B
%%C
%%L

They don't have an A, so where do the attributes come in to the picture?


Because "%B,%C,%L" are replaced to "%~AB,%~AC,%~AL" :wink:
Therefore they fail.

But "%~A,%~B" doesn't fail, as they are replaced to "%~A~A,%~A~B", and then it parsed only the %~A~ and this seems to work (perhaps the second ~ disables the flag mechanism).

jeb


23 May 2011 07:36
Profile
Online
Expert

Joined: 12 Feb 2011 21:02
Posts: 1313
Location: United States (east coast)
Post Re: Return ANY string across ENDLOCAL boundry - BUG!
Ahhh, it all makes sense now. Armed with your explanation, I was able to change the algorithm to use J, K, L, M (M for <LF>), and that works as well. I'll probably stick with the numbers, but it helps to understand what is going on.

Thanks Jeb for making everything clear.

Dave


23 May 2011 07:59
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 


Who is online

Users browsing this forum: Bing [Bot], dbenham, Google [Bot], Yahoo [Bot] and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Forum style by Vjacheslav Trushkin for Free Forums/DivisionCore.