C Calling Conventions

The following program illustrates how to declare and call two standard C library functions, "atoi" and "strtol":

int atoi(const char *str)

long strtol(const char *str, char **endptr, int base)

Please note the following points:

  1. Since C is case-sensitive and PL/I is not, use EXTERNAL('name') to map the PL/I name to the function's real name.
  2. Since C arguments are passed by immediate value, specify the BYVALUE attribute for FIXED BINARY parameters.
  3. Because PL/I arguments are normally passed by reference, the BYVALUE attribute is not necessary for char * arguments declared CHARACTER(n). However, when a char * argument is declared POINTER, as in the ATOI_2 declaration, the BYVALUE attribute is required.
  4. By convention, C strings are terminated with a NULL byte.
  5. In this example, although char * is declared CHARACTER(80), any length long enough to hold the string and a terminating null byte would be all right. Of course, if the C function expected a pointer to a character string of a certain length, the PL/I and C declarations should agree.
  6. Note the use of the z-character constants for compatibility with C-style null-terminated strings, and the use of the SYSNULL() built-in, which returns 0, as opposed to the NULL() built-in, which returns -1 by default.
    CALLC: PROCEDURE OPTIONS(MAIN); 
    
    DECLARE
    
    ATOI   ENTRY(CHARACTER(80))
           RETURNS(FIXED BINARY(31)) 
           EXTERNAL('atoi'),
    
    ATOI_2 ENTRY(POINTER BYVALUE)
           RETURNS(FIXED BINARY(31)) 
           EXTERNAL('atoi'),
    
    STRTOL ENTRY(CHARACTER(80),
                 POINTER BYVALUE,
                 FIXED BINARY(31) BYVALUE) 
           RETURNS(FIXED BINARY(31)) 
           EXTERNAL('strtol'),
    
    BASE   FIXED BINARY(31),
    ENDPTR POINTER,
    INT    FIXED BINARY(31),
    LONG   FIXED BINARY(31),
    STR    CHARACTER(80),
    STRPTR POINTER;
    
    STR    = '2147483647'z;
    INT    = ATOI(STR);
    
    PUT SKIP LIST(INT);
    
    STRPTR = ADDR(STR);
    INT    = ATOI_2(STRPTR);
    
    PUT SKIP LIST(INT);
    
    STR    = '0x7fffffff'z;
    ENDPTR = SYSNULL();
    BASE   = 16;
    LONG   = STRTOL(STR, ENDPTR, BASE);
    
    PUT SKIP LIST(LONG);
    
    PUT SKIP LIST(STRTOL('0x7fffffff'z, SYSNULL(), 16));
    
    END CALLC;