DECUS C LANGUAGE SYSTEM Runtime Support Library Reference Manual by Martin Minow Edited by Robert B. Denny This document describes the RSX/VMS/RSTS/RT11 DECUS C language system runtime support library. DECUS Structured Languages SIG Version of 11-Nov-83 NOTE This software is made available without any support whatsoever. The person responsible for an implementation of this system should expect to have to understand and modify the source code if any problems are encountered in implementing or maintaining the compiler or its run-time library. The DECUS 'Structured Languages Special Interest Group' is the primary focus for communication among users of this software. UNIX is a trademark of Bell Telephone Laboratories. RSX, RSTS/E, RT11 and VMS are trademarks of Digital Equipment Corporation. CHAPTER 1 INTRODUCTION The C support library contains three major groups of functions: o Functions called by the compiler to perform certain mathematical operations (such as floating-point multiply or function entrance) that are not performed in-line. o Functions that may be called by C programs to perform operations, such as copying a string, that are more efficiently performed by optimized assembly language subroutines. o An implementation of (most of) the Unix Standard I/O library. CHAPTER 2 THE STANDARD LIBRARY The RSX standard run-time library is in LB:[1,1]C.OLB. The RT11 standard run-time library is in C:CLIB.OBJ. WARNING This version of the library is somewhat incompatible with previous versions of the Decus C compiler. This incompatibility allows greater compatibility with Unix Version 7, and the capability of generating global references and definitions containing the radix-50 '$' and '.' characters. The standard I/O interface header file is in C:STDIO.H, or LB:[1,1]STDIO.H and should be included in all C programs as follows: #include 2.1 INTRODUCTION TO UNIX-STYLE STREAM I/O This section presents an overview of the 'standard' I/O interface for C programs. These routines have proven easy to use and, while they do not provide the full functionality of RSX or RMS, they give the programer essentially all that is needed for everyday use. The discussion includes the following: - Opening and closing files - Reading data from files - Writing data to files Note that this file system is limited: files are sequential with only a limited amount of random-access capability. Also, little of the power of RMS/FCS is available. On the other hand, the limitations make C programs easily transportable to other C Runtime Support Library Page 2-2 Reference Manual operating systems. When a C program is started, three files are predefined and opened: stdin The 'standard' input file stdout The 'standard' output file stderr The 'standard' error file Stderr is always assigned to the command terminal. Stdin and stdout are normally assigned to the command terminal, but may be reassigned or closed when the program starts. 2.2 OPENING AND CLOSING FILES The fopen and fclose functions control access to files. They are normally used as follows: #include /* Define standard I/O */ FILE *ioptr; /* Pointer to file area */ ... if ((ioptr = fopen("filename", "mode")) == NULL) error("Can't open file"); All information about an open file is stored in a buffer whose address is returned by fopen(). The buffer is dynamically allocated when the file is opened and deallocated when the file is closed. Its format is described under the heading IOV. The mode string contains flags defining how the file is to be accessed: r Read only w Write new file a Append to existing file (or write new) (Doesn't work on RT11 modes). It also defines some record-control information: n No newlines mode ('binary' files) u RSX: The user program allocates record buffers RT11: Console output is done using .ttyout If mode 'n' is specified, the RSX I/O routines do not interpret the end of a RMS logical record as defining the end of a human-readable line. This is necessary to process 'binary' information. On RT11, the I/O routines do not remove carriage-returns from input files, nor do they insert carriage-returns when newlines are output. Mode 'u' is treated differently on RSX and RT11. If specified on RSX the user maintains the file's record buffer. The program may only call the fget() and fput() routines. Each such call will be translated directly to an RMS/FCS GET$ or PUT$ call. C Runtime Support Library Page 2-3 Reference Manual (In RT11 mode, fput() may be used to write binary records which are subsequently read by fget(). The file should be opened with 'n' mode.) If mode 'u' is specified on RT11 mode when opening the console terminal, single character output will be performed (using the RT11 monitor routine .ttyout). If not specified, output will be one line at a time (using the monitor routine .print). The library initialization process opens stderr in mode 'u' and stdout in normal mode. This means that mixing I/O to both units will result in synchronization problems. To obtain single-character output on stdout, the program need simply execute: if (freopen("tt:", "wu", stdout) == NULL) error(""); The program calls fclose(ioptr) to terminate processing on a file. This closes the file and reclaims system-controlled buffer space. fmkdl(ioptr) may be called to close and delete an open file. 2.3 READING DATA FROM A FILE The simplest way to read a file is to call the getchar() or getc() routines which read the next character from a file. For example, the following program counts the number of characters in a file: #include main() { register int ccount; register int lcount; register int c; FILE *ioptr; if ((ioptr = fopen("foo.bar", "r")) == NULL) error("Cannot open file"); ccount = 0; lcount = 0; while ((c = getc(ioptr)) != EOF) { count++; if (c == '\n') lcount++; } printf("%d characters, %d lines.\n", ccount, lcount); } Other input routines include: gets Read a line from the standard input fgets Read a line from a file fgetss Read a line from a file, remove terminator C Runtime Support Library Page 2-4 Reference Manual ungetc Push one character back on a file fseek Position the file to a specific record These routines are used together with the ferr() and feof() functions which allow testing for error and end of file conditions, respectively. The package assumes that all error conditions are lethal and force end of file. 2.4 WRITING DATA TO A FILE There are several routines for data output which are directly analagous to the data input routines: putchar Write a character to standard output putc Write a character to a specified file puts Write a string to the standard outpt fputs Write a string to a specified file fputss Write a record to a specified file ftell Return record location (for fseek) In addition, the printf() or fprintf() routine is used to format and print data (as was shown in the previous example). Printf() is flexible, powerful, and easy to use; and is perhaps the single most important routine in the file system. 2.5 INTERACTION WITH THE OPERATING SYSTEM The support library attempts to provide a consistant operating system interface on several implementations of quite different operating systems. The possiblities include: o Native RT11 o Native RSX-11M or IAS o RT11 emulated on RSTS/E o RSX-11M emulated on RSTS/E o RSX-11M emulated on VAX/VMS This section mentions the inconsistencies and random bugs that are more or less intentionally present. 2.5.1 Logical Unit Numbers RT11, RSTS/E, and RSX-11M use small integers to number all I/O channels. Unfortunately, the numbering is not consistent and channel usage differs among the various systems. This has resulted in several quirks: C Runtime Support Library Page 2-5 Reference Manual o On RT11, console terminal interaction uses the .ttyout and .print monitor functions. While no device is opened by the fopen() function, an channel number is reserved. o On RSX-11M, a channel must be allocated to the console terminal. When a C program starts, the 'command terminal' is opened on logical unit 1 and assigned to stderr. This is not done using the fopen() routine (although the stderr IOV structure is defined as if fopen() were called). Also, fclose() cannot close stderr. In addition to the standard I/O routines, there are two routines, msg() and regdmp(), that direct output to logical unit 1. These routines were used to debug the library, and are otherwise useful for disasters. Note that, on RT11, msg() and regdmp() use the .print monitor function. o On both systems, the first true files are stdin and stdout. These are opened on logical units 0 and 1 (RT11) or 2 and 3 (RSX). Code in fclose() double-checks that the logical unit number of the file being closed corresponds to the proper slot in the logical unit table. o Since the standard I/O routines know little about the operating system, they do not deal with certain special features. For example, on RT11, the 'user service routine' (USR) is used to open files. The file open routine does not attempt to locate IOV areas so that the USR does not swap over them. This can be a problem for very large programs. On RSX, logical unit numbers are assigned dynamically. This means that 'LUN assignment' cannot be reliably performed by task-build control files (or task initiation). 2.5.2 Wild-Card Files The fwild() and fnext() routines can be used to process 'wild-card' files. On RSX-11M and VMS/RSX emulation, the file name, extension, and/or file version may be expressed as '*' to indicate wild-card support. Due to restrictions in the RSX-11 Files-11 structure (ODS1), the ' ', ';0' and ';-1' version numbers will NOT function properly on native RSX-11. This means that '*.MAC' C Runtime Support Library Page 2-6 Reference Manual will not work, for instance. The algorithm in fwild() depends on the directory being sorted, as it is in the ODS2 file structure used on VAX/VMS. If you sort the directory to be used in an fwild() operation (use the SRD program available from DECUS with the /WB switch) in order of decreasing file version numbers, then the " ", ";0", and ";-1" versions will work. Wild-card devices, units, or UIC codes are not supported. Note that, on RSX11 emulated on VMS, the ';-1' (earliest version) requires special processing by the user program, as noted in the description of fwild(). On RSX-11M emulated on RSTS/E, the file name and/or extension may contain '*' or '?' wild-cards. Wild-card devices, units, or UIC (PPN) codes are not supported. On RT-11, the file name and/or extension may contain '*', '%' or '?' wild cards. The '?' wild-card is synonymous with '%'. Wild-card devices, or units are not supported. Since wild-card support is not an RT-11 system service, the filespec parsing and directory operations are handled by the C library fwild() and fnext() functions. The fwild/fnext module requires about 480 words of storage. Also, a file opened by wild-card uses a 1024 byte buffer, twice the normal size, which is shared between data and directory operations. 2.5.3 Memory allocation Memory is allocated using the malloc() function. It works correctly on all operating systems, expanding memory on RSX and RT11/RSTS. On 'native' RT11, all available memory is allocated by invoking the monitor .settop function with a '-2' argument. Neither library supports extended memory (PLAS) directives. The sbreak() routine may be used for permanent allocation of memory. Once memory has been allocated using sbreak(), it cannot be freed. CHAPTER 3 LIBRARY FUNCTION DESCRIPTIONS This chapter contains descriptions of each of the C-callable runtime library functions. In most cases the I/O functions match those of UNIX V7 closely, with differences normally called out. For more information, consult "The C Programming Language" by Brian Kernighan and Dennis Ritchie (Englewood Cliffs, NJ: Prentice-Hall, ISBN 0-13-110163-3). abs Integer absolute value abs(val) int val;