Chapter Contents

Previous

Next
SAS/C Compiler Changes in Release 7.50

Release 7.50 Changes to the SAS/C Compiler and Library User's Guide


IEEE and 64-Bit Updates to the Inline Machine Code Interface

The SAS/C support for IEEE Floating-Point computation and 64-Bit processing requires several changes to the documentation for the inline machine code interface. The following sections contain details about these changes. All of the following section names refer to sections in Chapter 13, "Inline Machine Code Interface."

Update to Built-in functions

In the section titled "Overview," add the following entry to the table under "Built-in functions:"

_ospc generate an OS/390 PC instruction


Updates to _diag, _cms202 and _ossvc


Updates to Code Macros


Updates to Inline Machine Code Usage Notes


Updates to the _bbwd Function


Updates to the _bfwd Function

The following changes should be made to the _bfwd function description:


Updates to the _branch Function

The following changes should be made to the _branch function description:


Updates to the _ldregs Function


New _ospc Function

Add the new function, _ospc, to the "Functions" section.

_ospc
Generate an MVS PC Instruction

SYNOPSIS
   #include <svc.h>
   void _ospc(void);

DESCRIPTION
_ospc generates a program call (PC) instruction, specifically, PC 0(14). This PC instruction is used to link to several MVS services. It is the caller's responsibility to set up arguments for the program call appropriately, using _ldregs or inline code functions.

Note:   The generated code assumes that the program call will not modify registers other than 14 through 1. This function should not be used to invoke system calls which do not honor this restriction.  [cautionend]

CAUTIONS
If you call _ospc incorrectly (for instance, if you pass any arguments), the second pass of the compiler produces an error message, sets the MVS return code to 8, and generates an EX 0,* instruction for _ospc. The generated instruction causes an execute exception (MVS ABEND code 0C3) if it is executed.

PORTABILITY
_ospc is not portable.

IMPLEMENTATION
_ospc first stores any values currently in use from general-purpose registers 0, 1, 14 and 15 and clears any information the compiler had about the contents of those registers. It assumes these registers may be altered by the program call. If necessary, _ospc then issues a SAM31 instruction to exit 64-bit mode. _ospc then saves the address of the PC instruction in the C Run-Time Anchor Block (CRAB) as an aid in traceback production in case the PC causes an ABEND. Next, _ospc issues the PC instruction. Finally, if the HUGEPTRS option was specified, _ospc issues the SAM64 instruction to resume 64-bit mode execution.

EXAMPLE
The following macro is a C macro with approximately the same functionality as the assembler macro:
     STORAGE OBTAIN,LENGTH=len,ADDR=addr,SP=sp,COND=YES


#include <code.h>
#include <genl370.h>
#include <svc.h>

#define STORAGE_OBTAIN(len,sp,addr) \
    (_ldregs(R0+R14+R15, (len), 16, (sp) << 8), \
     L(14, 0+b(14)), \
     L(14, 772+b(14)), \
     L(14, 160+b(14)), \
     _ospc(), \
     _stregs(R1+R15, (addr)))

RELATED FUNCTIONS
_ldregs, _ossvc, _stregs


Update to the _osarmsvc Function

The description of _osarmsvc should read:

_osarmsvc generates a supervisor call (SVC) instruction. _osarmsvc takes one argument (n) that specifies the number of the SVC to generate; n is an execution-time constant in the range of 0 to 255. No code is generated to change the addressing mode. The SVC will be issued in AR mode if the compiler armode option has been specified, and otherwise will be issued in primary address space mode. If _osarmsvc is issued in a program compiled with the HUGEPTRS option, execution is switched to 31-bit addressing before the SVC is issued, and restored to 64-bit addressing after the SVC completes.

Update to the _ossvc Function

The implementation section of the _ossvc function should read:

_ossvc first stores any values currently in use from general-purpose registers 0, 1, 14, and 15 and clears any information the compiler had about the contents of those registers. It assumes that these registers are, or may be, altered by the SVC. If needed, _ossvc then issues a SAC instruction to cancel access-register mode and/or a SAM31 instruction to cancel 64-bit addressing mode. _ossvc then saves the address of the SVC instruction in the C Run-Time Anchor Block (CRAB) as an aid to traceback production in case the SVC causes an ABEND. _ossvc then issues the requested SVC instruction. Finally, _ossvc issues a either a SAC or a SAM64 instruction, or both, to restore the program's original addressing mode.

