JPL C library 21-MAR-81 JPL C library This documents the JPL C runtime library. It is intended to be compatible with `A new input-output package' on unix as far as is pratical and still compatible with other i/o created under RSX. It was created with the following goals in mind. 1. It should permit an efficient implementation of unix style i/o on an RSX system. Thus it needs to do its own disk buffering. 2. It should be compatible with RSX. 3. It should permit floating point using the Whitesmiths compiler. Note however, that Whitesmiths does not support the standard i/o libary and the decus library does not support floating point or true Unix i/o (i.e. efficient array of bytes concept). 4. It should be compatible with other routines supplied with any of the C librarys except where i/o is concerned. It is intended that this package be used when the package of disk virtual memory routines is used or if Unix compatibility is desired. The library also contains several general purpose string maniputulation and list management routines. As a convenience, it also contains all the math routines generated inline by the Whitesmiths compiler. The supported command line features are: >file redirect output (create next higher version) >file redirect output to end of file >=file redirect output into file (or create if no file) "..." quoted arguments (for imbeded spaces, tabs etc) Each program using the library must have the line #include which defines certain macros and variables. The library containing the routines is [1,1]jplclib.olb which is included in the task build file as ll:[1,1]jplstart,jplclib/lb If other routines from other c librarys are to be used, the references to those libraries must follow the above. For example: sample,sample/-sp = sample ll:[1,1]jplstart,jplclib/lb !this must be first ll:[1,1]clib/lb,picslo/lb !then these may occur / stack=1000 -1- JPL C library 21-MAR-81 JPL C library libr=fcsres:ro // The following names may be referenced by users: stdin The external variable containing a file pointer for standard input stdout The external variable containing a file pointer for standard output EOF The value -10 as returned by the RSX file system for end of file. NULL The value 0 or what a null pointer would contain RELATIVE The value -1 or what is used in get/put at routines FILE A type definition for a file variable. Note that the user would always declare any file variable as a pointer, e.g. FILE *fd; Calls The routines in the library are in nearly one-to-one correspondence with those in the standard Library. In several cases the names has been changed. This is an attempt to reduce confusion. FILE *fopen(filename,type,class) char *filename, *type *class Fopen opens the file and, if needed, allocates a buffer for it. Filename is a character string specifying the name. Type is a character string (not a single characataer). It may be "r","w", "u", or "a" to indicate intent to read, write, update or append. The value returned is a file pointer. If it is NULL the attempt is open failed. The value of class may be "r" or "u". If "r", then record i/o is used otherwise unstructured (an array of bytes) i/o is implemented. "u" i/o uses multiple buffers which are linked in a least recently used list such that disk i/o is kept to a minimum. The number of buffers may be set after the open (but before any i/o) using the function `lrumax' described below. When the type is spelled out (e.g. "read", "write" etc.) then if an error occurs on the open, a message will be output to the ti: terminal. When the type is write, a new version of a file is always created. When the type is update, an attempt on the old file is tried first followed by a creation if no file existed. If the old file exists but cannot be accessed, then an error condition is raised. FILE *freopen(filename,type,ioptr) char *filename, *type;FILE *ioptr The stream named by ioptr is closed, if necessary, and then -2- JPL C library 21-MAR-81 JPL C library reopened as if by fopen. If the attempt to open fails, NULL is returned, otherwise ioptr, which will now refer to the new file. Often the reopened stream is stdin or stdout. int getc(ioptr) FILE *ioptr returns the next character from the stream named by ioptr, which is a pointer to a file such as returned by fopen, or the variable stdin. The integer EOF is returned on end-of-file or when an error occurs. The null character '\O' is a legal character for unstructered i/o, but is not possible in record i/o. putc(c,ioptr) FILE *ioptr Putc writes the character c on the output stream named by ioptr, which is a value returned from fopen or perhaps stdout or stderr. The value 1 is returned if all is ok, or a small negative value is returned on error. fclose(ioptr) FILE *ioptr The file corresponding to ioptr is closed after any buffers are emptied. A buffer allocated by the IO system is freed. Fclose is automatic on normal termination of the program. fflush(ioptr) FILE *ioptr Any buffered information on the (output) stream named by ioptr is written out (but the file otherwise remains in the same state.) exit(errcode) Exit terminates the process and returns its argument as status to the parent. All open files are automatically closed before the actual exit. feof(ioptr) FILE *ioptr returns non-zero when end-of-file has occurred on the specified input stream. ferror(ioptr) FILE *ioptr returns a negative number when an error has occurred after call to fopen or 1 if all is ok. This value is in an external variable which is set by the fopen routine and remains available until another fopen call. getchar() is identical to getc(stdin). putchar(c) is identical to putc(c,stdout). char *gets(s) char *s -3- JPL C library 21-MAR-81 JPL C library reads characters up to a new-line from the standard input. The new-line character is replaced by a null character. It is the user's re- sponsibility to make sure that the character array s is large enough. Gets returns its argument, or NULL if end-of-file or error occurred. Note that this routine is not compatible with fgets; it is included for downward compatibility. char *fgets(s,n,ioptr) char *s; FILE *ioptr reads up to n characters from the stream ioptr into the character pointer s. The read terminates with a new-line character. The new-line character is placed in the buffer followed by a null character. The first argument, or NULL if error or end-of-file occurred, is returned. puts(s) char*s writes the null-terminated string (character array) s on the standard output. A new-line is appended. No value is returned. Note that this routine is not compatible with fputs; it is included for downward compatibility. *fputs(s,ioptr) char*s; FILE *ioptr writes the null-terminated string (character array) s on the stream ioptr. No new-line is appeneded. No value is returned. ungetc(c,ioptr) FILE *ioptr The argument character c is pushed back on the input stream named by ioptr. Only one character may be pushed back. This is only implemented for "r" class files (see fopen 3rd parameter). printf(format,al,...) char*format fprintf(ioptr,format,al,...) FILE *ioptr; char *format sprintf(s,format,al,...) char *s, *format Printf writes on the standard output. Fprintf writes on the named output stream. Sprintf puts characters in the character array (string) named by s. Usage printf(format, arg1, ...); char *format; fprintf(iov, format, arg1, ...); FILE *iov; char *format; sprintf(buffer, format, arg1, ...); char *buffer; char *format; -4- JPL C library 21-MAR-81 JPL C library Description printf() converts, formats, and prints its arguments, under control of the first argument, writing output via putchar(). fprintf() writes its output to the indicated file. sprintf() writes its output to the indicated string buffer. The first argument is a character string which contains two types of objects: plain characters, which are simply copied to the output stream, and conversion specifications, each of which causes conversion and printing of the next successive argument to printf. Each conversion specification is introduced by the character %. Following the %, there may be - an optional minus sign "-" which specifies left adjustment of the converted argument in the indicated field. - an optional digit string specifying field width; if the converted argument has fewer characters than the field width, it will be blank-padded on the left (or right, if the left-adjustment indicator has been given) to make up the field width. If the field width is specified as '*' or '?', the next argument is used. (Note: '?' is obsolete.) - an optional period "." which serves to separate the field width from the next digit string; - an optional digit string (precision) which specifies the number of digits to appear after the decimal point for e- and f-conversion, or the maximum number of characters to be printed from a string. If the precision is specified as '*' or '?', the next argument is used. - a character which indicates the type of conversion to be applied. The conversion characters and their meanings are d Signed-decimal u Unsigned-decimal o Octal X Hexadecimal, 10-15 are represented by A-F x Hexadecimal, 10-15 are represented by a-f The integer argument is converted to decimal, octal, or hexadecimal notation respectively. Any of the conversion characters may be preceeded by 'l' to signal "long" integer argument. Note that the Unix usage of capital letters to represent long arguments is not supported. f The argument is converted to decimal notation in the style "[-]ddd.dd" where the number of d's after the decimal point equals the precision specification for -5- JPL C library 21-MAR-81 JPL C library the argument. If precision is missing, 6 digits are given; if explicitly 0, no digits and no decimal point are printed. The argument should be float or double. e The float or double argument is converted in the style "[-]d.ddde+-dd" where there is one digit before the decimal point and the number after is equal to the precision specified for the argument; if the precision is missing, 6 digits are produced. g Floating point of some sort. c The argument character is printed. (Note that 'lc' takes a long integer argument.) r Remote format. The next printf() argument is the format. Note that this is not a subroutine. The current format is not processed further. For example: bug(args) { error("Error at %r", &args); } This routine might be called as follows: bug("Error %d at %s\n", val, name); s The argument is taken to be a string (character pointer) and characters from the string are printed until a null character or until the number of characters indicated by the precision specification is reached; however if the precision specification is 0 or missing all characters up to null are printed. If no recognizable character appears after the %, that character is printed; thus % may be printed by the use of the string %%. In no case does a non-existant or small field width cause truncation of a field; padding takes place only if the specified field width exceeds the actual width. Characters generated by printf() are printed by calling putchar(). %r may be non-transportable. scanf(format,al,...) char*format fscanf(ioptr,format,al,...) FILE *ioptr;char *format sscanf(s,format,al,...) char*s,*format Scanf reads from the standard input. Fscanf reads from the named -6- JPL C library 21-MAR-81 JPL C library input stream. Scanf reads from the character string supplied as s. The specifications are identical to those of the Portable Library. Scanf reads characters, interprets them according to a format, and stores the results in its arguments. It expects as arguments a control string format, described below, and a set of arguments, each of which must be a pointer, indicating where the converted input should be stored. Scanf returns as its value the number of successfully matched and assigned input items. This can be used to decide how many input items were found. On end of file, EOF is returned; note that this is different from O, which means that the next input character does not match what was called for in the control string. Usage scanf(fmt, pointer(s)); char *fmt; /* Format string */ fscanf(fd, fmt, pointer(s)); FILE *fd; /* Input file pointer */ char *fmt; /* Format string */ sscanf(buf, fmt, pointer(s)); char *buf; /* Input text buffer */ char *fmt; /* Format string */ Description Using the format string, these functions parse the input file (or given text file), storing the results in the pointer arguments. The three routines differ as follows: scanf Reads from the standard input file. fscanf Reads from the indicated file. sscanf Reads from the text buffer. The format string may contain control characters to direct the conversion of the input textual data: ' ' Blanks, tabs, or newlines are ignored in format strings. To match whitespace, use "%[ \t\n]". x An ordinary character (not %) must match the next input character. % Conversion specifications consist of a '%', an optional '*' (to supress assignment), an optional maximum numeric field width, and a conversion specifier. -7- JPL C library 21-MAR-81 JPL C library Unless value assignment was supressed by the '*' format modifier, the next field is converted and stored in the variable pointed to by the corresponding argument. An input field is defined as a string of non-space characters, extending to the first inappropriate character or until the field width (if given) is exhausted. The following conversion characters are specified: % A single '%' is expected in the input, no assignment is done. d An integer of the specified class (decimal, octal, or o hexadecimal) is expected. The corresponding argument x should be an integer pointer. If the format specifer is given in upper-case, or preceeded by 'l', a long integer will be stored. For example, "%ld" is identical to "%D". Leading whitespace will be ignored. A null field is not converted. Scanf() returns a count of the number of fields converted, but does not indicate which fields were ignored. s A character string is expected. The input field will be terminated by a space, tab, or newline. The corresponding argument should point to a buffer large enough to contain the text and a terminating NULL. Leading whitespace will be ignored. c A single character is read. Leading white space is not supressed -- to read the next non-blank character, use "%1s". If a field width is given the corresponding argument is a pointer to a vector of characters and the indicated number of characters are read. e A floating-point number is converted and stored f appropriately. If the format indicator is capitalized, or preceeded by 'l', a double- precision floating-point number will be stored. The floating-point format is the same as in the C language: an optionally signed string of digits possibly containing a decimal point, followed by an optional exponent field which consists of an 'E' or 'e' followed by an optionally signed integer. [ ] A string not to be delimited by white-space characters. Unless the first character is '^', the format constitutes an acceptance list: the input field is all characters until the first character which is not in the set within brackets. Note that leading whitespace is not ignored. If the first character after the left bracket is '^', the format defines a stop list: the input field is all characters until the first character specified -8- JPL C library 21-MAR-81 JPL C library within the bracketed string. The corresponding argument points to a character vector. The result will be null-terminated. Scanf() returns the number of successfully matched and assigned input items. If the end of input was reached, EOF (-1) is returned. For example: main() { register int c; int i; char text[10]; c = scanf("%d%9s", &i, &text); printf("i = %d, text = %s\n", i, text); } If the input line is "150 foobar", the program will print: i = 150, text = foobar For example, the call int i; float x; char name [50]; scanf ("%d%f%s", &i, &x, name); with the input line 25 54.32E-1 thompson will assign to i the value 25, x the value 5.432, and name will contain "thompson\O". Or, int i; float x; char name [50] scanf ("%2d%f%d%[1234567890]",&i, &x, name); with input 56789 0123 56a72 will asisgn 56 to i, 769.0 to x, skip "0123", and place the string "56\O" in name. The next call to getchar will retrun 'a'. Diagnostics Scanf() returns -1 if an end of file (end of string) condition exists and no data was stored. It returns -2 if a palpably incorrect format, such as "%" is encountered. getat(ioptr,disk,var,size) FILE *ioptr; long disk; char *var; int size -9- JPL C library 21-MAR-81 JPL C library Retreives size bytes from file ioptr into variable var at location disk in the file. If disk is RELATIVE then the seek to location disk is suppressed, i.e. the transfer starts from where the i/o left the seek pointer. putat(ioptr,disk,var,size) FILE *ioptr; long disk; char *var; int size Transfers size bytes into file ioptr from variable var at location disk in the file. If disk is RELATIVE then the seek to location disk is suppressed, i.e. the transfer starts from where the i/o left the seek pointer. -10- JPL C library 21-MAR-81 JPL C library The following general purpose routines are also available in the library. char *alloc(size) int size This allocates some space from the heap. If no space is available NULL is returned. The space allocated is alligned properly for any data type. char *cat[s,a,b,c...,#0] char *s,*a,... This copies a into s then appends b,c... to s. Enough storage to hold all the strings is the responsibility of the caller. Returns pointer to end of string s. char *moveb[a,b,n] char *a,*b; int n: moves n chars from a to b returns pointer to next char in b (where a null usually goes). scopy[a,b] char *a,*b copies b into a; b must be big enough. eq[a,b,n] char *a,*b; int n; compares n chars returns 0=if the strings are different and 1 if they are identical. This version of eq is case sensitive. fields(string,vector) char *string, *vector[] This routine finds character fields and returns pointers to them. It also places a null at the end of each field (thus it destroys the original string). fields are delimeted by: whitespace comma slash back slash colon fields can be quoted as follows: {...} ^x...x where x is arbitrary "..." '...' char *i2a(i,a) int i; char *a; converts i into ascii at a. Returns pointer to end of ascii string where a null would go. However, the null is not placed in the output. lfield(string,vector) char *string, *vector[] Small version of fields routine. Only recognizes fields separated by whitespace and commas. -11- JPL C library 21-MAR-81 JPL C library pos(in,of,st) char *in,*of; int st; finds position in 'in' of 'of' starting the search at the 'st'-th character position in 'in'. returns 0 if not found else position. e.g. pos["in-here","he",#1] returns 4 val(s,base) char *s; int base; returns the binary value of the ascii string in s. Base may be 2-10. may have a '-' sign for two's compliment of resultant value. seg(s,in,from,too) char *s,*in; int from,too; extracts segment in 'in' positions 'from' to 'to'. Result into s returns length of s strlen(s) char *s; Returns the length of a null terminated string. system(s) char *s; spawns s with stop for; returns 1st word of exit status. time(s) char *s; return time as a string looks like: dd/mm/yy hh:mm:ss The following routines manage doubly linked lists of variable length. ilist(lhead) int lhead[3]; Initialize a list head. List heads are 6 byte arrays where the 1st word is initialized to the address of the listhead itself, the 2nd and 3rd words are the links. If there was any data in this node then it would have been at word 4. Word one points to this location. All nodes look like: data[0] right link data[1] left link pointers->data[2-n] data A listhead looks like: lhead[0] pointer-to-data in list ----| lhead[1] pointer-to-right-link | lhead[2] pointer-to-left-link | lhead[3..n] nothing allocated here <---| Then the listhead array is used by referencing the contents of the first element which points to the first node. This value is usually placed in another pointer. A three word list head is not really necessary but is convenient for the case of a zero length list. Thus no -12- JPL C library 21-MAR-81 JPL C library special checking needs to be done when deleting the last element of a list. Also, the first word of the three is actually a listhead to the other two in the 3 word array. example: int lh[3]; char *head; head = ilist(lh); char *delete(ptr) char *ptr Deletes the node ptr from the list it is in. Returns ptr which is now a doubly linked list of one element. char *insert(x,newx) char *x,*newx Inserts the node newx after the node x in the list x is in. returns pointer newx. char *prev(ptr) char *ptr Returns a pointer to the previous node in the list. char *next(ptr) char *ptr Returns a pointer to the next node in the list. char *release(ptr) char *ptr This releases storage for the node pointed to by ptr. char *new(size) int size Allocates a node for a structure of size "size". Also allocates storage for the link fields (which precede the storage of "size" bytes. The pointer returned points to the start of the data (not the links which are a -2 and -4 from the data). Note that release must be used to return storage allocated by new since each of these routines know about the extra 4 bytes of linkage. New also initializes the link fields such that the node is a complete list of one item. ldump(listhead) char *listhead This performs a quick dump of a doubly linked list using printf. it outputs all the pointers and the first word of each node (not the listhead). -13- JPL C library 21-MAR-81 JPL C library The following macros are defined: #define abs(x) ((x < 0) ? -(x) : (x)) #define isalpha(c) (islower(c) || isupper(c)) #define isdigit(c) ('0' <= (c) && (c) <= '9') #define islower(c) ('a' <= (c) && (c) <= 'z') #define isupper(c) ('A' <= (c) && (c) <= 'Z') #define iswhite(c) ((c) <= ' ' || 0177 <= (c)) /* ASCII ONLY */ #define max(x, y) (((x) < (y)) ? (y) : (x)) #define min(x, y) (((x) < (y)) ? (x) : (y)) #define tolower(c) (isupper(c) ? ((c) + ('a' - 'A')) : (c)) #define toupper(c) (islower(c) ? ((c) - ('a' - 'A')) : (c)) See the Whitesmiths manual for descriptions if necessary. -14-