Introduction

Macros are more difficult to debug than regular syntax, because one cannot "walk" the macro step by step. We have to call it an let it go. The first step to debug a macro is to run the command SET MPRINT=yes /PRINTBACK=yes. This allows you to "see" the macro in the Output window.

Another useful method is to insert SAVE OUTFILE commands in strategic places and look at these files after the macro has finished to see where things starts to go off tracks.

Remember that (most of the time) computers do what you tell them to do, not what you want them to do :-)

Things to watch for

Misspelled or missing parameter name

Just check it, check it thoroughly. It looks trivial but this error occurs often (even to me!)

The MXLOOPS parameter

(this was posted by Mike Lacey to the SPSS newsgroup on June 20,2000).

I just spent a day being fooled by a feature of the LOOP structure, namely the function of the (implicit) MXLOOPS variable. Perhaps what MXLOOPS does is well known to other syntax users, but I suspect not.

MXLOOPS is the maximum number of iterations for an un-indexed use of LOOP.

MXLOOPS defaults to 40, but can be set using SET MXLOOPS = n.

This seems unproblematic, but note that is in effect even when a loop is controlled by an IF-clause.

See what happens with the following syntax:

COMPUTE TRIALS = 100.
COMPUTE #I = 1.
LOOP.
IF RV.UNIFORM(0,1) < 0.0001 X = 1.
COMPUTE #I = #I + 1.
END LOOP IF (#I > TRIALS) or (X = 1).

Despite the intent of this loop to run for 100 trials or until X = 1, whichever comes first, it will never run more than MXLOOPS times. With the default of MXLOOPS = 40, it will run only 40 times maximum. In other words, the apparent user control of the loop is overridden by MXLOOPS.

The solution is to take active control of MXLOOPS by setting your own "infinite loop protection" somewhere prior to the loop in question, e.g. SET MXLOOPS = 1E8. for the brave.

Incorrect use of !POS parameter

Say you define a macro as follows:

DEFINE !mymacro (age=!TOKENS(1) /!POS=!CMDEND)
…
!ENDDEFINE.

and you call the macro as follows:

!mymacro age=18 29 35 78.

The macro will not work because the parameter "age" will NOT be defined! Yes the macro call contains age=18 and this appears to define the parameter age. The problem is that, by definition, the first parameter is !POS, moreover, in this case, !POS goes up to the command terminator; hence !POS ="age=18 29 35 78". The macro parser does not see the parameter "age".

The odd feature of the macro parser

If some of the parameter values feed to the macro are combinations of numbers and letters such as

  • numbers followed by strings (for instance 123ab), or
  • numbers followed by strings followed by numbers (for instance 123ab21), or
  • underscore followed by a number (for instance _1)

It is likely that the "odd feature" of the macro parser is the culprit. See this file for more explanations.