Update to the _stregs Function

Add the following paragraph after the fourth paragraph of the description of the _stregs function:

Each argument other than the mask to _stregs must have a type of pointer. The pointer must address a data type which is appropriate to the register being stored. For instance, it is erroneous to attempt to store a general purpose register via a pointer to double. In access register mode, you can store both a general register and the corresponding access register if the argument is a pointer to a _ _far pointer. Similarly, if ARCHLEVEL(D) has been specified you can store all 64-bits of a general purpose register if the corresponding _stregs argument is a pointer to long, long long, or a _ _huge pointer. It is permitted but not recommended for an argument to _stregs to have type void *. In this case, the amount of data stored is determined by the size of the register.


Updates for Floating-Point Support

The following sections contain information about specific changes to the SAS/C Compiler and Library User's Guide for floating-point support.

Updates to Numerical Limits

In Chapter 2, "Source Code Conventions," under the section titled, "Numerical Limits," replace the tabled labeled "Integral Type Sizes" with the following table:

Integral Type Sizes
Type Length in Bytes Range
char
1 0 to 255 (EBCDIC character set)
signed char
1 -128 to 127
short
2 -32768 to 32767
unsigned short
2 0 to 65535
int
4 -2147483648 to 2147483647
unsigned int
4 0 to 4294967295
long (NOHUGEPTRS)
4 -2147483648 to 2147483647
unsigned long (NOHUGEPTRS)
4 0 to 4294967295
long (HUGEPTRS)
8 -9223372038854775808 to 9223372036854775807
unsigned long (HUGEPTRS)
8 0 to 18446744073709551615
long long
8 -9223372038854775808 to 9223372036854775807
unsigned long long
8 0 to 18446744073709551615

In Chapter 2, "Source Code Conventions," under the section titled, "Numerical Limits," replace the tabled labeled "Float and Double Type Sizes" with the following table:

Float and Double Type Sizes
Type Length in Bytes Range
float
4 +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-1.4E-45 to +/-3.4E38 (_ _binfmt)
double
8 +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-4.9E-324 to +/-1.8E308 (_ _binfmt)
long double
8 +/-5.4E-70 to +/-7.2E75 (_ _hexfmt)+/-4.9E-324 to +/-1.8E308 (_ _binfmt)


Updates to Language Extensions

In Chapter 2, "Source Code Conventions," under the section titled, "Language Extensions," the section titled, "Specifying floating-point constants in hexadecimal," should read:

SAS/C now supports the C99 hexadecimal format for floating-point numbers. The syntax is

0x<hexdecimal-digits>.<hexdecimal digits>P<binary exponent><suffixes>

A simple example of a C99 hexadecimal floating point constant is 1.AP-12. This constant has the value of 1+(10/16) times two to the minus twelfth power. The hexadecimal point is optional in the format, and only one of the two sequences of digits shown is required. For instance, 0xABCP14, 0xABC.P14 and 0x.ABCP14 are all valid hexadecimal floating-point constants. The hexadecimal digits and the letter P can appear in either upper or lower case. A suffix of F or L can follow a constant to indicate a float or long double constant. As a SAS/C extension, a suffix of B or H can also be used to indicate a _ _binfmt or _ _hexfmt constant. You can use both a C99 suffix and a SAS/C suffix on the same constant, for example, 0x0.C04P0FB.

Note:   If you use both suffixes, the SAS/C suffix must appear after the C99 suffix.  [cautionend]

Additionally, SAS/C continues to support its previous format for specifying floating-point numbers in hexadecimal. This format enables specification of the exact bit pattern of a floating-point constant. Unlike the C99 format, this format can be used to describe NaNs and infinities. The syntax is

0.x<hexadecimal digits>[.<suffixes>]

