Download resolveIt.sas resolveIt.sasSubmit a comment

/* Richard A. DeVenezia
 * www.devenezia.com
 *
 * Originally posted to SAS-L Feb 7, 2004
 */

%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;

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);
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