/*--------------------------------------------------------------------+
| |
| Copyright (c) 1995, SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| |
| S A S / C S A M P L E |
| |
| Name: LOADMAC |
| |
| Language: C |
| |
| EntryPoint: MAIN |
| |
| Entry Type: Standard C Entry Linkage (via main) |
| |
| Files Note: 'prefix' is the installation defined high level |
| qualifier for the SAS/C product. |
| |
| Function: Dynamically load and call an assembler routine to |
| sum a list of variables and return the sum to the |
| caller. |
| |
| Purpose: Demonstrate SAS/C assembler communications by |
| - dynamic loading of assembler programs via loadm |
| - using the __ref to build a call-by-reference |
| parameter list |
| - converting remote function pointers to local |
| function pointers |
| |
| MVS - |
| Source: prefix.SAMPLE.ASM(LOADMAC) |
| |
| Compile/Link/Go: prefix.SAMPLE.AUX(LOADMAJ) |
| |
| CMS - |
| |
| Source: SAMPLASM MACLIB (LOADMAC) |
| |
| Assemble: global maclib lcuser |
| hlasm loadmaa |
| |
| Load: lked loadmaa (libe dynamc name loadmaa |
| |
| Compile: global maclib lc370 |
| lc370 loadmac |
| |
| Load: global txtlib lc370std lc370bas |
| load loadmac(nomap rmode 24 amode 24 |
| |
| Genmod: genmod loadmac |
| |
| Execute: loadmac |
| |
| Notes: |
| - LOADMAC sets runtime options in the source. |
| |
+--------------------------------------------------------------------*/
#include <stdio.h>
#include <dynam.h>
#include <options.h>
#define MODNAME "LOADMAA"
/* The following demonstrates how to specify runtime options in */
/* in source code. They are not required for the proper executiuon */
/* of the LOADMA sample. */
extern int _options = _VERSION + _BTRACE + _USAGE + _WARNING;
int main()
{
/*--------------------------------------------------------*/
/* Function pointer for the address returned by loadm. */
/* Note: by default this is a remote function pointer. */
/*--------------------------------------------------------*/
int (*fp) (); /* C Function Pointer */
/*--------------------------------------------------------*/
/* Function pointer for the assembler program that will */
/* be dynamically loaded. This is a 'local' pointer to */
/* a program to be called with standard VL-type plist */
/* that is call-by-REFerence. */
/* */
/* Use of the __ref keyword tells the compiler to build */
/* a plist with pointers to the formal arguments. */
/* */
/*--------------------------------------------------------*/
__local __ref int (*asmfp)();
/*--------------------------------------------------------*/
/* Variables */
/*--------------------------------------------------------*/
int retcode = 0;
int h = 1;
int i = 2;
int j = 3;
int k = 4;
int sum = 0;
int check_sum;
/*--------------------------------------------------------*/
/* Load the assembler program dynamically via loadm, */
/* loadm returns a remote C function pointer. If */
/* the load fails for any reason, a NULL pointer is */
/* returned. */
/* */
/* Note: Under MVS the modules to be loaded must reside */
/* in STEPLIB, task library, or the system link */
/* list. Under CMS, modules to be loaded may */
/* reside in DYNAMC LOADLIB or in other locations */
/* defined by use of the addsrch routine of SAS/C. */
/*--------------------------------------------------------*/
loadm(MODNAME, &fp);
if (fp == NULL) /* Was loadm successful ? */
{
printf("\n\n loadm failed for module %s!!", MODNAME);
exit(16);
};
/*--------------------------------------------------------*/
/* The function pointer returned by loadm is a remote */
/* function pointer which can only be used with calls */
/* to other C modules. LOADMAA is an assembler module, */
/* this requires the remote function pointer be converted */
/* to a local function pointer for the call to LOADMAA. */
/* An assignment with casting converts the remote */
/* function pointer to a local function pointer. */
/*--------------------------------------------------------*/
asmfp = (__ref int (*)()) fp; /* Convert remote(to local */
/*--------------------------------------------------------*/
/* Call the assembler routine via the local funciton */
/* pointer with 2 arugments. */
/*--------------------------------------------------------*/
sum = (asmfp)(h,i); /* Summary number 1 */
printf("\n\nVariable Length with 2 arguments, "
"the sum of %d and %d is %d\n", h, i, sum);
check_sum = h+i;
/*--------------------------------------------------------*/
/* See how things went and set return code accordingly. */
/*--------------------------------------------------------*/
if (sum == check_sum) /* Verify Sum is corrrect.*/
{
printf("\nSum of %d was correct.\n", sum);
retcode = 0;
}
else
{
printf("\nSum of %d was NOT CORRECT!.\n", sum);
printf("It should have been %d!\n",check_sum);
retcode = 12;
};
/*--------------------------------------------------------*/
/* Call the assembler routine via the local funciton */
/* pointer with 4 arugments. */
/*--------------------------------------------------------*/
sum = (asmfp)(h,i,j,k); /* Summary number 2 */
printf("\n\nVariable Length with 4 arguments, "
"the sum of %i, %i, %i and %i is %i\n",
h, i, j, k, sum);
check_sum = h+i+j+k;
/*--------------------------------------------------------*/
/* See how things went and set return code accordingly */
/* if there is an error. */
/*--------------------------------------------------------*/
if (sum == check_sum) /* Verify Sum is corrrect.*/
{printf("\nSum of %d was correct.\n", sum);}
else
{
printf("\nSum of %d was NOT CORRECT!.\n", sum);
printf("It should have been %d!\n",check_sum);
retcode = 12;
};
/*--------------------------------------------------------*/
/* Unload the assembler function using the remote */
/* C function pointer. */
/*--------------------------------------------------------*/
unloadm(fp);
exit(retcode);
}
|