Chapter Contents |
Previous |
Next |
Systems Programming with the SAS/C Compiler |
The SPE library contains functions in the following four categories:
bldexit
)
malloc
and
free
)
waitrd
and
FREEMAIN
)
Most of the functions that comprise the SPE library belong to category 4 and are also considered part of the full SAS/C library. SPE Library Functions lists the functions in the other three categories. The Implementation (Source) column shows whether the function is implemented as a function or as a macro and the name of the corresponding source file, if any. The functions are divided into groups according to the area of the SPE library to which they belong. The functions in category 3 would not normally be used under CICS.
Following
SPE Library Functions are descriptions of the functions in categories 1, 2, and 3. The
format
function and
vformat
functions (category 4) are also documented in
this section. Although
these functions can be used in the full C library,
sprintf
or
vsprintf
is usually more
useful in that framework.
aleserv |
Access list
management services
#include <osdspc.h> int aleserv(char *request, ...);
_Lreason
keyword is used to pass back a reason code in the
event that the service fails. The next argument should be a pointer to an int
that will contain the reason code as set in R0 by the
ALESERV macro if the ALESERV macro returns nonzero in R15.
_Lstoken
keyword is equivalent to the Assembler STOKEN keyword.
The next argument should be the address of an 8-character array. This array
is filled in by the EXTRACT and EXTRACTH service and is required as input
to the ADD and SEARCH services.
_Laccess
keyword is equivalent to the Assembler ACCESS keyword.
The next argument should be one of the following strings:
_Lal
keyword is
equivalent to the Assembler AL
keyword. The next argument should be one of the following
strings:
_Lalet
keyword is equivalent to the Assembler ALET
keyword. The next argument should be a pointer to a 4
byte field containing an ALET that you provide, or that the system returns.
For ADD and ADDPASN, the system returns the ALET
of the added
entry.
For the EXTRACT request, you provide the ALET
whose STOKEN you require.
For the SEARCH request, you specify where in the access list the system is to begin the search.
_Lchkpt
keyword is equivalent to the Assembler
CHKPT
keyword. The next argument should be one of the following
strings:
_Lend
keyword
indicates the end of the list of keywords.
The following parms can be used by authorized programs only:
_Lchkeax
keyword is equivalent to the Assembler DREF keyword.
The next argument should be one of the following strings:
The aleserv
function
is implemented by the source module L$UDSPC.
For an example of the aleserv
function, see the examples under dspserv
.
atexit |
Register
Program Cleanup Function in SPE
#include <stdlib.h> int atexit(_remote void (*func)());
Refer to Chapter 6, "Function Descriptions," in
SAS/C Library Reference, Volume 1
for a description of
atexit
.
atexit
returns 0 if successful or
a non-zero value if unsuccessful.
atexit
is portable.
The SPE implementation of
atexit
is in L$UATEX. This
version enforces the ANSI Standard limit of 32 registered functions.
bldexit |
Build System Exit Linkage in SPE
#include <bldexit.h> void *bldexit(__remote void (*func)(), unsigned flags);
bldexit
builds linkage code enabling
a C function to be invoked as a synchronous or asynchronous exit routine.
bldexit
is supported only when the SPE framework is used; it is not
supported with the standard C framework.
The
func
argument is the address of the
C function that is called by the operating system as an exit routine. The
flags
argument is the sum of zero or more flags indicating attributes
of the required exit routine linkage. Note that the exit is expected to be
entered with register 14 containing a return address and register 15 serving
as a base register.
The following exit attributes can be set:
exit
function (or any function it calls) is compiled with
the armode
option or uses the access registers
in some other way.
The linkage code generated by
bldexit
is stored in an exit element
allocated with GETMAIN or DMSFREE. When
the exit is no longer required, you should call the
freeexit
routine to release this storage.
bldexit
returns the address of the
exit linkage code. This address should be passed as an argument to the system
call that defines the operating system exit.
The
longjmp
and
exit
functions cannot be called from a routine entered via
bldexit
linkage code. An attempt to do so results in a user ABEND 1224.
Routines entered via
bldexit
must be executed
as interrupts and cannot execute in parallel with the interrupted code. For
example,
bldexit
cannot be used for code that runs under an
SRB because if the code takes a page fault, the interrupted C code can resume
execution, causing stack overlays and other disasters.
bldexit
is not portable.
See Interrupt Handling in SPE for argument specifications for
bldexit
exit
routines.
Source for
bldexit
is supplied in
L$UEXLK. You can modify this source to define attribute bits to support exits
with unusual linkages not already supported.
This example shows use of
bldexit
with the SPIE SVC
to define a C function to be called if a protection or addressing exception
occurs. The C function writes a backtrace using the
btrace
function and executes a retry in order to terminate the program's execution
with a failure return code.
#include <osmain.h> #include <setjmp.h> #include <bldexit.h> #include <svc.h> struct PICA { /* Map the Program Interrupt Control Area. */ char *exit; unsigned short bits; }; #define SPIE(pica, addr, mask) \ (pica.bits = mask, pica.exit = addr, \ *(char *) &pica = 0x0f,_ldregs(R1, &pica), \ _ossvc(14), _stregs(R1)) int oldpica; /* previous program's PICA */ jmp_buf retrybuf; static void pgmchk(); extern void msgwtr(); /* unshown message writer routine */ osmain() { struct PICA my_PICA; void *exitloc; int rc = 0; /* success or failure code */ if (setjmp(retrybuf)) goto pgm_check; exitloc = bldexit(&pgmchk, _ASYNCH+_NOR13); oldpica = SPIE(my_PICA, exitloc, 0x0c00); /* Intercept 0C4 and 0C5, */ /* then do some real work. */ goto quit; pgm_check: rc = 16; /* Set program failure code. */ quit: _ldregs(R1, oldpica); _ossvc(14); /* restore old SPIE */ freeexit(exitloc); return rc; } static void pgmchk(sa, poi) void **sa; char **poi; { struct { /* the Program Interrupt Element */ struct PICA *pica; short misc1; short int_code; /* interrupt code */ char *addr; /* location of interrupt/retry */ char *regs[5]; /* saved registers */ } *PIE; char msgbuf[40]; PIE = sa[3]; /* R1 addresses PIE on entry */ *poi = PIE->addr; /* store program check location */ /* for btrace */ format(msgbuf, "Program check %d!", PIE->int_code); msgwtr(msgbuf); btrace(msgwtr); PIE->addr = bldretry(retrybuf, 1); return; }
bldretry |
Build System Retry Linkage via longjmp in SPE
#include <bldexit.h> void * bldretry(jmp_buf env, int code);
bldretry
is called to build linkage
code enabling a program location defined with
setjmp
to be used as a
retry routine. The
env
argument is a
jmp_buf
, which has been initialized by an earlier call to
setjmp
.
(The
jmp_buf
type is defined in the header file
<setjmp.h>
. See "Program Control Functions" in Chapter 2 of the
SAS/C Library Reference, Volume 1
for further information.) The
code
argument is an integer
value to be returned by the resumed call to
setjmp
. If the value of
code
is 0, 1 is returned.
bldretry
returns the address of retry
linkage code constructed by
bldretry
. This address should be supplied
to the operating system as the address at which retry is to take place.
On completion of a successful retry, the effect is the
same as the effect of a
longjmp(env,code)
.
The values in registers on entry to the retry routine
are ignored. If you need to pass information from an exit routine to a retry
routine, you should use other mechanisms, such as
extern
storage, for this
purpose.
The retry linkage code is freed immediately before the
longjmp
to the location defined by
env
is performed. You must
call
bldretry
again to perform another retry.
btrace |
void btrace(__remote void(*func)());
Refer to Chapter 6, "Function Descriptions" in
SAS/C Library Reference, Volume 1
for more details. Note that SPE does not support a 0
func
address.
When
btrace
is called directly or indirectly
from a
bldexit
exit function, the traceback will be incomplete
unless the exit has stored the point of interrupt. See the description of
bldexit
for more information.
btrace
is not portable.
The SPE implementation of
btrace
is in L$UBTRC.
dspserv |
#include <osdspc.h> int dspserv(char *request, ...);
_Dreason
keyword is used to pass back a reason code in the
event that the service fails. The next argument should be a pointer to an int
that will contain the reason code as set in R0 by the
DSPSERV macro if the DSPSERV macro returns non-0 in R15.
_Dstoken
keyword is equivalent to the Assembler
STOKEN
keyword. The next argument should be the address of
an 8-character array. The CREATE service returns the STOKEN
in this array. All other services require the STOKEN
as
input.
_Dname
keyword is equivalent to the Assembler
NAME
keyword. The next argument should be an 8-character array.
This parm is required for the CREATE service. Depending on the setting of
the _Dgenname
parm, all or part of this name
will be used to name the dataspace.
_Dgenname
keyword is equivalent to the Assembler
GENNAME
keyword. The next argument should be one of the following
strings:
_Doutname
keyword is equivalent to the Assembler
OUTNAME
keyword. The next argument should be an 8-character
array. If specified, the name of the dataspace will be returned here if _Dgenname
YES or COND was specified on a CREATE
request.
_Dstart
keyword is equivalent to the Assembler
START
keyword. The next argument should be a pointer that
contains the beginning address of a block of storage in a dataspace. This
parameter is required on RELEASE, LOAD, and OUT requests.
_Dblkmax
keyword is related to the Assembler
BLOCKS
keyword. The next argument should be an integer value
containing the maximum size in blocks that a new dataspace can grow to. The
limit is 524,287 blocks. This parm should only be used with the CREATE service.
This parm is optional, and if it is omitted, the default maximum size will
be taken from site installation defaults or IBM defaults (at the time of this
writing, 239 blocks.)
_Dblkinit
keyword is related to the Assembler
BLOCKS
keyword. The next argument should be an integer value
specifying the initial size (in blocks) of a dataspace. This parm should be
used only with the CREATE service. This parm is optional, and if omitted,
the default initial size will be taken from site installation defaults or
IBM defaults (at the time of this writing, 239 blocks.)
_Dblksize
keyword is related to the Assembler
BLOCKS
keyword. The next argument should be an integer value
containing a size in blocks. This parm should used with one of the following
services: RELEASE, EXTEND, LOAD, or OUT. This parm indicates the size of storage
to be affected by one of these services.
_Dttoken
keyword is equivalent to the Assembler
TTOKEN
keyword. The next argument should be the address of
an 16-byte array that has been set to indicate a TCB. This is usually returned
from a call to the TCBTOKEN macro. The CREATE service will use this field
to assign the dataspace to a TCB and the DELETE service will use it to delete
a dataspace owned by another TCB. This parameter is optional.
_Dorigin
keyword is equivalent to the Assembler ORIGIN
keyword. The next argument should be the address of
a pointer that will be set to either 0 or 4096, indicating the lowest address
of a new address space. This parm is optional for the CREATE service.
_Dnumblks
keyword is equivalent to the Assembler NUMBLKS
keyword. The next argument should be the address of
an int
where one of the following will be returned:
for "CREATE" | the maximum size (in blocks) of the newly created dataspace. |
for "EXTEND" | the number of blocks by which the dataspace was extended. |
_Dranglist
keyword is equivalent to the Assembler
RANGLIST
keyword. The next argument should be the address
of a range list. The range list consists of a number of entries
(as specified by _Dnumrange
) where each entry
is 8 bytes long. The first four bytes of the entry contain the starting virtual
storage address of the dataspace range to be released, and the second four
bytes contain the number of pages in the dataspace range to be released. _Dranglist
is an optional parameter of the RELEASE
service.
_Dnumrange
keyword is equivalent to the Assembler
NUMRANGE
keyword. The next argument should be an integer value
representing the number of entries in the range list. _Dnumrange
is an optional parameter of the RELEASE
service.
_Dvar
keyword is equivalent to the Assembler
VAR
keyword. The next argument should be one of the
following
strings:
_Dend
keyword
indicates the end of the list of keywords.
The following parms can be used by authorized programs only:
_Ddref
keyword is equivalent to the Assembler
DREF
keyword. The next argument should be one of the following
strings:
"YES" | Disabled programs can access the dataspace. |
"NO" |
Only enabled programs can access
the dataspace. _Ddref is an optional parameter
of the CREATE service. |
_Dscope
keyword
is equivalent to the Assembler SCOPE
keyword.
The next argument should be one of the following strings:
"SINGLE" | The dataspace may only be referenced by the owning address space. |
"ALL" or "COMMON" | The dataspace may be referenced by many address spaces. |
_Dkey
keyword is equivalent to the Assembler
KEY
keyword. The next argument should be a pointer to a byte
containing the storage key of the dataspace to be created. The key should
be placed in bits 0-3 of the byte. _Dkey
is
an optional parameter of the CREATE service and if it is omitted, the key
associated with the dataspace will be the same as that of the caller.
_Dfprot
keyword is equivalent to the Assembler FPROT
keyword. The next argument should be one of the following
strings:
_Ddisabled
keyword is equivalent to the Assembler DISABLED
keyword. The next argument should be one of the following strings:
"NO" |
The caller is enabled for I/O and
external interrupts. _Ddisabled,
NO is the default. |
"YES" | Valid only for RELEASE requests of pages that reside in DREF storage. |
The dspserv
function
is implemented by the source module L$UDSPC.
#include <osdspc.h> #include <string.h> char stoken[8]; void _ _far * pFar; int rc; int alet; void *origin; rc = dspserv("CREATE", _Dstoken, stoken, _Dname, "LSC", _Dorigin, &origin, _Dend); if (rc != 0) abend(1); rc = aleserv("ADD", _Lstoken, stoken, _Lalet, &alet, _Lend); if (rc != 0) abend(2); memcpy(&pfar, &alet, 4); memcpy(((char *) &pfar)+4, &origin, 4); strcpy(pFar, "DATASPACE STORAGE");
#include <osdspc.h> char stoken[8]; int rc; int numblks; int reason; rc = dspserv("EXTEND", _Dstoken, stoken, _Dreason, &reason, _Dblksize, 300, _Dnumblks, &numblks, _Dend); if (rc != 0) abend(1);
#include <osdspc.h> char stoken[8]; int rc; rc = dspserv("DELETE", _Dstoken, stoken, _Dend); if (rc != 0) abend(1);
exit |
#include <stdlib.h> void exit(int code);
exit
terminates the program and returns
control to its caller. The integer argument
code
is returned in register
15. The meaning or value of the exit code is subject to alteration by a start-up
routine.
Control does not return from
exit
.
exit
is portable.
The SPE implementation of
exit
is in L$UMAIN and
L$UEXIT. If
blkjmp
is used,
exit
is implemented as
a call to
longjmp
. However,
exit
does not call
longjmp
if the
longjmp
routine is not linked into
the load module. In a multiple load module application, it may be desirable
to modify L$UEXIT so that
longjmp
is always called.
falloc |
Create a dataspace, or allocate storage from an existing dataspace
#include <osdspc.h> void __far * falloc(struct _DSPC ** dspc, size_t size);
The falloc
function is
implemented by the source module L$UFALC.
#include <osdspc.h> #include <string.h> void __far * fptr; pDSPC pdspc = 0; fptr = falloc(&pdspc, 4096); if (fptr) memcpy(fptr, "New dataspace");
ffree |
#include <osdspc.h> void ffree(void __far * fptr);
The ffree
function is
implemented by the source module L$UFALC.
#include <osdspc.h> #include <string.h> void __far * fptr; pDSPC pdspc = 0; fptr = falloc(&pdspc, 4096); memcpy(fptr, "New dataspace"); ffree(fptr);
format |
Write Formatted Output to a
String
#include <lclib.h> int format(char *s, const char * form , ...);
format
is similar to the
sprintf
function except that it does not support the floating-point conversions
(
e
,
E
,
f
,
g
,
G
).
Refer to Chapter 6, "Function Descriptions" in
SAS/C Library Reference, Volume 1 for more information.
format
returns the number of characters
written to the location addressed by
s
.
If there is an error during output,
format
returns a negative number. The absolute value of this number equals the number
of characters written up to the point of error or 1, if none are written.
format
is not portable.
format
is implemented as a faster,
smaller version of
sprintf
.
free |
#include <stdlib.h> void free(char *block);
free
frees a block of memory previously
allocated by the
malloc
function.
block
is a pointer to the
memory block.
See the IMPLEMENTATION section for the
malloc
function.
free
is highly portable.
Any
malloc
memory that has not been freed
at program termination will be automatically freed.
See the IMPLEMENTATION section for the
malloc
function for more details about the implementation of
free
.
freeexit |
#include <bldexit.h> void freeexit(void *area);
freeexit
frees the memory associated
with a
bldexit
exit routine. The argument to
freeexit
is the address returned by the previous call to
bldexit
.
Do not call
freeexit
for an exit routine
that is defined to the operating system.
freeexit
is not portable.
getenv |
Get
Value of Environment Variable in SPE
#include <stdlib.h> char *getenv(const char *name);
The
getenv
function searches an environment
variable list for a variable
name
that matches the string pointed
to by the
name
argument. See the description of the
putenv
function for a discussion on altering and creating environment variables.
The
getenv
function returns a pointer
to the string value associated with the matched name in the environment variable
list. If a matching name is not found,
getenv
returns the value
NULL
.
A subsequent call to
getenv
overwrites the array
pointed to by the first call.
The
getenv
function is defined in accordance
with the ANSI Standard for C and POSIX.1.
The only environment variables accessible to the SPE
getenv
are those added by a previous call to
putenv
or
setenv
. Note that if you have a program called with
exec
-linkage
that uses the
oemain
start-up routine, the environment variables
passed by the caller of
exec
are added to the environment
using
putenv
before control is passed to the initial function.
loadm |
Dynamically Load
a Load Module in SPE
#include <dynam.h> void loadm(char *name, __remote /* type */ **fpp());
loadm
loads the module named by the
first argument string
name
and stores a C function pointer
referencing the initial function of the module.
loadm
provides an indirect return
value in the form of a function pointer that addresses the entry point of
the loaded module. If the module is in the C language, calling the returned
function always transfers control to the
_dynamn
function of the
module.
If the module to be loaded cannot be found, a
NULL
pointer is stored in the location addressed by
fpp
.
Errors are implementation defined.
Subordinate load modules must be linked with the SPE
version of the #DYNAMN (for reentrant load modules) or #DYNAMNR (for non-reentrant
load module) code. This code is in L$UDYNM and L$UDYNR, respectively. The
SPE implementation of
loadm
cannot load modules linked with
the full library version of #DYNAMN or #DYNAMNR. Similarly, the full library
implementation of
loadm
cannot load modules linked with the SPE version
of #DYNAMN or #DYNAMNR.
loadm
is nonportable.
The SPE implementation of
loadm
is in L$ULDR. Under
OS/390,
loadm
is implemented via SVC 8; under CMS, it is
implemented via the NUCXLOAD command; and under CICS, it is implemented via
the EXEC CICS LOAD command. Note that the SPE
loadm
is substantially
less functional than that of the full library; therefore, this version should
be considered as a prototype only. Any serious use of
loadm
in SPE will require L$ULDR to be extended or rewritten.
malloc |
#include <stdlib.h> char *malloc(size_t size);
malloc
allocates a block of dynamic
memory of the size requested by
size
.
malloc
returns the address of the
first character of the new block of memory. The allocated block is suitably
aligned for storage of any type of data.
Errors are implementation defined. See IMPLEMENTATION below.
If adequate memory is not available or if 0 bytes were
requested, a NULL (0) pointer is returned.
The contents of a block of memory on allocation are random.
The
realloc
function is not supported,
and the full-library
realloc
function does not work with
L$UHEAP. You may implement this function as a simple extension to the existing
implementation.
malloc
is highly portable.
The SPE version of
malloc
is supplied in source
as L$UHEAP. The following description of the function is based on this implementation.
The external variable
_heap
can be used to define
the total amount of storage to be reserved for
malloc
allocation. By
default, the amount reserved is determined by the start-up routine. Unlike
the full-library
malloc
, this version does not attempt to allocate
more storage if the initial amount is insufficient.
The
malloc
implementation in L$UHEAP respects
two macros, CHECKING and SYNCH. If CHECKING is defined, code that checks
for overlays of allocated memory is generated. If an overlay is detected,
user ABEND 1206 is issued. If the
free
function detects an
invalid argument, user ABEND 1208 is issued.
If SYNCH is defined, code is generated that allows
malloc
to be used in asynchronous exits. The supplied object code
is compiled with SYNCH defined and CHECKING undefined.
Note that the
calloc
and the pool allocation
functions are compatible with L$UHEAP. Refer to "Memory Allocation Functions"
in Chapter 2 of
SAS/C Library Reference, Volume 1 for more information.
oeabntrap |
#include <oespe.h> int oeabntrap(int code);
oeabntrap
is used to intercept OS/390
ABENDs and transform them into an appropriate USS signal. If the program
is being debugged with
dbx
(or any other similar debugger),
the debugger is informed of the ABEND and is allowed to recover it.
oeabntrap
is supported only in SPE programs; similar functionality
is defined automatically when the standard C framework is used.
The
code
argument is a symbolic value
indicating the particular function wanted, one of
TRAP_ON
,
TRAP_OFF
, or
TRAP_AUTO
. When
code
is
TRAP_ON
, the ABEND trapping functionality is enabled. When
code
is
TRAP_OFF
, ABEND trapping functionality is disabled. When
code
is
TRAP_AUTO
, ABEND trapping functionality is enabled, and an
atexit
routine is defined to disable ABEND trapping at the end of program execution.
If an ABEND occurs while ABEND trapping is enabled, the following events take place:
ptrace
system call is issued
to inform any debugger of the event. If the debugger requests that the ABEND
be recovered, an appropriate ESTAE retry is issued.
kill
system call. If a debugger requested the signal,
the signal is chosen by the debugger. If not, an appropriate signal is selected
by the retry routine (SIGILL, SIGSEGV, or SIGFPE for program check ABENDs,
SIGABRT for user ABENDs, SIGABND for system ABENDs).
oeabntrap
returns
0
if its function was successful. It returns a positive value if the call had
no effect (for instance, specifying
TRAP_OFF
before any trap
was established). It returns a negative value if any other error occurred.
If you issue your own ESTAE macros in addition to using
oeabntrap
, it is your responsibility to make sure that your exits do
not interfere with the operation of
oeabntrap
.
oeabntrap
is not portable.
Source for
oeabntrap
is supplied in
SPE source modules L$UZABN and L$UZEST.
This example uses
oeabntrap
to catch ABENDs
and defines a SIGSEGV handler to call the
btrace
function to show
the location of the error.
#include <oespe.h> #include <unistd.h> #include <lclib.h> #include <string.h> #include <setjmp.h> #include <signal.h> jmp_buf ABEND_escape; /* where to run to after an ABEND */ static int ABEND_trapped; void trace_out(char *line) { /* this function writes a btrace output line to file descriptor 2 */ write(2, line, strlen(line)); write(2, "\n", 1); } void ABEND_handler(int signum) { char buf[60]; sprintf(buf, "Interrupted by signal %d!\n", signum); write(2, buf, strlen(buf)); btrace(&trace_out); longjmp(ABEND_escape, 1); } int ptrvalid(int *ptr) { /* return whether storage addressed by ptr can be read */ sigaction segv_action, prev_action; int ok; volatile int value; if (ABEND_trapped = 0) { oeabntrap(TRAP_AUTO); /* possibility of error ignored */ ABEND_trapped = 1; } if (setjmp(ABEND_escape) != 0) goto failed; /* set up retry from handler */ segv_action.sa_handler = &ABEND_handler; sigemptyset(segv_action.sa_mask); segv_action.sa_flags = 0; struct sigaction(SIGSEGV, &segv_action, &prev_action); /* we'll try to access the storage even if sigaction fails... */ value = *ptr; /* force reference to *ptr */ ok = 1; /* it must be valid */ goto complete; failed: ok = 0; /* the pointer is no good */ complete: sigaction(SIGSEGV, &prev_action, 0); /* restore previous SIGSEGV handling */ return ok; }
putenv |
Update
Environment Variable in SPE
#include <lclib.h> int putenv(const char *string);
The
putenv
function alters an environment
variable's value or creates an environment variable with a name and value
corresponding to the string pointed to by the
string
argument. The format
of the
string
argument is
variable-name=value
""
if it is not specified. All blanks
are significant in the string.
The
putenv
function returns
0
if successful.
The
putenv
function is not portable.
It is a complementary extension to
getenv
.
setenv |
Modify
Environment Variables in SPE
#include <stdlib.h> int setenv(const char *name, const char *value)
setenv
adds or replaces environment
variables.
name
is the name of the environment variable.
value
is the new value to be assigned to the environment variable.
setenv
returns
0
if it is successful.
setenv
returns
-1
if it is not successful.
If
name
includes an equal sign (=),
setenv
will fail.
setenv
is defined in accordance with
POSIX.1a.
unloadm |
Dynamically Unload a Load Module
in SPE
#include <dynam.h> void unloadm(__remote /* type */ (*fp)());
unloadm
unloads the executable module
containing the function addressed by
fp
. If the module is no
longer in use,
unloadm
deletes it from memory.
unloadm
does not have a return value.
Errors are implementation defined.
Attempting to call a function in an unloaded module is not recommended.
No provision is made for unloading modules at program
termination automatically. However, this sort of functionality can be implemented
in a function that is registered with
atexit
.
unloadm
is nonportable.
Refer to the IMPLEMENTATION section for
loadm
.
vformat |
Write Formatted Output to a String
#include <lclib.h> int vformat(char *s, const char *form, va_list arg);
vformat
is equivalent to
format
with the variable argument list replaced by
arg
. The
arg
parameter has been initialized by a type
va_start
macro and possibly
by
va_arg
calls.
vformat
does not change the
va_arg
list pointers; for example, it does not use the
va_start
,
va_arg
, or
va_end
macros to process
the variable argument list.
vformat
returns the number of characters
written to the location addressed by
s
.
If there is an error during output,
vformat
returns a negative number. The absolute value of this number equals
the number of characters written up to the point of the error.
vformat
is not portable.
vformat
is implemented as a faster,
smaller version of
vsprintf
.
#include <lclib.h> #include <stdarg.h> /* Format an error message buffer via format */ /* Format the remaining buffer with vformat */ void error (char *msg_buf, char *fname, *format, ...) va_list args; int msg_len; va_start(args, format); msg_len = format(msg_buf,"ERROR in %s: ", fname); if (msg_len > 0) msg_buf += msg_len; else msg_buf -= msg_len; vformat(msg_buf, format, args); va_end(args); }
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.