Friday, March 23, 2012

More on the streamDelim Macro Variable

Based on my last post (Processing External Files with PROC STREAM) you may now be curious about the rationale for the streamDelim macro variable as well as what else you can do with it.

But first, an announcement: The sasCommunity page SAS® Server Pages: Generating Dynamic Content has been updated to include:
  • The hopefully final title of the eBook
  • The list of chapters and topics covered
  • A link to the preview copy of Chapter 1 at the SAS press site (which provides more details on the book's content)
  • A list of my blog entries about SAS Server Pages (which will be regularly updated).
Please check it out.

Now back to streamDelim - why is it needed and what else can it be used for?

In working with Rick Langston of SAS R&D on this, one of the features we really wanted to support was the ability to use %include to include an external file into a SAS Server Page. In order to allow %include to be recognized and handled correctly it needs to be on a statement boundary - i.e., immediately after a semi-colon. So a way was needed to force a statement boundary without having the semi-colon appear in the output. The led to the resetDelim option (in the TS1M0 and TS1M1 releases of SAS 9.3):

proc stream . . . . resetDelim="a_SAS_name_token";

where you specify some text as a delimiter that does not occur in your input SAS Server Pages. This means that the following text could be used to allow %include to be recognized:

a_SAS_name_token; %include fileref-or-path-to-file;

but doing it that way allowed for the possibility of inconsistent values between the input SAS Server Page and the PROC STREAM statement (i.e., a SAS Server Page could be created or edited and not have the same value, or vice-versa). To address this, the TS1M2 release uses the value of a macro variable, streamDelim, as the delimiter. And if this macro variable does not exist, PROC STREAM creates it.

The resetDelim option still exists and that is why the following technique (mentioned in my last blog posting) works:

%let streamDelim = __&sysfunc(datetime(),z18.);
proc stream . . . . resetDelim = "&streamDelim";

So what else can you do with streamDelim?

You can use the following text in your SAS Server Page to force a new line or line break:

&streamDelim newline;

The tokenization process that PROC STREAM uses to resolve macro references ignores/loses line breaks (as many macro programmers know). There are any number of reasons you might want to force going to a new line, e.g.,:
  • readability of the generated text
  • to prevent line breaks forced by the output LRECL in places that might introduce errors (e.g., in a long select tag)
  • to deal with // style JavaScript comments (which says that all the rest of the text on the current line is a comment)
Another reason is that you might want to include a file - but you don't want it submit it to the resolution process. The readfile parameter will do this , e.g.:

&streamDelim readfile fileref-or-path-to-file;

And again, there are multiple reasons for not wanted resolution to occur:
  • no macro resolution is needed or desired
  • proper handling of JavaScript - && is the JavaScript AND operator. Macro resolution will convert && to & causing the JavaScript to not function correctly
Future blog posts will talk about when and how to use these features.