LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (November 2002, week 4)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Mon, 25 Nov 2002 11:13:05 -0500
Reply-To:     Ian Whitlock <WHITLOI1@WESTAT.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
Comments:     To: Quentin and Amanda McMullen <qandamcmullen@POP.MAIL.RCN.NET>
Comments:     cc: "Quentin_McMullen@BROWN.EDU" <Quentin_McMullen@BROWN.EDU>
From:         Ian Whitlock <WHITLOI1@WESTAT.COM>
Subject:      Re: macro resolution inside *-comments
Content-Type: text/plain; charset="iso-8859-1"

Quentin,

You have opened an old can of worms. Let's look at the logical problems.

Fact 1: The SAS code

* something ;

is a SAS comment. In particular, it is SAS code, in contrast to

/* something */

which is simply a comment.

Fact 2: SAS macro is a system of instructions for generating SAS code.

Question: Can a generated system of code make comments on the generating system?

Now we have a conflict of interest - who owns what comments? Well, in the beginning:

/* something */

was a comment through out the system, i.e. in both SAS and SAS macro. No problem anywhere.

%* something ;

was a comment inside macro and illegal in open code. No problem when the single and double quoting scandals are not operative.

* something ;

was flotsam and jetsam in a macro program to be passed on to the SAS compiler where it was treated as a comment, just as the same code would be when outside of macro. No inherent problem, but it does require a good deal of understanding.

Consider

58 %macro w ; 59 /* not all comments are equal */ 60 * simple data step ; 61 data w ; 62 x = 1 ; 63 run ; 64 %mend w ; 65 66 options mprint ; 67 %w MPRINT(W): * simple data step ; MPRINT(W): data w ; MPRINT(W): x = 1 ; MPRINT(W): run ;

Note that the first comment is not passed to the MPRINT. Of course not, it is a comment. The second comment however is passed to MPRINT. That was the way the system was intended. It gives one the ability to distinguish comments on macro instructions, which should be in the macro but not in it's execution, and comments on the SAS instructions which should show with the generated code for the benefit of anyone reading the SAS log and in need of comments about the generated code.

This system also allows one to generate comments just like code. For example,

81 %macro w ; 82 %local i j ; 83 /* not all comments are equal */ 84 * %do i = 1 %to 5 ; 85 simple, %do j = 1 %to &i ; very %end ; simple data step 86 %end ; 87 ; 88 data w ; 89 x = 1 ; 90 run ; 91 %mend w ; 92 93 options mprint ; 94 %w MPRINT(W): * simple, very simple data step simple, very very simple data step simple, very very very simple data step simple, very very very very simple data step simple, very very very very very simple data step ; MPRINT(W): data w ; MPRINT(W): x = 1 ; MPRINT(W): run ;

Neat, I like the idea, although I admit I have never found the need to use it before; it gives me confidence that the system is well designed and consistent.

However, many people like *-comments and were used to using them when they wrote SAS code. So when they started writing macro code they soon complained about the fact that sometimes there habit caused trouble and wanted the system cured rather than there habit. As you might imagine it presents a real difficulty because you cannot consistently support both FACT 1, FACT 2, and have *-comments treated as SAS statements, and comments in both SAS macro and macro.

Here is the conflict.

97 %macro me; 98 %put Macro Running!; 99 %mend me;

100 %macro q ; 101 * %put ========== ; 102 * %me ; 103 * %put ========== ; 104 %mend q ; 105 %q ========== MPRINT(Q): * * %me ; ========== MPRINT(Q): *

Note that the %PUT statements executed and that the semicolons are owned by the %PUT statements. Hence the double semicolon before %ME and now semicolon after the third asterisk. That should be a time bomb waiting to go off when the next line of code is submitted. However it isn't.

106 data w ; 107 x = 1 ; 108 run ;

NOTE: The data set WORK.W has 1 observations and 1 variables. NOTE: DATA statement used: real time 0.04 seconds

Now we have the ugly fact that sometimes SI will sometimes end a statement for you and sometimes it will not. Is it any wonder they don't want to illuminate this dark corner with documentation?

Note that the user outcry has so far created a system where %DO is a macro instruction demanding execution even inside generated comments while %ME is not. In short %ME, is a second class macro instruction. The matter gets worse with

109 * %put is this a comment? ;

110 * Well sometimes ;

