Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
kcc-4/include/libc.doc
There are 10 other files named libc.doc in the archive. Click here to see a list.
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.
[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 "Standard I/O")
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 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 "<xxx.h>".
Port: A status code indicating portability, as follows:
E = file #includes "c-env.h" for environment configuration.
<sys> - 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 <stddef.h>,<stdio.h> *
typedef ... ptrdiff_t; <stddef.h> *
typedef ... size_t; <stddef.h> *
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; <errno.h> *
constant ERANGE; <errno.h> *
__DATE__ in KCC *
__FILE__ in KCC *
__LINE__ in KCC *
__TIME__ in KCC *
__STDC__ NOT YET (in KCC)
va_alist,va_dcl <varargs.h> * KCC Non-ANSI form
va_list,va_start,va_arg,va_end <varargs.h> * KCC Non-ANSI form
va_list,va_start,va_arg,va_end <stdarg.h> * 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 <vararg.h> and <stdarg.h> 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: <ctype.h>, 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; <ctype.h> 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. <ctype.h> 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: <string.h>, 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 <strung.h>:
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. <string.h> must be
included. <strings.h> also exists for BSD compatibility; it merely
includes <string.h>.
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 <string.h> as per ANSI, but <memory.h>
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; <stdio.h> *
struct FILE; <stdio.h> *
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; <stdio.h> (m) *
FILE *stdout; <stdio.h> (m) *
FILE *stderr; <stdio.h> (m) *
int fseek(fp,off,typ); FSEEK *
long ftell(fp); FTELL *
void rewind(fp); REWIND *
int fgetc(fp); FGETC *
int getc(fp); <stdio.h> (m) *
int getchar(); <stdio.h> (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); <stdio.h> (m) *
int putchar(c); <stdio.h> (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); <stdio.h> (m) *
int ferror(fp); <stdio.h> (m) *
void clearerr(fp); <stdio.h> (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 seen in a write-up of ANSI C from Aug-87 Dr. Dobbs:
int fgetpos(FILE *stream, fpos_t *pos); ??
int fsetpos(FILE *stream, const fpos_t *pos); ??
Additional STDIO functions for V7/BSD compatibility:
constant BUFSIZ; <stdio.h> * V7/BSD
constant NULL; <stdio.h> * V7/BSD
FILE *fdopen(fd,type); FDOPEN * V7/BSD open w/existing FD
int fileno(fp); <stdio.h> (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[]; <stdio.h> * 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 <file's> or 7 7 yes if size 7
BINARY <file's> 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. <stdlib.h> 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
<stdlib.h>, but in non-ANSI implementations there is no associated
header file. You should either include <stdlib.h>, 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. <math.h> 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 <stdlib.h> by
ANSI, in <math.h> 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 <time.h> *
CLK_TCK <time.h> *
struct tms <sys/times.h> *
void times(tmsbuf); USYS/TIMES * (see USYS.DOC)
time_t time(tptr); USYS/TIME E *10 (see USYS.DOC)
time_t <time.h> *
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; <sys/time.h> 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
Aug-87 Dobbs/ANSI also includes:
size_t strftime(char *s, size_t maxsize, const char *format); ??
Tests: LIB/TEST/TTIME.C
Notes:
All CARM facilities are supported.
[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 operation
system, use the (non-standard) tadl_t facilities.
Section 21: Control Functions Src: lib/, lib/usys/
Name Module Port Comments
macro assert(); <assert.h> *
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[]; <setjmp.h> E *10 KCC specific
int setjmp(env); SETJMP E *10 KCC specific
void longjmp(env,status); SETJMP E *10 KCC specific
typedef ... onexit_t; <stdlib.h> *
onexit_t onexit(func); ONEXIT *
constant SIG_IGN; <signal.h> *
constant SIG_DFL; <signal.h> *
constant SIG_ERR; <signal.h> *
constant SIGxxx; <signal.h> *
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!
In Aug-87 Dr. Dobbs they have, instead of onexit(),
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
--------------------
Aug-87 Dr. Dobbs shows this bizarro function (and the new header file
<locale.h>), of which I have no clue:
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; <netdb.h> 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 BSD(3X): TERMCAP functions Src: <trmcap.h>, 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 <trmcap.h> 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 KCC-1: KCC-specific general-purpose functions Src: lib/
Name Module Port Comments
<lots> <jsys.h> T20,10X Defines JSYS nums and arg vals
jsys JSYS E T20,10X Support for T20/10X syscalls
regex* <regex.h> ? GNU version.
regex* REGEX * GNU version.
Not used, problems with overly
long variable names. Foo.
syscal <sysits.h> 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 <jsys.h>
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 <jsys.h> 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.