The indicated digits are stored exactly as specified in memory. If there are fewer than eight digits (for a float) or fewer than sixteen digits (for a double or long double), the remaining digits are considered to be zero. If any suffixes are present, they must be preceded by a period. A suffix of B or H can be used to specify the floating point format, and one of F or L can be used to specify float or long double. As with the C99 format, if both suffixes are used, the format suffix must come last. If there are no suffixes, the constant is assumed to be of type double, and to have the default format. A simple example of a SAS/C-format floating-point constant is 0.x7ff8.B, which represents the binary floating-point default quiet NaN.

Using Both IBM and IEEE Floating-Point Formats

In Chapter 2, "Source Code Conventions," under the section titled, "Language Extensions," following the section titled, "The #pragma map statement," add a new section titled "Using both IBM and IEEE floating-point formats" that contains the following text:

Most SAS/C programs will use only one format of floating-point number, either the traditional IBM mainframe format or the IEEE format. The choice between formats is made by specifying or omitting the BFP option. However, advanced programs and libraries might need to use both formats in a single compilation, or to support callers that use either format. This section describes the rules and special considerations required to use both floating-point formats.

The type modifiers _ _binfmt and _ _hexfmt can be used in floating-point type specifiers to indicate the floating-point format. Floating-point types without an explicit format specification have the default format, as determined by whether the BFP option was specified.

Floating-point constants can be specified with an H or B suffix to indicate hexadecimal or binary format respectively. Constants without a suffix are assumed to have the default format. A format suffix can appear in combination with a type suffix (F or L), but the format suffix must always come last.

A floating-point value can be converted from one format to another using a cast, assignment, or initialization. Conversion can also occur when an argument is passed to a function with a prototype, or when a function value is returned. Format conversions do not otherwise occur. For instance, adding a _ _binfmt double to a _ _hexfmt double is invalid. You should use a cast to clarify such expressions.

Conversions from hexadecimal format to binary format are performed according to the current IEEE rounding mode. Conversions from binary to hexadecimal format are exact for doubles, and for floats they are rounded according to the normal hexadecimal format rules. If the conversion cannot be performed, for example, the source is out of range or a NaN, the results are undefined and no signal or exception is raised.

When a function can be used from both BFP and NOBFP programs, its prototype should specify _ _binfmt or _ _hexfmt for each floating-point argument or for a floating-point return type. This will force a conversion to occur when the function is called from a compilation with the incorrect default.

The SAS/C math library is compatible with both formats. When a mathematical function such as exp is called, the version of the function used is the one specified by the BFP or NOBFP option. This is true whether or not math.h is included. If math.h is included, each floating-point function argument will be converted to the default format. If math.h is not included, it is the programmer's responsibility to pass data of the correct floating-point format. For a few low-level functions that are not particularly meaningful for hexadecimal floating point, such as isnan, if math.h is not included, the binary version is always called. Because C99 defines these functions as macros, it is technically undefined what happens if you attempt to use them without including the corresponding header file.

The symbols defined by the float.h header file always reference the default floating-point format, as determined by the presence or absence of the BFP option.

Updates to Floating Point (G.3.6)

In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," add the following updates to the section titled, "Floating Point (G.3.6).


Update to Registers (G.3.8)

In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," the first sentence in the section titled, "Registers (G.3.8)" should read:

There can be up to six integer or pointer register variables, and up to two floating-point register variables (up to eight if the ARCHLEVEL(C) compiler option is in effect).

Update to Library Functions (G.3.14)

In Chapter 2, "Source Code Conventions," under the section titled, "Implementation-defined Behavior," under the section titled, "Library Functions (G.3.14)," make the following changes to the list:


Updates to Arithmetic Data Types

In Chapter 3, "Code Generation Conventions," in the section titled, "Arithmetic Data Types," change the table labeled, "Data Type Characteristics," to the following:

Data Type Characteristics
Type Length Alignment Range
char 1 byte 0 to 255 (EBCDIC character set)
signed char 1 byte - 128 to 127
unsigned char 1 byte 0 to 255 (EBCDIC character set)
short 2 halfword - 32768 to 32767
unsigned short 2 byte 0 to 65535
int 4 word - 2147483648 to 2147483647
unsigned int 4 word 0 to 4294967295
long (NOHUGEPTRS)
4 word - 2147483648 to 2147483647
unsigned long (NOHUGEPTRS)
4 word 0 to 4294967295
long (HUGEPTRS)
8 doubleword -9223372038854775808 to 9223372036854775807
unsigned long (HUGEPTRS)
8 doubleword 0 to 18446744073709551615
long long
8 doubleword -9223372038854775808 to 9223372036854775807
unsigned long long
8 doubleword 0 to 18446744073709551615
float
4 word =/ - 5.4E - 79 to =/ - 7.2E75
double
8 doubleword =/ - 5.4E - 79 to =/ - 7.2E75
long double
8 doubleword =/ - 5.4E - 79 to =/ - 7.2E75
char

