Date: Wed, 13 May 2009 13:27:30 -0700
Reply-To: "Huang, Ya" <Ya.Huang@AMYLIN.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: "Huang, Ya" <Ya.Huang@AMYLIN.COM>
Subject: Re: Macro quoting again !
Content-Type: text/plain; charset="us-ascii"
Thank you Chang and Mark, both suggestions work. Though I'm getting
dizzy by these many of %%%%%%%% :-)
From: Terjeson, Mark [mailto:Mterjeson@russell.com]
Sent: Wednesday, May 13, 2009 1:11 PM
To: Huang, Ya; SAS-L@LISTSERV.UGA.EDU
Subject: RE: Macro quoting again !
The resolving of macros, as I've mentioned before, when you think of SAS
macros in terms of text substitution coupled with staying aware of how
many times it will make passes until all macro goodies found have been
resolved, will help you find the problem here.
Example: We know that on the first pass
through the macro processor it looks for &, %, and other macro goodies.
If we have
the first pass will find one ampersand and then look in the macro
variable lookup table for MYVAR and if found, return the contents.
If we want the contents of MYVAR to actually BE the macro variable name
for some other storage item we would fetch the other storage item
for this the macro processor gobbles up double && and %% and leave you
with just one.
That way the first pass through, doing some mental text substitution the
&&&myvar would find the first two && ampersands and return one ampersand
as well as seeing next the &myvar and fetching the contents ofthe myvar
storage. Let's say that the MYVAR storage contained ABC. Then
after the first pass through would resolve to
and then on the second pass &abc would get resolved and the contents of
It gets a little tricky because having one macro call another macro DOES
NOT process and resolve the inner macro call first and then process the
outer macro. You may know other porogramming languages that have macro
routines which like objects one could call the other. Here in SAS land,
the SAS macro goodies are not entities or objects or independent
routines being called. The SAS macro processing merely scans the code
text submitted and looks for string patterns to do text substitution on.
(of course in a much more glorified sense) Therefore, in your example
below you must think of the macro processor scanning all the text from
the top down (and it could care less of boundaries or statements, etc.
It is just ignoring most of the code and only responding to the macro
goodies and flagging. So when you original had %(%%%( the first pass
gobbled up %( as an escape character on the parenthesis and resulted in
just (, then the next two %% get consolidated to %, and the last %)
turns into ). Then we are left
with (%) but now because we have one
more additional layer of nesting the macro processor will pass through
again and the sequence of parsing and keeping track of opens and closes
of the parens gets out of sync because there are now two passes of
flagging characters getting gobbled up.
To fix this, your original code for one
non-nested macro with one pass through
the parser, had %% in the middle. Knowing now that there is gonna be two
passes through we find that if we just add another pair of %% to make
four the first pass will take
and then the second pass will take that
pair down to
which is what you wanted to be left with after all said and done.
Thus, the following adjusted code works.
Hope this is helpful.
Investment Business Intelligence
Investment Management & Research
Global Leaders in Multi-Manager Investing
From: SAS(r) Discussion [mailto:SAS-L@LISTSERV.UGA.EDU] On Behalf Of Ya
Sent: Wednesday, May 13, 2009 10:52 AM
Subject: Macro quoting again !
Macro a with a get the result as expected. But macro b is not, why is
1 %macro a(tit=);
2 %put &tit;
5 %a(tit=%str(Change %(%%%)));
7 %macro b(mlst=);
12 %a(tit=%str(Change %(%%%)))