C Info (26 August 1980) --- C --- C is an implementation language, similar to BCPL except with data types. It is the primary language used on Unix systems. This implementation runs under the ITS and TOPS-20 operating systems. This implementation is moderately compatible with the Unix C implementation. However, the Unix system calls are NOT implemented. Some portions of the UNIX Standard I/O library are implemented by C10STD. See C10STD.C (in on XX, and in ITS machines in the C; directory) for details. Further information is available from Eliot Moss (EBM @ XX). --- Compiling --- CC is the C compiler command. Usage is :cc file1.c file2.c ... (more on pathnames below in I/O discussion) where the arguments are the path names of C source files which are to be compiled. Each file will be compiled in turn, and if the compilation is successful, the resulting relocatable file will be placed in the file "file*.stk". Arguments beginning with the '-' character are taken to be compiler options. Available options include: -c compile only, do not assemble -g do not delete MIDAS file -x syntax check only -s produce symbol table (not very useful) -b compile big function (FUNCTION TOO LARGE) For example, the command :cc foo.c would compile the C program in the file "foo.c" in the current directory, and place the resulting relocatable program in the file "foo.stk". --- Loading --- Relocatable programs produced by the C compiler are loaded together with the C support routines using the STINKR loader. To load program files "foo", "bar", and "bletch" and produce a runnable file "foo", type the following to STINKR: x c/clib l foo l bar l bletch o ts.foo ^@ The ^@ (ASCII NUL) terminates the terminal input file. These commands (minus the ^@) could also be written in a file, say "foo.stinkr", in which case one could invoke STINKR by saying :stinkr foo and STINKR would read the commands from the command file. --- Library --- The above STINKR commands will load in a set of library routines for performing I/O, etc. Here is an introduction to that library (the source files, which are in on XX, are the definitive documentation). Here are some handly declarations for use below: char c; /* an ASCII character */ int i, n, cc; /* an integer */ int *p; /* an integer pointer */ int b; /* a boolean */ char *s, *s1, *s2; /* strings */ char *fn; /* a file name or a path name (defined below) */ FILE *fd; /* a "file descriptor" (can be declared INT) */ /* I/O routines -- see also C10IO, C10MIO */ /* COPEN - opens an I/O channel */ fd = copen (fn, mode, options); /* open file */ char *fn; /* file name */ char mode; /* 'r', 'w', or 'a' (append) */ char *options; /* 0 (char I/O), "s" (string file), "b" (binary) */ /* for string file, pass string as fn */ /* returns - if open fails */ /* Other routines: */ cprint (fd, s, a1, a2, ...); /* print s on fd */ /* s is printed on the output file fd. If fd is not supplied, it defaults to cout, the standard output, i.e., cprint ("foo", ...) defaults fd to cout. s may contain format descriptors, of the following forms: %c - print a character %d - print an integer in decimal %o - print an integer in octal %s - print a string %z - print N copies of a character (N supplied via field width - read on) These use the other arguments, a1, a2, etc., in order. For example, cprint (fd, "%c plus %d equals %s.\n", '2', 1+1, "4") results in 2 plus 2 equals 4. The format letter may be preceded by a number, giving the minimum field width. The output is normally right justified in the field, but is left justified in a field of size at least N if -N is given as the width. Spaces are the normal padding character, used to fill out if the argument does not fill the specified number of columns. If a '0' character immediately follows the '%', then '0' will be used as the padding character. If the character following the '0' is not a digit, then it will be used as the padding character instead of '0'. Here are some examples of cprint (s, 312): s = "%d" ==> 312 s = "%9d" ==> 312 s = "%09d" ==> 000000312 s = "%0*9d" ==> ******312 s = "%-0*9d" ==> 312****** s = "%o" ==> 470 For a more complete explanation, read CPRINT.C. It is even possible to define your own formats, etc. */ c = cgetc (fd); /* get character (text input) */ c = cputc (c, fd); /* put character (text output) */ /* Note: these are redundant because cgetc and cputc do the right thing for binary files */ i = cgeti (fd); /* get integer (binary input) */ i = cputi (i, fd); /* put integer (binary output) */ ungetc (c, fd); /* push unit back on input stream */ /* Several (but not very many) units may be pushed back on any channel. */ b = ceof (fd); /* indicates whether the channel is at end of file; always FALSE for output. */ cflush (fd); /* flush the buffer -- writes any not yet written output */ cclose (fd); /* close channel, after doing a cflush for any buffered output */ c = getchar (); /* cgetc (cin); */ s = gets (s); /* reads from cin until a newline, storing into s. Returns the original argument; does not store the newline. */ putchar (c); /* cputc (c, cout); */ puts (s); /* writes all of s to cout, and a newline afterwards */ /* FILENAMES -- see also C10FNM */ /* The standard ITS format filenames are supported, with the following terminology: dev:dir;name type dev - device dir - directory name - first file name type - second file name All these components are stored WITHOUT punctuation, as sixbit words, once parsed. UNIX format ("pathnames") is also supported, for ease in designing programs to run on more than one of TOPS20, ITS, UNIX, and VAX/VMS. The interpretation is as follows: /dev/dir1/name.type converts to dev:dir;name type If there is no leading /, there is no dev part. The available routines are described below. */ fnparse (old, dev, dir, nm, typ, gen, attr) char *old, *dev, *dir, *nm, *typ, *gen, *attr; /* parses a name into its components; the gen and attr components will always be null, but are there for generality of interface to other operating systems. */ char *fngdv (old, buf) char *old, *buf; char *fngdr (old, buf) char *old, *buf; char *fngnm (old, buf) char *old, *buf; char *fngtp (old, buf) char *old, *buf; char *fnggn (old, buf) char *old, *buf; char *fngat (old, buf) char *old, *buf; /* extract the relevant component only */ fncons (buf, dev, dir, nm, typ, gen, attr) char *buf, *dev, *dir, *nm, *typ, *gen, *attr; /* construct a filename (ITS format) from its components */ char *fnsdf (buf, old, dv, dir, nm, typ, gen, attr) char *old, *buf, *dv, *dir, *nm, *typ, *gen, *attr; /* buf is set to contain a new filename with the supplied components substituted for null components of the filename in old */ char *fnsfd (buf, old, dv, dir, nm, typ, gen, attr) char *old, *buf, *dv, *dir, *nm, *typ, *gen, *attr; /* buf is set to contain a new filename with the supplied components substituted for components of the filename in old. This is different from fnsdf in that non-zero component arguments (dv, dir, etc.) are substituted even if old is not null in the corresponding field. */ /* a FILESPEC is a structure containing the 4 components as sixbit integers ... */ fparse (old, fs) char *old; filespec *fs; /* parse a filename, handles both ITS and UNIX formats */ prfile (fs, buf) filespec *fs; char *buf; /* converts the filespec to a string, inserting standard punctuation */ /* STORAGE ALLOCATION */ p = salloc (n); /* allocate n words, return pointer to it */ sfree (p); /* free storage allocated by salloc */ s = calloc (n); /* allocate n characters, return ptr to it */ cfree (s); /* free storage allocated by calloc */ /* In this implementation words and chars are the same; but it is bad style to depend on it, for some day packed strings might be implemented ... */