LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous (more recent) messageNext (less recent) messagePrevious (more recent) in topicNext (less recent) in topicPrevious (more recent) by same authorNext (less recent) by same authorPrevious page (March 2004, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Fri, 12 Mar 2004 18:46:18 -0500
Reply-To:     Quentin McMullen <quentin_mcmullen@BROWN.EDU>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Quentin McMullen <quentin_mcmullen@BROWN.EDU>
Subject:      Re: tip macro Put_
Comments: To: Ron Fehd <rjf2@CDC.GOV>

On Fri, 12 Mar 2004 10:19:40 -0500, Fehd, Ronald J. (PHPPO) <rjf2@CDC.GOV> wrote:

>I developed this module to write the parameter list >of a parameterized %include program, >either of routine/sub-routine/module > >testers wanted, >commentary, critique (always) welcome

<snip>

Hi Ron,

Thanks for sharing this. In the macro context, there are two things I might like from a macro %showscope():

1) A list of all variables local to the calling macro. (This is equivalent to a list of macro parameters, if the call to %showscope is early enough). 2) A list of all variables that are *available* to the calling macro (i.e. those that are local or exist in an outer scope).

I've got a macro that comes close to what I want (with lots of ugly SQL code that could no doubt be improved upon):

4817 options nomprint; 4818 4819 %*Ex 1 seems to work okay; 4820 %let a=1; 4821 %let z=0; 4822 %macro outer(x=,y=,z=); 4823 %showscope(macro=outer) 4824 %inner(x=9,y=9) 4825 %mend outer; 4826 4827 %macro inner(x=,y=); 4828 %showscope(macro=inner) 4829 %mend inner; 4830 4831 %outer(x=1,y=2,z=3) NOTE: Parameters local to outer are: &X[SCOPE:OUTER]=1 &Y[SCOPE:OUTER]=2 &Z [SCOPE:OUTER]=3 NOTE: Macro variabls available to outer are: &X[SCOPE:OUTER]=1 &Y [SCOPE:OUTER]=2 &Z[SCOPE:OUTER]=3 &A[SCOPE:GLOBAL]=1 NOTE: Parameters local to inner are: &X[SCOPE:INNER]=9 &Y[SCOPE:INNER]=9 NOTE: Macro variabls available to inner are: &X[SCOPE:INNER]=9 &Y [SCOPE:INNER]=9 &Z[SCOPE:OUTER]=3 &A[SCOPE:GLOBAL]=1

The logic for the list of "available" variables is tricky. As the Maven knows well, when %showscope() runs inside inner, it will need to look first to the symbol table of %INNER, then to the symbol table of %OUTER, then to the global symbol table. It works fine in the above case with only one level of macro nesting. However, if there are 2 levels of nesting (i.e. %inner called by %outer called by %bigouter), I had problems. %showscope knows it should check the symbol table for %inner first, and the global table last, but it doesn't know the order for searching tables from %outer and %bigouter. I gave up on this (for now :)

Below is my %showscope, certainly not ready for production. But not too much wasted effort for a Friday late afternoon/evening....

%macro showscope (macro= /*name of macro whos scope is checked*/ ); /********************************************************************** Macro: showscope

Abstract: Build a list of all defined macro variables in current scope (or outer scope). That is, all macro variables that will resolve, excluding automatic macro vars.

Usage:

Example: %macro inner(x=,y=); %showscope(macro=inner) %mend inner; %inner(x=1,y=1)

Description:

Parameters: macro= name of macro whos scope is checked

Author: Quentin McMullen

Date: 03/12/2004

Category:

Keyword:

OS:

Notes: This ignores issue of offset for long macro variables.

**********************************************************************/

%local mvars1 /*list of local macro vars*/ mvars2 /*list of all available macro vars (local or outer scope)*/ ;

%*List of vars that are local to calling macro; proc sql noprint; select '%nrstr(&)'||trim(name)||'[SCOPE:'||trim(scope)||']='|| trim(value) into :mvars1 separated by " " from dictionary.macros where scope="%upcase(&macro)" ; quit;

%*List of vars that are local to calling macro ; %*or are available to calling macro cuz they exist in outer local ; %*scope or global scope. If a var exists in both local scope and ; %*an outer scope, we take value from the first local scope in which ; %*it is found. So macro value comes from either: a) local symbol table ; %*b) local table of calling macro, or c) global table. ; %*Note when there are multiple nestings of calling macros, I cant tell ; %*which local value to use. ; proc sql noprint; select '%nrstr(&)'||trim(name)||'[SCOPE:'||trim(scope)||']='|| trim(value) into :mvars2 separated by " " from ( /*local vars*/ select name,value,scope from dictionary.macros where scope="%upcase(&macro)" union corr all /*vars local to outer scope, vars local to more than one outer scope are ignored */ select name,value,scope from dictionary.macros where scope NOT IN ("GLOBAL" "AUTOMATIC" "SHOWSCOPE") and name NOT IN (select name from dictionary.macros where scope="%upcase(&macro)" ) group by name having count(*)=1 /*this is bad, ignores mvars defined in multiple outer scopes*/ union corr all /*global vars*/ select name,value,scope from dictionary.macros group by name having count(*)=1 and scope="GLOBAL" ) ; quit;

%put NOTE: Parameters local to &macro are: &mvars1; %put NOTE: Macro variabls available to &macro are: &mvars2; %mend showscope;

options nomprint;

%*Ex 1 seems to work okay; %let a=1; %let z=0; %macro outer(x=,y=,z=); %showscope(macro=outer) %inner(x=9,y=9) %mend outer;

%macro inner(x=,y=); %showscope(macro=inner) %mend inner;

%outer(x=1,y=2,z=3)

%*Ex 2 breaks when there are multiple outer scopes ; %*macro var Z is available to inner, but I cant see how ; %*to have %showscope() know to pull value from scope of %outer ; %*rather than scope of %bigouter. ; %macro bigouter(z=); %outer(x=0,y=0,z=0) %mend bigouter; %bigouter(z=1)

Kind Regards, --Quentin


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