/* Richard A. DeVenezia * www.devenezia.com * * Originally posted to SAS-L Feb 7, 2004 */ /*----- * group: Macro programming * purpose: Resolve any level of indirect addressing as specified in a template expression */ %macro resolveIndirectAddressing (tokenValue, resolutionTemplate, trace=0); %local level levelTemplate token initialTokenValue intermediatetokenValue lengthResolutionTemplate p0 p1 guard maxGuard done ; %let maxGuard = 10; %if &trace %then %let initialTokenValue=&tokenValue; %let resolutionTemplate = &resolutionTemplate->; %let lengthResolutionTemplate = %length (&resolutionTemplate); %let guard = 1; %let level = 0; %let p0 = 0; %let p1 = 0; %let done = 0; %do %while (not &done) ; %let level = %eval (&level+1); %let p0 = %eval (&p0+&p1+1); %if &p0 > &lengthResolutionTemplate %then %let p1 = 0; %else %let p1 = %index (%substr(&resolutionTemplate,&p0),->); %if &p1 = 0 %then %let done = 1; %else %do; %if &trace %then %let intermediateTokenValue = &tokenValue; %* the crux of resolving the indirect addressing; %let levelTemplate = %substr(&resolutionTemplate,&p0,%eval(&p1-1)); %let templateResolved = %sysfunc (tranwrd (&levelTemplate,:,&tokenValue)); %let tokenValue = &&&templateResolved; %if &trace %then %put intermediateTokenValue=&intermediatetokenValue levelTemplate=&levelTemplate templateResolved=&templateResolved newTokenValue=&tokenValue; %end; %let guard = %eval(&guard + 1); %if &guard > &maxGuard %then %do; %put ERROR: resolveIt exceeded the guard limit of &maxGuard; %let done = 1; %end; %end; %if &trace %then %do; %let level = %eval(&level-1); %put NOTE: initial token value: &initialTokenValue; %put NOTE: resolutionTemplate: &resolutionTemplate; %put NOTE: &level levels resolved.; %put NOTE: final resolution: &tokenValue; %end; &tokenValue %mend; /**html *

Sample code

*/ %let i=1; %let a1=2; %let b2=3; %let c3=4; %let d4=5; %let e5=6; %let f6=7; %put %resolveIndirectAddressing (&i, a:->b:->c:->d:->e:->f:); %let i=1; %let a1z=2; %let b2y=3; %let c3x=4; %let d4w=5; %put %resolveIndirectAddressing (&i, a:z->b:y->c:x->d:w, trace=1); /**html *
intermediateTokenValue=1 levelTemplate=a:z templateResolved=a1z newTokenValue=2
intermediateTokenValue=2 levelTemplate=b:y templateResolved=b2y newTokenValue=3
intermediateTokenValue=3 levelTemplate=c:x templateResolved=c3x newTokenValue=4
intermediateTokenValue=4 levelTemplate=d:w templateResolved=d4w newTokenValue=5
NOTE: initial token value: 1
NOTE: resolutionTemplate: a:z->b:y->c:x->d:w->
NOTE: 4 levels resolved.
NOTE: final resolution: 5
5
*/