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 (February 2007, week 1)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Fri, 2 Feb 2007 18:17:29 -0500
Reply-To:     Chang Chung <chang_y_chung@HOTMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Chang Chung <chang_y_chung@HOTMAIL.COM>
Subject:      Re: Macro Quoting Tid Bit
Comments: To: Toby Dunn <tobydunn@HOTMAIL.COM>

On Fri, 2 Feb 2007 22:26:32 +0000, toby dunn <tobydunn@HOTMAIL.COM> wrote:

>From a little Birdie: > >.. When %SYSFUNC is used, a Macro variable passed to a function is expanded >and resolved before a value is passed. This means that delta characters >from Macro quoting have been removed and the function will never see them. > >.. With %SYSCALL, Macro variables are passed directly to the CALL routine >without any expansion or resolution. This is done because a CALL routine >could modify the variable's value, so the true value of the variable must be >passed. This also means any delta characters from Macro quoting are passed >to the function.

Hi, Thanks Toby, and thanks Little Birdie! So, this means that it is a feature, not a bug.... Well, this came out before, but recently, it came out of the discussion between Toby and me. Here is an interesting consequencies of the above bug.. uh, feature. Below, we are trying to match a percent sign using prxsubstr through %sysfunc. This function is supposed to return the position and the length of the match. The position returned in this case is 0(zero) since the percent sign has been quoted away.

%let t=%nrstr(abcd %b); %let pos=0; %let len=0; %let prx =%sysfunc(prxparse("%")); %syscall prxsubstr(prx,t,pos,len); %put p=&p.; /* it returns p=0, why? it is quoted away. */

In fact, there is a tech note on this http://support.sas.com/techsup/unotes/SN/013/013067.html, where si suggests single quoting the target string like: /* single quote */ %let t = %nrstr('abcd %b'); %let pos=0; %let len=0; %let prx =%sysfunc(prxparse("%")); %syscall prxsubstr(prx,t,pos,len); %put pos=&pos.; /* this time it returns 8 */ The note says that since then pos returns consistently 1 off. We can then subtract 1 from the pos and that is the correct pos.

Well, not quite. This applies only when we know how the string t was quoted. Frequently all we know is that the input string has been quoted, not knowing how or how many times. In many cases in writing a general-use macro, we habitually %superq() input string, whenever there is a chance of something dangerous inside the input string. In this case, it is easy to get pos=0 again, if the macro var t has been quoted again in process. %let t = %nrstr('abcd %b'); %let pos=0; %let len=0; %let prx =%sysfunc(prxparse("%")); %let t = %superq(t); /* quoted again */ %syscall prxsubstr(prx,t,pos,len); %put pos=&pos.; /* this time it returns 0 again */

Frankly, I feel that preserving delta characters in %syscall seems to make it almost unusable in macro context. And I am not sure if I fully understand the reason why the delta characters has to be preserved. Especially in this example, the variable t is not even involved in returning the new values back at all!

Cheers, Chang


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