KCC Runtime Library documentation This file summarizes the overall contents of the KCC C library, and is used by implementors as a status file to determine the portability or availability of particular library functions. This file does NOT document what the functions do or how to use them, because this information is already available in published form (see [CARM] and [UPM] at the end of this page). The organization of routines here follows that of the descriptions in Part II of [CARM]. Note that as of this writing there are two versions of CARM; the first (v1) appeared in 1984, and the second (v2) in 1987. All references here are to the most recent (v2) version, and the organization of this file follows sections 13-22 of v2 rather than section 11 of v1. KCC implements all CARM routines. In addition, there are other routines which are part of KCC's C library, either for compability with Un*x systems like V7 and BSD, or to provide access to certain operating system functions. For the most part these have been listed in whichever CARM section below is most appropriate, right after the "official" CARM functions. Additional information: [CARM] Book: "C: A Reference Manual", Second edition, ISBN 0-13-109802-0 by Samuel P. Harbison & Guy L. Steele, Jr. Also known as "H&S". This is a very good reference and describes most of the library functions. [UPM] Book: "Unix Programmer's Manual". 4.2/4.3BSD version (Reference Guide) printed by the USENIX Association. [MAN] Files: "man foo" on most Un*x systems. [TMX] File: LIBTMX.DOC - documents the extended time functions, time_*(). [USYS] File: USYS.DOC - contains a summary of those particular KCC functions which simulate UN*X system calls. This is considerably more implementor-oriented. [SIGS] File: SIGNAL.DOC - contains an overview of the KCC signal implementation. [LIBC] File: LIB/CODING.DOC - describes guidelines for writing KCC library functions and identifies certain crucial files. This is primarily for implementors. Contents summary: Section 13: Standard Language Additions Section 14: Character Processing (V1: Sec 11.1) Section 15: String Processing (V1: Sec 11.2) Section 16: Memory Functions Section 17: Input/Output Facilities (V1: Sec 11.5) Section 18: Storage Allocation (V1: Sec 11.4) Section 19: Mathematical Functions (V1: Sec 11.3) Section 20: Time and Date Functions Section 21: Control Functions Section 22: Miscellaneous Functions Section BSD(3N): BSD network functions Section TRM(3X): TERMCAP terminal independent functions Section TMX(3X): Time and Date Functions (Extended) Section KCC-1: KCC-specific general-purpose functions Library function listing format: Name Module Port Comments (routine name) (source file) (see below) Name: Name of the function, variable, or macro. Module: Source file module. "XXX" means the pathname "lib/XXX.C" unless the section identifies a different source directory, such as "usys/" or "stdio/", etc. Header files are shown as "". Port: A status code indicating portability, as follows: E = file #includes "c-env.h" for environment configuration. - runs on the given sys, one of: T20,10X,T10,WAITS,ITS. *10 = portable to all of the above PDP-10 systems. * = fully portable (either no OS-dependent stuff, or a fully-portable conditional exists) Section 13: Standard Language Additions Name Module Port Comments NULL , * typedef ... ptrdiff_t; * typedef ... size_t; * int errno; usys/URT * (see USYS.DOC) char *strerror(errnum); STRERR E T20,10X void perror(s); stdio/PERROR E T20,10X int sys_nerr; STRERR * char *sys_errlist[]; STRERR * constant EDOM; * constant ERANGE; * __DATE__ in KCC * __FILE__ in KCC * __LINE__ in KCC * __TIME__ in KCC * __STDC__ NOT YET (in KCC) va_alist,va_dcl * KCC Non-ANSI form va_list,va_start,va_arg,va_end * KCC Non-ANSI form va_list,va_start,va_arg,va_end * KCC ANSI form Notes: All CARM facilities are supported, but __STDC__ is not defined and will not be until KCC can provide full ANSI support. This of course must wait until the ANSI draft standard becomes more concrete. The standard set of UN*X error codes are provided, in particular EDOM and ERANGE. All others apply only to failing UN*X system call simulations. Both and are provided. Since they are incompatible, they cannot be used together and only one of them can be included by any particular program. Section 14: Character Processing (V1: Sec 11.1) Src: , lib/ctype.c Name Module Port Comments int isalnum(c); CTYPE * int isalpha(c); CTYPE * int isascii(i); CTYPE * CARM/BSD int iscntrl(c); CTYPE * int iscsym(c); CTYPE * CARM only int iscsymf(c); CTYPE * CARM only int isdigit(c); CTYPE * int isodigit(c); CTYPE * CARM only int isxdigit(c); CTYPE * int isgraph(c); CTYPE * int isprint(c); CTYPE * int ispunct(c); CTYPE * DIFFERENT (no space!) CARM goofed. int islower(c); CTYPE * int isupper(c); CTYPE * int isspace(c); CTYPE * int iswhite(c); - - rare variant of isspace, not provided. int toascii(i); CTYPE * CARM/BSD int toint(c); CTYPE * CARM only int tolower(c); CTYPE * allows any case int toupper(c); CTYPE * allows any case int _tolower(c); CTYPE * CARM only int _toupper(c); CTYPE * CARM only Tests: LIB/TEST/TCTYPE.C tests all these functions. Notes: All CARM facilities are supported; must be included. All work with any unsigned 9-bit character value and EOF; most are macros and very fast. None evaluate their argument more than once. The ispunct() function differs from the CARM description, which claims that "space" is included in the set. Neither the BSD nor the ANSI draft version of ispunct() does this however, so we have assumed that H&S made a mistake here, and the KCC version excludes "space". BSD's implementation of tolower and toupper is incorrect (corresponds to _tolower and _toupper). KCC's corresponds to CARM. Implementation notes: The flag table is large enough that any unsigned 9-bit char value can be safely used as index. On the PDP-10 the table is an integer array for speed, and is fully portable, but the macro _CT_TABTYPE can be defined during installation if a char array is preferable. defines all of the macros. CTYPE.C defines the _ctyp1 and _ctyp2 tables, plus some small auxiliary routines that the macros may call. Section 15: String Processing (V1: Sec 11.2) Src: , lib/ Name Module Port Comments char *strcat(s1,s2); STRING * char *strncat(s1,s2,n); STRING * int strcmp(s1,s2); STRING * int strncmp(s1,s2,n); STRING * char *strcpy(s1,s2); STRING * char *strncpy(s1,s2,n); STRING * int strlen(s); STRING * char *strchr(s,c); STRING * char *index(s,c); STRING * synonym for "strchr" int strpos(s,c); STRING * CARM only char *strrchr(s,c); STRING * char *rindex(s,c); STRING * synonym for "strrchr" int strrpos(s,c); STRING * CARM only int strspn(s,set); STRING * int strcspn(s,set); STRING * char *strpbrk(s,set); STRING * char *strrpbrk(s,set); STRING * CARM only char *strstr(src, sub); STRING * CARM/ANSI only char *strtok(str, set); STRING * ANSI/BSD/S5/CARM (not V7) double strtod(str, ptr); ATOI * long strtol(str,ptr,base); ATOI * unsigned long strtoul(str,p,b); ATOI * double atof(str); ATOI * int atoi(str); ATOI * long atol(str); ATOI * Additional non-CARM functions: Non-case-sensitive versions of the above functions are provided by the STRUNG module, declared in : int strCMP(s1, s2); STRUNG * int strnCMP(s1, s2, n); STRUNG * char *strCHR(s, c); STRUNG * char *strSTR(src, sub); STRUNG * Tests: LIB/TEST/TSTRIN.C partially tests these functions. Notes: All CARM facilities are supported. must be included. also exists for BSD compatibility; it merely includes . Implementation notes: This stuff can use more conditionalizing in order to optimize for specific configurations. The routines are portable, but are coded to encourage use of the PDP-10 ILDB/IDPB instructions (opposite of the optimal PDP-11 order!) Section 16: Memory Functions Src: lib/ Name Module Port Comments char *memchr(ptr,val,len); MEMSTR E * ANSI/BSD/CARM/S5 int memcmp(ptr1,ptr2,len); MEMSTR E * ANSI/BSD/CARM/S5 int bcmp(ptr1,ptr2,len); MEMSTR E * BSD/CARM (calls memcmp) char *memcpy(dest,src,len); MEMSTR E * ANSI/BSD/CARM/S5 char *memccpy(dest,src,c,len); MEMSTR E * BSD/CARM/S5 void *memmove(dest,src,len); MEMSTR E * ANSI/ CARM (needs optimiz) char *bcopy(src,dest,len); MEMSTR E * BSD/CARM (calls memcpy) char *memset(ptr,val,len); MEMSTR E * ANSI/BSD/CARM/S5 void bzero(ptr,len); MEMSTR E * BSD/CARM (calls memset) Tests: LIB/TEST/TBCOPY.C tests bcopy() and bzero(). Notes: All CARM facilities are supported. The header file for declaring these routines is as per ANSI, but also exists for BSD compatibility. These are guaranteed to work for all valid KCC byte sizes, i.e. any of 6, 7, 8, 9, and 18-bit bytes. Remember that the arguments must be of type (char *), rather than (int *). Both memcpy() and memset() have special optimization built into them so that they are very fast for large amounts of data. memmove() is much slower. Section 17: Input/Output Facilities (V1: Sec 11.5) Src: lib/stdio/ Name Module Port Comments constant EOF; * struct FILE; * FILE *fopen(path,typ); FOPEN * See notes on next page. int fclose(fp); FCLOSE * int fflush(fp); FFLUSH * also works on input streams FILE *freopen(path,typ,fp); FREOPE * int setvbuf(fp,buf,type,size); SETBUF * void setbuf(fp,buf); SETBUF * FILE *stdin; (m) * FILE *stdout; (m) * FILE *stderr; (m) * int fseek(fp,off,typ); FSEEK * long ftell(fp); FTELL * void rewind(fp); REWIND * int fgetc(fp); FGETC * int getc(fp); (m) * int getchar(); (m) * int ungetc(c,fp); UNGETC * char *fgets(s,n,fp); FGETS * char *gets(s); GETS * int fscanf(fp,fmt,ptrs); SCANF * int scanf(fmt,ptrs); SCANF * int sscanf(s,fmt,ptrs); SCANF * int fputc(c,fp); FPUTC * int putc(c,fp); (m) * int putchar(c); (m) * int fputs(s,fp); FPUTS * int puts(s); PUTS * int fprintf(fp,fmt,args); PRINTF * int printf(fmt,args); PRINTF * int sprintf(s,fmt,args); PRINTF * int vfprintf(fp,fmt,arg); PRINTF * int vprintf(fmt,arg); PRINTF * int vsprintf(s,fmt,arg); PRINTF * int fread(ptr,siz,cnt,fp); FREAD * int fwrite(ptr,siz,cnt,fp); FWRITE * int feof(fp); (m) * int ferror(fp); (m) * void clearerr(fp); (m) * int remove(filename); REMOVE * just calls unlink() int rename(oldnam,newnam); RENAME * null file, uses USYS rename(). FILE *tmpfile(); TMPFIL * char *tmpnam(buf); TMPNAM E T20,10X char *mktemp(buf); MKTEMP E T20,10X uses HPTIM%, not getpid These functions were recently added to the ANSI C draft (not yet implemented): int fgetpos(FILE *stream, fpos_t *pos); ?? int fsetpos(FILE *stream, const fpos_t *pos); ?? Additional STDIO functions for V7/BSD compatibility: constant BUFSIZ; * V7/BSD constant NULL; * V7/BSD FILE *fdopen(fd,type); FDOPEN * V7/BSD open w/existing FD int fileno(fp); (m) * V7/BSD int getw(fp); GETW * V7/BSD Get word (int) int putw(w,fp); PUTW * V7/BSD Put word (int) void setbuffer(fp,buf,size); SETBUF * BSD void setlinebuf(fp); SETBUF * BSD do linebuffering Additional KCC functions: FILE *sopen(s,type); SOPEN * (KCC only) open string for I/O Internal globals, not for user consumption: FILE _sios[]; * internal array void _cleanup(); CLEANU * called by exit() for cleanup Tests: LIB/TEST/TFSEEK.C, TFTEL1.C, TFTEL2.C - tests fseek/ftell LIB/TEST/TPRINT.C - tests printf. Notes for Section 17 (STDIO): See <.LIB.STDIO>-READ-.-THIS- for implementation-specific details. Note that some facilities, in particular putc and getc, are implemented as macros. In general, the sequence CR-LF is converted to LF on 7-bit input, and LF converted to CR-LF on 7-bit output. This conversion is performed by the system call read/write functions and not by STDIO, however. See the notes on fopen() below for details. [17.2] (V1 11.5.7) fflush(): This should normally only be called on an output stream; however, if called on an input stream, fflush() flushes any buffered but unread data. This feature is probably not portable. [17.2] (V1 11.5.10, 11.5.15) fopen(), freopen(): These implement all the H&S type specification characters, with certain defaults and settings appropriate for the PDP-10 world: String Mode Start Description "r", "rb" R 0 Open existing file for reading. Error if not found. "w", "wb" W 0 Create a new file for writing. "a", "ab" W EOF Append to existing file (create new if necessary). "r+","r+b" R/W 0 Open existing file for updating. Error if not found. "w+","w+b" R/W 0 Create a new file for updating. "a+","a+b" R/W EOF Append to existing file (create new if necessary). Note that on TOPS-20 and TENEX, files have version numbers, and writing a file never truncates an existing one; "w" and "w+" always create new versions. A stream can be either "text" or "binary", as per the ANSI draft description; a "b" in the string specifies binary. The characteristics of the two types of streams are: Bytesize(old) Bytesize(new) LF-conversion TEXT or 7 7 yes if size 7 BINARY or 9 9 no, never When an OLD, existing file is opened (for reading, appending, or updating), normally the bytesize of the file is used as the bytesize of the stream. If the file bytesize is 7, 8, or 9 then that size is used. If the file bytesize is 0 or 36 then the default (7 or 9) is used instead. If the file bytesize is anything other than 0, 7, 8, 9, or 36 then the behavior is undefined. When a NEW file is created, its bytesize will be that of the stream, which is normally 7 for text, 9 for binary. Note that older versions of a file may have a different bytesize -- the notion of checking these to set the bytesize was considered, but rejected in the interest of simplicity. Whether LF conversion is performed on the stream is a little simpler. A text stream is only converted if the stream bytesize is 7; otherwise conversion does NOT happen. A binary stream is never converted, regardless of the bytesize. The user can override either the bytesize or the conversion by adding explicit specification characters, which should come after any regular specification characters: "C" Force LF-conversion. "C-" Force NO LF-conversion. "7" Force 7-bit bytesize. "8" Force 8-bit bytesize. "9" Force 9-bit bytesize. "T" Open for thawed access (TOPS-10/TENEX only) These are KCC-specific however, and are not portable to other systems. Note that the actual LF conversion is done by the USYS (Unix simulation) level calls (read() and write()) rather than STDIO. [17.5] fseek(), ftell(), rewind(): For binary streams (no LF conversion), the I/O pointer value returned by ftell() and used in fseek() is the same as the USYS (and T20) pointer value; arithmetic can be done on this pointer to derive new pointers as arguments to fseek(). However, for text streams when LF conversion is being done, the I/O pointer value is a composite which cannot be manipulated; the argument to fseek() can only be 0 or a value previously returned by ftell() for that stream. This corresponds to the restrictions described in H&S. fseek() does not yet work for "+" text streams (i.e. LF-converted streams open for both reading and writing). [17.6] (V1 11.5.34) ungetc(): The number of characters that can be pushed back with ungetc is a site-dependent option available at library compile-time. _SIO_NPBC in STDIO.H defaults to 1. [17.8] (V1 11.5.16, 11.5.28, 11.5.30) fscanf(), scanf(), sscanf(): Common sense was used in implementing the various conversion routines when there was doubt about CARM's description: For numeric conversions ('d', 'u', 'o', 'x', 'f'), there must be at least one digit present for the parse to succeed, despite CARM's claim that "some number" of digits, "possibly none" are allowed. For string scanners ('s' and '['), at least one character must be read. [17.11] (V1 11.5.11, 11.5.23, 11.5.29) printf(), fprintf(), sprintf(): An additional facility has been provided for the user to assign his own conversion specification character to arbitrary functions. This function is "prf_bind()" in module PRINTF, which should be seen for details. Unfortunately this is not portable. [17.13] (V1 11.5.14,11.5.19) fread(), fwrite(): These are implemented assuming that the input stream is open in 9-bit binary mode, such that all 36 bits of an int can be read with four successive bytes. No byte-size or mode checking is done, so it is the user's responsibility to make sure the stream is open correctly. [17.16] tmpfile(), tmpnam(), mktemp(): On TOPS-20/TENEX these are implemented using a time value from the system rather than getpid() due to the difficulty of ensuring that getpid() is unique. This may change. Additional STDIO routines from 4.2BSD: See a BSD UPM section 3S for details on those routines. Some of them existed in V7 as well, such as fdopen(), fileno(), getw(), putw(), and setbuf(). Additional STDIO routines (KCC specific, not portable): sopen(): opens a string as a source or destination for I/O. The first arg is a string pointer, second is a standard fopen type specification. The implementation of this is not yet complete: only "r" and "w" are implemented. "a" (append) mode does NOT do the obvious thing; place has been kept for "w+" to automatically expand the given string if the end is reached (assuming it was allocated by malloc). If a NULL string pointer is given, a string buffer is allocated starting at max_size characters. The file pointer cannot be repositioned (e.g. a string can be scanned only once). These things may be finished some day. Section 18: Storage Allocation (V1: Sec 11.4) Src: lib/ Name Module Port Comments char *malloc(size); MALLOC * char *calloc(cnt,siz); MALLOC * (calls malloc) char *mlalloc(lsize); MALLOC * CARM only. (calls malloc) char *clalloc(lcnt,lsize); MALLOC * CARM only. (calls malloc) void free(ptr); MALLOC * void cfree(ptr); MALLOC * Not in ANSI. (calls free) char *realloc(ptr,size); MALLOC * char *relalloc(ptr,size); MALLOC * CARM only. (calls realloc) -------------------- Additional non-CARM functions: These are temporary only and their use in new code is not advisable; they will probably go away soon. int _palloc(n); allocate n pages of memory void _pfree(page); free allocated pages Tests: LIB/TEST/TMALL1.C, TMALL2.C Notes: All CARM facilities supported. can be included. Since "long" is the same size as "int" for KCC, the long and int forms of calls are functionally identical. For portability the "long" forms should not be used. Note that in ANSI these facilities can be declared with , but in non-ANSI implementations there is no associated header file. You should either include , or you should be VERY careful about pre-declaring these functions properly, and be SURE that routines which expect a char pointer argument are given one. A common mistake is failing to declare malloc(), so that the compiler is unaware of the proper conversions that must be applied to the return value (which is a PDP-10 byte pointer). This sort of type mismatch error can go undetected on some machines but will cause you all kinds of mysterious grief on the PDP-10. Using brk() and sbrk() is not prohibited, but doing so is guaranteed to confuse the storage allocator and cause problems if you also use malloc() and friends. The KCC functions conform to the ANSI/CARM descriptions of how they should behave, particularly when given strange arguments like NULL pointers. This is different from the behavior on BSD, where a zero size will still return something from malloc and realloc (rather than ignoring and freeing). [18.1] (V1 11.4.1,11.4.3,11.4.5,11.4.6) calloc(),clalloc(),malloc(),mlalloc(): clalloc() == calloc() on the PDP-10. These will return NULL if either argument is zero (as per ANSI). mlalloc() == malloc() on the PDP-10. These also return NULL if given a zero argument (as per ANSI). [18.2] (V1 11.4.2, 11.4.4) free(), cfree(): cfree() == free() on the PDP-10. CARM claims that for maximum portability it is best to use cfree() only to deallocate memory allocated by calloc(), and free() only to deallocate memory allocated by malloc(). However, the ANSI draft has flushed cfree() altogether. free() does nothing if given a NULL argument (as per ANSI). If given a bad pointer, free() calls abort() after sending the following message to stderr: "free(): tried to free invalid block" [18.3] (V1 11.4.7, 11.4.8) realloc(), relalloc(): relalloc() == realloc() on the PDP-10. These behave as per ANSI for unusual arguments: if the pointer is NULL, it acts like malloc(); if the size is zero, it acts like free() and returns NULL. If given a bad pointer, realloc() calls abort() after sending the following message to stderr: "realloc(): tried to reallocate invalid block". Section 19: Mathematical Functions (V1: Sec 11.3) Src: lib/math/ Name Module Port Comments int abs(x); ABS * PRIMITIVE: C code double fabs(x); FABS * PRIMITIVE: C code long labs(x); LABS * PRIMITIVE: C code div_t div(n,d); DIV E * PRIMITIVE: C or PDP10 code ldiv_t ldiv(n,d); DIV E * PRIMITIVE: C or PDP10 code double ceil(x); CEIL * based on modf() double floor(x); FLOOR * based on modf() double fmod(x,y); FMOD * based on modf() double exp(x); EXP *10 PRIMITIVE: uses _sign,fabs,modf,ldexp double log(x); LOG *10 based on _xexp, _xmant, _poly double log10(x); LOG10 * based on log() double frexp(x,nptr); FREXP *10 PRIMITIVE: MACH DEP C code! double ldexp(x,n); LDEXP *10 PRIMITIVE: MACH DEP C code! double modf(x,nptr); MODF E *10 PRIMITIVE: MACH DEP asm code! double pow(x,y); POW * based on exp(), log(), modf() double sqrt(x); SQRT * based on _xexp(), _xmant(), ldexp() int rand(); RAND E *10 PRIMITIVE: mach dep C code srand(seed); RAND E *10 PRIMITIVE: C code double cos(x); COS *10 PRIMITIVE: uses fmod,sin,sqrt,_poly double sin(x); SIN *10 PRIMITIVE: uses fmod,cos,sqrt,_poly double tan(x); TAN * based on sin(), cos() double acos(x); ACOS * based on atan() double asin(x); ASIN * based on atan() double atan(x); ATAN *10 PRIMITIVE: uses _sign, _poly double atan2(y,x); ATAN2 * based on atan() double cosh(x); COSH * based on exp() double sinh(x); SINH * based on exp() double tanh(x); TANH * based on exp() -------------------- Additional support routines, NOT IN CARM: These exist only to support the above routines and should not be used by user code. double _sign(x, y); SIGN * PRIMITIVE: C code double _poly(x, y, z); POLY * PRIMITIVE: C code int _xexp(x); XEXP *10 PRIMITIVE: MACH DEP C code! double _xmant(x); XMANT *10 PRIMITIVE: MACH DEP C code! Tests: LIB/TEST/TMATH.C (Why don't we have good precision for atan()?? E-9 only) Notes: All CARM facilities are supported. must be included. These are mostly derived from the Portable Math Library written by Fred Fish. [19.8] (V1 11.3.25) tan(): According to CARM, "If the argument is so close to an odd multiple of pi/2 that the correct result value is too large to be represented, then the largest representable positive floating-point number is returned and the error code ERANGE is stored into the external variable errno". The actual error check done is to see if for tan(x), cos(x) == 0. If so, the error behavior above is done. [19.9] (V1 11.3.5) atan2(): For atan2(0, 0), the value 0 is returned and errno set to EDOM. [19.10] (V1 11.3.22) sinh(): sinh() of a negative argument that is too large returns the largest representable negative float-point number. Other notes: ANSI and CARM have the same functions. There are a few differences about domain/range error specifications which are minor. The BIG incompatibility is: ANSI modf() is incompatible with CARM and BSD, because the 2nd arg is (double *) instead of (int *)!!! The functions abs, labs, rand, and srand are declared in by ANSI, in by CARM. BSD appears to have all CARM functions except labs() and fmod(). BSD has these functions which are not in ANSI or CARM: (all return double unless otherwise indicated) Documented in UPM: gamma, hypot, cabs, j0, h1, jn, y0, y1, yn Undocumented: asinh, acosh, atanh, erf, erfc, expm1, log1p rint, lgamma, copysign, drem, logb, scalb, cbrt finite (returns int), infnan (VAX only) Section 20: Time and Date Functions Src: lib/, lib/usys/ Name Module Port Comments clock_t clock(); CLOCK E *10 clock_t * CLK_TCK * struct tms * void times(tmsbuf); USYS/TIMES * (see USYS.DOC) time_t time(tptr); USYS/TIME E *10 (see USYS.DOC) time_t * char *asctime(ts); CTIME E *10 char *ctime(timptr); CTIME E *10 struct tm *gmtime(t); CTIME E *10 struct tm *localtime(t); CTIME E *10 time_t mktime(tmptr); CTIME E *10 double difftime(t1,t0); CTIME E *10 -------------------- Additional non-CARM functions: char *timezone(mwest, dstt); CTIME E *10 For BSD/V7 compatibility (!S5) typedef ... tadl_t; E *10 Type for local TAD value tadl_t tadl_get(); USYS/TIME E *10 Get current local TAD value tadl_t tadl_to_utime(time); USYS/TIME E *10 Convert time_t to tadl_t time_t tadl_from_utime(tadl); USYS/TIME E *10 Convert tadl_t to time_t Internal globals, not for user consumption: struct tm *_lbrktime(); CTIME E ITS,T10,WAITS For use by USYS/TIME int _tmisdst(); CTIME E ITS,T10,WAITS For use by USYS/TIME The latest ANSI C draft also includes this function (not implemented yet): size_t strftime(char *s, size_t maxsize, const char *format); ?? Tests: LIB/TEST/TTIME.C Notes: All CARM facilities are supported. For additional time functions, see the TMX(3X) section. [20.1] clock(), times(): CLK_TCK is uniformly 1000 (i.e. runtime is in milliseconds). The BSD times() call is supported, although only crudely; it does not return its children's runtime. It could if this was needed. [20.2] time_t, time(): The type of time_t is "int". The value is the same as that for a standard UN*X implementation, i.e. the number of seconds since 1/1/1970 GMT. This is NOT a TOPS-20 or TENEX GTAD format time and date. If you wish to manipulate time-and-date (TAD) values of the local operating system, use the (non-standard) tadl_t facilities. Section 21: Control Functions Src: lib/, lib/usys/ Name Module Port Comments macro assert(); * int system(cmd); SYSTEM E T20,10X (partial implem) int exec*(); USYS/FORKEX E T20,10X (partial implem) void exit(status); USYS/URT E T20,10X void _exit(status); USYS/URT E T20,10X void abort(); ABORT *10 typedef ... jmp_buf[]; E *10 KCC specific int setjmp(env); SETJMP E *10 KCC specific void longjmp(env,status); SETJMP E *10 KCC specific typedef ... onexit_t; * onexit_t onexit(func); ONEXIT * constant SIG_IGN; * constant SIG_DFL; * constant SIG_ERR; * constant SIGxxx; * void (*signal(sig,func)); USYS/SIGNAL * See USYS.DOC int raise(sig); USYS/SIGVEC E T20,10X See USYS.DOC int kill(pid,sig); USYS/SIGVEC E T20,10X See USYS.DOC int (*ssignal(softsig,func))(); SSIGNA * int gsignal(softsig); SSIGNA * void psignal(sig,prefix); PSIGNA * void sleep(secs); USYS/SLEEP E *10 See USYS.DOC unsigned alarm(secs); USYS/ALARM E T20 See USYS.DOC -------------------- Additional functions: int _setjmp(env); SETJMP E *10 For BSD compatibility int _longjmp(env,val); SETJMP E *10 For BSD compatibility void longjmperror(); SETJMP E *10 For BSD compatibility int forkexec(); USYS/FORKEX E T20,10X Combines fork & exec! The latest ANSI C draft has replaced onexit() with: int atexit(void(*func)(void)) Notes: All CARM facilities exist, although some may not be as completely supported as for a real UN*X system. [21.2] exec(), system(): The various forms of exec() all exist, but none of them do anything with the "envp" environment pointer. For the very common situation where a fork() is followed by an exec(), the forkexec() call should be used instead; it is MUCH faster. system() is not a full implementation. On TOPS-20 the command string is parsed assuming that the first word is a system program name, which is then invoked (using forkexec()) with the full string as an RSCAN% argument. Unfortunately there is no convenient way to feed input directly into an inferior EXEC. This call could be changed to use a PTY, but this would be much slower. [21.3] abort(), exit(): abort() does no cleanup actions whatsoever. It simply attempts to execute a zero instruction, which generates an illegal instruction fault on the PDP-10. This can be ignored by the signal handler, but if so then the program will loop indefinitely; abort() NEVER returns to its caller. exit() cleans up by calling all functions registered with onexit(). The STDIO buffers are the last thing cleaned up. [21.4] setjmp(), longjmp(): In addition to the above, KCC also implements the BSD facilities of _setjmp(), _longjmp(), and longjmperror(). A checksum is stored in jmp_buf, and longjmp() checks this as well as other things; if anything looks bad, it calls longjmperror(). longjmperror() can be defined by the user (the default routine simply prints "longjmp botch"). If it returns, abort() is called. [21.5] onexit(): Up to 32 functions can be registered, as per CARM. [21.6] signal(), raise(), kill(), gsignal(), ssignal(), psignal(): The implementation of signals is more complete than you might expect. The software signal functions gsignal() and ssignal() operate as described in CARM, as does the signal description function psignal(). Note that psignal() outputs to the STDIO stream "stderr" rather than the UN*X file descriptor 2. raise(sig) is implemented simply as kill(getpid(),sig). The signal() and kill() functions are "UN*X system calls" and as such are treated specially. What KCC actually implements corresponds to the 4.3BSD signal handling mechanism, using the sigvec() call and a signal block mask. The main difference from standard UN*X is that when a signal is caught, its handler is NOT reset to SIG_DFL; also, most system calls are resumed rather than forced to fail with EINTR. For a fuller description the file SIGNAL.DOC should be consulted. [21.7] sleep(), alarm(): alarm() is implemented as described in CARM. On TOPS-20 this uses the TIMER% jsys. A signal handler for SIGALRM must be defined before the first call to alarm(), otherwise nothing will happen. The TOPS-20 implementation of sleep() uses a timer separate from that of alarm(). If any signal is handled, sleep() will return immediately with errno set to EINTR; it does not return any value. Section 22: Miscellaneous Functions Src: lib/ Name Module Port Comments int main(argc,argv); * * User program! char *ctermid(s); CTERMI E T20 char *cuserid(s); CTERMI E T20 char *getcwd(buf,size); GETCWD E T20 char *getwd(path); GETCWD E T20 char *getenv(name); GETENV E T20 Note 10X does not have LNMST%. char *getlogin(); GETLOG E T20 int getopt(argc,argv,optstr); GETOPT * Note other externals defined! int putenv(namval); GETENV E T20 char *bsearch(ky,bs,ct,sz,cmp); BSEARC * void qsort(base,cnt,siz,cmp); QSORT * GNU version -------------------- The latest ANSI C draft has added a new function and new header file: char *setlocale(int category, char *locale); Notes: All CARM functions are supported insofar as possible. [22.1] main(): The runtime startup provides main() with argc and argv, as parsed from the command line (on TOPS-20 this is the RSCAN% buffer). However, it does NOT provide "env" or "environ". [22.2] ctermid(), cuserid(): These are System V functions and are not present in BSD or ANSI. KCC implements them as per the CARM description. [22.3] getcwd(), getcd(): Implemented as per description. [22.4] getenv(), getlogin(), getopt(), putenv(): CARM goofed by only describing getenv(). KCC implements all of these, but the environment variables need further explanation. [22.5] bsearch(): This is a new function in ANSI. [22.6] qsort(): KCC uses the GNU (Free Software Foundation) implementation of this function. Section BSD(3N): UPM(3N) BSD network functions Src: lib/network/ Name Module Port Comments struct hostent; Defs for following struct hostent *gethostent(); GETHST - not yet done struct hostent *gethostbyaddr(adr,l,t); GETHST E T20,10X struct hostent *gethostbyname(nam); GETHST E T20,10X void sethostent(flg); GETHST - not yet void endhostent(); GETHST - not yet Section TRM(3X): TERMCAP functions Src: , lib/trmcap.c Name Module Port Comments int tgetent(bp,name); TRMCAP * int tgetnum(id); TRMCAP * int tgetflag(id); TRMCAP * char *tgetstr(id, area); TRMCAP * char *tgoto(cm, destcol, destline); TRMCAP * int tputs(cp, affcnt, outc); TRMCAP * Tests: Compile lib/trmcap.c with -DTEST to generate a test program. Notes: This should be a full TERMCAP emulation. The code is derived from that of Gnuemacs (of the Free Software Foundation). The functions are kept in a library separate from the normal C library; to use them, the program must #include and the "-ltrm" switch must be given on the KCC command line. The terminal database file on TOPS-20 is kept in C:TRMCAP.DAT. Programs using these functions must include declarations of the following variables, which TERMCAP expects to use: char PC; char *BC; char *UP; short ospeed; Section TMX(3X): Time and Date Functions (Extended) Src: , lib/ Name Module Port Comments struct tmx * includes struct tmz * int time_parse(str, tmx, endptr); TIMEPA * time_t time_make(tmx); TIMEMK * int time_lzone(tmz); TIMEZN E * int time_tzset(); TIMEZN E * Notes: Documentation is in the file C:LIBTMX.DOC. These functions were written by Ken Harrenstien and are distributed in a quasi-public fashion, similar to GNU software. They are not supported by any specific C implementation but because the code is available and is portable to any reasonable system, it should be safe to write code using these functions. These functions are kept in a library separate from the normal C library; to use them, the program must #include and the "-ltmx" switch must be given on the KCC command line. Section KCC-1: KCC-specific general-purpose functions Src: lib/ Name Module Port Comments T20,10X Defines JSYS nums and arg vals jsys JSYS E T20,10X Support for T20/10X syscalls regex* ? GNU version. regex* REGEX * GNU version. Not used, problems with overly long variable names. Foo. syscal ITS Defines ITS system-call macro. _scall SYSCAL E ITS C support for ITS syscalls int muuo(ins,d,e); MUUO T10,WAITS Execute MUUO int calli(n,ac,ret); MUUO T10,WAITS Execute CALLI Notes on jsys(): The jsys() function has been provided for ease in performing simple TOPS-20/TENEX monitor calls without being forced to resort to asm(). The calling convention is: #include int jsys(num, acs); int num, acs[5]; The jsys number is given in "num", and registers 1 through 4 are given and returned in the "acs" array. Offsets in acs correspond to machine registers; thus acs[1] goes into AC1 before the call and then takes the value of AC1 after the call. acs[0] is not used unless the call fails. The include file defines all JSYS names, including certain flags which tell the jsys() routine what behavior to expect from that JSYS. This information allows jsys() to present completely regular behavior to the C user, regardless of which JSYS is invoked. jsys() returns: == 0 if it failed. The JSYS error code is returned in acs[0]. If something was wrong with the arguments to jsys() itself, so that no JSYS was done, the error code will be 0. < 0 if it was interrupted. This is only possible if the JSYS_OKINT flag was OR'd into "num" for the call. The return value will be -2 if the interrupt happened before the JSYS was invoked, and -1 if it actually interrupted the JSYS. > 0 if it succeeded. The return value will be one of 1, 2, or 3 depending on whether the JSYS returned to .+1, .+2, or .+3. Note that interruption is ONLY allowed if the JSYS_OKINT flag is set in the "num" argument. Thus, for example, the following call can be interrupted: jsys(WAIT|JSYS_OKINT, acs); but this call will NOT be interrupted: jsys(PMAP, acs); If the user program does direct JSYS calls itself with asm() then the signal handling code permits these to be interrupted, and tries to restart the JSYS when the signal handler returns, but this is not guaranteed to work for all possible cases. The jsys() call by contrast is always guaranteed to behave in a predictable way. Things are not yet completely normalized for TENEX, because the need to handle .ICILI (illegal instruction) interrupts and emulate ERJMP complicates matters.