Chapter Contents

Previous

Next
SAS Macro Language: Reference

Troubleshooting Your Macros

Commonly Encountered Problems lists some problems you may encounter when working with the macro facility. Because for many of these situations error messages aren't written to the SAS log, solving them can be hard. For each problem, the table gives some possible causes and some solutions.

Commonly Encountered Problems
Problem Cause(s) Explanation
Display manager session hangs after you submit a macro definition. You type and submit code but nothing happens.

  • Syntax error in %MEND statement

  • Missing semicolon, parenthesis, or quotation mark

  • Missing %MEND statement

  • Unclosed comment

The %MEND statement is not recognized and all text is becoming part of the macro definition.
Display manager session hangs after you call a macro An error in invocation, such as forgetting to provide one or more parameters, or forgetting to use parentheses when invoking a macro that is defined with parameters. The macro facility is waiting for you to finish the invocation.
The macro does not compile when you submit it. A syntax error exists somewhere in the macro definition. Only syntactically correct macros are compiled.
The macro does not execute when you call it or partially executes and stops.

  • A bad value was passed to the macro (for example, as a parameter).

  • A syntax error exists somewhere into the macro definition.

A macro successfully executes only when it receives the correct number of parameters that are of the correct type.
The macro executes but the SAS code gives bad results or no results. Incorrect logic in the macro os SAS code. Computers do what you tell them, not what you intended to tell them.
Code runs fine if submitted as open code, but when generated by a macro, the code doesn't work and issues strange error messages.

  • Tokenization is not as you intended.

  • A syntax error exists somewhere in the macro defintion.

Rarely, macro quoting functions alter the tokenization of text enclosed in them. Use the %UNQUOTE function.

See "%UNQUOTE" in Chapter 13.

A %MACRO statement generates "invalid statement" error.

  • The MACRO system option is turned off.

  • A syntax error exists somewhere in the macro defintion.

For the macro facility to work, the MACRO system option must be one. Edit your SAS configuration file accordingly.

Common Macro Error Messages and Causes lists some common macro error and warning messages. For each message, some probable causes are listed, and pointers to more information are provided.

Common Macro Error Messages and Causes
Error Message Possible Causes For More Information
Apparent invocation of macro xxx not resolved.

  • You have misspelled the macro name.

  • MAUTOSOURCE system option is turned off.

  • MAUTOSOURCE is on, but you have specified an incorrect path in the SASAUTOS=system option.

  • You are using the autocall fackility but have given the macro and file different names.

  • You are using the autocall facility but didn't give the file the .SAS extension

  • There is a syntax error within the macro defintion.

  • Check the spelling of the macro name

  • "Solving Problems with the Autocall Facility" on page 121.

  • "Developing Bug-free Macros" on page 112.

Apparent symbolic reference xxx not resolved.

  • You are trying to resolve a macro variable in the same DATA step as the CALL SYMPUT that created it.

  • You have misspelled the macro variable name.

  • You are referencing a macro variable that is not in scope.

  • You have omitted the period delimiter when adding text to the end of the macro variable.

  • "Resolving Timing Issues" on page 118

  • Check the spelling of the macro variable

  • "Solving Problems with Macro Variable Scope" on page 115

  • "Solving Macro Variable Resolution Problems" on page 114

  • "Generating a Suffix for a Macro Variable Reference" in Chapter 1.



Solving Macro Variable Resolution Problems

When the macro processor examines a name token that follows an &, it searches the macro symbol tables for a matching macro variable entry. If it finds a matching entry, it pulls the associated text from the symbol table and replaces &name on the input stack. When a macro variable name is passed to the macro processor but the processor does not find a matching entry in the symbol tables, it leaves the token on the input stack and generates this message:

WARNING: Apparent symbolic reference NAME not resolved.

The unresolved token is transferred to the input stack for use by other parts of the SAS System.

Note:   You receive the WARNING only if the SERROR system option is on.  [cautionend]

To solve these problems, check that you've spelled the macro variable name right and that you are referencing it in an appropriate scope.