unsigned char

defines an 8-bit unsigned integer



signed char

short

short int

defines an 8-bit signed integer

defines a 16-bit signed integer

unsigned short

unsigned short int

defines a 16-bit unsigned integer



int
defines a 32-bit signed integer
long

long int

defines a 32-bit signed integer if the HUGEPTRS option is not specified, or a 64-bit signed integer if HUGEPTRS is specified.


unsigned

unsigned int

defines a 32-bit unsigned integer



unsigned long unsigned long int
defines a 32-bit unsigned integer if the HUGEPTRS option is not specified, or a 64-bit unsigned integer if HUGEPTRS is specified.


unsigned unsigned int
defines a 32-bit unsigned integer



long long
defines a 64-bit unsigned integer
unsigned long long
defines a 64-bit unsigned integer
_ _hexfmt float
defines a 32-bit signed floating-point number in the standard 370 representation, that is, a sign bit, a 7-bit biased hexadecimal exponent, and a 24-bit fractional part. The exponent bias is 64. All constants and results generated by compiled code are normalized (except for constants specified in hexadecimal notation). This representation is equivalent to approximately 6 or 7 decimal digits of precision.
_ _binfmt float
defines a 32-bit signed floating-point number in IEEE binary format, that is, a sign-bit, an 8-bit biased binary exponent, and a 23-bit fractional part with an implied leading 1. The exponent bias is 127. See the IBM 390 Principles of Operation for details on the representation of NaNs, infinities, denormalized numbers, etc. This representation is equivalent to approximately 6 or 7 decimal digits of precision.
_ _binfmt double _ _binfmt long double
defines a 64-bit signed floating-point number in IEEE binary format, that is, a sign bit, an 11-bit biased binary exponent, and a 52-bit fractional part with an implied leading 1. The exponent bias is 1023. See the IBM 390 Principles of Operation for details on the representation of NaNs, infinities, denormalized numbers, etc. This representation is equivalent to approximately 16 decimal digits of precision.
_ _hexfmt double _ _hexfmt long double
defines a 64-bit signed floating-point number in the standard 370 representation, that is, a sign bit, a 7-bit biased hexadecimal exponent, and a 56-bit fractional part. The exponent bias is 64. All constants and results generated by compiled code are normalized (except for constants specified in hexadecimal notation). This representation is equivalent to approximately 16 or 17 decimal digits of precision

In the same section, the two paragraphs following the table labeled, "Data Type Characteristics," should read:

Note that in contrast to the signed integer representations, negative floating-point numbers are not represented in two's complement notations; positive and negative numbers differ only in the sign bit.

In both floating-point formats, there are multiple representations of 0; in hexadecimal floating point, any value with a 0 fractional part is treated as zero, regardless of the exponent. Code that checks float or double objects for 0 by means of type punning (that is, examining the objects as if they were a nonfloating-point type such as int) might fail when the value is an unusual representation of 0, such as an IEEE negative zero.

Updates to Arithmetic Exceptions

In Chapter 3, "Code Generation Conventions," under the section titled, "Arithmetic Exceptions," add the following updates:


Updates to Register Conventions

In Chapter 3, "Code Generation Conventions," under the section titled, "Register Conventions," the second item in the list should read:

If the compiler option ARCHLEVEL(B) (or greater) is not specified, register 5 is the base register for the current function. If ARCHLEVEL(B) is in effect, register 5 is not reserved by the compiler, except during the prolog, and is assigned usage dynamically.


Updates to the CENTRY Macro

In Chapter 11, "Communication with Assembler Programs," add the following information to the section titled, "The CENTRY macro."