(Does the blank line between 109 and 110 indicate that the %PUT partially executed? I don't know.) So a %PUT in a * statement in open code is not a macro instruction, while the %PUT in the same statement is a macro instruction when it is inside a macro. Perhaps this should be a monument to showing that SI is so strong on CRM that they are willing to produce and inconsistent system in order to please their customers, or a monument to the chaos caused when one fails to educate the customer.

Now as for your question? When you issued %BAD did the system forget to insert a semi-colon for you or did you forget to end bad a macro call with a semicolon? (I find it more and more annoying that SI is gradually developing a system where one should add spurious semi-colons simply to please the various cooks. For example, my good and valid code often has the first word in SAS instructions in red in the enhanced editor. Or more importantly, RSUBMIT will not be recognized unless there is a preceeding semicolon in the physical file.)

NOTE: SCL source line. 111 %bad /* call to non-existing macro creates error msg */ ; - 180 WARNING: Apparent invocation of macro BAD not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

112 * %me ; /* macro IS invoked inside comment */ 113 * seems to be a comment here ;

Only you can answer that question.

Fortunately, I never developed an appetite for *-comments. Hence, it has been no hardship for me simply avoid them and the inherent can of worms that they have wrought since version 5, except when I have to work with someone else's code. In some areas SI is pretty good on compatibility, but this is one area where they feel free to (and perhaps are now required to) blow with the wind. So any conclusions you come to from the above execution of SAS 8.2 may or may not be true in older versions and future versions. I do not like to be arbitrarily restricted in the style of code I write, but this is one area into which I will not go.

In general I see the log as a factual report of what was generated, and comments as belonging with the generating code. Hence the restriction has not been a great imposition for me. However, there is little wrong with the more sophisticated rule - never allow macro instructions, and I include macro invocation as macro instructions, between an asterisk and the closing semi-colon. It is not nice to make a rule macro cannot appear in a SAS statement, but these statements are just comments after all, so it should not a big deal.

IanWhitlock@westat.com

PS. If you search the archives, you should find some previous comments I have made on comments. Unfortunately, I do not remember how far back you should go or to which versions they pertain.

-----Original Message----- From: Quentin and Amanda McMullen [mailto:qandamcmullen@POP.MAIL.RCN.NET] Sent: Sunday, November 24, 2002 12:32 AM To: SAS-L@LISTSERV.UGA.EDU Subject: macro resolution inside *-comments

Hi All,

Some time ago (v6.12?), I think I was of the mind that macro references could be resolved inside of *-comments.

More recently I had thought that *-comments would hide both macro variables and macro invocations from the macro processor. Then tonight I stumbled across the following. It seems that if I attempt to call a macro that does not exist, and in the next statement have a *-comment that includes inside a macro variable or macro name, the macro processor will see the macro instruction.

I submitted the code below (v8.2 Win XP):

%macro me; %put Macro Running!; %mend me;

* %me ; /* macro not invoked inside comment */ %bad /* call to non-existing macro creates error msg */ * %me ; /* macro IS invoked inside commment */

%let mvar=I resolved1; * &mvar ; /* macro var not resolved inside comment */ %bad /* call to non-existing macro creates error msg */ * &mvar ; /* macro var is sort of resolved inside comment (i.e. macro reference disappears) */

%bad /* call to non-existing macro creates error msg */ * &mvar2 ; /* attempt to resolve non-existing macro var inside comment, generates err msg */

And was surprised to see that in each line following a call to %bad, SAS looks inside of the *-comment and invokes the macro, or tries to resolve the macro variable. The log is below (pretty hard to read).

1 %macro me; 2 %put Macro Running!; 3 %mend me; 4 5 * %me ; /* macro not invoked inside comment */ 6 %bad /* call to non-existing macro creates error msg */ _ _ _ 180 180 180 WARNING: Apparent invocation of macro BAD not resolved. ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. 7 * Macro Running! 7 ! %me ; 7 ! /* macro IS invoked inside commment */ 8 9 %let mvar=I resolved1; 10 11 * &mvar ; /* macro var not resolved inside comment */ 12 %bad /* call to non-existing macro creates error msg */ _ _ _ 180 180 180 WARNING: Apparent invocation of macro BAD not resolved. ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. 13 * &mvar ; WARNING: Apparent invocation of macro BAD not resolved. WARNING: Apparent symbolic reference MVAR2 not resolved. 13 ! /* macro var is sort of resolved inside comment (i.e. macro reference 13 ! disappears) */ 14 15 %bad /* call to non-existing macro creates error msg */ _ _ _ 180 180 180 ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. ERROR 180-322: Statement is not valid or it is used out of proper order. 16 * &mvar2 ; 16 ! /* attemps to resolve macro var inside comment, generates err msg */ ERROR: Errors printed on page 1. ERROR: Errors printed on page 1. ERROR: Errors printed on page 1. 2 The SAS System 00:17 Sunday, November 24, 2002

NOTE: SAS Institute Inc., SAS Campus Drive, Cary, NC USA 27513-2414 NOTE: The SAS System used: real time 0.37 seconds cpu time 0.37 seconds ;

Kind Regards, --Quentin


Back to: Top of message | Previous page | Main SAS-L page