Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
kcc-6/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 an excellent reference and
describes most of the library functions. The second edition
has a number of egregious typos, but most are readily
apparent.
[K&R] Book: "The C Programming Language", Second edition, ISBN 0-13-110362-8
by Brian W. Kernighan & Dennis M. Ritchie
Primarily a C language tutorial. The appendix describing
the C library is skimpy and based entirely on an old draft
of the proposed ANSI C standard.
[UPM] Book: "Unix Programmer's Manual", 4.2/4.3BSD version (Reference Guide)
printed by the USENIX Association.
[MAN] Files: "man funct-name" on most Un*x systems.
KCC-specific documentation:
[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.
[COD] 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 "<xxx.h>".
Port: A status code indicating portability, as follows:
* = fully portable (either no OS-dependent stuff, or a
fully-portable conditional exists)
E = file #includes <c-env.h> for environment configuration.
If any <syscode> is given, E is always implied.
*10 = PDP-10 portable (no OS conditionals)
KCC = portable but dependent on the KCC compiler.
<syscode> - runs on the given systems, as flagged by:
2 - T20, TOPS-20
X - 10X, TENEX
I - ITS
T - T10, TOPS-10
W - WTS, WAITS (T10-like)
C - CSI, CompuServe (T10-like)
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 2XITWC
void perror(s); stdio/PERROR *
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__ in KCC * (NOT YET!!)
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/gen/ctype.c
Name Module Port Comments
int isalnum(c); CTYPE *
int isalpha(c); CTYPE *
int isascii(i); CTYPE * CARM/BSD only
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 only
int toint(c); CTYPE * CARM only
int tolower(c); CTYPE * allows any case, as per ANSI
int toupper(c); CTYPE * allows any case, as per ANSI
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 a
512-word 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/gen/
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/gen/
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 2XITWC
char *tmpnam(buf); TMPNAM 2XITWC
char *mktemp(buf); MKTEMP E *10 uses 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; <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
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/STDIO.DOC for internal 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; they are not checked.
Some systems, specifically ITS, TOPS-10, WAITS, and CSI,
have no way to remember a file's byte-size. For these systems, the
bytesize is always 7 if "text" and 9 if "binary".
"LF conversion" means that the two-character sequence of CR and
LF is converted to LF on input, and vice versa on output. For TOPS-10
based systems, NUL characters are also ignored completely, and for WAITS,
E directory pages are skipped.
A text stream is only LF-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 (Un*x
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
OS) 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():
These functions return the number of characters output, or a
negative number (EOF) if there was an output error on the stream; if
ferror() indicates that the stream has an error at the start of the
call, no output is attempted at all.
The return value merely reports the number of characters given
to putc() and does not take any eventual LF conversion into account,
since that conversion is a function of the USYS level code (i.e. the write()
syscall) rather than the STDIO level code. Thus the return value cannot
be used to form fseek pointers, which is an unportable idea anyway.
An additional facility exists with which users can assign their
own conversion specification characters 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():
The filenames produced by these functions are generated as follows,
where "pid" is the process PID and "ver" is a number derived from the current
time of day. "ppp" and "vv" represent 3- and 2- digit forms of pid and ver.
tmpfile: "pppCvv.TMP" (T20/10X: "TMPFIL-pid.ver.0;T")
tmpnam: "pppCvv.TMP" (T20/10X: "TMPNAM-pid.TMP.ver")
mktemp: "ARGXXX" => "ARGppp"
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):
FILE *sopen(cp, type, max_size);
sopen() opens a string as a source or destination for standard
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; unfortunately ANSI has not provided a corresponding
portable function, which has discouraged use and development.
Section 18: Storage Allocation (V1: Sec 11.4) Src: lib/gen/
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)
--------------------
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 very 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. It is even possible for
some erroneous code to keep working until run in a program that uses
extended addressing.
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.5] (V1 11.3.18) modf():
According to CARM, the 2nd argument is (int *). However, all
of V7, BSD and ANSI state that it is (double *), which makes more
sense; accordingly, the KCC implementation uses the V7/BSD/ANSI
interpretation and the second argument must be (double *).
[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 modf(), as described above.
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 2XITWC
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 2XITWC (see USYS.DOC)
time_t <time.h> *
char *asctime(ts); CTIME E *
char *ctime(timptr); CTIME E *
struct tm *gmtime(t); CTIME E *
struct tm *localtime(t); CTIME E *
time_t mktime(tmptr); CTIME E *
double difftime(t1,t0); CTIME E *
--------------------
Additional non-CARM functions:
char *timezone(mwest, dstt); CTIME E * For BSD/V7 compatibility (!S5)
typedef ... tadl_t; <sys/time.h> 2XITWC Type for local TAD value
tadl_t tadl_get(); USYS/TIME 2XITWC Get current local TAD value
tadl_t tadl_to_utime(time); USYS/TIME 2XITWC Convert time_t to tadl_t
time_t tadl_from_utime(tadl); USYS/TIME 2XITWC Convert tadl_t to time_t
Internal globals, not for user consumption:
struct tm *_lbrktime(); CTIME --ITWC For use by USYS/TIME
int _tmisdst(); CTIME --ITWC 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 basic 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 provided.
Section 21: Control Functions Src: lib/, lib/usys/
Name Module Port Comments
macro assert(); <assert.h> *
int system(cmd); SYSTEM 2X---- (partial implem)
int exec*(); USYS/FORKEX 2X-TWC (partial implem)
void exit(status); USYS/URT 2XITWC
void _exit(status); USYS/URT 2XITWC
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 2X---- See USYS.DOC
int kill(pid,sig); USYS/SIGVEC 2X---- 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 2----- 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 2X-TWC 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. TOPS-10 type systems cannot
do fork() at all, just exec().
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" so that it acts like BSD). 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 on TOPS-20 and TENEX is more
complete than you might expect. However, signals are not supported yet
for any other system.
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(), unlike the BSD implementation where sleep()
invokes (and thus resets) 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/gen/
Name Module Port Comments
int main(argc,argv); * * User program!
char *ctermid(s); CTERMI 2X---- S5/CARM
char *cuserid(s); CTERMI 2X---- S5/CARM
char *getcwd(buf,size); GETCWD 2----- S5/CARM
char *getwd(path); GETCWD 2----- BSD/ /CARM
char *getenv(name); GETENV 2----- ANSI/BSD/S5/CARM
char *getlogin(); GETLOG 2----- BSD/ /CARM
int getopt(argc,argv,optstr); GETOPT * BSD/ /CARM
char *optarg; GETOPT * BSD/ /CARM (yeccch!)
int optind, opterr; GETOPT * BSD/ /CARM (yeccch!)
int putenv(namval); GETENV 2----- S5/CARM
char *bsearch(ky,bs,ct,sz,cmp); BSEARC * ANSI/ /S5/CARM
void qsort(base,cnt,siz,cmp); QSORT * ANSI/BSD/S5/CARM (GNU version)
--------------------
Additional non-CARM functions:
char *ttyname(fd); TTYNAM 2X---- For BSD/V7 compat
int isatty(fd); TTYNAM 2X---- For BSD/V7 compat
The latest ANSI C draft has added a new function and new header file:
<locale.h>
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. On TOPS-20, the logical device names available to the job
are considered the "environment"; when searching for an environment
variable "XXX", getenv() looks for the logical name "CENV-XXX:" and
returns the contents of that string if one exists, converted to
lowercase. If there is no such logical name (either job-wide or system-wide)
then getenv checks for the special names "TERM" and "HOME", which
it will set appropriately.
[22.5] bsearch():
This is a new function in ANSI, apparently from SYSV.
[22.6] qsort():
KCC uses the GNU (Free Software Foundation) implementation of
this function.
Section BSD(3N): UPM(3N) BSD network functions Src: lib/gen/
Name Module Port Comments
struct hostent; <netdb.h> Defs for following
struct hostent *gethostent(); GETHST - not yet
struct hostent *gethostbyaddr(adr,l,t); GETHST 2X----
struct hostent *gethostbyname(nam); GETHST 2X----
void sethostent(flg); GETHST - not yet
void endhostent(); GETHST - not yet
Section TRM(3X): TERMCAP functions Src: <trmcap.h>, lib/user/
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 TMX(3X): Time and Date Functions (Extended) Src: <timex.h>, lib/user/
Name Module Port Comments
struct tmx <timex.h> * includes <time.h>
struct tmz <timex.h> *
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 <timex.h> and the "-ltmx"
switch must be given on the KCC command line.
Section KCC-1: KCC-specific general-purpose functions Src: lib/gen/
Name Module Port Comments
<lots> <macsym.h> 2X---- Defines MACSYM-like macros
<lots> <monsym.h> 2X---- Defines monsym()
<lots> <jsys.h> 2X---- Defines JSYS numbers
jsys JSYS 2X---- T20/10X system call support
syscal <sysits.h> --I--- Defines ITS system-call macro.
_scall SYSCAL --I--- C support for ITS syscalls
<lots> <uuosym.h> ---TWC Defines uuosym()
MUUO_* <muuo.h> ---TWC Execute specific MUUO
int muuo(ins,d,e); MUUO ---TWC TOPS-10 system call support
The GNU version of regex is also included, but is not actually used
pending redefinition of a great many overly long variable names.
regex* <regex.h> ? GNU version.
regex* REGEX * GNU version.
System programming - General
Programs which need to interact more closely with the operating
system may find it necessary to know the values of certain monitor
symbols and perhaps make some system calls. Rather than using asm(),
such interactions should be made using the facilities that KCC provides
for this:
<macsym.h> General-purpose system-independent macros
<monsym.h> Access to MONSYM.UNV (TOPS-20/TENEX)
<uuosym.h> Access to UUOSYM.UNV (TOPS-10)
<csisym.h> Access to CSISYM.UNV (CSI)
<wtssym.h> Access to WTSSYM.UNV (WAITS)
The <macsym.h> file defines some macros which are parallels to
those in MACRO's MACSYM.UNV file. They are system-independent, but
specific to PDP-10 CPUs.
Each of the <*sym.h> files provide a way to examine, at compile
time, the values defined in their respective UNV files. Each defines
two macros for this purpose: taking <monsym.h> as an
example:
Facility Macros
<monsym.h> monsym() monsymdefined()
<uuosym.h> uuosym() uuosymdefined()
<wtssym.h> wtssym() wtssymdefined()
<csisym.h> csisym() csisymdefined()
The argument to a XXXsym() macro must be a single string literal, such
as monsym(".FHSLF"). It may be either upper or lower case. The resulting
value has type (int) and is a compile-time constant which can also be
used in #if preprocessor tests. A compiler error will occur if the symbol
is not found.
To merely test whether a symbol is defined, use monsymdefined(".FHSLF")
which will have the value 1 if the symbol is defined, 0 otherwise.
System programming - TOPS-20/TENEX
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. It is
important that the JSYS numbers be obtained from <jsys.h> rather than
by using the monsym() macro, because of the flag definitions in <jsys.h>
which ensure predictable return results.
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.
System programming - TOPS-10 (including WAITS and CSI)
The <muuo.h> facility has been provided for ease in performing
simple TOPS-10 monitor calls without being forced to resort to asm().
There are several variants, all of which take a string literal to identify
the desired MUUO:
Macro Args / Vals Example
MUUO ("nam") - MUUO("RESET")
MUUO_CH ("nam",ch) ch => AC# MUUO_CH("SEEK", chan)
MUUO_AC ("nam",ac) ac => c(AC) MUUO_AC("SLEEP", 30)
MUUO_VAL ("nam",av) c(AC) => *av MUUO_VAL("GETPPN", &ppn)
MUUO_ACVAL("nam",ac,av) ac => c(AC) => *av MUUO_ACVAL("GETTAB", arg, &val)
MUUO_TTY ("nam",e) e => E MUUO_TTY("OUTCHR", &chr)
MUUO_IO ("nam",ch,e) ch => AC#, e => E MUUO_IO("OPEN", chan, &opnblk)
Where:
"nam" - a MUUO name defined in UUOSYM.
ch - a channel number value, type (int) (Should be [0-017])
ac - an integer argument value, type (int)
av - return value address, type (int *)
e - a word address, type (int *)
Most of these are necessary to support the various forms of CALLI; the
last two, MUUO_TTY and MUUO_IO, respectively support TTCALL and all the
other I/O UUOs. There is no support for the INIT UUO.
All of the macros return a value as follows:
-1 UUO was interrupted (not implemented yet)
0 UUO took the .+1 return (no skip)
1 UUO took the .+2 return (skipped)
If you want to invoke a monitor call that only exists on a WAITS or
CSI system, and thus is not defined by UUOSYM, then you can use these
alternate forms:
WTSUUO... For an UUO defined by WTSSYM
CSIUUO... For an UUO defined by CSISYM
If you include <muuo.h>, it is not necessary to also include <uuosym.h>
(or the other alternates) because <muuo.h> already does this.