[This site is not connected with the SAS Institute]
[last updated - 01 September 2003]
SCL and Data sets
In the old days, "SCL" stood for "Screen control language". Now it stands
for "SAS component language". You would use SCL when writing SAS/AF applications.
But SCL was very different from normal SAS code with its procedural steps
and data steps. SCL was more like other computer languages. You could still
have the same SAS data sets with SCL but you had to access them in a way
similar to how you access random-access files in other languages. Let's
call these random-access files "data sets" to keep things in familiar terms
since they are effectively the same. To access a data set you had to open
it first. To get hold of a record you had to issue a get. To replace
a record with changed values in it you had to issue a put. And when
you were finished you had to issue a close. So you had to do something
similar with SCL and if you used to write SAS/AF applications then you
would be familiar with accessing SAS data sets in this way.
%sysfunc and SCL
%sysfunc has been around for nearly as long as SCL. %sysfunc allows macro
code to use functions native to SAS code and also SCL. These functions
include those for reading SAS data sets as used in SCL. So this means that
you can do data set processing using pure macro code. For normal processing
of data then doing it the macro way is not a good idea. Data steps are
a lot faster. But there are times when it becomes useful. If you need a
piece of information from a SAS data set while you are writing macro code
then it might make more sense to access this information using macro code
rather than a data step. It so happens that SAS stores information about
macro variables in the views sashelp.vmacro and dictionary.macros
and sometimes you need to know this information when writing macro code.
It makes more sense to read this information using pure macro code in macros
if you can so that you don't have to break up the flow of your macro code.
For example, suppose you want to test for the existence of a global macro
variable. It would be neater and more convenient if it could be done like
this:
%if %globexist(macrovar) %then %do ....
rather than have to break out of your macro code and insert a data step.
%globlist
With macro variable information being held in the views sashelp.vmacro
and dictionary.macros I considered it a prime candidate for writing a macro
containing pure macro code to access this information. Of particular interest
was a list of global macro variables. I know you can display these using
%put _global_ but the information is not in a very convenient form. So
I wrote a macro called globlist to extract this
information. This is the only macro so far on this web site that actually
reads a data set using pure macro code (although I have other macros that
open data sets to extract data set information such as attrn).
So you can learn how this is done using this macro as a guide and use that
as the basis of writing your own code when you come across a need.
I'll include a link to this macro again further down the page. I'll
point out the important features of this macro here and it would be useful
if you spotted this in the code. It may be better to print off a copy of
the macro so you can refer to it. Although in this case the macro is reading
a SAS view I will refer to it as a data set since the processing is the
same and chances are when you write your own code to do this then you will
be reading a data set.
1) Note the setting up of local macro variables. This is something you
should always do in a macro. Although the scope of a new macro variable
in a macro is only local, you don't know whether there is a macro variable
outside your macro of the same name. It would be very confusing if your
macro updated macro variables outside your macro so it is important to
explicitly define them as local.
2) Note that the data set is open in input sequential
mode and returns a file number to the macro variable dsid. If this number
is zero then the open has failed. You should always check for this condition
and put out a message if this fails. Note that %put %sysfunc(sysmsg());
puts out the message generated by SAS rather than your own message. I put
two messages out. The first is my own error message saying in which macro
the failure has occurred. It is a good idea to do this as it helps the
debugging process. The system message that follows then says specifically
what is wrong.
3) Note that you have to access fields in a data set by their variable
number. Since I want to read the scope and name fields then
I have to find out what variable number they are. This is done using the
varnum
function. And also note that the data set is referred to by its resolved
dsid number and not by data set name.
4) You read a data set sequentially by using the fetch function.
This returns a code as well. If the code is zero then the record was successfully
fetched. If it returns a 1 then you have tried to read past the end of
the data set so you need to end off your processing.
5) Fetching a record does not automatically give you access to the information
in the field you want. You have to use the getvarc function to get
the value for a character variable.
6) You should always remember to close the data set when you
have finished with it.