Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 1 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 2 Objectives 3 Perform application development in stages. Implement parameter validation. Store re-usable code as macro programs. Create local macro variables. Add comments to macro programs. Developing Best Practices In order to improve macro application development, the Orion Star programmers implemented these guidelines for new programs and applications: 1. Develop the application in stages. 2. Prevent program failures associated with usersupplied values by validating parameters. 3. Create user-defined macro functions or routines for repetitive tasks. 4. Create local macro variables when possible. 5. Document all programs to help with maintenance. 4 Guideline 1: Develop in Stages To isolate SAS syntax/logic from macro syntax/logic during development, implement your application in stages. Stage 1: Write and debug the desired code without macro techniques. Use hardcoded program elements. Use a fixed set of data. proc print data=orion.continent; title "ORION.CONTINENT Data Set"; run; 5 continued... Guideline 1: Develop in Stages Stage 2: Generalize the application. Activate the SYMBOLGEN system option for debugging macro variable resolution. Replace hardcoded elements with macro variable references. Use %LET statements to try different values. options symbolgen; %let dsn=orion.continent; proc print data=&dsn; title "%upcase(&dsn) Data Set"; run; 6 continued... Guideline 1: Develop in Stages Stage 3: Create a macro definition. Convert %LET statements to macro parameters. Activate the MPRINT system option to view the generated SAS code. Call the macro with different parameter values. %macro printone(dsn); proc print data=&dsn; title "%upcase(&dsn) Data Set"; run; %mend printone; options mprint; %printone(orion.continent) 7 continued... Guideline 1: Develop in Stages Stage 4: Add macro-level programming. Perform conditional logic with %IF statements. Perform iterative logic with %DO statements. Activate the MLOGIC system option to verify the macro programming flow and logic. %macro printone(dsn); %if &dsn ne %then %do; proc print data=&dsn; title "%upcase(&dsn) Data Set"; run; %end; %mend printone; options mlogic; %printone(orion.continent) 8 Guideline 2: Validate Parameters The Orion Star programmers found that user-supplied parameters can cause difficulties for macro applications. They decided that macro applications should test parameters for the following conditions: null values invalid values cross-validation of parameters 9 Guideline 2: Validate Parameters To validate parameters, perform these steps: 1. Establish rules for valid values with the following criteria, for example: a. Are null values valid? b. What are valid values? 2. Validate parameter values against valid values. 3. Generate an error or warning message when invalid values are encountered. Possibly terminate the macro. 10 11 2.01 Quiz Based on the following macro definition, what parameter values could cause this program to fail? %macro printdsn(path, dsn, obs); libname orion "&path"; proc print data=orion.&dsn (obs=&obs); run; %mend printdsn; 12 m202a01 2.01 Quiz – Correct Answer Based on the following macro definition, what parameter values could cause this program to fail? Null values for any of three parameters could cause a problem with the macro’s execution. An invalid path could cause the macro to fail. Special characters, such as & and % found in the path value, could cause problems with the macro call. An invalid data set name or nonexisting data set could cause the macro to fail. A nonnumeric value for OBS could cause the macro to fail. 13 Guideline 3: Create Reusable Macros Some Orion Star macro programs became lengthy and difficult to maintain. Instead of writing one massive program, the programmers decided to develop small modules or macros and then put them together. The advantages of writing a macro definition in smaller pieces include the following: testing of each piece separately maintaining each piece separately creating reusable modules of code 14 Guideline 3: Create Reusable Macros Other advantages of building a library of reusable macros include the following: simplifying code hiding complex code sharing and reusing code reducing maintenance 15 16 2.02 Quiz Open the program m202a02. Which sections can be placed in separate macros and considered reusable? 17 2.02 Quiz – Correct Answer Open the program m202a02. Which sections can be placed in separate macros and considered reusable? the %PUT statements for message generation the routine to convert macro variable to uppercase the routine that checks the number of observations 18 Guideline 4: Create Local Macro Variables Whenever possible, Orion Star applications should create local macro variables. Local macro variables exist only as long as a macro executes. Using local macro variables prevents the following: inadvertently altering a global macro variable's value needing to delete macro variables after a macro finishes executing 19 Guideline 5: Comment Macro Applications Comments were somewhat lacking in the past. Orion Star decided that every macro should start with a comment block that describes its functionality, parameters, and requirements. Comments in a macro program can be defined using these techniques: %* macro comment statements; /* block comments */ * SAS comment statements; Comments in the form of /* comment */ are the safest comments to use inside a macro definition. 20 Guideline 5: Comment Macro Applications Partial SAS Program %macro archive(dsn); /*-----------------------------------------------------*/ /* ARCHIVE - Archive data set, appending current date */ /* to build a new (unique by day) name for the copy. */ /*-----------------------------------------------------*/ /* Parameter DSN: Master table to be archived */ /*-----------------------------------------------------*/ /* Requires these other macros: */ /* %VALIDDSN - validates a SAS data set name */ /*-----------------------------------------------------*/ %* %put Activating the MPRINT and MLOGIC options.; *options mprint mlogic; 21 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 22 Objectives 23 Use macro debugging options during macro development. Debugging and Troubleshooting Macros The Orion Star programmers encountered different challenges during macro development versus macro use. During development they encountered the following problems: macro logic and code generation errors the open code recursion error the "Black Hole" macro problem 24 Development Debugging Options (Review) These two solutions enable tracing macro variable resolution: the SYMBOLGEN option to display the results of resolving macro variable references the %PUT statement to write a variable's value to the log These three solutions aid in debugging macro definitions: the MLOGIC option to display macro execution messages the MPRINT option to display SAS statements generated by macro execution the %PUT statement to check the evaluation of a condition 25 Solving Open Code Recursion Problems Open code recursion occurs when your code mistakenly causes a macro statement to call another macro statement. The most common reason is a missing semicolon. SAS Log A missing semicolon in the %LET statement caused the open code recursion. 115 %let newvar=new value 116 %put NEWVAR has the value &newvar; ERROR: Open code statement recursion detected. 26 Solving Open Code Recursion Problems To recover from an open code recursion error, first submit a single semicolon. If that does not work, submit the following code: *'; *"; *); */; %mend; run; Submit this string until this message appears in the SAS log: ERROR: No matching %MACRO statement for this %MEND statement. 27 Solving the “Black Hole” Macro Problem A “Black Hole” macro problem occurs when the SAS windowing environment stops responding after you submit a macro definition. You type and submit code, but nothing happens. Generally this occurs when the macro processor does not recognize the %MEND statement and all text becomes part of the macro definition. This can happen as a result of one of these problems: omitting a %MEND statement omitting a semicolon in the statement preceding the %MEND statement unmatched quotation marks or unclosed parentheses an unclosed comment 28 Solving the “Black Hole” Macro Problem 120 %macro printone(dsn); The missing semicolon in the 121 %if &dsn ne %then %do; 122 proc print data=&dsn; %END statement causes the 123 title "%upcase(&dsn) Data Set"; windowing environment to stop 124 run; 125 %end responding. 126 %mend printone; NOTE: Extraneous information on %END statement ignored. 127 %printone(orion.continent) 128 %put This should print in the log.; 129 %put So should this.; The PRINTONE macro and the %PUT statements do not execute. 29 Solving the “Black Hole” Macro Problem To exit the macro “Black Hole,” submit the following code: *'; *"; *); */; %mend; run; Submit this string until the following message appears in the SAS log: ERROR: No matching %MACRO statement for this %MEND statement. 30 31 2.03 Quiz 1. Open and submit the program m202a03. 2. Look at the log to determine the reason that the macro does not execute. 3. Correct the problem and resubmit the program. 4. If the macro still fails to execute, type and submit the following statement: *'; *"; *); */; %mend; run; 5. When the following message appears in the log, submit the macro definition and ensure that it executes properly. ERROR: No matching %MACRO statement for this %MEND statement. 32 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 33 Objectives 34 Write custom messages to the log. Write custom messages using the DATA step. Use the %WINDOW and %DISPLAY statements. Generating Custom Messages The Orion Star users requested feedback via custom messages. To facilitate this request, the programmers will use one of these three techniques: the %PUT statement to display messages in the Log window the DATA step to write to the current output location %WINDOW and %DISPLAY statements to create a custom message window After the messages are issued, the macro’s execution can be terminated if the error is severe. 35 Terminating Macro Execution To terminate macro execution, use the %RETURN statement. General form of the %RETURN statement: %RETURN; To terminate the currently executing macro, along with the current SAS job or SAS session, use the %ABORT statement with the ABEND option. General form of the %ABORT statement: %ABORT ABEND; 36 Terminating Macro Execution The %RETURN and %ABORT statements usually appear as part of %IF-%THEN logic and generally eliminate the need for %ELSE statements. %macro printone(dsn); %if &dsn eq %then %return; proc print data=&dsn; title "%upcase(&dsn) Data Set"; run; %mend printone; The %RETURN statement eliminated the need for the PROC PRINT step to be contained within %ELSE logic. 37 Generating Custom Log Messages The Orion Star programmers will generate custom log messages using the %PUT statement. To make the custom messages resemble standard ERROR, NOTE, and WARNING messages, start the message text with the corresponding keyword. %put ERROR: This is an error message.; %put WARNING: This is a warning message.; %put NOTE: This is a note.; Partial SAS Log ERROR: This is an error message. WARNING: This is a warning message. NOTE: This is a note. 38 m202d01 Generating Custom Log Messages For messages that span several lines, it might be desirable to suppress the words ERROR, NOTE, and WARNING on subsequent lines. Use a hyphen instead of a colon to suppress the keywords. %put ERROR: This is an error message.; %put ERROR- It spans several lines.; %put ERROR- Notice the indention.; Partial SAS Log ERROR: This is an error message. It spans several lines. Notice the indention. 39 m202d01 Generating Custom Output Messages The DATA step is generally used to create data sets but can also be used to write custom text to the current output destination. A typical DATA step for writing text contains at least four parts: 40 a DATA _NULL_ statement to invoke the DATA step a FILE statement to direct the output PUT statements to write lines to the specified output location a RUN statement to terminate the DATA step Generating Custom Output Messages data _null_; file print; put #5 @20 "Welcome to SAS Macro Language 2"; run; DATA Step Output The PRINT option in the FILE statement sends the 41 results to the current output location (Output window, LST file, or SASLIST location). Generating Custom Output Messages This demonstration illustrates using the DATA step to generate custom messages in the Output window. 42 m202d02 Creating Custom Message Windows Use the %WINDOW statement to define the size, text, and attributes of the custom message window. General form of the %WINDOW statement: %WINDOW window-name <columns=n rows=n> field-definition-1 <field-definition-n>; %window welcome columns=25 rows=10 #3 @10 'Welcome to SAS Macro Language 2.' #5 @10 'Press ENTER to close this window.'; 43 Creating Custom Message Windows Use the %DISPLAY statement to display the window. General form of the %DISPLAY statement: %DISPLAY window-name; %display welcome; 44 Using %WINDOW and %DISPLAY to Generate Custom Message Windows This demonstration illustrates using the %WINDOW and %DISPLAY statements to create a custom message window. 45 m202d03 Generating Custom Messages Although the different methods are not mutually exclusive, there are situations or applications where one is more appropriate. %PUT DATA Step %WINDOW %DISPLAY Interactive SAS X X X SAS Enterprise Guide X X Noninteractive Programs X X Stored Processes X SAS/IntrNet Applications X With any application, also consider the user of the application when you determine the best method. 46 X Exercise This exercise reinforces the concepts discussed previously. 47 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 48 Objectives 49 Avoid excessive macro processing. Use memory resources efficiently. Create autocall macros to minimize macro compilation. Create stored compiled macros to avoid repeated macro compilation. Efficiency Considerations with Macro “The macro facility is a powerful tool for making your SAS code development more efficient.” “Usually, efficiency issues are discussed in terms of CPU cycles, elapsed time, I/O hits, memory usage, disk storage, and so on.” “The area of efficiency most affected by the SAS macro facility is human efficiency – how much time is required to both develop and maintain a program.” from SAS® Macro Language: Reference 50 Macro More Efficient The Orion Star programmers realize that incorporating macro code into a SAS application does not necessarily make the application more or less efficient. Because most macros generate SAS code, they want to concentrate on making the resulting SAS code more efficient. They plan to use macro techniques only when necessary. They will balance efficiency factors to reach a solution that is best for the application. Considerations include the following: how often you run the application machine resource savings versus maintainability and ease of use 51 Avoiding Extra Macro Processing Methods to minimize the work performed by the macro processor include the following: 1. Avoid nested macro definitions. 2. Minimize function calls, which are CPU-intensive, by assigning function results to macro variables. 3. Delete global macro variables. 4. Use the %RETURN statement to terminate macros when parameters fail validation and to eliminate the need for additional %ELSE logic. 5. Turn off macro debugging options in production jobs. 6. Store and reuse macros. 52 Example 1: Avoid Nested Macro Definitions When macro definitions are nested, the execution of the OUTER macro includes recompilation of the INNER macro. %macro outer; proc catalog cat=work.sasmacr; contents; title "Macros Before Nested Macro"; run; %macro inner; %put The inner macro is executing.; %mend inner; contents; title "Macros After Nested Macro"; run; quit; %mend outer; %outer 53 m202d04 Example 1: Avoid Nested Macro Definitions Partial PROC CATALOG Output Macros Before Nested Macro Contents of Catalog WORK.SASMACR # Name Type Create Date Modified Date ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ 1 OUTER MACRO 23Jun08:18:18:12 23Jun08:18:18:12 Macros After Nested Macro Contents of Catalog WORK.SASMACR # Name Type Create Date Modified Date ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ 1 INNER MACRO 23Jun08:18:18:13 23Jun08:18:18:13 2 OUTER MACRO 23Jun08:18:18:12 23Jun08:18:18:12 54 Example 2: Assign Results to Variables Assigning macro function results to a macro variable provides the following functionality: Repeated execution of the same macro function can be avoided. Leading and trailing blanks are removed automatically through the %LET statement. Intermediate results can be monitored using the SYMBOLGEN system option during debugging. 55 Example 2: Assign Results to Variables Use this program: %macro country(name); %let name=%upcase(&name); proc print data=orion.country; where upcase(Country_Name)="&name"; title "Report for &name"; run; %mend country; options symbolgen; %country(united states); Instead of this program: %macro country(name); proc print data = orion.country; where upcase(Country_Name)="%upcase(&name)"; title "Report for %upcase(&name)"; run; %mend country; options symbolgen; %country(united states); 56 m202d05 Example 3: Delete Macro Variables Because symbol tables are stored in memory, deleting macro variables when they are no longer needed can save memory resources. To delete global macro variables, use the %SYMDEL statement. Partial SAS Log %global VAR1 VAR2 VAR3 VAR4 VAR5 ; %put _global_; GLOBAL VAR1 GLOBAL VAR2 GLOBAL VAR3 GLOBAL VAR4 GLOBAL VAR5 %symdel VAR1 VAR2; %put _global_; GLOBAL VAR3 GLOBAL VAR4 GLOBAL VAR5 57 m202d06 Example 3: Delete Macro Variables To delete a series of macro variables, use the SYMDEL routine in the DATA step. General form for the SYMDEL routine: CALL SYMDEL(<macro-variable>); where macro-variable can be any of the following: the name of a macro variable within quotation marks but without an ampersand the name of a DATA step character variable, specified with no quotation marks, which contains the name of a macro variable a character expression that constructs a macro variable name 58 59 2.04 Quiz Open the program m202a04. Add the following statement after the %GLOBAL statement and after the DATA _NULL_ step: %put _global_; 1. What was the result of the %PUT statement after the %GLOBAL statement? 2. What was the result of the %PUT statement after the DATA _NULL_ step? 60 2.04 Quiz – Correct Answer Open the program m202a04. Add the following statement after the %GLOBAL statement and after the DATA _NULL_ step: %put _global_; 1. What was the result of the %PUT statement after the %GLOBAL statement? 57 %global VAR1 VAR2 VAR3 VAR4 VAR5 ; 58 59 %put _global_; GLOBAL VAR1 GLOBAL VAR2 GLOBAL VAR3 GLOBAL VAR4 GLOBAL VAR5 61 continued... 2.04 Quiz – Correct Answer 2. What was the result of the %PUT statement after the DATA _NULL_ step? data temp; set sashelp.vmacro; where scope='GLOBAL' and name like 'VAR%'; run; NOTE: There were 5 observations read from the data set SASHELP.VMACRO. WHERE (scope='GLOBAL') and name like 'VAR%'; NOTE: The data set WORK.TEMP has 5 observations and 4 variables data _null_; set temp; call symdel(name); run; NOTE: There were 5 observations read from the data set WORK.TEMP. %put _global_; 62 No macro variables are listed. All were deleted. Example 4: Use the %RETURN Statement Because the %RETURN statement terminates normal execution, the %ELSE statement is not required. %macro no_else(dsn); %if &dsn = %then %return; proc print data=&dsn; title "%upcase(&dsn) Data Set"; run; %mend no_else; 63 Example 5: Deactivate Debug Options in Production Turn off the SYMBOLGEN and MLOGIC system options in production jobs. Writing messages to the log expends resources. Custom error messages written to the log might be more difficult to locate. Keep the MPRINT system option synchronized with the SOURCE system option to request (or suppress) the display of executed SAS code in the SAS log. 64 Example 6: Store and Reuse Macros Session-compiled macros are macros that are compiled and stored in a SAS catalog in the Work library and only exist during the current SAS session. Orion Star plans to save frequently used macros between sessions, using either the autocall macro facility or the stored compiled macro facility. 65 Autocall macro facility stores the source code for SAS macros in a collection of external files or SAS catalogs called an autocall library. The macro is automatically compiled when the macro is called. Stored compiled macro facility stores compiled macros in a permanent SAS catalog. Example 6: Store and Reuse Macros The Orion Star programmers plan to use the autocall facility in these circumstances: New macro programs are being developed. A group of users or an application shares macros. A macro definition is routinely modified. A macro is used in different operating environments. 66 Creating an Autocall Macro To create an autocall macro, the name of the file must match the macro name. For the PRINTDSN macro to be an autocall macro, it is saved in a file named PRINTDSN. Each autocall macro is stored as one of the following: a file with the extension .sas for directory-based systems The UNIX operating system requires the filename to be in lowercase letters. 67 a member of a partitioned data set (PDS) for z/OS Accessing Autocall Macros The following steps enable you to access a macro defined in an autocall library: 1. Specify the SAS system option MAUTOSOURCE. 2. Use the SAS system option SASAUTOS= to identify the name of the autocall library or to associate a fileref of SASAUTOS with the autocall library. 3. Call any macro in the library during the SAS session. 68 Autocall Facility System Options The MAUTOSOURCE system option controls whether the autocall facility is available. General form of the MAUTOSOURCE system option: OPTIONS MAUTOSOURCE | NOMAUTOSOURCE; The default option is MAUTOSOURCE. 69 Autocall Facility System Options The SASAUTOS= system option controls where the macro facility looks for autocall macros. General form of the SASAUTOS= system option: OPTIONS SASAUTOS=(library-1,...,library-n, SASAUTOS); The values of library-1 through library-n are references to source libraries containing macro definitions. The fileref SASAUTOS identifies the location for the autocall macros supplied by SAS. 70 Accessing Autocall Macros Does the macro exist in the Work library? Yes Execute the compiled macro. No Does the macro exist in the autocall library? Yes Include and submit a macro definition to compile the macro. Execute the compiled macro. 71 No WARNING: Apparent invocation of macro not resolved. Accessing Autocall Macros Two problems might occur when you create and/or debug autocall macros. An incorrect path specification exists in the SASAUTOS= option. The autocall macro is changed, but subsequent calls to the macro do not reflect the changes. 72 Debugging Autocall Macros What do you do if you cannot access your autocall macro? WARNING: Apparent invocation of macro not resolved. The most common reason for this warning is an incorrect path specification in the SASAUTOS= option. By default, SAS does not search the autocall libraries for a member that was not found during an earlier search. Correcting the SASAUTOS= option does not result in SAS locating the autocall macro. 73 Debugging Autocall Macros Use the MRECALL option to recover from errors caused by a call to a macro in an unavailable autocall library. General form of the MRECALL option: OPTIONS NOMRECALL | MRECALL; Set the MRECALL option and call the macro again after making the autocall library available. 74 Debugging Autocall Macros After an autocall macro is compiled, SAS will not recompile the source code even if the macro definition changed. It is important to do one of the following: exit SAS delete the session-compiled macro use the %INCLUDE statement to recompile the new modified autocall macro General form for the %INCLUDE statement: %INCLUDE 'external-file' | fileref; 75 76 2.05 Quiz 1. Open and submit the program m202a05 that calls the autocall macro FREQ. Did the macro execute? 2. Uncomment the appropriate OPTION statement to modify the SASAUTOS= option and resubmit the program. Did the macro execute? 3. Add the MRECALL option and resubmit the program. Did the macro execute? 4. Open the program FREQ, uncomment the %PUT statements, and save the changed program. 5. Submit the following macro call: %freq(,Customer_Gender) Were the messages from the %PUT statements written to the log? 77 continued... 2.05 Quizz 6. Does the MRECALL option force the FREQ macro to be recompiled? 7. Submit the following %INCLUDE statement and macro call: %include 'freq.sas'; %freq(,Customer_Gender) Were the messages from the %PUT statements written to the log? 78 2.05 Quiz – Correct Answer 1. Open and submit the program m202a05 that calls the autocall macro FREQ. Did the macro execute? No, the default autocall location is SASAUTOS=SASAUTOS. 2. Uncomment the appropriate OPTION statement to modify the SASAUTOS= option and resubmit the program. Did the macro execute? No, SAS will not search the autocall libraries for a member that was not found during an earlier search. 3. Add the MRECALL option and resubmit the program. Did the macro execute? Yes, the MRECALL option causes SAS to search the autocall libraries again. 79 continued... 2.05 Quiz – Correct Answer 4. Open the program FREQ, uncomment the %PUT statements, and save the changed program. 5. Submit the following macro call: %freq(,Customer_Gender) Were the messages from the %PUT statements written to the log? No, SAS will not recompile the FREQ macro after it is compiled successfully. 80 continued... 2.05 Quiz – Correct Answer 6. Does the MRECALL option force the FREQ macro to be recompiled? No, the MRECALL option will not force a macro to recompile. 7. Submit the following %INCLUDE statement and macro call: %include 'freq.sas'; %freq(,Customer_Gender) Were the messages from the %PUT statements written to the log? Yes. 81 The Autocall Facility Advantages of the Autocall Facility Conditionally executed macros are compiled only if they are actually invoked. You do not have to submit the source code for the macro definition before calling the macro. You can set up multiple autocall libraries. Macro definitions are easily viewed and edited with any text editor. You can create a pool of easily maintained macros that different applications and users can access. Disadvantages of the Autocall Facility The macro must be compiled the first time that it is called in a SAS session. 82 Example 6: Store and Reuse Macros The Orion Star programmers plan to use the stored compiled macro facility for production-level jobs to save macro compilation time for macros that contain many macro statements. 83 Creating a Stored Compiled Macro These steps create a permanently stored compiled macro: 1. Assign a libref to the SAS data library where the compiled macro is to be stored. 2. Set system options MSTORED and SASMSTORE=libref. 3. Submit the macro definition using the STORE option in the %MACRO statement. 84 Stored Compiled Macro Facility System Options The MSTORED system option controls whether the stored compiled macro facility is available. General form of the MSTORED system option: OPTIONS NOMSTORED | MSTORED; The default option is NOMSTORED. 85 Stored Compiled Macro Facility System Options The SASMSTORE= system option controls where the macro facility looks for and writes stored compiled macros. General form of the SASMSTORE= system option: OPTIONS SASMSTORE=libref; The libref points to an allocated SAS data library. 86 USING the STORE, SOURCE, and DES= Options General form of a stored compiled macro definition: %MACRO macro-name (parameters) / STORE SOURCE DES='text' SECURE; macro-text %MEND macro-name; To do this… 87 Use this option store the compiled macro as a catalog entry in a permanent SAS library STORE store the source code of the macro, along with the compiled code, as an entry in a SAS catalog SOURCE specify a description for the macro entry in the macro catalog DES='text' encrypt the stored compiled macro (The %COPY statement does not display the source code.) SECURE Accessing Stored Macro Source Code Use a %COPY statement to retrieve the source code of a compiled stored macro. General form of the %COPY statement: %COPY macro-name / SOURCE <OUT='external file'>; If the OUT= option is omitted, source code is written to the SAS log. 88 89 2.06 Quiz 1. Open the program m202a06. Add the STORE and SOURCE options to the %MACRO statement. %macro freq(dsn, tablevar)/store source; 2. Write a %COPY statement to view the source code in the log. 90 2.06 Quiz – Correct Answer Partial SAS Log 91 60 options mstored sasmstore=sasuser; 61 62 %macro freq(dsn, tablevar)/store source; . . . Lines removed . . . 74 %mend freq; 75 76 %copy freq / source; %macro freq(dsn, tablevar)/store source; %if &dsn = %then %do; %put You need to provide a data set name.; %return; %end; %if &tablevar = %then %do; %put You need to provide a table variable.; %return; %end; proc freq data = &dsn; tables &tablevar; run; %mend freq; Using the SECURE Option The SECURE option can be used to write secure macros that will protect intellectual property that is contained in the macros. %macro freq(dsn, tablevar)/store source secure; %if &dsn = %then %do; %put You need to provide a data set name.; %return; %end; %if &tablevar = %then %do; %put You need to provide a table variable.; %return; %end; proc freq data = &dsn; tables &tablevar; run; %mend freq; 92 m202d07 Using the SECURE Option There is no output produced when you use the %COPY statement. %copy freq / source; SAS Log 340 %copy freq / source; NOTE: The macro %FREQ was compiled with the /SECURE option. No output will be produced for this %COPY statement. 93 m202d07 Accessing Stored Compiled Macros To access stored compiled macros, you must perform the following steps: 1. Assign a libref to the SAS data library containing a SASMACR catalog. 2. Set system options MSTORED and SASMSTORE=libref. 3. Call any macro stored in libref.SASMACR. 94 Accessing Stored Compiled Macros Is PRINTDSN.MACRO in WORK.SASMACR catalog? Yes Execute sessioncompiled PRINTDSN macro. Yes Execute stored compiled PRINTDSN macro. No libref.SASMACR catalog? No autocall library? No Yes Requires MSTORED and SASMSTORE= system options Compile and execute PRINTDSN autocall macro. Requires MAUTOSOURCE and SASAUTOS= system options WARNING: Apparent invocation of macro PRINTDSN not resolved. 95 Using a Stored Compiled Macro The following are restrictions on stored compiled macros: You can only store compiled macros in the SASMACR catalog. You should not rename this catalog or its entries. You cannot copy compiled macros across operating systems or across releases of SAS. You must copy the source program and re-create the stored compiled macro. 96 Stored Compiled Macro Facility Advantages of Stored Compiled Macros SAS does not have to compile a macro definition when a macro call is made. Users cannot modify compiled macros. Session-compiled macros and the autocall facility are available in the same session. Disadvantages of Stored Compiled Macros Because you cannot edit a compiled macro, you must save and maintain the source for the macro definition. There can be only one SASMACR catalog per library. Stored compiled macros are not portable across operating environments. 97 Exercise This exercise reinforces the concepts discussed previously. 98 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 99 Objectives 100 Define the scope of a macro variable. Control the scope of a macro variable created by the SYMPUTX routine. Global versus Local Macro Variables Although global macro variables are available for the duration of a SAS session, Orion Star wants to create local macro variables whenever possible. Advantages of local macro variables include the following: conserve memory prevent accidentally updating a global macro variable's value 101 Rules for Creating and Updating Variables (Review) When the macro processor receives a request to create or update a macro variable during macro execution, the macro processor follows these rules: %let macvar=value; Does MACVAR already exist in a local table? Yes Update MACVAR in a local table. No Does MACVAR already exist in the global table? No Yes Update MACVAR in the global table. Create MACVAR in the local table. 102 Rules for Resolving Variables (Review) To resolve a macro variable reference during macro execution, the macro processor follows these rules: &macvar Does MACVAR exist in a local table? Yes Retrieve from local table. No Does MACVAR exist in the global table? No Yes Retrieve from global table. Return tokens to the word scanner. Issue a warning to the SAS log: Apparent symbolic reference MACVAR not resolved. 103 Resolving Variables in Nested Symbol Tables (Review) Multiple local tables can exist concurrently during macro execution. The search begins with the most local table and, if necessary, moves outward to the global table. Global Table MACRO1 Local Table MACRO2 Local Table MACRO3 Local Table 104 MACRO4 Local Table Creating Local Macro Variables (Review) Local macro variables can be created within a macro definition by any of the following methods: %LET statement DATA step SYMPUTX routine PROC SQL SELECT statement INTO clause %LOCAL statement Macros defined with parameters also create local macro variables. 105 Creating Local Macro Variables The Orion Star programmers want to ensure that the macro processor creates a local macro variable. They will use one of the following techniques: the %LOCAL statement the L argument for the SYMPUTX routine 106 The %LOCAL Statement (Review) General form of the %LOCAL statement: %LOCAL macro-variable1 macro-variable2 …; 107 The %LOCAL statement adds one or more macro variables to the local symbol table with null values. It has no effect on variables already in the local table. It can appear only inside a macro definition. The SYMPUTX Routine (Review) The optional scope argument of the SYMPUTX routine specifies where to store the macro variable. CALL SYMPUTX(macro-variable, text <,scope>); The value for scope can be one of the following: 108 G specifies the global symbol table. L specifies the current macro's local symbol table. If no local symbol table exists for the current macro, a local symbol table is created. 109 2.07 Quiz 1. Open the program m202a07. Submit the program and examine the log messages. What are the problems with this program? 2. Insert the following %PUT statement after the RUN statement in the MAKELIST macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? 110 2.07 Quiz – Correct Answer 1. Open the program m202a07. Submit the program and examine the log messages. What are the problems with this program? The scope argument in the SYMPUTX routine forces the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 into the symbol table for the MAKELIST macro. Therefore, they are not available to the CUSTOMERS macro. 111 continued... 2.07 Quiz – Correct Answer 2. Insert the following %PUT statement after the RUN statement in the MAKELIST macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? MAKELIST 112 Omitting the Scope Argument If the SCOPE option is omitted and no local symbol tables exist, the SYMPUTX routine will store the macro variables in the global symbol table. %macro makelist; data _null_; set orion.country end=final; call symputx(cats('country', _n_), Country); call symputx(cats('countryname', _n_), Country_Name); if final=1 then call symputx('n', _n_); run; %put _user_; No scope specification %mend makelist; 113 m202d08 Omitting the Scope Argument Partial Log 25 %makelist NOTE: There were 7 observations read from the data set ORION.COUNTRY. NOTE: DATA statement used (Total process time): real time 0.53 seconds cpu time 0.10 seconds GLOBAL COUNTRY5 TR GLOBAL COUNTRY2 CA GLOBAL COUNTRY3 DE GLOBAL COUNTRY1 AU GLOBAL N 7 GLOBAL COUNTRYNAME1 Australia GLOBAL COUNTRYNAME2 Canada GLOBAL COUNTRYNAME3 Germany GLOBAL COUNTRYNAME4 Israel GLOBAL COUNTRYNAME5 Turkey GLOBAL COUNTRYNAME6 United States GLOBAL COUNTRYNAME7 South Africa GLOBAL COUNTRY6 US GLOBAL COUNTRY7 ZA GLOBAL COUNTRY4 IL 114 m202d08 115 2.08 Quiz 1. Open the program m202a08. Delete the scope argument from the three CALL SYMPUTX statements and insert the following %PUT statement after the %END statement in the CUSTOMERS macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? 116 2.08 Quiz – Correct Answer 1. Open the program m202a08. Delete the scope argument from the CALL SYMPUTX statement and insert the following %PUT statement after the %END statement in the CUSTOMERS macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? Global symbol table 117 Correcting the Scope Issues with SYMPUTX The Orion star programmers want to correct the scope problems with the SYMPUTX routine without creating global macro variables. To ensure the scope of the macro variables, they will use the following technique: omit the scope argument for the SYMPUTX routine use a %LOCAL statement 118 Correcting the Scope Issues with the SYMPUTX Routine This demonstration illustrates how to correct the scope issues with the SYMPUTX routine. 119 m202d09 Correcting the Scope Issues with SYMPUTX In some applications, the name and number of created macro variables might be unknown. Without the SCOPE argument, the SYMPUTX routine will store macro variables in the first symbol table that it encounters. call symputx(cats('country',_n_), Country); Does the MAKELIST macro have a local table? Yes Store the macro variables in the MAKELIST symbol table. No Does the CUSTOMER macro have a local table? No Yes Store the macro variables in the CUSTOMER symbol table. Store the macro variables in the global symbol table. 120 121 2.09 Quiz 1. Open the program m202a09. Delete all macro variables from the %LOCAL statement except for the macro variable I. Insert the following %PUT statement after the %END statement in the CUSTOMERS macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? 2. Move the %LOCAL statement after the call to the MAKELIST macro. In which symbol table are the macro variables saved? 122 2.09 Quiz – Correct Answer 1. Open the program m202a09. Delete all macro variables from the %LOCAL statement except for the macro variable I. Insert the following %PUT statement after the %END statement in the CUSTOMERS macro: %put _user_; In which symbol table are the macro variables N, COUNTRY1 through COUNTRY 7, and COUNTRYNAME1 through COUNTRYNAME7 saved? CUSTOMERS symbol table 123 continued... 2.09 Quiz – Correct Answer 2. Move the %LOCAL statement after the call to the MAKELIST macro. In which symbol table are the macro variables saved? Global symbol table 124 The %SYMLOCAL Function The %PUT statement is useful when you want to display the contents of a symbol table. To test whether a macro variable is in the local symbol table, the Orion Star programmers plan to use the %SYMLOCAL function. General form of the %SYMLOCAL function: %SYMLOCAL(macro-variable-name) The %SYMLOCAL function returns a value of 1 if the macro variable is found in a local symbol table and a 0 if not. 125 The %SYMLOCAL Function Partial SAS Log 223 224 225 226 227 228 229 230 231 %macro scope; data _null_; call symputx('dog','Paisley','L'); run; %if %symlocal(dog)=1 %then %put NOTE: DOG is in the local table.; %else %put WARNING: DOG is in the global table.; %mend scope; %scope NOTE: DOG is in the local table. 232 233 /* Omitting the scope argument on SYMPUTX */ 234 %macro scope; 235 data _null_; 236 call symputx('dog','Paisley'); 237 run; 238 %if %symlocal(dog)=1 %then %put NOTE: DOG is in the local table.; 239 %else %put WARNING: DOG is in the global table.; 240 %mend scope; 241 242 %scope WARNING: DOG is in the global table. 126 m202d10 Chapter 2: Framework for Developing Macro Applications 2.1 Applying Best Practices 2.2 Debugging and Troubleshooting 2.3 Generating Custom Messages 2.4 Creating Efficient Macros 2.5 Understanding Symbol Tables 2.6 Creating Portable Applications (Self-Study) 127 Objectives 128 Use automatic macro variables to identify the operating environment. Use automatic macro variables to identify the version of SAS. Use automatic macro variables to identify the software that is currently licensed. Defining Portability Orion Star has select macros that must run in multiple operating environments. The programmers plan to optimize a programmer’s development effort by designing portable macros. Portable macro applications must identify the following information: the host environment(s) the version(s) of SAS currently licensed SAS software 129 Identifying the Host Environment The SYSSCP automatic macro variable stores the abbreviation of the host environment. Values for SYSSCP include the following: 130 Value of SYSSCP Operating System WIN Windows XP, Vista, Server 2003, Server 2008 SUN 4 SOLARIS2 or SUN4.1.x OS z/OS Identifying the Host Environment The macro LIBASSIGN uses SYSSCP to determine the host platform and assigns a libref using the appropriate syntax for the operating environment. %macro libassign; %local location; %if &sysscp=WIN %then %let location=s:\workshop; %else %if &sysscp=OS %then %let location=edu999.workshop.sasdata; %else %let location=/local/users/edu999; libname orion "&location"; %mend libassign; 131 m202d11 Identifying the Version of SAS The SYSVER automatic macro variable identifies the version of SAS software. It can be used to generate code that depends on the version. %if &sysver=9.2 %then %do; %let setinoption=options minoperator; %let ifvalue=&place in AU CA DE IL TR US ZA; %let resetinoption=options nominoperator; %end; %else %do; %let ifvalue=&place=AU or &place=CA or &place=DE or &place=IL or &place=TR or &place=US or &place=ZA; %end; The IN operator is new in SAS 9.2. The list of values is not enclosed in parentheses. 132 m202d12 Identifying SAS Products Licensed The result of the %SYSPROD function indicates whether a product is licensed. %macro chart; %local procname; %if %sysprod(graph) %then %let procname=gchart; %else %let procname=chart; proc &procname data=orion.customer_dim; vbar Customer_Age_Group; run; quit; %mend chart; %chart 133 m202d13