v15: Problem with ALIAS in command group

May 30, 2008
212
1
#1
Was just testing v15 and noticed that one of my batch-files did not work.

I narrowed it down to aliases not being recognized in command groups.

Demo:
Code:
@echo off
setlocal
 
alias echotest=`echo test`
 
echo 1 - call alias, works
echotest
 
echo 2 - alias on same line in command group - works
(echotest & echotest)
 
echo 3 - no alias in command group and on separate lines, works
(
    echo test no alias
    echo test no alias
)
 
echo 4 - alias on separate lines in command group, fails in v15, works in v12!
(
    echotest
    echotest
)
Output:
1 - call alias, works
test
2 - alias on same line in command group - works
test
test
3 - no alias in command group and on separate lines, works
test no alias
test no alias
4 - alias on separate lines in command group, fails in v15, works in v12!
test
TCC: C:\Users\Niklas\test2.btm [22] Unknown command "echotest"
 
May 30, 2008
212
1
#3
Thanks for the quick response!

The new build fixed this issue, as did unchecking "Duplicate CMD bugs" in the previous build.

(I'm not sure why I have that option checked, guess it always was and I never thought to change it. The only cmd-files I run are basically the ones for Visual Studio environment setup, and they hardly need this switch)

However, some new issues appeared once this was out of the way.

Seems that iff-then-else do not work in a multi-line command group either if "Duplicate CMD bugs" is checked.

Code:
@echo off
setlocal
 
alias echotest=`echo test`
 
echo test then branch
(
iff 1 == 1 then
    echo then
    echotest
else
    echo error!
    echotest
endiff
)
 
echo test else branch
(
iff 1 == 2 then
    echo error!
    echotest
else
    echo else
    echotest
endiff
)
 
quit
 
REM alias multilinealias=`((echo SELECT "ID","Title","Date" FROM Files LEFT OUTER JOIN Dates USING(ID) ^
REM                              WHERE Id = Test;)| y)`
This outputs:

test then branch
then
test

with "Duplicate CMD bugs" checked.

And with "Duplicate CMD bugs" unchecked you get the expected:

test then branch
then
test
test then done!
test else branch
else
test
test else done!

Another possibly unrelated issue is the multiline alias. If uncommented you get this output with "Duplicate CMD bugs" checked:

test then branch
then
test
TCC: C:\Users\Niklas\test3.btm [32] No closing quote
TCC: C:\Users\Niklas\test3.btm [33] No closing quote

But I guess that's probably because the parser is already in a messed up state at that point. The extra error messages do not show up of you put the alias definition at the beginning of the test file.


Also, a question about having "&" at the end of lines in a command group. Like:

Code:
echo test else branch
(
iff 1 == 2 then
    echo error! &
    echotest
else
    echo else &
    echotest
endiff
)
I currently have it like this in many places in my actual batch-file and it works as I expect (not interpreted as Linux DETACH syntax). But it also works if I remove them. Might be that I originally used if instead of iff. (I assume they would be required with if?)

So, would it be a good idea to remove them in case the parser subtly changes and starts to interpret them as DETACH at some point?
 

rconn

Administrator
Staff member
May 14, 2008
10,506
94
#4
Seems that iff-then-else do not work in a multi-line command group either if "Duplicate CMD bugs" is checked.
Already fixed in build 27 (which I'm uploading now) -- another user had already (privately) reported this. It was not directly related to the alias expansion in command groups issue, though it was triggered by the change in v15 to duplicate more CMD IF bugs.
 

rconn

Administrator
Staff member
May 14, 2008
10,506
94
#5
Also, a question about having "&" at the end of lines in a command group. Like:

Code:
echo test else branch
(
iff 1 == 2 then
    echo error! &
    echotest
else
    echo else &
    echotest
endiff
)
I currently have it like this in many places in my actual batch-file and it works as I expect (not interpreted as Linux DETACH syntax). But it also works if I remove them. Might be that I originally used if instead of iff. (I assume they would be required with if?)

So, would it be a good idea to remove them in case the parser subtly changes and starts to interpret them as DETACH at some point?
The '&' isn't at the end of the line when it's in a command group -- the command processor treats a command group as a single line by reading each line and appending a '&', so you're ending up with a conditional command -- i.e.:

Code:
echo test else branch
( iff 1 == 2 then & echo error! && echotest & else & echo else && echotest & endiff )
Since an ECHO will always succeed, your conditional && will succeed and act the same as a single &. But I certainly wouldn't call it a good idea!

Bottom line -- you can't use the trailing & to detach a command when it's in a command group. (What if you were redirecting the output of the command group -- how would the parser know what to do with an embedded implicit DETACH in the middle of the group?)
 
May 30, 2008
212
1
#6
The '&' isn't at the end of the line when it's in a command group -- the command processor treats a command group as a single line by reading each line and appending a '&', so you're ending up with a conditional command -- i.e.:

Bottom line -- you can't use the trailing & to detach a command when it's in a command group. (What if you were redirecting the output of the command group -- how would the parser know what to do with an embedded implicit DETACH in the middle of the group?)
Thanks for the explanation. I certainly don't want to DETACH anything in the command group, my worry was that the trailing & could accidentally have that effect if anything changed. The whole command group is in fact redirected in the actual batch file, that's why I'm using it.


I found some other issue with command groups and Duplicate CMD bugs in the latest build, this time a pure performance issue, but one that could be annoying.

Code:
@echo off
setlocal
 
setdos /c}
 
timer on
(
    echo 1
    echo 2
    echo 3
    echo 4
    echo 5
    echo 6
    echo 7
    echo 8
    echo 9
    echo 10
)
timer off

TCC v15 with Duplicate Bugs on:

22:26 (2013-03-31) C:\Users\Niklas>test4
Timer 1 on: 22:31:29
1
2
3
4
5
6
7
8
9
10
Timer 1 off: 22:31:31 Elapsed: 0:00:01,41

You can practically see the lines being added one by one to the display.

NOTE: Only happens with "setdos /c}" included.

TCC v12 (dupl. bugs on and off) and v15 (dupl. bugs off):
22:32 (2013-03-31) C:\Users\Niklas>test4
Timer 1 on: 22:32:09
1
2
3
4
5
6
7
8
9
10
Timer 1 off: 22:32:09 Elapsed: 0:00:00,00
 

rconn

Administrator
Staff member
May 14, 2008
10,506
94
#7
NOTE: Only happens with "setdos /c}" included.
I can't conceive of any reason to do that -- can you explain why?

Changing the command separator will definitely break the command group processing if DupBugs is enabled. The parser is trying to convert a "&" to a "&&" to emulate the CMD bug, and changing the separator turns it into a "}&" (which won't mean anything sensible). It's cruel to tell the parser you want it to act like CMD, and then pass it a command line that CMD can't comprehend! ;)
 
May 30, 2008
212
1
#8
I can't conceive of any reason to do that -- can you explain why?
I'm using a command group to generate data (commands) that is piped to an external program.

Sometimes the data might include the "&" character so I have to make TCC ignore it somehow. Since I use a command group using SETDOS to disable multiple commands will not work, and that would also prevent piping to the external program.

So it seemed easiest to temporarily change the command separator to something that will never appear in the program data.

I guess it would be possible to write the input data to a temp-file and then pipe that to the external program, but I prefer pipes when possible. Less book-keeping. If there are other ways I'd like to hear about them.

Changing the command separator will definitely break the command group processing if DupBugs is enabled. The parser is trying to convert a "&" to a "&&" to emulate the CMD bug, and changing the separator turns it into a "}&" (which won't mean anything sensible). It's cruel to tell the parser you want it to act like CMD, and then pass it a command line that CMD can't comprehend! ;)
Yeah, that's a little unfortunate. It's not my intention to make life hard for the parser!

Actually, I don't really care about DupBugs and CMD compatibility at all in this case, since it's my own btm-file. I only have DupBugs enabled (for now) because it's the default setting for TCC (I created a new empty profile to check). So leaving it on seems safest since I'm not really sure about what all it does. And you never know if you might want to run some CMD-file.

Also, why would this option affect the execution of BTM-files? Seems like that would be unnecessary unless it's a common practice to migrate CMD-files to BTM-files while keeping most of the CMD code as-is.

ETA: I assume what the DupBugs option does changed a little in-between v12 and v15, as none of these issues popped up then with the same options checked and the same btm-file.
 

rconn

Administrator
Staff member
May 14, 2008
10,506
94
#9
Also, why would this option affect the execution of BTM-files? Seems like that would be unnecessary unless it's a common practice to migrate CMD-files to BTM-files while keeping most of the CMD code as-is.
There's only one parser, that is used for preprocessing internal commands, external commands, aliases, and all kinds of batch files. It's not practical to have a custom parser for every individual case, nor would it be particularly desirable for the parser to behave differently (and usually unexpectedly) depending on the target. And the type of command to be executed isn't determined until the very end of the parsing process.

ETA: I assume what the DupBugs option does changed a little in-between v12 and v15, as none of these issues popped up then with the same options checked and the same btm-file.
More CMD.EXE bugs were identified (or introduced) since v12 was released.
 
May 30, 2008
212
1
#10
There's only one parser, that is used for preprocessing internal commands, external commands, aliases, and all kinds of batch files. It's not practical to have a custom parser for every individual case, nor would it be particularly desirable for the parser to behave differently (and usually unexpectedly) depending on the target. And the type of command to be executed isn't determined until the very end of the parsing process.
Hm, seems to me that TCC could implicitly do something like this when running a BTM (not CMD or BAT) file:

Code:
@echo off
setlocal
option //DuplicateBugs=No
 
setdos /c}
 
timer on
(
    echo 1
    echo 2
    echo 3
    echo 4
    echo 5
    echo 6
    echo 7
    echo 8
    echo 9
    echo 10
)
timer off
 
endlocal
REM DuplicateBugs still set to "No" here :(
Only TCC could do better, since it would always restore the value of DuplicateBugs to whatever it was before the BTM-file was run.

The BTM-file can of course do this itself as well, it just has to query the value before changing it and then restoring it before it quits. But that's not as fool-prof, as it can be forcefully interrupted before it has the chance to do so. In that case the option will still be changed for rest of that TCC session even if it's not saved to TCMD.INI.

So, I'll go with using this manual option myself for the BTM where DuplicateBugs causes issues and stop pestering you about it. :)
 

rconn

Administrator
Staff member
May 14, 2008
10,506
94
#11
Hm, seems to me that TCC could implicitly do something like this when running a BTM (not CMD or BAT) file:
I could, provided that:

1) There are no BTM files already in existence (so I wouldn't have to worry about breaking existing functionality)
2) Nobody has ever renamed a CMD or BAT file to BTM in order to get faster execution