Chapter Contents |
Previous |
Next |
Code Generation Conventions |
SAS/C software
allows two types of function pointers, remote and local. Function pointers
of each type may be declared using the nonstandard keywords
_ _remote
and
_ _local
. Function pointers are remote by
default. Normally, you do not need to be concerned with the details of function-pointer
implementation. If all of your programs are in C, the compiler takes care
of setting up the pointer and calling a function through the pointer. This
section provides information for users who have to build or use C function
pointers in assembler language routines, who have to map between function
pointers and data pointers, or who need to know the details of function-pointer
implementation for some other purpose.
Remote Function Pointers |
By
default, all function pointers are remote. You can also explicitly declare
a remote function pointer using the positional type qualifier keyword
_ _remote
. For example:
int _ _remote (*remote_fp)(void);
Remote function pointers are 4 bytes long and are aligned on a fullword boundary. They are indirect, that is, they do not point directly to executable code. Remote function pointers can call a function in another load module which has a different pseudoregister vector. A remote function pointer must define both the address of the called function and the new pseudoregister vector. An indirect implementation makes it possible for remote function pointers to contain both pieces of data. A remote function pointer points to an object containing two 4-byte addresses. The first address is the address of the function, the second is the address of the pseudoregister vector for the load module containing the function. For more information, refer to External Variables.
The following example illustrates this procedure:
Sample Assembler Language Routine for Calling a Function with a Remote Function Pointer
L R15,FUNCPTR Load function pointer into R15. L RX,12(,R12) Save current pseudoregister vector address. This assumes that R12 has the CRAB address. MVC 12(4,R12),4(R15) Copy new pseudoregister vector address into CRABPRV. L R15,0(,R15) Load function address into R15. BALR R14,R15 Call the function. ST RX,12(,R12) Restore old pseudoregister vector address. . . . FUNCPTR DS A
If you are using the
norent
compiler option,
the format of a remote function pointer that has not yet been used to call
a function is slightly different. A function pointer in this state addresses
an object containing three addresses. The first is the address of a library
routine (L$CFNAD), the second addresses the object itself, and the third addresses
the entry point of the function. The procedure for calling a function through
a function pointer in this format is no different from that outlined above.
Steps 2, 3, and 5 (the psuedoregister vector address swap) must be performed.
You can identify a function pointer in this format by testing bit 0 of the
second address. If the bit is set to 1, the function pointer is in this format.
Local Function Pointers |
To declare a local function pointer, specify the keyword
_ _local
preceding the open parenthesis of the function pointer
declaration, as in the following example:
int _ _local (*local_fp)(void);
int _ _remote (*_ _local(*local_fp)(void))(int);
The above declaration could not be specified using the previously documented
syntax without use of a typedef
. Nevertheless,
in practice, a typedef
would be recommended
for clarity.
The
pflocal
compiler option can be used
to specify that all function pointers in a program are local except for those
specifically declared with the
_ _remote
keyword.
For more information on the
pflocal
option, see Compiler Options.
In assembler language terminology, the pointer can be thought of as a V-type address constant. To call a function through a local function pointer in assembler language, load the value of the function pointer into the appropriate general register, usually general register 15, and call the function with the instruction sequence expected by the function. Sample Assembler Routine for Calling a Function with a __local Function Pointer illustrates the standard calling sequence.
Sample Assembler Routine for Calling a Function with a __local Function Pointer
L R15,FUNCPTR Load __local function pointer into R15. BALR R14,R15 Call the function. ST R15,RETVAL Save function return value. . . . FUNCPTR DS A
Function pointers declared using the
_ _asm
,
_ _ref
, or
_ _ibmos
keyword
are local by default. You can, however, use the
_ _local
keyword
in such a declaration without causing an error.
It is possible to convert a remote function
pointer to a local
function pointer by assignment or with a cast. This can be used to obtain
the entry point address of a C function or to pass the entry point address
to an assembler language routine. For instance, the code in Conversion of a Remote Function Pointer to a Local Function Pointer passes the actual entry
point address of
vdefexit
to
ISPLINK
.
Conversion of a Remote Function Pointer to a Local Function Pointer
#include <stddef.h> extern int cuserxt(); extern __asm int ISPLINK(); /* Declare ISPLINK as an */ /* assembler language function. */ void main() { struct { _ _local int (*exit)(); char *data; } udata; char name[41] ; . . . /* Assign the cuserexit function pointer */ /* to the _ _local function */ /* pointer udata.exit. */ udata.exit = cuserxt; udata.data = NULL; /* Define an ISPF variable as using a user exit. */ (void) ISPLINK("VDEFINE ", "NAME ", name, "USER ", @40, " ", @udata); . . . }
Since local function pointers do not contain a pseudoregister
address, conversion from local to remote is not possible. You can frequently
use the
buildm
function to create a remote function pointer
from a local function pointer. For more information on the
buildm
function, see Chapter 1, "Dynamic-Loading Functions," in
SAS/C Library Reference, Volume 2 .
Note:
Never attempt to use a function pointer to modify the
code of a function. In addition to the reentrancy implications, note that
a
_ _remote
function pointer does not address the function's code
directly, and using it to store new data will produce unpredictable results.
For more information about using assembler language
routines in C programs, see Communication with Assembler Programs.
For more information about the
_ _remote
and
_ _local
keywords, refer to Source Code Conventions.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.