Additionally, SAS/C Library Reference, Volume 2 documents the SAS/C socket library for TCP/IP and SAS/C POSIX support.
Most functions in the SAS/C library are compatible with industry-recognized C library standards, including
stat
and link
functions are limited to use with OpenEdition files, other functions
such as open
, read
, write
, and access
can
be used with most MVS and CMS file types.
Unlike the ISO/ANSI and POSIX libraries, the traditional UNIX library is not defined as a formal standard. Rather, the traditional UNIX library is informally defined by consensus with a number of different UNIX implementations, based on both System V and BSD.
Although SAS/C does not and cannot support every function defined
by every historical UNIX variant, the library does attempt to offer
support for a large subset of the core UNIX functionality, especially
functions frequently used in portable programs. Note, however,
that some core functions, such as fork
and kill
, cannot be
implemented under MVS or CMS by an application-level library such as
the SAS/C library without operating system support (such as
OpenEdition MVS).
SAS/C, Release 6.00 directly uses the MVS support for OpenEdition, and you can use it with the Shell and Utilities product. The dbx debugger does not support SAS/C programs, but you can use the traditional SAS/C debugger under the shell instead of using dbx.
Using the underlying functionality of the MVS support for OpenEdition, SAS/C, Release 6.00 enables you to
To support these features, the Institute made some changes to the SAS/C compiler and debugger, but most changes are localized to the resident and transient libraries. Compile-time header files are also significantly changed.
The POSIX 1003.1 standard is an ISO standard that specifies operating system functionality in a C language interface. With OpenEdition, the SAS/C library implements this interface under MVS. OpenEdition and SAS/C also implement portions of the 1003.1a draft standard and related extensions. POSIX 1003.1 is based on common elements of a number of UNIX operating systems.
The SAS/C POSIX implementation is documented in Part 3, "SAS/C POSIX Support," in SAS/C Library Reference, Volume 2 .
Table 1.1 shows the likely result of using different releases of the compiler
and the resident and transient libraries to compile and link programs. If you
are unsure which version of the library you are using, you can use the
=version
run-time option, which displays the library version numbers.
Note: Combining more than three versions of the compiler and resident and transient libraries becomes very complicated and is not documented here. In Table 1.1 where a row contains two entries of "older," they refer to the same older version.
Table 1.1 Likely Results of Mixing Releases of the Compiler and Libraries
Program Transient Resident Compiler Likely Library Library Release Result: Release Release Will Program Run?
1 current current current Yes 2 current current previous Yes 3 current current older Yes 4 current previous current No 5 current previous previous Yes 6 current previous older Yes 7 current older current No 8 current older previous No 9 current older older Yes 10 previous current current No 11 previous current previous No 12 previous current older No 13 previous previous current No 14 previous previous previous Yes 15 previous previous older Yes 16 previous older current No 17 previous older previous No 18 previous older older Yes 19 older current current No 20 older current previous No 21 older current older No 22 older previous current No 23 older previous previous No 24 older previous older No 25 older older current No 26 older older previous No 27 older older older Yes
For maximum portability and efficiency, always include the header files for all of the library functions called in a compilation. This practice has two benefits:
Functions defined by the ISO/ANSI standard are declared in the header file
mandated by the standard. For example, the fopen
function is declared
in <stdio.h>
. The names of the standard header files are
<assert.h>
<ctype.h>
<errno.h>
<float.h>
<limits.h>
<local.h>
<math.h>
<setjmp.h>
<signal.h>
<stdarg.h>
<stddef.h>
<stdio.h>
<stdlib.h>
<string.h>
<time.h>
Functions defined by another standard are declared in the header file mandated by the standard. If that file is also an ISO/ANSI C standard header file, you must use a feature test macro to make the declaration visible. Feature test macros are described in more detail in the next section.
Functions which are not defined by the ISO/ANSI Standard but which are related to standard
functions are declared in separate header files. These header filenames are
similar to the Standard names but have the prefix lc
.
For example, the function afopen
is declared in <lcio.h>
. The
names of these header files are
<lcdef.h>
<lcio.h>
<lcjmp.h>
<lclib.h>
<lcmath.h>
<lcsignal.h>
<lcstring.h>
<lctype.h>
If you include the lc-
header file, you do not need to include the
standard header file. In all cases, the lc-
prefixed header contains
a #include
statement for the standard header file. For example, the
header file <lcstring.h>
contains the statement #include <string.h>
.
(It is not an error to explicitly include both files.) The SAS/C library
contains many nonstandard functions and header files that are not associated
with standard features. For details on nonstandard functions and header files that are
not associated with standard features, see SAS/C Library Reference, Volume 2 .
#define
statement or by using the define
compiler option.
_SASC_POSIX_SOURCE
_SASC_POSIX_SOURCE
has
no effect on non-ISO/ANSI header files.
_POSIX_SOURCE
_POSIX_SOURCE
should be defined only for
programs which are intended to be POSIX-conforming and which do not use any
non-ISO/ANSI or non-POSIX library features.
_POSIX1_SOURCE
_POSIX_SOURCE
. If this macro is
defined as 2, symbols sanctioned by the POSIX.1a draft standard related to
features implemented by OpenEdition MVS will also be made visible.
Like _POSIX_SOURCE
, _POSIX1_SOURCE
should
not be defined in any program that uses non-ISO/ANSI non-POSIX features.
_POSIX_C_SOURCE
_POSIX_SOURCE
, plus making visible symbols
sanctioned by the POSIX.2 draft standard related to features
implemented by SAS/C. If _POSIX_C_SOURCE
is defined to any other
value, it has the same effect as defining _POSIX_SOURCE
. Like
_POSIX_SOURCE
, _POSIX_C_SOURCE
should not be
defined in any program that uses non-ISO/ANSI non-POSIX features.
_SASC_POSIX_SOURCE
is automatically defined. This does not
ensure that your program is POSIX compliant; it only makes visible POSIX symbols in
ISO/ANSI standard header files.
int
variable errno
contains the number of the most
recent error or warning condition detected by the run-time library. To use
this value, include the header file <errno.h>
.
If no error or warning condition is detected, the value of errno
is 0.
After program execution starts, errno
is never reset to 0 by the
library. Programs that use errno
for information about unusual
conditions must set it to 0 before calling a library routine that may detect
such a condition.
The <errno.h>
file contains declarations of the errno
variable
and definitions of symbolic names for the values that can be assigned. These
names rather than numeric values should be used for errno
.
SAS/C defines a number of general-use errno
names. There are also many
errno
names associated with specific sublibraries, notably the SAS/C
socket library and the SAS/C POSIX support. Socket errno
names are documented in
Chapter 15, "The BSD UNIX Socket Library," in SAS/C Library Reference, Volume 2 , and
errno
names related to OpenEdition
are documented in Chapter 19, "Introduction to POSIX," in SAS/C Library Reference, Volume 2 .
For a complete
listing of all errno
values, see SAS/C Compiler and Library Quick Reference Guide .
The following list defines the error names and meanings that are for general use, and thus not associated with a specialized API, such as sockets:
EARG
EBADF
ENOTOPEN
)
ECONV
ECORRUPT
EDEVICE
EDOM
EDUPKEY
EEXIST
EFATTR
EFFORM
EFORBID
EILSEQ
EINTR
EINUSE
EINVAL
EARG
)
EIO
EDEVICE
)
ELIBERR
ELIMIT
EMFILE
ELIMIT
)
ENFILE
ENFOUND
ENOENT
ENFOUND
)
ENOMEM
ENOSPC
ENOSYS
ENOTOPEN
EBADF
EPREV
ERANGE
ESYS
EUNSUPP
EUSAGE
The variable errno
is implemented as a macro. If you use errno
without including <errno.h>
, the correct data may not be accessed.
The only portable values for errno
are EDOM
and ERANGE
.
The following example illustrates the use of errno
:
#include <errno.h> #include <stdio.h> FILE *f; char *filename; if (!(f = fopen(filename, "r"))) { /* See if any file can be opened. */ if (errno == ELIMIT) { printf("Too many open files\n"); return(EOF); } else { printf("%s could not be opened, enter new filename\n", filename); getfname(filename); } }
<lcdef.h>
contains the declaration of a
nonstandard external variable, _msgno
. This variable contains the
message number of the last SAS/C library diagnostic. For example, if
the last message ID were LSCX503, _msgno
would contain 503.
_msgno
may provide more information about a failure than errno
.
For instance, trying to read a file that has not been created sets
errno
to ENFOUND, but you can use _msgno
to distinguish the
cases of an empty sequential file (_msgno
= 503) and a missing PDS
member (_msgno
= 504). _msgno
is not portable, so programs that
must be portable should use only errno
.
_msgno
is implemented as a macro, so you should not use the name for
any other purpose.
When the library calls an operating system service (including an OpenEdition
system call) that fails, information about the failure is saved in
a library structure. Macros are defined in <lcdef.h>
to enable user
code to determine the service that failed and the resulting failure
codes. Only the most recent failure information is saved; information is
not saved for successful services.
The following macros are defined:
__sysmi_macname
__sysmi_rc
errno
value.
__sysmi_reason
__sysmi_info
You can use the macro __sysmi_clear
to clear previously stored
system macro information. You may wish to call __sysmi_clear
before calling a routine that might store SYSMI information to ensure that
any such information relates to the most recently called function.
<lcdef.h>
.
The following pages describe these macros,
offsetof
, isunresolved
, isnotconst
,
isnumconst
, and isstrconst
.
#include <stddef.h> /* macro */ size_t offsetof(type, element)
offsetof
macro provides the decimal byte offset of a component
within a structure as a size_t
constant. This constant is generated at
compile time. Padding for alignment, if any, is included. The operands of
offsetof
are a structure type (type
) and a component of the
structure specification (element
). The component specification does
not include the structure type or the selection operators .
or
->
.
offsetof
returns the byte offset of element
.
.
or ->
selection operator.
Example 1.1
#include <stddef.h> struct AAA { /* Define structure AAA. */ double ddd; char ccc; int bbb; }; long x; /* x is the byte offset of component bbb in struct AAA. */ x = offsetof(struct AAA, bbb);Example 1.2 shows a structure,
data
, with an inner structure
base
.
Example 1.2
#include <stddef.h> struct data { /* Define struct data. */ int id; int *elem; char *name; struct { /* Define struct type base. */ double proj; } base; }; long ofs; /* ofs is the byte offset of base.proj. */ ofs = offsetof(struct data, base.proj);In Example 1.3,
complex
is defined via a typedef
statement to
be a structure type. The component specification inner.d[5]
specifies
an array element within an inner structure. The variable y
is set to
the offset of the sixth array element in the inner structure
(decimal 56
).
Example 1.3
#include <stddef.h> typedef struct { /* Define struct type complex. */ struct XXX *xptr, *xptr2; struct { /* Define struct type inner. */ int count, count2; double d[10]; } inner; struct XXX *xptr3; } complex; /* y is the byte offset of inner.d[5]. */ long y; y = offsetof(complex, inner.d[5]);
#include <lcdef.h> int isunresolved(name);
__weak
) to determine whether the symbol was resolved
by the linkage editor.
isunresolved
returns 0 if the symbol is resolved, or a nonzero value
if it is not resolved.
/* Test whether the function db_open() is present */ /* in the load module. If it is, call it. */ /* optional database open function */ extern int __weak db_open(char *); if (!isunresolved(db_open)) db_open("DBNAME");
#include <lcdef.h> int isnotconst(expression); int isnumconst(expression); int isstrconst(expression);
expression
and return a compile-time constant.
If expression
is the appropriate type of constant, a nonzero constant
is returned; otherwise, 0 is returned. The type tested for is numeric for
isnumconst
, string literal for isstrconst
, and nonconstant for
isnotconst
. The expression
constant can have any type.
expression
is never evaluated, and these macros always yield a constant,
regardless of the type of expression
.
The isnotcons
, isnumconst
, and isstrconst
macros
are used primarily to control the generation of code by in-line functions.
Because they produce compile-time constants, the macros can be tested at compile time,
enabling the compiler to eliminate sections of code that can never be executed.
Example 1.4
if (isnotconst(argv[])) /* true */ if (isnumconst(100)) /* true */ if (isstrconst("XYZ")) /* true */ if (isstrconst(c == 0 ? "A" : "B") /* false */
Example 1.5
#define MAXLEN 1024 if (isnumconst(MAXLEN) && 500 < MAXLEN) /* true */
Example 1.6
This example defines the function smemcpy
(meaning short memcpy
) that prevents the expansion of the
built-in memcpy
function unless the length argument
is a constant integer less than or equal to 256. If the length
argument is greater than 256 or is not a constant integer,
a call to the true memcpy
function is generated.
The if
condition is a constant expression and is evaluated at
compile time. The compiler generates code either for the then
branch or the else
branch, depending on the result of the test.
Under no conditions is code for both branches generated.
#include <lcdef.h> #include <string.h> #define smemcpy(d, s, len) inline_memcpy(d, s, len, isnumconst(len)) __inline void *inline_memcpy(void *d, const void *s, size_t len, int cnst) { if (cnst && len < 257) memcpy(d, s, len); else (memcpy)(d, s, len); return d; }
abs
function is a good example:
#include <math.h> int gt5(register int i){ return (i < -5) ? i + 5 : abs(i); }Given this C function, the compiler generates a single IBM 370 machine instruction called Load Positive Register (LPR) to get the absolute value of
i
. However, calling and executing the true abs
function in this
example requires the execution of 20 machine instructions.
The compiler and library implement built-in functions by defining a macro in
the header file that prefixes the string __builtin_
to the function
name. For example, the strcpy
function is declared as follows:
#define strcpy(x, y) __builtin_strcpy(x, y)The compiler recognizes the prefix and generates the appropriate machine instructions. If you do not include the header file, the compiler does not recognize the function as a built-in function and generates a call for the function.
For some built-in functions, the compiler may generate a call to the true function as part of the code sequence. This occurs when the value of one or more of the function arguments cannot be determined at compile time and may fall outside of the range of values that the in-line code can handle. At execution time, the arguments are evaluated, and either the in-line code is executed or the true function is called.
If a built-in function is called with invalid arguments or an invalid number of arguments, a call to the true function is generated.
Following is a list of all SAS/C built-in functions:
_bbwd abs memcpyp strncmp _bfwd ceil memscan strscan _branch fabs memscntb strscntb _cc floor memset strxlt _cms202 fmax memxlt tolower _code fmin min toupper _diag getc modf _label labs putc _ldexp max sigchk _ldregs memcmp strcmp _ossvc memcmpp strcpy _stregs memcpy strlenFollowing is a list of all SAS/C functions implemented as macros, other than built-in functions:
ABEND * TPUT_USERID * getchar pause CHAP * TTIMER * htonl pdset * CMSSTOR_OBT *+ WAIT1 * htons pdval * CMSSTOR_REL *+ WAITM * isalnum pfree DEQ * WAITT * isalpha putchar DETACH * WRTERM * iscics setbuf DMSFREE * appcconn *+ iscntrl shvdrop * DMSFREE_V * appcrecv *+ iscsym shvfetch * DMSFRET * appcscfd *+ iscsymf shvfirst * ENQ * appcscnf *+ isdigit shvnext * ESTAE * appcsdta *+ isebcdic shvset * ESTAE_CANCEL * appcserr *+ isgraph sigsetjmp * FREEMAIN * appcsevr *+ islower strcspn GETLONG * appcsreq *+ isnotconst * strspn GETMAIN_C * assert * isnumconst * toebcdic GETMAIN_V * atof isprint typlin * GETMAIN_U * atoi ispunct unloadd GETSHORT * cfgetispeed isspace va_arg * POST * cfgetospeed isstrconst * va_end PUTLONG * cmspush * isunresolved * va_start * PUTSHORT * cmsqueue * isupper waitrd *+ RDTERM * difftime isxdigit xedpoint STATUS * e_SVC202 labs xedread STIMER * execdrop * localtime xedstate STIMERM_CANCEL *+ execfetch * memchr xedwrite STIMERM_SET * execset * ntohl STIMERM_TEST * exit ntohs SVC202 fattr + offsetof * TGET * ffixed + onjmp * TPUT * fnm + onjmpout * TPUT_ASID * fterm + palloc* = may not be undefined.
Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.