Proper use of ON ERRORMSG inside a DO WHILE loop?

May 23, 2010
6
0
#1
I'm pretty much a neophyte when it comes to TCC programming. At the moment, I'm trying to understand the working of ON ERRORMSG when it's used inside a DO loop.

As for the DO construct itself: Is there any difference between these two constructs? (Leading question, as my examples below show that yes, there is.)
Code:
do while condition (
  commands
  ...
  )
 
do while condition
  commands
  ...
  enddo
On to ON ERRORMSG. This .btm file accepts multiple filenames as input parameters, iterates through them in a DO loop, and performs different commands depending on whether each file exists. (Yes, I know that doing a DIR isn't a good way to test whether a file exists; but it's a good way to confound my understanding of the ON ERRORMSG construct as used within the loop.)
Code:
  echo at start, parms are %$
  do while (%1) ne ()
    echo at top of do, parm is %1
    on errormsg goto BAD_FILESET
    dir %1
    on errormsg
    echo process valid fileset %1 here...
    goto NEXT_FILESET
:BAD_FILESET
    on errormsg
    echo process bad fileset %1 here...
:NEXT_FILESET
    echo on to next fileset
    shift
  enddo
It's easy for you to run this file and see the output. Here's a summary when run against one file that exists and one that doesn't:
Parentheses version:
foo fgood fbad: processes fgood correctly, stops at end of first iteration through loop
foo fbad fgood: processes fbad correctly, aborts with "Unknown command" on final parenthesis. (If I move the parenthesis up to after the shift, it gives no error, but still stops the DO loop.)
ENDDO version:
foo fgood fbad: processes fgood correctly, aborts with "Unknown command" on the enddo.
foo fbad fgood: processes fbad correctly, aborts with "Unknown command" on the enddo.

If I remove all error handling and the goto labels (in other words, all the useful stuff):
Code:
  echo at start, parms are %$
  do while (%1) ne () (
    echo at top of do, parm is %1
    dir %1
    echo on to next fileset
    shift )
then the code works as expected.

If I add one extraneous label back in:
Code:
  echo at start, parms are %$
  do while (%1) ne () (
    echo at top of do, parm is %1
    dir %1
:FURBLE
    echo on to next fileset
    shift )
then the code will loop forever on the first file in the list if I use the parentheses construct; but will process all files in the list if I use the ENDDO construct.

As you can see, I have a lot to learn here. Any help would be appreciated.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,599
46
Albuquerque, NM
prospero.unm.edu
#2
I would suggest unlearning the parentheses format. That's a hack, intended to make it possible to use DO at the command line. In a batch file, you should use DO/ENDDO, just like IFF/ENDIFF, SWITCH/ENDSWITCH, TEXT/ENDTEXT....

Not sure about your ON ERRORMSG issue, but GOTO inside a DO loop seems like a bad idea to me. You might need to use GOTO /I. Perhaps GOSUB might be a better approach here?
 
#3
GOTO /I is certainly needed.

I agree with Charles; avoid the parentheses version. It's meant for the command line. I use it in a batch file only if

1. I could write the command on one line, and
2. still see the whole line in my editor

And putting the ON command inside the DO loop (and repeatedly turning it off/on) seems odd, and certainly isn't necessary. This works nicely.

Code:
echo at start, parms are %$

on errormsg goto /i BAD_FILESET

do while (%1) ne ()
    echo at top of do, parm is %1
    dir /k /m %1
    echo process valid fileset %1 here...
    goto /i NEXT_FILESET
:BAD_FILESET
    echo process bad fileset %1 here...
:NEXT_FILESET
    echo on to the next file set
    shift
enddo
 
May 23, 2010
6
0
#4
(1) Cool. I was unaware of the GOTO /I option. It pays to read the manual...
(2) I will abandon the use of the parentheses to set the scope of the DO. That also solves the last problem I mentioned.
(3) A single ON ERRORMSG at the top will work if I want the same error-handler for all errors. But I was under the impression that I had to turn off the initial ON ERRORMSG GOTO X with a bare ON ERRORMSG if I didn't want the code under label X to be directed back to label X in case of another error, thus triggering an infinite loop. How else could this be coded other than using multiple ONs?
(3a) As Charles intimates, GOSUB is usually preferable to GOTO, as the code is more modular and less spaghetti-like. But placing an ON inside the subroutine still effectively places it inside the DO loop.

Thanks to you both for your assistance.