Change the form of a call to the CENTRY macro to:

     label         CENTRY DSA=dsa-size,
                        BASE=base-reg,
                        FNM=function-name,
                        STATIC=NO/YES,
                        INDEP=NO/YES,
                        LASTREG=last-reg,
                        STKBELOW=YES/NO,
                        BFP=YES/NO,
                        HUGEPTR=YES/NO,
                        AFPSAVE=afp-save-area,
                        AFPLAST=last-afp-reg,
                        HGRSAVE=hgr-save-area,
                        HGRLAST=last-hgr-reg

Add the following entries to the list of keywords:

STKBELOW=YES/NO
specifies whether the assembler routine requires its DSA be allocated below the 16-megabyte line. The default is STKBELOW=NO.

BFP=YES/NO
indicates whether the assembler routine should be marked as using BFP as the default floating-point format. The setting of the BFP keyword matters only if the assembler routine calls a C library function whose behavior depends on how its caller was compiled, such as printf or sqrt.

HUGEPTR=YES/NO
indicates whether the assembler routine should be marked as running in 64-bit addressing mode. The setting of the HUGEPTR keyword matters only if the assembler routine calls a C library function whose behavior depends on how its caller was compiled, such as printf or strtol. Note that CENTRY does not change the program's addressing mode. If your assembler code requires 64-bit addressing, you should change addressing mode yourself after completion of CENTRY.

AFPSAVE=afp-save-area
specifies the location of a save area where non-volatile auxiliary floating point registers used by the assembler routine are to be stored. (These are floating point registers 8 through 15.) If your assembler code modifies any of them, you must code the AFPSAVE keyword. The save area must be specified by a symbolic name, and must be allocated on a fullword boundary in the first 1024 bytes of the DSA. (If CENTRY specifies DSA=0, the save area must be located within the CRABTAUT work area.) The area must be large enough to save all the registers specified by the AFPLAST keyword. If you modify any of the non-volatile AFP registers, but do not specify the AFPSAVE keyword, ABENDs or floating-point errors are likely in any C code which executes after the assembler routine has returned.

AFPLAST=last-afp-reg
specifies the last non-volatile AFP register used by the assembler routine. The AFP registers are stored in order, starting with register 8. Thus, if you specify AFPLAST=10, floating point registers 8, 9 and 10 will be saved by CENTRY.

HGRSAVE=hgr-save-area
specifies the location of a save area where the high-order portions of the 64-bit general registers are to be stored. If your assembler code modifies any of them, you must code the HGRSAVE keyword. The save area must be specified by a symbolic name, and must be allocated on a fullword boundary in the DSA. (If CENTRY specifies DSA=0, the save area must be located within the CRABTAUT work area.) The area must be large enough to save the high-order portions of all the registers specified by the HGRLAST keyword. If you modify the high-order part of any register, but do not specify the HGRSAVE keyword, ABENDs are likely in any C code which executes after the assembler routine has returned.

HGRLAST=last-hgr-reg
specifies the last general register whose high-order portion is modified by the assembler routine. The high-order parts of the general registers are stored in order, starting with register 14. Thus, if you specify AFPLAST=6, the high-order portion of registers 14, 15 and 0 through 6 will be saved by CENTRY.


Updates to the CEXIT Macro

In Chapter 11, "Communication with Assembler Programs," add the following information to the section titled, "The CEXIT macro."

Change the form of a call to the CEXIT macro to:

     label        CEXIT RC=return-info/(reg),
                        DSA=YES/0,
                        INDEP=NO/YES,
                        LASTREG=lastreg,
                        MPSAFE=NO/YES,
                        AFPSAVE=afp-save-area,
                        AFPLAST=last-afp-reg,
                        HGRSAVE=hgr-save-area,
                        HGRLAST=last-hgr-reg,
                        HUGERC=NO/YES

Add the following entries to the list of keywords:

MPSAFE=NO/YES
specifies whether or not the application requires support for asynchronous signals in a multiprocessor environment. The default is MPSAFE=NO. MPSAFE=YES guarantees correct results even in the presence of asynchronous signals, but increases the overhead of CEXIT.

AFPSAVE=afp-save-area
specifies the location of the save area in which the CENTRY macro stored non-volatile AFP registers. See the description of the AFPSAVE keyword of CENTRY for more information.

