DECUS C LANGUAGE SYSTEM Compiler & Library Software Support Manual Runtime Support Library Reference Manual by Martin Minow Edited by Robert B. Denny This document describes the RSX/POS/VMS/RSTS/RT11 DECUS C lang- uage system runtime support library. It also contains all in- ternal functions and such compiler internal information as is available. DECUS Structured Languages SIG Version of 28-July-1984 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. The standard installation procedure yields two documents. The Runtime Support Library Reference Manual describes how to use the C library. The Compiler and Library Software Support Manual contains all user documentation plus additional information on the internals of both the library and the C compiler. This is the Software Support Manual. This release is the first to support the RMS-11(V2) file system. The runtime library may optionally be built to use RMS. If this is done, the advantages are compatibility across DECnet between RSX, POS and VMS systems, and transparent remote DECnet file access. RMS is the preferred system for use on MICRO-RSX and P/OS. CHAPTER 2 THE STANDARD LIBRARY This manual describes the DECUS C "standard I/O" package. It was developed with the idea of maintaining maximum compatibility with the UNIX Version 7 environment and maximum portability between Digital operating systems. This release (28-July-1984) of the library can be built for use on RSX-11 (and friends) and P/OS to use either FCS-11 or RMS-11(V2) record I/O systems. FCS-11 is the traditional record I/O package used on RSX and the RSTS/RSX emulator. In the last several years, however, the RMS-11 system has undergone a major overhaul, the result of which is a very complete, reasonably fast record I/O package. P/OS (the Professional 300 series operating system) and MICRO-RSX are oriented toward RMS-11. Both systems are shipped with the RMS resident shared library (called RMSRES) genned into the system. You might as well use it if you can afford the loss of 8K words (2 APR's) of virtual address space. It is possible to use RMS without RMSRES but your task image will be larger than it would if you used FCS. NOTE The RMSRES shared library is "vectored". What this means is that the entry points are kept in a fixed table at the base of the region, and their locations are guaranteed not to change with successive releases of RMS. So you can build tasks against RMSRES without the worry that the task will fail if the library is revised. One other bit of trivia ... RMSRES on P/OS, MICRO-RSX, RSX-11M and M-PLUS and, yes, even RSTS/E (V8 & later) have IDENTICAL vectoring. The native RSX library build command file MMAKLB.COM gives you the choice of building the FCS or RMS flavors of the library. This manual describes the DECUS C "standard i/o" package. It was developed with the idea of maintaining maximum compatibility with the UNIX Version 7 environment and maximum portability C Runtime Support Library Page 2-2 Reference Manual between Digital operating systems. Also, if you are on an RSX-11M, RSX-11M PLUS or MICRO-RSX system, you should see your system mangler and find out if (s)he has installed the FCS or RMS flavor of the standard I/O library. If you don't know what all of this means, don't worry. Your only concern is what is needed to link programs. It is different for RMS or FCS. All C programs should be linked together with the run-time support library. On systems that support logical device descriptors, this will generally be stored in the C: logical device/account. On RSX-11M, the library will be found in LB:[1,1]. On PRO/Toolkit (native P/OS) the library will be found in LB:[1,5]. To link a C program, proceed as follows: RSX (FCS flavor): LINK/CHECK/OPT/EXE:task objects+LB:[1,x]C/LIB RSX/POS (RMSRES flavor): LINK/CHECK/OPT/EXE:task objects+LB:[1,x]C/LIB Option? STACK=1024 Option? LIBR=RMSRES:RO Option? RT11 & TSX+ R LINK *save,map=objects,C:SUPORT,C:CLIB/B:2000 *^C Note that, on RSX-11M, the task should be built checkpointable. This is automatic on RSTS/E and VMS emulated modes. On native RSX-11M, the task-builder may be rebuilt with /CHECKPOINT as the default. If the /CHECKPOINT option is not given, the task may abort (no memory) when started. Stack extension is needed if subroutines locally allocate large amounts of data or if RMSRES is in use. The easiest way to handle this is to make a command file for linking. On RT11, note that the '/B' (bottom) switch must be given to increase the size of the run-time stack. This is needed as local variables are allocated on the stack. If the stack size is not increased, the program may abort without any error message. The standard I/O interface header file is in C:STDIO.H, or LB:[1,1]STDIO.H on native RSX-11 or LB:[ZZDECUSC] on POS PRO/Toolkit, and should be included in all C programs as follows: #include C Runtime Support Library Page 2-3 Reference Manual WARNING If you are using the RMS flavor of the standard I/O package, there is an alternate header file that describes the modified "iov" for RMS. It is called RMSTDIO.H. Programs which make use of the "secret" fields in the iov must use RMSTDIO.H. Otherwise, STDIO.H is fine. 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 - Interaction with host operating system - DECnet considerations (RMS only) 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 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) C Runtime Support Library Page 2-4 Reference Manual 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. (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. C Runtime Support Library Page 2-5 Reference Manual 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) { ccount++; 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 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() C Runtime Support Library Page 2-6 Reference Manual 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 and in some cases two different record I/O packages (FCS and RMS). The possiblities include: Operating systems: o Native RT11 o Native RSX-11M, RSX-11M PLUS, IAS and MICRO-RSX o P/OS (Professional 350 operating system) o RT11 emulated on RSTS/E o RSX-11M emulated on RSTS/E o RSX-11M emulated on VAX/VMS Record I/O systems (RSX, RSTS, P/OS) o Native FCS-11 (RSX and friends) o FCS-11 emulated on RSTS/E(RSX) o Native RMS-11 (RSX, P/OS, RSTS/E(RSX)) 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: o On RT11, console terminal interaction uses the .ttyout and .print monitor functions. While no device is opened by the fopen() function, a 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 C Runtime Support Library Page 2-7 Reference Manual 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. 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 File and Directory Names ____ ___ _________ _____ Unfortunately, each operating system has its own way of naming files and directories. Programs written with portability in mind should NOT make assumptions about the format or structure of file names. 2.5.3 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' will not work, for instance. The algorithm in fwild() depends C Runtime Support Library Page 2-8 Reference Manual on the directory being sorted, as 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. With FCS, wild-card devices, units, directory names, or UIC codes are not supported. With RMS, wildcard directory names and UIC's are allowed, except with remote (DECnet) files. Note that VMS V4 may support RMS-11(V2) under the (optional) AME. 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 file specification 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.4 DECnet Remote File Access ______ ______ ____ ______ If you are using the RMS version of the standard I/O library, your applications automatically have access to files on remote nodes on DECnet. As is the case on the VAX (RMS-32), the new RMS-11 provides transparent DECnet (DAP) remote file access. What this means to you is that you can develop distributed applications in DECUS C if you use the RMS flavor of the library. This is true of both RSX & friends and RSTS/E. If your network consists of a mixture of host types, such as VAXen, RSTS and RSX systems, remote file access can give you some surprises. Most of the quirks are listed in your system's DECnet "Cross System Notes". On RSX and P/OS, the DECnet remote file capability presents some interesting capabilities. For example, you may give full remote file specifications on the command line when redirecting stdin and stdout: $ FOO TT2>