When a macro variable resolves but does not resolve to the correct value, you can check several things. First, if the variable is a result of a calculation, make sure the correct values were passed into the calculation. And, make sure you have not inadvertently changed the value of a global variable. (See Solving Problems with Macro Variable Scope for more details on variable scope problems.)

Another common problem is adding text to the end of a macro variable but forgetting to add a delimiter that shows where the macro variable name ends and the added text begins. For example, suppose you want to write a TITLE statement with a reference to WEEK1, WEEK2, and so on. You set a macro variable equal to the first part of the string, then supply the week's number in the TITLE statement:

%let wk=week;

title "This is data for &wk1";   /* INCORRECT */

When these statements compile, the macro processor looks for a macro variable named WK1, not WK. To fix the problem, add a period (the macro delimiter) between the end of the macro variable name and the added text, as in the following statements:

%let wk=week;

title "This is data for &wk.1";
CAUTION:
Do not prefix macro variable names with AF, DMS, or SYS. The letters AF, DMS, and SYS are frequently used by the SAS System as prefixes for automatic variables. SAS does not prevent you from using AF, DMS, or SYS as a prefix for macro variable names. However, using these strings as prefixes may create a conflict between the names you specify and the name of an automatic macro variable (including automatic macro variables in later SAS releases).

If a name conflict occurs, SAS may not issue a warning or error message, depending on the details of the conflict. Therefore, the best practice is to avoid using the strings AF, DMS, or SYS as the beginning characters of macro names and macro variable names.  [cautionend]


Solving Problems with Macro Variable Scope

A common mistake that occurs with macro variables concerns referencing local macro variables outside their scope. As described in Chapter 5, "Scope of Macro Variables," macro variables are either global or local. Referencing a variable outside its scope prevents the macro processor from resolving the variable reference. For example, consider the following program:

%macro totinv(var);
   data inv;
      retain total 0;
      set sasuser.houses end=final;
      total=total+&var;
      if final then call symput("macvar",put(total,dollar14.2));
   run;
   %put **** TOTAL=&macvar ****;
%mend totinv;

%totinv(price)
%put **** TOTAL=&macvar ****;   /* ERROR */

When you submit these statements, the %PUT statement in the macro TOTINV writes the value of TOTAL to the log, but the %PUT statement that follows the macro call generates a warning message and writes the text TOTAL=&macvar to the log, as follows:

TOTAL= $1,240,800.00
WARNING: Apparent symbolic reference MACVAR not resolved.
**** TOTAL=&macvar ****
The second %PUT statement fails because the macro variable MACVAR is local to the TOTINV macro. To correct the error, you must use a %GLOBAL statement to declare the macro variable MACVAR.

Another common mistake that occurs with macro variables concerns overlapping macro variable names. If, within a macro definition, you refer to a macro variable with the same name as a global macro variable, you affect the global variable, which may not be what you intended. Either give your macro variables distinct names or use a %LOCAL statement to explicitly define a local macro variable. See "Forcing a Macro Variable to Be Local" in Chapter 5 for an example of this technique.


Solving Open Code Statement Recursion Problems

Recursion is something calling itself. Open code recursion is when your open code erroneously causes a macro statement to call another macro statement. The most common error that causes open code recursion is a missing semicolon. In the following example, the %LET statement is not terminated by a semicolon:

%let a=b   /* ERROR */
%put **** &a ****;

When the macro processor encounters the %PUT statement within the %LET statement, it generates this error message:

ERROR: Open code statement recursion detected.

Open code recursion errors usually occur because the macro processor is not reading your macro statements as you intended. Careful proofreading can usually solve open code recursion errors, because this type of error is mostly the result of typos in your code, not errors in execution logic.

To recover from an open code recursion error, first try submitting a single semicolon. If that does not work, try submitting the following string:

*'; *"; *); */; %mend; run;

Continue submitting this string until the following message appears in the SAS log:

ERROR: No matching %MACRO statement for this %MEND statement.

If the above method does not work, close your SAS session and restart SAS. Of course, this causes you to lose any unsaved data, so be sure to save often while you are developing your macros, and proofread them carefully before you submit them.


Solving Problems with Macro Functions