AFPLAST=last-afp-reg
specifies the last non-volatile AFP register to be restored by CEXIT. The value must be the same as specified by the corresponding CENTRY call. See the CENTRY macro description for further information.

HGRSAVE=hgr-save-area
specifies the location of the save area in which the CENTRY macro stored the high-order portions of general purpose registers. See the description of the HGRSAVE keyword of CENTRY for more information.

HGRLAST=last-hgr-reg
specifies the last general register whose high-order portion is to be restored by CEXIT. The value must be the same as specified by the corresponding CENTRY call. See the CENTRY macro description for further information.

HUGERC=NO/YES
indicates whether the RC value is a huge (64-bit) pointer. If HUGERC=YES is specified, the HGRSAVE and HGRLAST keywords must also be specified.

Note:   The CEXIT macro does not change addressing modes. CEXIT cannot be executed in 64-bit addressing mode. It is the responsibility of the assembler routine to return to 31-bit addressing before issuing the CEXIT macro. Failure to observe this restriction is likely to cause difficult to diagnose ABENDs.  [cautionend]


Updates to the AR370 Archive Utility


Updates to AR370 Command Modifiers

In Appendix 2, "The AR370 Archive Utility," in the section titled, "Combinations of command and command modifier charecters," update the table labeled "Command and Command Modifier Combinations" with the -y command modifier as indicated below:

Command and Command Modifier Combinations
Command Accepted Modifiers and Commands
d e, f, j, q, t, v, y
m e, f, j, q, t, v, y and a | b
r e, f, j, q, t, v, y and a | b
t d, e, f, j, m, r, v, x, y
x e, f, j, t, v, y


Update to the AR370 INCLUDE Statements

In the section titled "AR370 INCLUDE Statements,"add the following caution at the end of the text.

CAUTION:
The new member name may be any name up to a maximum of 18 characters. It is strongly recommended that the name be a valid MVS PDS member name or data set name. Other names may be difficult to manipulate with the AR370 utility.   [cautionend]

Update to Optional Modifier Characters

In the section titled "Optional Modifier Characters," add the following entry to the list of characters:
w Used in conjunction with the replace (r) command to allow truncation of member names at 18 characters.


Update to the SYSARWRK Data Definition

In Appendix 2, "The AR370 Archive Utility," under the section titled, "AR370 JCL requirements," add the following text at the end of the section:

If SYSARWRK is not specified, a temporary work data set will be used that is defined with the minimum size that is allowed. To avoid running out of space in this temporary data set, allocate SYSARWRK with adequate space to handle your data set. SYSARWRK will be used then instead of the default work data set.


Enhancements to the All-Resident C Programs

In Chapter 10, "All-Resident C Programs," update the the section titled, "Restrictions," with the following information:


Update to the _branch, _bbwd, and _bfwd Functions

In Chapter 13, "Inline Machine Code Interface," in the section titled, "Functions," update the CAUTIONS sections of the _branch, _bbwd, and _bfwd functions with the text indicated for each function.

_branch

Note:   The _branch function should not be used to branch to a label defined in a different built-in code sequence, especially one in a different block. This action may cause a compiler error or incorrect results at execution time.  [cautionend]

_bbwd

Note:   The _bbwd function should not be used to branch to a label defined in a different built-in code sequence, especially one in a different block. This action may cause a compiler error or incorrect results at execution time.  [cautionend]

_bfwd

Note:   The _bfwd function should not be used to branch to a label defined in a different built-in code sequence, especially one in a different block. This action may cause a compiler error or incorrect results at execution time.  [cautionend]


Update to the oeabntrap Function Description

In Chapter 14, "Systems Programming with the SAS/C Compiler," in the section titled, "The SPE Library," replace the oeabntrap example with the following example:

#include <oespe.h>
#include <unistd.h>
#include <lclib.h>
#include <string.h>
#include <setjump.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 */
    struct 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;
    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;
}


Updates to the pow Function Example

In Chapter 4, "Optimization," in the section titled, "Using inline functions to generate optimized code," replace the example code for the pow function with the following code:

#include <lcdef.h> [1]   
#include <math.h> [2]   
#undef pow [3]   
#define pow(x, p) power(x, p, isnumconst(p)) [4]   

