Friday, October 19, 2007

Label at the End of Block

One thing I hate about batch file is, there is no real language definition you can refer to (or is there?).  So a lot of things I have to find out by myself the hard way.

Here's an example of this:

@echo off

for /L %%i in (1,1,10) do (

  if %%i GEQ 5 goto :NOPRINT

  echo %%i

  :NOPRINT

)

This gives an error saying that ") was unexpected at this time".  It is obvious what this means, and it is obvious how to fix it.  Just put a comment between the label and the closing bracket.

@echo off

for /L %%i in (1,1,10) do (

  if %%i GEQ 5 goto :NOPRINT

  echo %%i

  :NOPRINT

  REM can't have label immediately preceding closing bracket
)

I know this is not really anything useful, just a rant, that's all.

Evil Delayed Expansion

Wait, what's this?  How come something so useful as delayed expansion (see previous posts here and here to see how useful it is) be evil?  Well, it's not the feature itself that's evil, but rather the way you can end up spending a long time trying to figure out what's wrong if you make a simple, stupid mistake.

What mistake am I talking about?  Consider this:

@echo off

setlocal enabledelayedexpansion

set COUNT=0

for /L %%i in (1,1,10) do (

  set /A COUNT=%COUNT% + 1

  echo !COUNT!
)

Simple enough, you said.  And you must have spotted the bug (if you have not, try to run it and see what happens).  Now, of course if the loop body is much more complicated it would not be as easy.  You see, the problem is that what you are doing is completely legal.  Having %COUNT% in the loop body is fine as long as you don't expect it to be delay-expanded.  It's a feature, but when you make that silly mistake (or more likely, someone else in your team), then it's not going to be pleasant to hunt the problem down.