mirror of
https://github.com/PDP-10/its.git
synced 2026-01-13 15:27:28 +00:00
Binary-only compiler and library, plus documentation and include files for compiling new programs.
935 lines
37 KiB
Plaintext
Executable File
935 lines
37 KiB
Plaintext
Executable File
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 "<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 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
|
||
|
||
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
|
||
|
||
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(); <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!
|
||
|
||
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:
|
||
<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.
|
||
|
||
[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 TRM(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 TMX(3X): Time and Date Functions (Extended) Src: <timex.h>, lib/
|
||
|
||
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/
|
||
|
||
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.
|