static __inline double power(double a, double p, int p_is_constant)
{

      /* Test the exponent to see if it's   */
      /*  - a compile-time integer constant */
      /*  - a whole number                  */
      /*  - nonnegative                     */
   if (p_is_constant && (int) p == p && (int) p >= 0) { [5]   

      int n = p;

           /* Handle the cases for 0 <= n <= 4 directly. */
   [6]      if (n == 0) return 1.0;
         else if (n == 1) return a;
         else if (n == 2) return a * a;
         else if (n == 3) return a * a * a;
         else if (n == 4) return (a * a) * (a * a);

            /* Handle 5 <= n <= 16 by calling power            */
            /* recursively.                                    */
            /* Note that power is invoked directly, specifying */
            /* 1 as the value of the p_is_constant argument.   */
            /* This is because the isnumconst macro returns    */
            /* "false" for the expressions (n/2) and           */
            /* ((n+1)/2), which would defeat the optimization. */
   [7]      else if (n <= 16)
         return power(a, (double)(n/2), 1) *
                      power(a, (double)((n+1)/2), 1);

            /* Handle n > 16 via a loop.  The loop below       */
            /* calculates (a ** (2 ** x))                      */
            /* for 2 <= x <= n and sums the results for each   */
            /* power of 2 that has the corresponding bit set   */
            /* in n.                                           */
   [8]      else {
         double prod = 1.0;
         for (; n != 0; a *= a, n >>= 1)
            if (n & 1) prod *= a;
         return prod;
      }
   }

      /* Finally, if p is negative or not a whole number, */
      /* call the library pow function.  The pow macro    */
      /* is defeated by surrounding the name "pow" with   */
      /* parentheses.                                     */
   else [9]   
      return (pow)(a, p);
}


Update to the description of the long long Data Type

In Chapter 2, "Source Code Conventions," replace the tenth and eleventh paragraghs of the section titled, "Description of the long long Data Type," with the following text.

One way in which the SAS/C long long implementation differs from the C99 standard is in the interpretation of decimal constants. According to C99, a decimal constant that is too large to fit into a long, such as 3000000000 on the mainframe, should be assumed to be a long long. According to the 1989 ANSI/ISO standard, the type of this constant is unsigned long. SAS/C continues to treat any such constant within the range of unsigned long as unsigned long, to avoid changing the meaning of existing programs. This behavior is compatible with most compilers for other platforms that support a long long type.

The C99SUBSET option will cause unsuffixed decimal constants to be interpreted with C99 rules, that is, they can never be unsigned. You can use the standard C language suffixes to control the type of a decimal constant. For example, 3000000000UL will have a type of unsigned long regardless of compiler options, but 3000000000 will have a type that depends on compiler option settings: long long (C99SUBSET, NOHUGEPTRS), long (HUGEPTRS), or unsigned long (default options).


Update to the rtconst Option Description

In Chapter 7, "Linking C Programs," under the section titled, "COOL Options," add the following text to the description of the rtconst option.

Usually the run-time constant section can be removed without affecting normal program execution. However, a very large function compiled with the archlevel(b) option (or greater) may require the run-time constant CSECT to be present to execute correctly. COOL will preserve the run-time constant section for a compilation including such a function, even if rtconst has been specified.


Update to the enforce, mention, and suppress Option Descriptions

In Chapter 6, "Compiler Options," in the section titled, "Option Descriptions," the descriptions of the enforce, mention, and suppress options need to be updated to remove the information stating that "Only warnings in the range 0-199 and 300-499 are affected."


Updates to the #pragma Options

In Chapter 6, "Compiler Options," in the section titled, "The #pragma options statement," add the following options to the list of #pragma options:
armode
indep
sname(value)


Update to the ENXREF COOL Option Description

In Chapter 7, "Linking C Programs," in the section titled, "COOL Options," replace the third paragraph of the enxref description with the following text.

You can use the references option (-Areferences under USS) to modify the behavior of the sname, cid, or linkid cross-reference listing so that unresolved external references are included in the cross-references listing. You must use the references option in conjunction with one or more of these listing options: sname, cid, or linkid. For example:

enxref(sname references)

specifies an sname cross-reference listing that includes cross-references for external symbols that are declared but not defined.


Updates to the COOL Options Tables