Some common causes of problems with macro functions include

If you encounter an error related to a macro function, you may also see other error messages, generated by the invalid tokens left on the input stack by the macro processor.

Consider the following example. The user wants to use the %SUBSTR function to assign a portion of the value of the macro variable LINCOLN to the macro variable SECONDWD. But a typo exists in the second %LET statement, where %SUBSTR is misspelled as %SUBSRT:

%macro test;
%let lincoln=Four score and seven;
%let secondwd=%subsrt(&lincoln,6,5);   /* ERROR */
%put *** &secondwd ***;
%mend test;

%test

When the erroneous program is submitted, the following appears in the SAS log:

WARNING: Apparent invocation of macro SUBSRT not resolved.

The error messages clearly point to the function name, which is misspelled.


Solving "Apparent Invocation of Macro Not Resolved" Problems

When a macro name is passed to the macro processor but the processor does not find a matching macro definition, it generates the following message:

WARNING: Apparent invocation of macro NAME not resolved.

This error could be caused by the misspelling of the name of a macro or a macro function, or it could be caused by an error in a macro definition that caused the macro to be compiled as a dummy macro. A dummy macro is a macro that the macro processor partially compiles but does not store.

Note:   You receive this warning only if the MERROR system option is on.  [cautionend]


Solving the "Black Hole" Macro Problem

One error that is most frustrating to new users of the macro language is one that is not accompanied by any error message (and is therefore hard to solve if you are a novice). When the macro processor begins compiling a macro definition, it reads and compiles tokens until it finds a matching %MEND statement. If you omit a %MEND statement or cause it to be unrecognized by omitting a semicolon in the preceding statement, the macro processor does not stop compiling tokens. Every line of code you submit becomes part of the macro.

Resubmitting the macro definition and adding the %MEND statement does not correct the error. When you submit the corrected definition, the macro processor treats it as a nested definition in the original macro definition. The macro processor must find a matching %MEND statement to stop compilation.

Note:   It is a good practice to use the %MEND statement with the macro name, so you can easily match %MACRO and %MEND statements.  [cautionend]

If you recognize that SAS is not processing submitted statements and you are not sure how to recover, submit %MEND statements one at a time until the following message appears in the SAS log:

ERROR: No matching %MACRO statement for this %MEND statement.

Then recall the original erroneous macro definition, correct the error in the %MEND statement, and submit the definition for compilation.

There are other syntax errors that can create similar problems, such as unmatched quotation marks and unclosed parentheses. Often, one of these syntax errors leads to others. Consider the following example:

%macro rooms;
   /* other macro statements */
   %put **** %str(John's office) ****;   /* ERROR */
%mend rooms;

%rooms

When you submit these statements, the macro processor begins to compile the macro definition ROOMS. However, the single quotation mark in the %PUT statement is not marked by a percent sign. Therefore, during compilation the macro processor interprets the single quote as the beginning of a literal token. It does not recognize the closing parenthesis, the semicolon at the end of the statement, or the %MEND statement at the end of the macro definition.

To recover from this error, you must submit the following:

');
%mend;

If the above methods do not work, try submitting the following string:

*'; *"; *); */; %mend; run;

Continue submitting this string until the following message appears in the SAS log:

ERROR: No matching %MACRO statement for this %MEND statement.

Obviously, it is easier to catch these types errors before they occur. You can avoid subtle syntax errors by carefully checking your macros before submitting them for compilation. Refer to Developing Bug-free Macros for a syntax checklist.

Note:   Another cause of unexplained and unexpected macro behavior is using a reserved word as the name of a macro variable or macro. For example, the SAS System reserves names starting with SYS; you should not create macros and macro variables with names beginning with SYS. Also, most host environments have reserved words too. For example, on PC-based platforms, the word CON is reserved for console input. Check Appendix 1, "Reserved Words in the Macro Facility," for reserved SAS System keywords; check your SAS companion for host environment reserved words.  [cautionend]


Resolving Timing Issues

Many macro errors occur because a macro variable resolves at a different time than when the user intended or a macro statement executes at an unexpected time. A prime example of the importance of timing is when you use CALL SYMPUT to write a DATA step variable to a macro variable. You cannot use this macro variable in the same DATA step where it is defined; you can use it only in subsequent steps (that is, after the DATA step's RUN statement).

The key to forestalling timing errors is to understand how the macro processor works. In simplest terms, the two major steps are compilation and execution. The compilation step resolves all macro code to compiled code. Then the code is executed. Most timing errors occur because the user expects something to happen during compilation that doesn't actually occur until execution or, conversely, expects something to happen later but is actually executed right away.

Here are two examples to help you understand why the timing of compilation and execution can be important.

Example of a Macro Statement Executing Immediately

In the following program, the user intends to use the %LET statement and the SR_CIT variable to indicate whether a data set contains any data for senior citizens:

data senior;
   set census;
   if age > 65 then
   do;
      %let sr_cit = yes;  /* ERROR */
      output;
   end;
run;

However, the results differ from the user's expectations. The %LET statement is executed immediately, while the DATA step is only being compiled--before the data set is read. Therefore, the %LET statement executes regardless of the results of the IF condition. Even if the data set contains no observations where AGE is greater than 65, SR_CIT is always yes.

The solution is to set the macro variable's value by a means that is controlled by the IF logic and does not execute unless the IF statement is true. In this case, the user should use CALL SYMPUT, as in the following correct program:

%let sr_cit = no;
data senior;
   set census;
   if age > 65 then
   do;
      call symput ("sr_cit","yes");
    output;
   end;
run;

When this program is submitted, only if an observation is found with AGE greater than 65 is the value of SR_CIT set to yes. Note that the variable was initialized to no. It is generally a good idea to initialize your macro variables.

Macro Resolution Occurs During DATA Step Compilation

In the previous example, you learned you had to use CALL SYMPUT to conditionally assign a macro variable a value in a DATA step. So, you submit the following program:

%let sr_age = 0;
data senior;
   set census;
   if age > 65 then
   do;
      call symput("sr_age",age);
      put "This data set contains data about a person";
      put "who is &sr_age years old."; /* ERROR */
   end;
run;
If AGE was 67, you'd expect to see a log message like this one:
This data set contains data about a person
who is 67 years old.

However, no matter what AGE is, the following message is sent to the log:

This data set contains data about a person
who is 0 years old.

Why is this? Because when the DATA step is being compiled, &SR_AGE is sent to the macro facility for resolution, and the result is passed back before the DATA step executes. To achieve the desired result, submit this corrected program instead:

%let sr_age = 0;
data senior;
   set census;
   if age > 65 then
   do;
      call symput("sr_age",age);
      stop;
   end;
run;

data _null_;
   put "This data set contains data about a person";
   put "who is &sr_age years old.";
run;

Note:   Use double quotation marks in statements like PUT, because macro variables do not resolve when enclosed in single quotation marks.  [cautionend]

Here is another example of erroneously referring to a macro variable in the same step that creates it:

data _null_;
   retain total 0;
   set mydata end=final;
   total=total+price;
   call symput("macvar",put(total,dollar14.2));
   if final then put "*** total=&macvar ***"; /* ERROR */
run;

Submitting these statements writes the following lines to the SAS log:

WARNING: Apparent symbolic reference MACVAR not resolved.

*** total=&macvar ***

As this DATA step is tokenized and compiled, the & causes the word scanner to trigger the macro processor, which looks for a MACVAR entry in a symbol table. Because such an entry does not exist, the macro processor generates the warning message. Because the tokens remain on the input stack, they are transferred to the DATA step compiler. During DATA step execution, the CALL SYMPUT statement creates the macro variable MACVAR and assigns a value to it. However, the text &macvar in the PUT statement occurs because the text has already been processed while the macro was being compiled. If you were to resubmit these statements, then the macro would appear to work correctly, but the value of MACVAR would reflect the value set during the previous execution of the DATA step. This can be misleading.

Remember that in general, the % and & trigger immediate execution or resolution during the compilation stage of the rest of your SAS code.

For more examples and explanation of how CALL SYMPUT creates macro variables, see "Creating Macro Variables with the CALL SYMPUT Routine" in Chapter 5.


Solving Problems with the Autocall Facility

The autocall facility is an efficient way of storing and using production (debugged) macros. When a call to an autocall macro produces an error, the cause is one of two things:

If the error is the autocall library specification and the MERROR option is set, SAS can generate any or all of the following warnings:

WARNING: No logical assign for filename FILENAME.
WARNING: Source level autocall is not found or cannot be opened.
         Autocall has been suspended and OPTION NOMAUTOSOURCE has 
         been set. To use the autocall facility again, set OPTION
         MAUTOSOURCE.
WARNING: Apparent invocation of macro MACRO-NAME not resolved.

If the error is in the autocall macro definition, SAS generates a message like the following:

NOTE: Line generated by the invoked macro "MACRO-NAME".

Fixing Autocall Library Specifications

When an autocall library specification causes an error, it is because the macro processor cannot find the member containing the autocall macro definition in the library or libraries specified in the SASAUTOS system option.

To correct this error, follow these steps.

  1. If the unresolved macro call created an invalid SAS statement, submit a single semicolon to terminate the invalid statement. This enables the SAS System to correctly recognize subsequent statements.

  2. Look at the value of the SASAUTOS system option by printing the output of the OPTIONS procedure or by viewing the OPTIONS window in the SAS Display Manager System. (Or, edit your SAS configuration file or SAS autoexec file.) Verify each fileref or directory name. If you find an error, submit a new OPTIONS statement or change the SASAUTOS setting in the OPTIONS window.

  3. Check the MAUTOSOURCE system option. If SAS could not open at least one library, it sets the NOMAUTOSOUCE option. If NOMAUTOSOURCE is present, reset MAUTOSOURCE with a new OPTIONS statement or the OPTIONS window.

  4. If the library specifications are correct, check the contents of each directory to verify that the autocall library member exists and that it contains a macro definition of the same name. If the member is missing, then add it.

  5. Set the MRECALL option with a new OPTIONS statement or the OPTIONS window. By default, the macro processor only searches once for an undefined macro. Setting this option causes the macro processor to search the autocall libraries for the specification again.

  6. Call the autocall macro. This includes and submits the autocall macro source.

  7. Reset the NOMRECALL option.

Note:   Some host environments have environment variables or system-level logical names assigned to the SASAUTOS library; check your SAS companion for more information on details about how the SASAUTOS library specification is handled in your host environment.  [cautionend]

Fixing Autocall Macro Definition Errors

When the autocall facility locates an autocall library member, the macro processor compiles any macros in that library member and stores the compiled macros in the catalog containing stored compiled macros. For the rest of your SAS session, invoking one of those macros retrieves the compiled macro from the WORK library. Under no circumstances does the autocall facility use an autocall library member when a compiled macro with the same name already exists. Thus, if you invoke an autocall macro and discover you made an error when you defined it, you must correct the autocall library member for future use and compile the corrected version directly in your program or session.

To correct an autocall macro definition in a display manager session, do the following:

  1. Use the INCLUDE command to bring the autocall library member into the SAS PROGRAM EDITOR window. If the macro is stored in a catalog SOURCE entry, use the COPY command to bring the program into the PROGRAM EDITOR window.

  2. Correct the error.

  3. Store a copy of the corrected macro in the autocall library with the FILE command for a macro in an external file or with a SAVE command for a macro in a catalog entry.

  4. Submit the macro definition from the PROGRAM EDITOR window.

The macro processor then compiles the corrected version, replacing the incorrect compiled macro. The corrected, compiled macro is now ready to execute at the next invocation.

To correct an autocall macro definition in an interactive line mode session, do the following:

  1. Edit the autocall macro source with a text editor.

  2. Correct the error.

  3. Use a %INCLUDE statement to bring the corrected library member into your SAS session.

The macro processor then compiles the corrected version, replacing the incorrect compiled macro. The corrected, compiled macro is now ready to execute at the next invocation.

File and Macro Names for Autocall

When you want to use a macro as an autocall macro, you must store the macro in a file with the same name as the macro. Also, the file extension must be .SAS (if your operating system uses file extensions). If you experience problems with the autocall facility, be sure the macro and file names match and the file has the right extension when necessary.


Displaying Information about Stored Compiled Macros

To display the list of entries in a catalog containing compiled macros, you can use the display manager CATALOG window or the CATALOG procedure. The following PROC step displays the contents of a macro catalog in a SAS data library identified with the libref MYSASLIB:

libname mysaslib 'SAS-data-library';
   proc catalog catalog=mysaslib.sasmacr;
      contents;
   run;
   quit;

You can also use PROC CATALOG to display information about autocall library macros stored in SOURCE entries in a catalog. You cannot use PROC CATALOG or the CATALOG window to copy or rename stored compiled macros.

In Release 6.11 or later, you can use PROC SQL to retrieve information about all compiled macros. For example, submitting the following statements produces output similar to Output from PROC SQL:

proc sql;
   select * from dictionary.catalogs
        where memname in ('SASMACR');

Output from PROC SQL
        Library   Member    Member    Object    Object
        Name      Name      Type      Name      Type
                                              Date      Object
        Object Description                    Modified  Alias
        ------------------------------------------------------------
        WORK      SASMACR   CATALOG   FINDAUTO  MACRO
                                                  05/28/96

        SASDATA   SASMACR   CATALOG   CLAUSE    MACRO
        Count words in clause                     05/24/96

        SASDATA   SASMACR   CATALOG   CMPRES    MACRO
        CMPRES autocall macro                     05/24/96

        SASDATA   SASMACR   CATALOG   DATATYP   MACRO
        DATATYP autocall macro                    05/24/96

        SASDATA   SASMACR   CATALOG   LEFT      MACRO
        LEFT autocall macro                       05/24/96

To display information about compiled macros when you invoke them, use the SAS system options MLOGIC, MPRINT, and SYMBOLGEN. When you specify the SAS system option MLOGIC, the libref and date of compilation of a stored compiled macro are written to the log along with the usual information displayed during macro execution.


Solving Problems with Expression Evaluation

The following macro statements use an implicit %EVAL function:

%DO %IF-%THEN %SCAN
%DO %UNTIL %QSCAN %SYSEVALF
%DO %WHILE %QSUBSTR %SUBSTR

In addition, you can use the %EVAL function to perform an explicit expression evaluation.

The most common errors that occur while evaluating expressions are the presence of character operands where numeric operands are required or ambiguity about whether a token is a numeric operator or a character value. Chapter 6, "Macro Expressions," discusses these and other macro expression errors.

Quite often, an error occurs when a special character or a keyword appears in a character string. Consider the following program:

%macro conjunct(word= );
   %if &word = and or &word = but or &word = or %then   /* ERROR */
      %do %put *** &word is a conjunction. ***;

   %else
      %do %put *** &word is not a conjunction. ***;
%mend conjunct;

In the %IF statement, the values of WORD being tested are ambiguous--they could also be interpreted as the numeric operators AND and OR. Therefore, the SAS System generates the following error messages in the log:

ERROR: A character operand was found in the %EVAL function or %IF 
       condition where a numeric operand is required. The condition
       was:word = and or      &word = but or       &word = or
ERROR: The macro will stop executing.

To fix this problem, use the quoting functions %BQUOTE and %STR, as in the following corrected program:

%macro conjunct(word= );
   %if %bquote(&word) = %str(and) or %bquote(&word) = but or
          %bquote(&word) = %str(or) %then
      %do %put *** &word is a conjunction. ***;

   %else
      %do %put *** &word is not a conjunction. ***;
%mend conjunct;

In the corrected program, the %BQUOTE function quotes the result of the macro variable resolution (in case the user passes in a word containing an unmatched quotation mark or some other odd value), and the %STR function quotes the comparison values AND and OR at compile-time, so they are not ambiguous. You do not need to use %STR on the value BUT, because it is not ambiguous (not part of the SAS or macro language). See Chapter 7, "Macro Quoting," for more information on using macro quoting functions.


Chapter Contents

Previous

Next

Top of Page

Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.