Previous Page | Next Page

Accessing External Shared Images from SAS

Examples of Accessing External Shared Images from SAS


Example 1: Updating a Character String Argument

This example uses the tmpnam routine that is part of HP's C Run-Time Library under the OpenVMS environment. The tmpnam routine generates a unique filename that can safely be used as a temporary filename.

The C source code for VMSLIB.C is the following:

#include <stdio.h>   /* Declares prototype:  char * tmpnam(char *s); */
#include <string.h>

vmstmpnam(char *s)
   {
   tmpnam(s);
   printf("tmpnam(%d) = %s\n",sizeof(s),s);

   return(0);
   }

The following code shows how the C source code could be compiled and linked using a DCL Command file, such as VMSLIB.COM.

$ cc/decc/obj=vmslib.o/arch=generic/name=(short,as_is)/pointer=64=argv vmslib.c
$ open/write optfile vmslib.opt
$ write optfile "CASE_SENSITIVE=YES"
$ write optfile "SYMBOL_VECTOR=(vmstmpnam=PROCEDURE)"
$ write optfile "vmslib.o"
$ close optfile
$ link/exe=vmslib.exe/share/bpage=13/map/cross/full vmslib.opt/opt

The following SAS source code can be used to create the SASCBTBL attribute table and call the routine from within the DATA step.

filename sascbtbl 'sas$worklib:temp.dat';
data _null_ file sascbtbl;
   input;
   put _infile_;
   datalines4;
routine vmstmpnam minarg=1 maxarg=1 module=vmslib;
arg 1 char update byaddr format=$cstr255.;
;;;;
data _null_;
   length tempname $255;
   retain tempname " ";
   tret = modulec('vmstmpnam',tempname);
   put tempname = ;
run;

The SAS log output would be the following:

Log Output for Updating a Character String Argument

tempname=aaa_ebba32

The POSIX standard for the maximum number of characters in a pathname is defined in <limits.h> to be 255 characters. Consequently, this example uses 254 characters as the length of the generated filename, tempname, with one character reserved for the null-terminator. The $CSTR255. informat ensures that the null-terminator and all subsequent characters are replaced by trailing blanks when control returns to the DATA step.


Example 2: Passing Arguments by Value

This example calls the access routine that is part of HP's C Run-Time Library under OpenVMS. The access routine checks for the existence and accessibility of a file based on the bit pattern contained in the mode argument. A return value of 0 indicates a successful completion and the requested access is permitted. A return value of -1 indicates a failure, and the requested access is not permitted.

Because the mode argument is passed by value, this example includes the BYVALUE option for arg 2 in the attribute table. If both arguments were pass by value, you could use the CALLSEQ=BYVALUE attribute in the ROUTINE statement, and it would not be necessary to specify the BYVALUE option in arg 2.

The C source code for the VMSLIB.C is:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

   /* The header file <unistd.h> declares the access prototype and defines the 
bit patterns for mode as:

   int access(const char *file_spec,int mode);

   #define F_OK   0   ... File existence
   #define X_OK   1   ... Execute access
   #define W_OK   2   ... Write access
   #define R_OK   4   ... Read access

   A logical OR of these values will test for more than one bit pattern. */

int vmsaccess(const char *file_spec,int mode)
   {
   int rc;

   if ((rc=access(file_spec,mode)) == -1)
      perror("vmsaccess");

   return(rc);
   }

The following example shows how the C source code is compiled and linked using a DCL Command file, such as VMSLIB.COM:

$ cc/decc/obj=vmslib.o/arch=generic/name=(short,as_is)/pointer=64=argv vmslib.c
$ open/write optfile vmslib.opt
$ write optfile "CASE_SENSITIVE=YES"
$ write optfile "SYMBOL_VECTOR=(vmsaccess=PROCEDURE)"
$ write optfile "vmslib.o"
$ close optfile
$ link/exe=vmslib.exe/share/bpage=13/map/cross/full vmslib.opt/opt

The following SAS source code can be used to create the SASCBTBL attribute table and call the routine from within the DATA step.

filename sascbtbl 'sas$worklib:temp.dat';
data _null_;
   file sascbtbl;
   input;
   put _infile_;
   datalines4;
routine vmsaccess minarg=2 maxarg=2 returns=short module=vmslib;
arg 1 char input byaddr  format=$cstr200.;
arg 2 num  input byvalue format=ib4.;
;;;;
data _null_;
   length path $200.;
   /* A test file's permissions have been modified to the following:
   set protection vmstest.com/prot=(system:r,owner:r,group:r,world:r) */
   path='sys$login:vmstest.com';
   /* User is testing for Write and Execute permissions (W_OK | E_OK) */
   rc = modulen( "*ie", 'vmsaccess', path, 3 );
   put rc = ;
run;

The SAS log output would be the following:

Log Output for Failure

rc=-1
This return code means that one of the following conditions was true: This return code means that requested access is not permitted.

The SAS source code is changed to check for Read permission,

rc = modulen( "*ie", 'vmsaccess', path, 4);

then the SAS log output is the following:

Log Output for Successful Completion

rc=0

Example 3: Invoking a Shared Image Routine from PROC IML

This example shows how to pass a matrix as an argument within PROC IML. The example creates a 4x5 matrix. Each cell is set to 10x+y+3, where x is the row number and y is the column number. For example, the cell at row 1 column 2 is set to (10*1)+2+3, or 15.

The example invokes several routines from the theoretical TRYMOD shared image. It uses the changd routine to add 100x+10y to each element, where x is the C row number (0 through 3) and y is the C column number (0 through 4). The first argument to changd specifies the extra amount to sum. The changdx routine works just like changd , except that it expects a transposed matrix. The changi routine works like changd except that it expects a matrix of integers. The changix routine works like changdx except that integers are expected.

Note:   A maximum of three arguments can be sent when invoking a shared image routine from PROC IML.  [cautionend]

In this example, all four matrices x1, x2, y1, and y2 should become set to the same values after their respective MODULEIN calls. Here are the attribute table entries:

routine changd module=trymod returns=long;
arg 1 input num format=rb8. byvalue;
arg 2 update num format=rb8.;
routine changdx module=trymod returns=long transpose=yes;
arg 1 input num format=rb8. byvalue;
arg 2 update num format=rb8.;
routine changi module=trymod returns=long;
arg 1 input num format=ib4. byvalue;
arg 2 update num format=ib4.;
routine changix module=trymod returns=long transpose=yes;
arg 1 input num format=ib4. byvalue;
arg 2 update num format=ib4.;

Here is the PROC IML step:

proc iml;
   x1 = J(4,5,0);
      do i=1 to 4;
         do j=1 to 5;
            x1[i,j] = i*10+j+3;
         end;
      end;
   y1= x1; x2 = x1; y2 = y1;
   rc = modulein('changd',6,x1);
   rc = modulein('changdx',6,x2);
   rc = modulein('changi',6,y1);
   rc = modulein('changix',6,y2);
   print x1 x2 y1 y2;
run;

The following are the results of the PRINT statement:

Invoking a Shared Image Routine from PROC IML

X1
 20        31        42        53        64
130       141       152       163       174
240       251       262       273       284
350       361       372       383       394
 X2
 20        31        42        53        64
130       141       152       163       174
240       251       262       273       284
350       361       372       383       394
 Y1
 20        31        42        53        64
130       141       152       163       174
240       251       262       273       284
350       361       372       383       394
 Y2
 20        31        42        53        64
130       141       152       163       174
240       251       262       273       284
350       361       372       383       394

Previous Page | Next Page | Top of Page