COOL Options (Short Forms)

The following table contains corrections to the table labeled, "COOL Options Equivalents," in Chapter 7, "Linking C Programs."

COOL Options Equivalents
Long Form Short Form
auto -a
clet -m
clet(all) -m
clet(noex) -mn
continue -zc
cxx -cxx
dupsname -zd
endisplaylimit -ynnnn
enexit -xt
enexitdate (xxx) -xt xxx
enxref (cid) -xxx
enxref (linked) -xxe
enxref (references) -xxy
enxref (sname) -xxs
extname -xn
files (xxx) -f xxx
gmap -yg
inceof -zi
libe -b
lineno -l
list -yl
noenxref -!xx
output fileid -o fileid
pagesize (nn) -s nn
prem -p
print -h
prmap -yp
rtconst -r
smpjclin -sj
smponly -sxo
smpxivec -sx
term -t
upper -u
verbose -zv
warn -w
xfnmkeep -xf
xsymkeep -xe


COOL Options

The following table contains corrections to the table labeled, "COOL Options," in Chapter 7, "Linking C Programs."

COOL Options
Option TSO CMS OS/390 Batch USS
-Agather


X
-Ainsert


X
allresident X X
X
arlib X


auto X X X
-Bep


X
-Blib


X
cics X X
X
cicsvse X X
X
clet X X X X
clet(all) X X X X
clet(noex) X X X X
continue X X X X
cxx X X

dupsname X X X X
endisplaylimit X X X X
enexit X X X X
enexitdata X X X X
entry X


enxref X X X X
extname X X X X
files

X
genmod
X

global
X

gmap X X X X
gos X X

inceof X X X X
-1


X
-L


X
lib X


libe
X

lineno X X X X
list X X X X
lked
X

lkedname X
X
load X

X
loadlib X


nocool X
X
output
X

pagesize X X X X
prem X X X X
print X X
X
prmap X X X X
rtconst X X X X
smpjclin X X X X
smponly X X X X
smpxivec X X X X
spe X X
X
start
X

term X X X
upper X X X X
verbose X X X X
warn X X X X
xfnmkeep X X X X
xsymkeep X X X X


Update to the _O_SNAME Symbol

In Chapter 6, "Compiler Options," in the section titled, "Preprocessor Symbols," add the following text to the explanation of the _O_SNAME option that follows the table labeled, "Preprocessor Symbols."

If you use the compiler sname option to set the _O_SNAME preprocessor symbol, it has an affect similar to using a #define preprocessor directive to define the symbolic name _O_SNAME. You cannot actually use a #define directive to define _O_SNAME. You must use the compiler sname option. Attempting to set the _O_SNAME symbol with a #define preprocessor directive will result in an LSCC133 error.


Update to the <resident.h> Documentation

In Chapter 10, "All-Resident C Programs," in the section titled, "Using <resident.h>," remove the note at the end of the section that reads,

Note:   The dollars compiler option must be used when compiling a C++ source file that contains <resident.h>.  [cautionend]
and replace it with the following text.

The dollars compiler option is no longer required when compiling a C++ source file that includes <resident.h>.


Updates to the SPE Functions

In Chapter 14, "Systems Programming with the SAS/C Compiler," in the section titled "The SPE Library," add the following functions to the table of SPE functions.

gethostbyaddr*
gethostbyname*
htonl
htons
IARV64
inet_addr
inet_lnaof
inet_makeaddr
inet_netof
inet_network
inet_ntoa
ntohl
ntohs
osdltok
osgttok
ossttok
WTP

After the section titled "HFS Access," create a new section titled "TCP/IP Access," and move the last paragraph of the section titled "HFS Access" into the new section. The paragraph to be moved reads:

SPE supports access to USS integrated sockets using the standard UNIX socket interface functions such as socket, accept, read, write, and so on. Note that only integrated sockets can be accessed. Starting with z/OS 1.2, the TCP/IP resolver functions; gethostbyname and gethostbyaddr are supported. However, other resolver type functions such as res_init and getservbyname are not supported because USS does not provide system calls for these functions.


Chapter Contents

Previous

Next

Top of Page

Copyright © 2004 by SAS Institute Inc., Cary, NC, USA. All rights reserved.