mirror of
https://github.com/PDP-10/its.git
synced 2026-03-26 10:12:37 +00:00
KCC - C compiler.
Binary-only compiler and library, plus documentation and include files for compiling new programs.
This commit is contained in:
6
Makefile
6
Makefile
@@ -7,9 +7,9 @@ NETMASK=255,255,255,248
|
||||
SRC = system syseng sysen1 sysen2 sysen3 sysnet kshack dragon channa \
|
||||
midas _teco_ emacs emacs1 rms klh syshst sra mrc ksc eak gren \
|
||||
bawden _mail_ l lisp libdoc comlap lspsrc nilcom rwk \
|
||||
inquir acount gz sys decsys ecc alan sail kcc
|
||||
DOC = info _info_ sysdoc sysnet kshack _teco_ emacs emacs1
|
||||
BIN = sys2 device emacs _teco_ lisp liblsp alan inquir sail comlap
|
||||
inquir acount gz sys decsys ecc alan sail kcc kcc_sy c
|
||||
DOC = info _info_ sysdoc sysnet kshack _teco_ emacs emacs1 c kcc
|
||||
BIN = sys2 device emacs _teco_ lisp liblsp alan inquir sail comlap c
|
||||
|
||||
# These directories are put on the minsys tape.
|
||||
MINSYS = _ sys
|
||||
|
||||
@@ -163,6 +163,7 @@ A list of [known ITS machines](doc/machines.md).
|
||||
- INSTAL, install executables on other ITS machines.
|
||||
- ITSDEV, ITS device server.
|
||||
- JOBS, list jobs by category.
|
||||
- KCC, C compiler (binary only).
|
||||
- LISP, lisp interpreter and runtime library (autoloads only).
|
||||
- LOADP, displays system load.
|
||||
- LOCK, shut down system.
|
||||
|
||||
BIN
bin/c/[clib].11
Executable file
BIN
bin/c/[clib].11
Executable file
Binary file not shown.
BIN
bin/c/[clib].14
Executable file
BIN
bin/c/[clib].14
Executable file
Binary file not shown.
BIN
bin/c/[clib].16
Executable file
BIN
bin/c/[clib].16
Executable file
Binary file not shown.
BIN
bin/c/[clib].9
Normal file
BIN
bin/c/[clib].9
Normal file
Binary file not shown.
BIN
bin/c/[crel].16
Executable file
BIN
bin/c/[crel].16
Executable file
Binary file not shown.
BIN
bin/c/ts.cc
Executable file
BIN
bin/c/ts.cc
Executable file
Binary file not shown.
BIN
bin/c/}c.bin
Executable file
BIN
bin/c/}c.bin
Executable file
Binary file not shown.
BIN
bin/c/}lp.bin
Executable file
BIN
bin/c/}lp.bin
Executable file
Binary file not shown.
BIN
bin/c/}m.bin
Executable file
BIN
bin/c/}m.bin
Executable file
Binary file not shown.
53
doc/_info_/cc.recent
Executable file
53
doc/_info_/cc.recent
Executable file
@@ -0,0 +1,53 @@
|
||||
18 April 1977
|
||||
|
||||
--- C ---
|
||||
|
||||
C is an implementation language, similar to BCPL except with data
|
||||
types. Further information is be available from Alan Snyder (AS@DM).
|
||||
C is currently available only on DM and MC.
|
||||
|
||||
--- Compiling ---
|
||||
|
||||
CC is the C compiler command. Usage is
|
||||
|
||||
:CC file1.name file2.name ...
|
||||
|
||||
where the arguments are the path names of C source files which are to
|
||||
be compiled. Each file will be compiled in turn, and if the
|
||||
compilation is successful, the resulting relocatable file will be
|
||||
placed in the file file?.rel. Arguments beginning with the '-'
|
||||
character are taken to be compiler options. Available options include:
|
||||
|
||||
-c compile only, do not assemble
|
||||
-g do not delete MIDAS file
|
||||
-x syntax check only
|
||||
-s produce a symbol table listing
|
||||
-b compile big function (FUNCTION TOO LARGE)
|
||||
|
||||
For example, the command
|
||||
|
||||
:cc foo.c
|
||||
|
||||
would compile the C program in the file FOO C in the current
|
||||
directory, and place the resulting relocatable program in the file
|
||||
FOO REL.
|
||||
|
||||
--- Loading ---
|
||||
|
||||
Relocatable programs produced by the C compiler are loaded together
|
||||
with the C support routines by using the STINKR loader. In order
|
||||
to load files FOO REL, BAR REL, and BLETCH REL and produce a
|
||||
runnable file TS FOO, type the following to STINKR:
|
||||
|
||||
x c/clib
|
||||
l foo
|
||||
l bar
|
||||
l bletch
|
||||
o ts.foo
|
||||
^@
|
||||
|
||||
The ^@ (ASCII NUL) terminates the teletype input file. These
|
||||
commands (minus the ^@) could also be written in a file, say
|
||||
FOO STINKR, in which case one could invoke STINKR with FOO
|
||||
as a JCL argument and STINKR would read the commands from the
|
||||
command file.
|
||||
249
doc/c/c.info
Executable file
249
doc/c/c.info
Executable file
@@ -0,0 +1,249 @@
|
||||
C Info (26 August 1980)
|
||||
|
||||
--- C ---
|
||||
|
||||
C is an implementation language, similar to BCPL except with
|
||||
data types. It is the primary language used on Unix systems.
|
||||
This implementation runs under the ITS and TOPS-20 operating
|
||||
systems. This implementation is moderately compatible with
|
||||
the Unix C implementation. However, the Unix system calls
|
||||
are NOT implemented.
|
||||
|
||||
Some portions of the UNIX Standard I/O library are
|
||||
implemented by C10STD. See C10STD.C (in <C.LIB> on XX,
|
||||
and in ITS machines in the C; directory) for details.
|
||||
|
||||
Further information is available from Eliot Moss (EBM @ XX).
|
||||
|
||||
--- Compiling ---
|
||||
|
||||
CC is the C compiler command. Usage is
|
||||
|
||||
:cc file1.c file2.c ...
|
||||
(more on pathnames below in I/O discussion)
|
||||
|
||||
where the arguments are the path names of C source files which
|
||||
are to be compiled. Each file will be compiled in turn, and if
|
||||
the compilation is successful, the resulting relocatable file
|
||||
will be placed in the file "file*.stk". Arguments beginning
|
||||
with the '-' character are taken to be compiler options.
|
||||
Available options include:
|
||||
|
||||
-c compile only, do not assemble
|
||||
-g do not delete MIDAS file
|
||||
-x syntax check only
|
||||
-s produce symbol table (not very useful)
|
||||
-b compile big function (FUNCTION TOO LARGE)
|
||||
|
||||
For example, the command
|
||||
|
||||
:cc foo.c
|
||||
|
||||
would compile the C program in the file "foo.c" in the current
|
||||
directory, and place the resulting relocatable program in the
|
||||
file "foo.stk".
|
||||
|
||||
--- Loading ---
|
||||
|
||||
Relocatable programs produced by the C compiler are loaded
|
||||
together with the C support routines using the STINKR loader.
|
||||
To load program files "foo", "bar", and "bletch" and produce a
|
||||
runnable file "foo", type the following to STINKR:
|
||||
|
||||
x c/clib
|
||||
l foo
|
||||
l bar
|
||||
l bletch
|
||||
o ts.foo
|
||||
^@
|
||||
|
||||
The ^@ (ASCII NUL) terminates the terminal input file. These
|
||||
commands (minus the ^@) could also be written in a file, say
|
||||
"foo.stinkr", in which case one could invoke STINKR by saying
|
||||
|
||||
:stinkr foo
|
||||
|
||||
and STINKR would read the commands from the command file.
|
||||
|
||||
--- Library ---
|
||||
|
||||
The above STINKR commands will load in a set of library routines
|
||||
for performing I/O, etc. Here is an introduction to that
|
||||
library (the source files, which are in <C.LIB> on XX, are the
|
||||
definitive documentation).
|
||||
|
||||
Here are some handly declarations for use below:
|
||||
|
||||
char c; /* an ASCII character */
|
||||
int i, n, cc; /* an integer */
|
||||
int *p; /* an integer pointer */
|
||||
int b; /* a boolean */
|
||||
char *s, *s1, *s2; /* strings */
|
||||
char *fn; /* a file name or a path name (defined below) */
|
||||
FILE *fd; /* a "file descriptor" (can be declared INT) */
|
||||
|
||||
/* I/O routines -- see also C10IO, C10MIO */
|
||||
|
||||
/* COPEN - opens an I/O channel */
|
||||
|
||||
fd = copen (fn, mode, options); /* open file */
|
||||
char *fn; /* file name */
|
||||
char mode; /* 'r', 'w', or 'a' (append) */
|
||||
char *options; /* 0 (char I/O), "s" (string file), "b" (binary) */
|
||||
/* for string file, pass string as fn */
|
||||
|
||||
/* returns -<ITS error code> if open fails */
|
||||
|
||||
/* Other routines: */
|
||||
|
||||
cprint (fd, s, a1, a2, ...); /* print s on fd */
|
||||
/* s is printed on the output file fd. If fd is not supplied,
|
||||
it defaults to cout, the standard output, i.e.,
|
||||
cprint ("foo", ...) defaults fd to cout. s may contain
|
||||
format descriptors, of the following forms:
|
||||
|
||||
%c - print a character
|
||||
%d - print an integer in decimal
|
||||
%o - print an integer in octal
|
||||
%s - print a string
|
||||
%z - print N copies of a character (N
|
||||
supplied via field width - read on)
|
||||
|
||||
These use the other arguments, a1, a2, etc., in order.
|
||||
For example,
|
||||
cprint (fd, "%c plus %d equals %s.\n", '2', 1+1, "4")
|
||||
results in
|
||||
2 plus 2 equals 4.
|
||||
|
||||
The format letter may be preceded by a number, giving
|
||||
the minimum field width. The output is normally right
|
||||
justified in the field, but is left justified in a field
|
||||
of size at least N if -N is given as the width. Spaces
|
||||
are the normal padding character, used to fill out if
|
||||
the argument does not fill the specified number of
|
||||
columns. If a '0' character immediately follows the
|
||||
'%', then '0' will be used as the padding character.
|
||||
If the character following the '0' is not a digit, then
|
||||
it will be used as the padding character instead of '0'.
|
||||
Here are some examples of cprint (s, 312):
|
||||
|
||||
s = "%d" ==> 312
|
||||
s = "%9d" ==> 312
|
||||
s = "%09d" ==> 000000312
|
||||
s = "%0*9d" ==> ******312
|
||||
s = "%-0*9d" ==> 312******
|
||||
s = "%o" ==> 470
|
||||
|
||||
For a more complete explanation, read CPRINT.C. It is
|
||||
even possible to define your own formats, etc. */
|
||||
|
||||
c = cgetc (fd); /* get character (text input) */
|
||||
c = cputc (c, fd); /* put character (text output) */
|
||||
|
||||
/* Note: these are redundant because cgetc and cputc do the
|
||||
right thing for binary files */
|
||||
|
||||
i = cgeti (fd); /* get integer (binary input) */
|
||||
i = cputi (i, fd); /* put integer (binary output) */
|
||||
|
||||
|
||||
ungetc (c, fd); /* push unit back on input stream */
|
||||
/* Several (but not very many) units may be pushed back
|
||||
on any channel. */
|
||||
|
||||
b = ceof (fd); /* indicates whether the channel is at
|
||||
end of file; always FALSE for output. */
|
||||
|
||||
cflush (fd); /* flush the buffer -- writes any not
|
||||
yet written output */
|
||||
|
||||
cclose (fd); /* close channel, after doing a cflush
|
||||
for any buffered output */
|
||||
|
||||
c = getchar (); /* cgetc (cin); */
|
||||
s = gets (s); /* reads from cin until a newline,
|
||||
storing into s. Returns the original
|
||||
argument; does not store the newline. */
|
||||
|
||||
putchar (c); /* cputc (c, cout); */
|
||||
puts (s); /* writes all of s to cout, and a
|
||||
newline afterwards */
|
||||
|
||||
/* FILENAMES -- see also C10FNM */
|
||||
|
||||
/* The standard ITS format filenames are supported, with the
|
||||
following terminology:
|
||||
|
||||
dev:dir;name type
|
||||
|
||||
dev - device
|
||||
dir - directory
|
||||
name - first file name
|
||||
type - second file name
|
||||
|
||||
All these components are stored WITHOUT punctuation, as sixbit
|
||||
words, once parsed. UNIX format ("pathnames") is also supported,
|
||||
for ease in designing programs to run on more than one of TOPS20,
|
||||
ITS, UNIX, and VAX/VMS. The interpretation is as follows:
|
||||
|
||||
/dev/dir1/name.type converts to
|
||||
dev:dir;name type
|
||||
|
||||
If there is no leading /, there is no dev part. The available
|
||||
routines are described below. */
|
||||
|
||||
fnparse (old, dev, dir, nm, typ, gen, attr)
|
||||
char *old, *dev, *dir, *nm, *typ, *gen, *attr;
|
||||
/* parses a name into its components; the gen and attr
|
||||
components will always be null, but are there for
|
||||
generality of interface to other operating systems. */
|
||||
|
||||
char *fngdv (old, buf) char *old, *buf;
|
||||
char *fngdr (old, buf) char *old, *buf;
|
||||
char *fngnm (old, buf) char *old, *buf;
|
||||
char *fngtp (old, buf) char *old, *buf;
|
||||
char *fnggn (old, buf) char *old, *buf;
|
||||
char *fngat (old, buf) char *old, *buf;
|
||||
/* extract the relevant component only */
|
||||
|
||||
fncons (buf, dev, dir, nm, typ, gen, attr)
|
||||
char *buf, *dev, *dir, *nm, *typ, *gen, *attr;
|
||||
/* construct a filename (ITS format) from its components */
|
||||
|
||||
char *fnsdf (buf, old, dv, dir, nm, typ, gen, attr)
|
||||
char *old, *buf, *dv, *dir, *nm, *typ, *gen, *attr;
|
||||
/* buf is set to contain a new filename with the
|
||||
supplied components substituted for null components of
|
||||
the filename in old */
|
||||
|
||||
char *fnsfd (buf, old, dv, dir, nm, typ, gen, attr)
|
||||
char *old, *buf, *dv, *dir, *nm, *typ, *gen, *attr;
|
||||
|
||||
/* buf is set to contain a new filename with the
|
||||
supplied components substituted for components of the
|
||||
filename in old. This is different from fnsdf in that
|
||||
non-zero component arguments (dv, dir, etc.) are
|
||||
substituted even if old is not null in the corresponding
|
||||
field. */
|
||||
|
||||
/* a FILESPEC is a structure containing the 4 components
|
||||
as sixbit integers ... */
|
||||
|
||||
fparse (old, fs) char *old; filespec *fs;
|
||||
/* parse a filename, handles both ITS and UNIX formats */
|
||||
|
||||
prfile (fs, buf) filespec *fs; char *buf;
|
||||
/* converts the filespec to a string, inserting standard
|
||||
punctuation */
|
||||
|
||||
|
||||
/* STORAGE ALLOCATION */
|
||||
|
||||
p = salloc (n); /* allocate n words, return pointer to it */
|
||||
sfree (p); /* free storage allocated by salloc */
|
||||
s = calloc (n); /* allocate n characters, return ptr to it */
|
||||
cfree (s); /* free storage allocated by calloc */
|
||||
|
||||
/* In this implementation words and chars are the same; but it
|
||||
is bad style to depend on it, for some day packed strings might
|
||||
be implemented ... */
|
||||
229
doc/c/c.mail
Executable file
229
doc/c/c.mail
Executable file
@@ -0,0 +1,229 @@
|
||||
Received: from grape.ARPA by MC.LCS.MIT.EDU 6 Jun 86 02:07:00 EDT
|
||||
Date: Thu, 5 Jun 86 23:06:03 pdt
|
||||
From: jeff@aids-unix (Jeff Dean)
|
||||
To: -s@ads.ARPA, jeff@ads.ARPA, c@mc
|
||||
|
||||
#ifdef HEADER
|
||||
From dan@rna Sat Jan 26 10:38:50 1985
|
||||
Received: from usenet by BRL-TGR.ARPA id a002453; 26 Jan 85 12:09 EST
|
||||
From: Dan Ts'o <dan@rna.uucp>
|
||||
Newsgroups: net.sources
|
||||
Subject: Multiple column filter
|
||||
Message-ID: <355@rna.UUCP>
|
||||
Date: 26 Jan 85 01:59:08 GMT
|
||||
Xref: seismo net.sources:2469
|
||||
To: unix-sources@BRL-TGR.ARPA
|
||||
|
||||
Here is a filter "mc" which rearranges input lines to multicolumned
|
||||
output. That is,
|
||||
|
||||
ls | mc
|
||||
|
||||
is like
|
||||
|
||||
ls -C (On Berkeley systems)
|
||||
|
||||
There are other ways of producing multicolumned output, of course.
|
||||
Two string to mind:
|
||||
|
||||
1)
|
||||
ls | pr -t -4 -l1
|
||||
|
||||
2)
|
||||
ls | paste - - - -
|
||||
|
||||
However, neither of these filters duplicates the "ls -C" output,
|
||||
where the columns proceed downward first, then on to the next column, which
|
||||
is what "mc" does.
|
||||
The original code came from the old Harvard UNIX V6 systems, but I
|
||||
had to modify it a bit to move out of the V6 PDP-11 world.
|
||||
To compile it,
|
||||
cc -O mc.c -ltermlib
|
||||
although, if you don't have libtermlib.a, commenting out three lines
|
||||
would do fine. In addition,
|
||||
mc -132
|
||||
specifies a 132-column output. Normally, columns is taken from TERMCAP.
|
||||
I find mc useful for all sorts of general purpose re-formatting, like
|
||||
directory listing of other OS's and long columns of numbers.
|
||||
|
||||
Cheers,
|
||||
Dan Ts'o
|
||||
Dept. Neurobiology
|
||||
Rockefeller Univ.
|
||||
1230 York Ave.
|
||||
NY, NY 10021
|
||||
212-570-7671
|
||||
...cmcl2!rna!dan
|
||||
|
||||
#endif
|
||||
/*
|
||||
* mc - Multiple column filter
|
||||
* Transform lines of input into listing of multiple columns
|
||||
* Original code from Harvard V6 Unix
|
||||
* Updated and reworked by Dan Ts'o, Rockefeller Univ.
|
||||
* Now has cat-like syntax:
|
||||
* mc [-] [file ...]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#define MEMINCR 1024L /* Memory buffer increments */
|
||||
#define ZSTACK1 (-1) /* An impossible (char *) (Sorry) */
|
||||
|
||||
char *nodename;
|
||||
int width;
|
||||
char *malloc(), **stack1();
|
||||
char *getenv();
|
||||
|
||||
main(c,v)
|
||||
char **v;
|
||||
{
|
||||
register int i,f;
|
||||
register char *cp;
|
||||
FILE *fd;
|
||||
char tbuf[1024];
|
||||
/* Uncomment if your stdio doesn't buffer stdout
|
||||
char buf[BUFSIZ];
|
||||
|
||||
setbuf(stdout, buf);
|
||||
*/
|
||||
f = 0;
|
||||
nodename = *v;
|
||||
cp = getenv("TERM");
|
||||
if (cp == NULL || tgetent(tbuf, cp) <= 0
|
||||
|| (width = tgetnum("co")-1) < 8)
|
||||
width = 79;
|
||||
while (c > 1 && v[1][0] == '-') {
|
||||
c--;
|
||||
v++;
|
||||
switch (v[0][1]) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
width = atoi(&v[0][1]);
|
||||
break;
|
||||
default:
|
||||
error("%s: Bad option\n", *v);
|
||||
}
|
||||
}
|
||||
|
||||
if (--c == 0)
|
||||
exit(xfer(stdin));
|
||||
else {
|
||||
while (c--) {
|
||||
v++;
|
||||
if (**v == '-' && v[0][1] == 0) {
|
||||
xfer(stdin);
|
||||
clearerr(stdin);
|
||||
}
|
||||
else {
|
||||
if ((fd = fopen(*v, "r")) == NULL) {
|
||||
fprintf(stderr, "%s: %s: Can't open\n",
|
||||
nodename, *v);
|
||||
f++;
|
||||
}
|
||||
else {
|
||||
xfer(fd);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(f ? -1 : 0);
|
||||
|
||||
}
|
||||
|
||||
xfer(fin)
|
||||
FILE *fin;
|
||||
{
|
||||
register int i;
|
||||
register char *cp;
|
||||
char line[1024];
|
||||
int max, items, columns;
|
||||
int row_p, index, rows, col_p;
|
||||
char **bot;
|
||||
|
||||
items = max = 0;
|
||||
while(fgets(line, sizeof line, fin) != NULL) {
|
||||
i = strlen(line);
|
||||
if (line[--i] == '\n')
|
||||
line[i] = 0;
|
||||
else
|
||||
i++;
|
||||
if(i >= width) {
|
||||
error("Line of length=%d is too long for width=%d\n",
|
||||
i, width);
|
||||
}
|
||||
if((cp = (char *)malloc(i+1)) == NULL)
|
||||
error("Out of memory\n");
|
||||
strcpy(cp, line);
|
||||
bot = stack1(cp);
|
||||
if(i > max) max = i;
|
||||
items++;
|
||||
}
|
||||
columns = width / (max+1);
|
||||
rows = (items + columns - 1) / columns;
|
||||
for(row_p = 0; row_p < rows; row_p++) {
|
||||
for(col_p = 0; col_p < columns; col_p++) {
|
||||
index = (col_p * rows) + row_p;
|
||||
if(index >= items)
|
||||
continue;
|
||||
if((col_p + 1) * rows + row_p >= items)
|
||||
printf("%s", bot[items - index - 1]);
|
||||
else
|
||||
printf("%-*s ", max, bot[items - index - 1]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
stack1(ZSTACK1);
|
||||
return ferror(fin);
|
||||
}
|
||||
|
||||
error(a, b, c, d, e)
|
||||
{
|
||||
fprintf(stderr, "%s: ", nodename);
|
||||
fprintf(stderr, a, b, c, d, e);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
char **stack1(s)
|
||||
char *s;
|
||||
{
|
||||
static char **s_beg, **s_end;
|
||||
static long nbuf = 0;
|
||||
register char **v, **u;
|
||||
register long n;
|
||||
|
||||
if (s == (char *) ZSTACK1) {
|
||||
if (nbuf > 0)
|
||||
free(s_beg);
|
||||
nbuf = 0;
|
||||
return 0;
|
||||
}
|
||||
if (nbuf == 0 || s_end <= s_beg) {
|
||||
n = MEMINCR * (nbuf+1);
|
||||
v = (char **)malloc(n*(sizeof (char *)));
|
||||
if (v == NULL)
|
||||
error("mc: Out of memory\n");
|
||||
s_beg = v;
|
||||
v += n;
|
||||
if (nbuf > 0) {
|
||||
u = s_end+(MEMINCR*nbuf);
|
||||
while (u > s_end)
|
||||
*--v = *--u;
|
||||
free(s_end);
|
||||
}
|
||||
nbuf++;
|
||||
s_end = v;
|
||||
}
|
||||
*--s_end = s;
|
||||
return s_end;
|
||||
}
|
||||
|
||||
|
||||
Date: Wed, 4 Jun 86 07:59:50 EDT
|
||||
From: "R. P. Miller" <ARPEE%MX.LCS.MIT.EDU@MC.LCS.MIT.EDU>
|
||||
To: C%MX.LCS.MIT.EDU@MC.LCS.MIT.EDU
|
||||
Message-ID: <[MX.LCS.MIT.EDU].924252.860604.ARPEE>
|
||||
|
||||
mail
|
||||
|
||||
2292
doc/c/c.refman
Executable file
2292
doc/c/c.refman
Executable file
File diff suppressed because it is too large
Load Diff
48
doc/c/cctty.info
Executable file
48
doc/c/cctty.info
Executable file
@@ -0,0 +1,48 @@
|
||||
The following library routines are available ON ITS ONLY:
|
||||
|
||||
Buffered I/O:
|
||||
Input: there is a default prompt string (settable), which is
|
||||
printed when ^L in typed; if the default prompt string is not set,
|
||||
then any partial (buffered) output line is used; delete deletes a
|
||||
character as usual; CR completes the reading of a buffered line.
|
||||
Output: nothing happens until the buffer is full, a CR is
|
||||
sent, or a tyo_flush is done.
|
||||
|
||||
char tyi (); reads one buffered character; CR is changed to LF
|
||||
tyo (c) char c; outputs a buffered char; ^P changed to ^
|
||||
followed by P; full buffer or CR causes buffer to be
|
||||
sent
|
||||
tyo_flush (); forces buffer to be sent
|
||||
tyos (s) char *s; calls tyo repeatedly, changing CR to LF
|
||||
setprompt (s) char *s; sets the default prompt string
|
||||
|
||||
Unbuffered I/O:
|
||||
char utyi (); flushes the output buffer and reads a char;
|
||||
no mapping or echoing performed
|
||||
utyo (c) char c; flushes the output buffer and send the
|
||||
char; no mapping done EXCEPT ^P changed to ^ followed
|
||||
by P
|
||||
spctty (c) char c; flushes the output buffer then sends
|
||||
^P followed by the argument; for ITS display codes.
|
||||
|
||||
Interrupts:
|
||||
^G and ^S are set to interrupt; they result in signals
|
||||
of ctrlg_interrupt and ctrls_interrupt, respectively. To
|
||||
associate a routine with them (one which does nothing is a good
|
||||
way to ignore the interrupts) you do:
|
||||
on (ctrlg_interrupt, f) (likewise for ^S)
|
||||
where f is a function taking no arguments and returning no
|
||||
results. The interrupt character will have been read at
|
||||
interrupt level. If you want to handle TTY interrupts yourself,
|
||||
you can do
|
||||
on (ttyi_interrupt, fn) and fn will be called on a
|
||||
tty input interrupt; ityic (tty_input_channel) will return
|
||||
an interrupt char (-1 means it went away); tty_input_channel
|
||||
is an int defined in one of the library routines. To set
|
||||
which chars will interrupt, you can use:
|
||||
ttyget (tty_input_channel, block)
|
||||
and ttyset (tty_input_channel, block)
|
||||
where block is an array of 4 ints; these 4 words are the
|
||||
results and the arguments of the corresponding ITS .call's,
|
||||
in the same order. Initially all chars activate, and ^G and ^S
|
||||
interrupt.
|
||||
1607
doc/c/cdoc.91
Executable file
1607
doc/c/cdoc.91
Executable file
File diff suppressed because it is too large
Load Diff
3
doc/kcc/-read-.-this-
Executable file
3
doc/kcc/-read-.-this-
Executable file
@@ -0,0 +1,3 @@
|
||||
This directory contains files for the KCC PDP-10 C compiler. Currently
|
||||
there is just this one directory, but as the port progresses I'm sure there
|
||||
will be others. -- Alan
|
||||
96
doc/kcc/agree.txt
Normal file
96
doc/kcc/agree.txt
Normal file
@@ -0,0 +1,96 @@
|
||||
KCC DISTRIBUTION POLICY
|
||||
|
||||
This file describes the general KCC distribution policy --
|
||||
licensing, restrictions, and that sort of thing. If you're not sure
|
||||
how it applies to your particular situation, just get in touch.
|
||||
|
||||
First, note that the files are copyrighted. However, we
|
||||
consider them "quasi-public" and distribute them freely; the problem
|
||||
is that sometimes true public-domain stuff is acquired by private
|
||||
parties and modified slightly to produce a licensed, costly product.
|
||||
We wish to prevent this by keeping the sources available to everyone
|
||||
who wants to use KCC, but unavailable to those who have ideas of
|
||||
selling it; hence the copyright. This applies to all modifications as
|
||||
well.
|
||||
|
||||
Second, since the software is provided free of charge, there
|
||||
is absolutely NO WARRANTY on anything in this distribution, nor any
|
||||
obligation to provide maintenance, and all of the usual software
|
||||
disclaimers apply to everything. If we were to be held responsible
|
||||
for any problems, we could not distribute KCC at all.
|
||||
|
||||
The situation with respect to including KCC as a component of
|
||||
commercial software packages is fuzzy. Our current inclination is to
|
||||
allow this as a convenience to the ultimate end users, provided they
|
||||
are given ALL of the distribution, including sources and this notice.
|
||||
However, certain cirumstances may force re-assessment of this
|
||||
position; e.g. extensive modifications, huge numbers of users,
|
||||
time-consuming maintenance requirements... people with such
|
||||
applications in mind should contact us.
|
||||
|
||||
People may be tempted to modify and "improve" the software.
|
||||
This is natural and to some extent desirable, but can quickly lead to
|
||||
chaos without some rules governing these additions and modifications.
|
||||
So we simply state that the use of KCC automatically implies agreement
|
||||
with the following policies:
|
||||
|
||||
General:
|
||||
1. KCC is maintained as a primary software tool for SRI-NIC,
|
||||
and ensuring that it remains reliable and useful for this purpose must
|
||||
necessarily have our highest priority.
|
||||
2. Next most important is conformance to the C language
|
||||
defined by Harbison and Steele, plus the forthcoming ANSI C standard
|
||||
(currently a X3J11 committee draft). This includes library functions.
|
||||
3. Software portability, particularly to 4.3BSD-type UN*X,
|
||||
is slightly more important than TOPS-20 efficiency.
|
||||
4. Licensed UN*X software sources will never be used or
|
||||
distributed, and such contributions cannot be accepted.
|
||||
|
||||
People making changes to KCC or the library should:
|
||||
|
||||
1. Retain the copyright notice for each module, and add a
|
||||
history notice comment describing the change.
|
||||
2. Relay your improvements to the maintainers of the canonical
|
||||
version, so that they can be incorporated into new releases!
|
||||
Otherwise both you and the rest of the world will lose.
|
||||
3. Realize that your changes may not be adopted exactly as
|
||||
provided, if they conflict with one of the general policies. New
|
||||
library functions are particularly prone to this problem. As a
|
||||
solution we will probably collect such things into a separate library
|
||||
or two (e.g. for TOPS-20 specific functions).
|
||||
|
||||
Finally:
|
||||
If at all possible, ask people who want copies of KCC to
|
||||
get it from the canonical source. If you must give
|
||||
them a copy, keep all of the original distribution
|
||||
intact in some form so that the baseline is constant.
|
||||
|
||||
|
||||
KCC is still under active development, and new releases (with
|
||||
all accumulated bug fixes, improvements, or new features) can be
|
||||
expected frequently. At all times there will exist only one canonical
|
||||
version of the software, from which all distributions are made. If
|
||||
you can make an Internet FTP connection to SRI-NIC.ARPA, you can
|
||||
retrieve it whenever you wish.
|
||||
|
||||
Canonical version: KCCDIST: directory on SRI-NIC.ARPA
|
||||
Maintainer mailbox: <BUG-KCC@SRI-NIC.ARPA>
|
||||
Information list: <INFO-KCC@SRI-NIC.ARPA>
|
||||
(to get on:) <INFO-KCC-REQUEST@SRI-NIC.ARPA>
|
||||
|
||||
BUG-KCC is for bug and problem reports and is sometimes used for
|
||||
discussion of esoteric internal issues. INFO-KCC members basically
|
||||
receive announcements of new releases and developments, and every site
|
||||
which has installed KCC should have at least one representative on
|
||||
that list. If enough users express interest, a user discussion group
|
||||
could also be started (probably this would deal with C on TOPS-20 in
|
||||
general rather than just KCC).
|
||||
|
||||
Good luck! Feel free to contact me about any problems or questions
|
||||
you have.
|
||||
|
||||
Ken Harrenstien Internet: <KLH@SRI-NIC.ARPA> Phone: (415) 859-6552
|
||||
Room EJ200
|
||||
SRI International
|
||||
333 Ravenswood Ave.
|
||||
Menlo Park, CA 94025
|
||||
963
doc/kcc/calls.intro
Executable file
963
doc/kcc/calls.intro
Executable file
@@ -0,0 +1,963 @@
|
||||
From Sun Release 3.2 Last change: 16 July 1986
|
||||
Liberated 4/15/88 by ALAN
|
||||
|
||||
|
||||
INTRO(2) SYSTEM CALLS INTRO(2)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
intro - introduction to system calls and error numbers
|
||||
|
||||
SYNOPSIS
|
||||
#include <errno.h>
|
||||
|
||||
DESCRIPTION
|
||||
This section describes all of the system calls. A "(2V)"
|
||||
heading indicates that the system call performs differently
|
||||
when called from programs that use the System V libraries
|
||||
(programs compiled using /usr/5bin/cc). On these pages,
|
||||
both the regular behavior and the System V behavior is
|
||||
described.
|
||||
|
||||
Most of these calls have one or more error returns. An
|
||||
error condition is indicated by an otherwise impossible
|
||||
return value. This is almost always -1; the individual
|
||||
descriptions specify the details. Note that a number of
|
||||
system calls overload the meanings of these error numbers,
|
||||
and that the meanings must be interpreted according to the
|
||||
type and circumstances of the call.
|
||||
|
||||
As with normal arguments, all return codes and values from
|
||||
functions are of type integer unless otherwise noted. An
|
||||
error number is also made available in the external variable
|
||||
errno, which is not cleared on successful calls. Thus errno
|
||||
should be tested only after an error has occurred.
|
||||
|
||||
Each system call description attempts to list all possible
|
||||
error numbers. The following is a complete list of the
|
||||
errors and their names as given in <errno.h>.
|
||||
|
||||
0 Error 0
|
||||
Unused.
|
||||
|
||||
1 EPERM Not owner
|
||||
Typically this error indicates an attempt to modify a
|
||||
file in some way forbidden except to its owner or
|
||||
super-user. It is also returned for attempts by ordi-
|
||||
nary users to do things allowed only to the super-user.
|
||||
|
||||
2 ENOENT No such file or directory
|
||||
This error occurs when a filename is specified and the
|
||||
file should exist but doesn't, or when one of the
|
||||
directories in a pathname does not exist.
|
||||
|
||||
3 ESRCH No such process
|
||||
The process or process group whose number was given
|
||||
does not exist, or any such process is already dead.
|
||||
|
||||
4 EINTR Interrupted system call
|
||||
An asynchronous signal (such as interrupt or quit),
|
||||
which the user has elected to catch, occurred during a
|
||||
system call. If execution is resumed after processing
|
||||
the signal, and the system call is not restarted, it
|
||||
will appear as if the interrupted system call returned
|
||||
this error condition.
|
||||
|
||||
5 EIO I/O error
|
||||
Some physical I/O error occurred. This error may in
|
||||
some cases occur on a call following the one to which
|
||||
it actually applies.
|
||||
|
||||
6 ENXIO No such device or address
|
||||
I/O on a special file refers to a subdevice which does
|
||||
not exist, or beyond the limits of the device. It may
|
||||
also occur when, for example, a tape drive is not on-
|
||||
line or a disk pack is not loaded on a drive.
|
||||
|
||||
7 E2BIG Arg list too long
|
||||
An argument list longer than 10240 bytes is presented
|
||||
to execve.
|
||||
|
||||
8 ENOEXEC Exec format error
|
||||
A request is made to execute a file which, although it
|
||||
has the appropriate permissions, does not start with a
|
||||
valid magic number (see a.out(5)).
|
||||
|
||||
9 EBADF Bad file number
|
||||
Either a file descriptor refers to no open file, or a
|
||||
read (respectively, write) request is made to a file
|
||||
which is open only for writing (respectively, reading).
|
||||
|
||||
10 ECHILD No children
|
||||
A wait was executed by a process that had no existing
|
||||
or unwaited-for child processes.
|
||||
|
||||
11 EAGAIN No more processes
|
||||
A fork failed because the system's process table is
|
||||
full or the user is not allowed to create any more
|
||||
processes.
|
||||
|
||||
12 ENOMEM Not enough memory
|
||||
During an execve, brk, or sbrk, a program asks for more
|
||||
address space or swap space than the system is able to
|
||||
supply, or a process size limit would be exceeded. A
|
||||
lack of swap space is normally a temporary condition;
|
||||
however, a lack of address space is not a temporary
|
||||
condition. The maximum size of the text, data, and
|
||||
stack segments is a system parameter. Soft limits may
|
||||
be increased to their corresponding hard limits.
|
||||
|
||||
13 EACCES Permission denied
|
||||
An attempt was made to access a file in a way forbidden
|
||||
by the protection system.
|
||||
|
||||
14 EFAULT Bad address
|
||||
The system encountered a hardware fault in attempting
|
||||
to access the arguments of a system call.
|
||||
|
||||
15 ENOTBLK Block device required
|
||||
A file which is not a block device was mentioned where
|
||||
a block device was required, for example, in mount.
|
||||
|
||||
16 EBUSY Device busy
|
||||
An attempt to mount a file system that was already
|
||||
mounted or an attempt was made to dismount a file sys-
|
||||
tem on which there is an active file (open file,
|
||||
current directory, mounted-on file, or active text seg-
|
||||
ment).
|
||||
|
||||
17 EEXIST File exists
|
||||
An existing file was mentioned in an inappropriate con-
|
||||
text, for example, link.
|
||||
|
||||
18 EXDEV Cross-device link
|
||||
A hard link to a file on another file system was
|
||||
attempted.
|
||||
|
||||
19 ENODEV No such device
|
||||
An attempt was made to apply an inappropriate system
|
||||
call to a device (for example, an attempt to read a
|
||||
write-only device) or an attempt was made to use a dev-
|
||||
ice not configured by the system.
|
||||
|
||||
20 ENOTDIR Not a directory
|
||||
A non-directory was specified where a directory is
|
||||
required, for example, in a pathname or as an argument
|
||||
to chdir.
|
||||
|
||||
21 EISDIR Is a directory
|
||||
An attempt was made to write on a directory.
|
||||
|
||||
22 EINVAL Invalid argument
|
||||
A system call was made with an invalid argument; for
|
||||
example, dismounting a non-mounted file system, men-
|
||||
tioning an unknown signal in sigvec or kill, reading or
|
||||
writing a file for which lseek has generated a negative
|
||||
pointer, or some other argument inappropriate for the
|
||||
call. Also set by math functions, see intro(3).
|
||||
|
||||
23 ENFILE File table overflow
|
||||
The system's table of open files is full, and tem-
|
||||
porarily no more opens can be accepted.
|
||||
|
||||
24 EMFILE Too many open files
|
||||
A process tried to have more open files than the system
|
||||
allows a process to have. The customary configuration
|
||||
limit is 30 per process.
|
||||
|
||||
25 ENOTTY Inappropriate ioctl for device
|
||||
The code used in an ioctl call is not supported by the
|
||||
object that the file descriptor in the call refers to.
|
||||
|
||||
26 ETXTBSY Text file busy
|
||||
An attempt to execute a pure-procedure program which is
|
||||
currently open for writing. Also an attempt to open
|
||||
for writing a pure-procedure program that is being exe-
|
||||
cuted.
|
||||
|
||||
27 EFBIG File too large
|
||||
The size of a file exceeded the maximum file size
|
||||
(1,082,201,088 bytes).
|
||||
|
||||
28 ENOSPC No space left on device
|
||||
A write to an ordinary file, the creation of a direc-
|
||||
tory or symbolic link, or the creation of a directory
|
||||
entry failed because no more disk blocks are available
|
||||
on the file system, or the allocation of an inode for a
|
||||
newly created file failed because no more inodes are
|
||||
available on the file system.
|
||||
|
||||
29 ESPIPE Illegal seek
|
||||
An lseek was issued to a socket or pipe. This error
|
||||
may also be issued for other non-seekable devices.
|
||||
|
||||
30 EROFS Read-only file system
|
||||
An attempt to modify a file or directory was made on a
|
||||
file system mounted read-only.
|
||||
|
||||
31 EMLINK Too many links
|
||||
An attempt to make more than 32767 hard links to a
|
||||
file.
|
||||
|
||||
32 EPIPE Broken pipe
|
||||
An attempt was made to write on a pipe or socket for
|
||||
which there is no process to read the data. This con-
|
||||
dition normally generates a signal; the error is
|
||||
returned if the signal is caught or ignored.
|
||||
|
||||
33 EDOM Math argument
|
||||
The argument of a function in the math library (as
|
||||
described in section 3M) is out of the domain of the
|
||||
function.
|
||||
|
||||
34 ERANGE Result too large
|
||||
The value of a function in the math library (as
|
||||
described in section 3M) is unrepresentable within
|
||||
machine precision.
|
||||
|
||||
35 EWOULDBLOCK Operation would block
|
||||
An operation which would cause a process to block was
|
||||
attempted on an object in non-blocking mode (see
|
||||
ioctl(2)).
|
||||
|
||||
36 EINPROGRESS Operation now in progress
|
||||
An operation which takes a long time to complete (such
|
||||
as a connect(2)) was attempted on a non-blocking object
|
||||
(see ioctl(2)).
|
||||
|
||||
37 EALREADY Operation already in progress
|
||||
An operation was attempted on a non-blocking object
|
||||
which already had an operation in progress.
|
||||
|
||||
38 ENOTSOCK Socket operation on non-socket
|
||||
Self-explanatory.
|
||||
|
||||
39 EDESTADDRREQ Destination address required
|
||||
A required address was omitted from an operation on a
|
||||
socket.
|
||||
|
||||
40 EMSGSIZE Message too long
|
||||
A message sent on a socket was larger than the internal
|
||||
message buffer.
|
||||
|
||||
41 EPROTOTYPE Protocol wrong type for socket
|
||||
A protocol was specified which does not support the
|
||||
semantics of the socket type requested. For example,
|
||||
you cannot use the ARPA Internet UDP protocol with type
|
||||
SOCK_STREAM.
|
||||
|
||||
42 ENOPROTOOPT Option not supported by protocol
|
||||
A bad option was specified in a getsockopt(2) or set-
|
||||
sockopt(2) call.
|
||||
|
||||
43 EPROTONOSUPPORT Protocol not supported
|
||||
The protocol has not been configured into the system or
|
||||
no implementation for it exists.
|
||||
|
||||
44 ESOCKTNOSUPPORT Socket type not supported
|
||||
The support for the socket type has not been configured
|
||||
into the system or no implementation for it exists.
|
||||
|
||||
45 EOPNOTSUPP Operation not supported on socket
|
||||
For example, trying to accept a connection on a
|
||||
datagram socket.
|
||||
|
||||
46 EPFNOSUPPORT Protocol family not supported
|
||||
The protocol family has not been configured into the
|
||||
system or no implementation for it exists.
|
||||
|
||||
47 EAFNOSUPPORT Address family not supported by protocol
|
||||
family
|
||||
An address incompatible with the requested protocol was
|
||||
used. For example, you shouldn't necessarily expect to
|
||||
be able to use PUP Internet addresses with ARPA Inter-
|
||||
net protocols.
|
||||
|
||||
48 EADDRINUSE Address already in use
|
||||
Only one usage of each address is normally permitted.
|
||||
|
||||
49 EADDRNOTAVAIL Can't assign requested address
|
||||
Normally results from an attempt to create a socket
|
||||
with an address not on this machine.
|
||||
|
||||
50 ENETDOWN Network is down
|
||||
A socket operation encountered a dead network.
|
||||
|
||||
51 ENETUNREACH Network is unreachable
|
||||
A socket operation was attempted to an unreachable net-
|
||||
work.
|
||||
|
||||
52 ENETRESET Network dropped connection on reset
|
||||
The host you were connected to crashed and rebooted.
|
||||
|
||||
53 ECONNABORTED Software caused connection abort
|
||||
A connection abort was caused internal to your host
|
||||
machine.
|
||||
|
||||
54 ECONNRESET Connection reset by peer
|
||||
A connection was forcibly closed by a peer. This nor-
|
||||
mally results from the peer executing a shutdown(2)
|
||||
call.
|
||||
|
||||
55 ENOBUFS No buffer space available
|
||||
An operation on a socket or pipe was not performed
|
||||
because the system lacked sufficient buffer space.
|
||||
|
||||
56 EISCONN Socket is already connected
|
||||
A connect request was made on an already connected
|
||||
socket; or, a sendto or sendmsg request on a connected
|
||||
socket specified a destination other than the connected
|
||||
party.
|
||||
|
||||
57 ENOTCONN Socket is not connected
|
||||
An request to send or receive data was disallowed
|
||||
because the socket is not connected.
|
||||
|
||||
58 ESHUTDOWN Can't send after socket shutdown
|
||||
A request to send data was disallowed because the
|
||||
socket had already been shut down with a previous
|
||||
shutdown(2) call.
|
||||
|
||||
59 unused
|
||||
|
||||
60 ETIMEDOUT Connection timed out
|
||||
A connect request failed because the connected party
|
||||
did not properly respond after a period of time. (The
|
||||
timeout period is dependent on the communication proto-
|
||||
col.)
|
||||
|
||||
61 ECONNREFUSED Connection refused
|
||||
No connection could be made because the target machine
|
||||
actively refused it. This usually results from trying
|
||||
to connect to a service which is inactive on the
|
||||
foreign host.
|
||||
|
||||
62 ELOOP Too many levels of symbolic links
|
||||
A pathname lookup involved more than 8 symbolic links.
|
||||
|
||||
63 ENAMETOOLONG File name too long
|
||||
A component of a pathname exceeded 255 characters, or
|
||||
an entire pathname exceeded 1023 characters.
|
||||
|
||||
64 EHOSTDOWN Host is down
|
||||
A socket operation failed because the destination host
|
||||
was down.
|
||||
|
||||
65 EHOSTUNREACH Host is unreachable
|
||||
A socket operation was attempted to an unreachable
|
||||
host.
|
||||
|
||||
66 ENOTEMPTY Directory not empty
|
||||
An attempt was made to remove a directory with entries
|
||||
other than . and .. by performing a rmdir system call
|
||||
or a rename system call with that directory specified
|
||||
as the target directory.
|
||||
|
||||
67 unused
|
||||
|
||||
68 unused
|
||||
|
||||
69 EDQUOT Disc quota exceeded
|
||||
A write to an ordinary file, the creation of a direc-
|
||||
tory or symbolic link, or the creation of a directory
|
||||
entry failed because the user's quota of disk blocks
|
||||
was exhausted, or the allocation of an inode for a
|
||||
newly created file failed because the user's quota of
|
||||
inodes was exhausted.
|
||||
|
||||
70 ESTALE Stale NFS file handle
|
||||
A client referenced a an open file, when the file has
|
||||
been deleted.
|
||||
|
||||
71 EREMOTE Too many levels of remote in path
|
||||
An attempt was made to remotely mount a file system
|
||||
into a path which already has a remotely mounted com-
|
||||
ponent.
|
||||
|
||||
72 unused
|
||||
|
||||
73 unused
|
||||
|
||||
74 unused
|
||||
|
||||
75 ENOMSG No message of desired type
|
||||
An attempt was made to receive a message of a type that
|
||||
does not exist on the specified message queue; see
|
||||
msgop(2).
|
||||
|
||||
76 unused
|
||||
|
||||
77 EIDRM Identifier removed
|
||||
This error is returned to processes that resume execu-
|
||||
tion due to the removal of an identifier from the IPC
|
||||
system's name space (see msgctl(2), semctl(2), and
|
||||
shmctl(2)).
|
||||
|
||||
DEFINITIONS
|
||||
Descriptor
|
||||
An integer assigned by the system when a file is referenced
|
||||
by open(2V), dup(2), or pipe(2) or a socket is referenced by
|
||||
socket(2) or socketpair(2) which uniquely identifies an
|
||||
access path to that file or socket from a given process or
|
||||
any of its children.
|
||||
|
||||
Directory
|
||||
A directory is a special type of file which contains entries
|
||||
which are references to other files. Directory entries are
|
||||
called links. By convention, a directory contains at least
|
||||
two links, . and .., referred to as dot and dot-dot respec-
|
||||
tively. Dot refers to the directory itself and dot-dot
|
||||
refers to its parent directory.
|
||||
|
||||
Effective User ID, Effective Group ID, and Access Groups
|
||||
Access to system resources is governed by three values: the
|
||||
effective user ID, the effective group ID, and the group
|
||||
access list.
|
||||
|
||||
The effective user ID and effective group ID are initially
|
||||
the process's real user ID and real group ID respectively.
|
||||
Either may be modified through execution of a set-user-ID or
|
||||
set-group-ID file (possibly by one of its ancestors) (see
|
||||
execve(2)).
|
||||
|
||||
The group access list is an additional set of group ID's
|
||||
used only in determining resource accessibility. Access
|
||||
checks are performed as described below in ``File Access
|
||||
Permissions''.
|
||||
|
||||
File Access Permissions
|
||||
Every file in the file system has a set of access permis-
|
||||
sions. These permissions are used in determining whether a
|
||||
process may perform a requested operation on the file (such
|
||||
as opening a file for writing). Access permissions are
|
||||
established at the time a file is created. They may be
|
||||
changed at some later time through the chmod(2) call.
|
||||
|
||||
File access is broken down according to whether a file may
|
||||
be: read, written, or executed. Directory files use the
|
||||
execute permission to control if the directory may be
|
||||
searched.
|
||||
|
||||
File access permissions are interpreted by the system as
|
||||
they apply to three different classes of users: the owner of
|
||||
the file, those users in the file's group, anyone else.
|
||||
Every file has an independent set of access permissions for
|
||||
each of these classes. When an access check is made, the
|
||||
system decides if permission should be granted by checking
|
||||
the access information applicable to the caller.
|
||||
|
||||
Read, write, and execute/search permissions on a file are
|
||||
granted to a process if:
|
||||
|
||||
The process's effective user ID is that of the super-
|
||||
user.
|
||||
|
||||
The process's effective user ID matches the user ID of
|
||||
the owner of the file and the owner permissions allow
|
||||
the access.
|
||||
|
||||
The process's effective user ID does not match the user
|
||||
ID of the owner of the file, and either the process's
|
||||
effective group ID matches the group ID of the file, or
|
||||
the group ID of the file is in the process's group
|
||||
access list, and the group permissions allow the
|
||||
access.
|
||||
|
||||
Neither the effective user ID nor effective group ID
|
||||
and group access list of the process match the
|
||||
corresponding user ID and group ID of the file, but the
|
||||
permissions for ``other users'' allow access.
|
||||
|
||||
Otherwise, permission is denied.
|
||||
|
||||
File Name
|
||||
Names consisting of up to 255 characters may be used to name
|
||||
an ordinary file, special file, or directory.
|
||||
|
||||
These characters may be selected from the set of all ASCII
|
||||
character excluding \0 (null) and the ASCII code for /
|
||||
(slash). (The parity bit, bit 8, must be 0.)
|
||||
|
||||
Note that it is generally unwise to use *, ?, [, or ] as
|
||||
part of filenames because of the special meaning attached to
|
||||
these characters by the shell. See sh(1). Although permit-
|
||||
ted, it is advisable to avoid the use of unprintable charac-
|
||||
ters in filenames.
|
||||
|
||||
Message Queue Identifier
|
||||
A message queue identifier (msqid) is a unique positive
|
||||
integer created by a msgget(2) system call. Each msqid has
|
||||
a message queue and a data structure associated with it.
|
||||
The data structure is referred to as msqid_ds and contains
|
||||
the following members:
|
||||
|
||||
struct ipc_perm msg_perm; /* operation permission struct */
|
||||
ushort msg_qnum; /* number of msgs on q */
|
||||
ushort msg_qbytes; /* max number of bytes on q */
|
||||
ushort msg_lspid; /* pid of last msgsnd operation */
|
||||
ushort msg_lrpid; /* pid of last msgrcv operation */
|
||||
time_t msg_stime; /* last msgsnd time */
|
||||
time_t msg_rtime; /* last msgrcv time */
|
||||
time_t msg_ctime; /* last change time */
|
||||
/* Times measured in secs since */
|
||||
/* 00:00:00 GMT, Jan. 1, 1970 */
|
||||
|
||||
msg_perm is an ipc_perm structure that specifies the message
|
||||
operation permission (see below). This structure includes
|
||||
the following members:
|
||||
|
||||
ushort cuid; /* creator user id */
|
||||
ushort cgid; /* creator group id */
|
||||
ushort uid; /* user id */
|
||||
ushort gid; /* group id */
|
||||
ushort mode; /* r/w permission */
|
||||
|
||||
msg_qnum is the number of messages currently on the queue.
|
||||
msg_qbytes is the maximum number of bytes allowed on the
|
||||
queue. msg_lspid is the process id of the last process that
|
||||
performed a msgsnd operation. msg_lrpid is the process id
|
||||
of the last process that performed a msgrcv operation.
|
||||
msg_stime is the time of the last msgsnd operation,
|
||||
msg_rtime is the time of the last msgrcv operation, and
|
||||
msg_ctime is the time of the last msgctl(2) operation that
|
||||
changed a member of the above structure.
|
||||
|
||||
Message Operation Permissions
|
||||
In the msgop(2) and msgctl(2) system call descriptions, the
|
||||
permission required for an operation is given as "{token}",
|
||||
where "token" is the type of permission needed interpreted
|
||||
as follows:
|
||||
|
||||
00400 Read by user
|
||||
00200 Write by user
|
||||
00060 Read, Write by group
|
||||
00006 Read, Write by others
|
||||
|
||||
Read and Write permissions on a msqid are granted to a pro-
|
||||
cess if one or more of the following are true:
|
||||
|
||||
The effective user ID of the process is super-user.
|
||||
|
||||
The effective user ID of the process matches
|
||||
msg_perm.[c]uid in the data structure associated with
|
||||
msqid and the appropriate bit of the ``user'' portion
|
||||
(0600) of msg_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
msg_perm.[c]uid and the effective group ID of the pro-
|
||||
cess matches msg_perm.[c]gid and the appropriate bit of
|
||||
the ``group'' portion (060) of msg_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
msg_perm.[c]uid and the effective group ID of the pro-
|
||||
cess does not match msg_perm.[c]gid and the appropriate
|
||||
bit of the ``other'' portion (06) of msg_perm.mode is
|
||||
set.
|
||||
|
||||
Otherwise, the corresponding permissions are denied.
|
||||
|
||||
Parent Process ID
|
||||
A new process is created by a currently active process (see
|
||||
fork(2)). The parent process ID of a process is the process
|
||||
ID of its creator.
|
||||
|
||||
Path Name and Path Prefix
|
||||
A pathname is a null-terminated character string starting
|
||||
with an optional slash (/), followed by zero or more direc-
|
||||
tory names separated by slashes, optionally followed by a
|
||||
filename. The total length of a pathname must be less than
|
||||
{MAXPATHLEN} (1024) characters.
|
||||
|
||||
More precisely, a pathname is a null-terminated character
|
||||
string constructed as follows:
|
||||
|
||||
<path-name>::=<file-name>|<path-prefix><file-name>|/
|
||||
<path-prefix>::=<rtprefix>|/<rtprefix>
|
||||
<rtprefix>::=<dirname>/|<rtprefix><dirname>/
|
||||
|
||||
where <file-name> is a string of 1 to 255 characters other
|
||||
than the ASCII slash and null, and <dirname> is a string of
|
||||
1 to 255 characters (other than the ASCII slash and null)
|
||||
that names a directory.
|
||||
|
||||
If a pathname begins with a slash, the search begins at the
|
||||
root directory. Otherwise, the search begins at the current
|
||||
working directory.
|
||||
|
||||
A slash, by itself, names the root directory. A dot (.)
|
||||
names the current working directory.
|
||||
|
||||
A null pathname also refers to the current directory. How-
|
||||
ever, this is not true of all UNIX systems. (On such sys-
|
||||
tems, accidental use of a null pathname in routines that
|
||||
don't check for it may corrupt the current working direc-
|
||||
tory.) For portable code, specify the current directory
|
||||
explicitly using ".", rather than "".
|
||||
|
||||
Process Group ID
|
||||
Each active process is a member of a process group that is
|
||||
identified by a positive integer called the process group
|
||||
ID. This is the process ID of the group leader. This
|
||||
grouping permits the signaling of related processes (see
|
||||
killpg(2)) and the job control mechanisms of csh(1).
|
||||
|
||||
Process ID
|
||||
Each active process in the system is uniquely identified by
|
||||
a positive integer called a process ID. The range of this
|
||||
ID is from 0 to 30000.
|
||||
|
||||
Real User ID and Real Group ID
|
||||
Each user on the system is identified by a positive integer
|
||||
termed the real user ID.
|
||||
|
||||
Each user is also a member of one or more groups. One of
|
||||
these groups is distinguished from others and used in imple-
|
||||
menting accounting facilities. The positive integer
|
||||
corresponding to this distinguished group is termed the real
|
||||
group ID.
|
||||
|
||||
All processes have a real user ID and real group ID. These
|
||||
are initialized from the equivalent attributes of the pro-
|
||||
cess which created it.
|
||||
|
||||
Root Directory and Current Working Directory
|
||||
Each process has associated with it a concept of a root
|
||||
directory and a current working directory for the purpose of
|
||||
resolving path name searches. A process's root directory
|
||||
need not be the root directory of the root file system.
|
||||
|
||||
Semaphore Identifier
|
||||
A semaphore identifier (semid) is a unique positive integer
|
||||
created by a semget(2) system call. Each semid has a set of
|
||||
semaphores and a data structure associated with it. The
|
||||
data structure is referred to as semid_ds and contains the
|
||||
following members:
|
||||
|
||||
struct ipc_perm sem_perm; /* operation permission struct */
|
||||
ushort sem_nsems; /* number of sems in set */
|
||||
time_t sem_otime; /* last operation time */
|
||||
time_t sem_ctime; /* last change time */
|
||||
/* Times measured in secs since */
|
||||
/* 00:00:00 GMT, Jan. 1, 1970 */
|
||||
|
||||
sem_perm is an ipc_perm structure that specifies the sema-
|
||||
phore operation permission (see below). This structure
|
||||
includes the following members:
|
||||
|
||||
ushort cuid; /* creator user id */
|
||||
ushort cgid; /* creator group id */
|
||||
ushort uid; /* user id */
|
||||
ushort gid; /* group id */
|
||||
ushort mode; /* r/a permission */
|
||||
|
||||
The value of sem_nsems is equal to the number of semaphores
|
||||
in the set. Each semaphore in the set is referenced by a
|
||||
positive integer referred to as a sem_num. sem_num values
|
||||
run sequentially from 0 to the value of sem_nsems minus 1.
|
||||
sem_otime is the time of the last semop(2) operation, and
|
||||
sem_ctime is the time of the last semctl(2) operation that
|
||||
changed a member of the above structure.
|
||||
|
||||
A semaphore is a data structure that contains the following
|
||||
members:
|
||||
|
||||
ushort semval; /* semaphore value */
|
||||
short sempid; /* pid of last operation */
|
||||
ushort semncnt; /* # awaiting semval > cval */
|
||||
ushort semzcnt; /* # awaiting semval = 0 */
|
||||
|
||||
semval is a non-negative integer. sempid is equal to the
|
||||
process ID of the last process that performed a semaphore
|
||||
operation on this semaphore. semncnt is a count of the
|
||||
number of processes that are currently suspended awaiting
|
||||
this semaphore's semval to become greater than its current
|
||||
value. semzcnt is a count of the number of processes that
|
||||
are currently suspended awaiting this semaphore's semval to
|
||||
become zero.
|
||||
|
||||
Semaphore Operation Permissions
|
||||
In the semop(2) and semctl(2) system call descriptions, the
|
||||
permission required for an operation is given as "{token}",
|
||||
where "token" is the type of permission needed interpreted
|
||||
as follows:
|
||||
|
||||
00400 Read by user
|
||||
00200 Alter by user
|
||||
00060 Read, Alter by group
|
||||
00006 Read, Alter by others
|
||||
|
||||
Read and Alter permissions on a semid are granted to a pro-
|
||||
cess if one or more of the following are true:
|
||||
|
||||
The effective user ID of the process is super-user.
|
||||
|
||||
The effective user ID of the process matches
|
||||
sem_perm.[c]uid in the data structure associated with
|
||||
semid and the appropriate bit of the ``user'' portion
|
||||
(0600) of sem_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
sem_perm.[c]uid and the effective group ID of the pro-
|
||||
cess matches sem_perm.[c]gid and the appropriate bit of
|
||||
the ``group'' portion (060) of sem_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
sem_perm.[c]uid and the effective group ID of the pro-
|
||||
cess does not match sem_perm.[c]gid and the appropriate
|
||||
bit of the ``other'' portion (06) of sem_perm.mode is
|
||||
set.
|
||||
|
||||
Otherwise, the corresponding permissions are denied.
|
||||
|
||||
Shared Memory Identifier
|
||||
A shared memory identifier (shmid) is a unique positive
|
||||
integer created by a shmget(2) system call. Each shmid has
|
||||
a segment of memory (referred to as a shared memory segment)
|
||||
and a data structure associated with it. The data structure
|
||||
is referred to as shmid_ds and contains the following
|
||||
members:
|
||||
|
||||
struct ipc_perm shm_perm; /* operation permission struct */
|
||||
int shm_segsz; /* size of segment */
|
||||
ushort shm_cpid; /* creator pid */
|
||||
ushort shm_lpid; /* pid of last operation */
|
||||
short shm_nattch; /* number of current attaches */
|
||||
time_t shm_atime; /* last attach time */
|
||||
time_t shm_dtime; /* last detach time */
|
||||
time_t shm_ctime; /* last change time */
|
||||
/* Times measured in secs since */
|
||||
/* 00:00:00 GMT, Jan. 1, 1970 */
|
||||
|
||||
shm_perm is an ipc_perm structure that specifies the shared
|
||||
memory operation permission (see below). This structure
|
||||
includes the following members:
|
||||
|
||||
ushort cuid; /* creator user id */
|
||||
ushort cgid; /* creator group id */
|
||||
ushort uid; /* user id */
|
||||
ushort gid; /* group id */
|
||||
ushort mode; /* r/w permission */
|
||||
|
||||
shm_segsz specifies the size of the shared memory segment.
|
||||
shm_cpid is the process id of the process that created the
|
||||
shared memory identifier. shm_lpid is the process id of the
|
||||
last process that performed a shmop(2) operation.
|
||||
shm_nattch is the number of processes that currently have
|
||||
this segment attached. shm_atime is the time of the last
|
||||
shmat operation, shm_dtime is the time of the last shmdt
|
||||
operation, and shm_ctime is the time of the last shmctl(2)
|
||||
operation that changed one of the members of the above
|
||||
structure.
|
||||
|
||||
Shared Memory Operation Permissions
|
||||
In the shmop(2) and shmctl(2) system call descriptions, the
|
||||
permission required for an operation is given as "{token}",
|
||||
where "token" is the type of permission needed interpreted
|
||||
as follows:
|
||||
|
||||
00400 Read by user
|
||||
00200 Write by user
|
||||
00060 Read, Write by group
|
||||
00006 Read, Write by others
|
||||
|
||||
Read and Write permissions on a shmid are granted to a pro-
|
||||
cess if one or more of the following are true:
|
||||
|
||||
The effective user ID of the process is super-user.
|
||||
|
||||
The effective user ID of the process matches
|
||||
shm_perm.[c]uid in the data structure associated with
|
||||
shmid and the appropriate bit of the ``user'' portion
|
||||
(0600) of shm_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
shm_perm.[c]uid and the effective group ID of the pro-
|
||||
cess matches shm_perm.[c]gid and the appropriate bit of
|
||||
the ``group'' portion (060) of shm_perm.mode is set.
|
||||
|
||||
The effective user ID of the process does not match
|
||||
shm_perm.[c]uid and the effective group ID of the pro-
|
||||
cess does not match shm_perm.[c]gid and the appropriate
|
||||
bit of the ``other'' portion (06) of shm_perm.mode is
|
||||
set.
|
||||
|
||||
Otherwise, the corresponding permissions are denied.
|
||||
|
||||
Sockets and Address Families
|
||||
A socket is an endpoint for communication between processes.
|
||||
Each socket has queues for sending and receiving data.
|
||||
|
||||
Sockets are typed according to their communications proper-
|
||||
ties. These properties include whether messages sent and
|
||||
received at a socket require the name of the partner,
|
||||
whether communication is reliable, the format used in naming
|
||||
message recipients, etc.
|
||||
|
||||
Each instance of the system supports some collection of
|
||||
socket types; consult socket(2) for more information about
|
||||
the types available and their properties.
|
||||
|
||||
Each instance of the system supports some number of sets of
|
||||
communications protocols. Each protocol set supports
|
||||
addresses of a certain format. An Address Family is the set
|
||||
of addresses for a specific group of protocols. Each socket
|
||||
has an address chosen from the address family in which the
|
||||
socket was created.
|
||||
|
||||
Special Processes
|
||||
The processes with a process ID's of 0, 1, and 2 are spe-
|
||||
cial. Process 0 is the scheduler. Process 1 is the ini-
|
||||
tialization process init, and is the ancestor of every other
|
||||
process in the system. It is used to control the process
|
||||
structure. Process 2 is the paging daemon.
|
||||
|
||||
Super-user
|
||||
A process is recognized as a super-user process and is
|
||||
granted special privileges if its effective user ID is 0.
|
||||
|
||||
Tty Group ID
|
||||
Each active process can be a member of a terminal group that
|
||||
is identified by a positive integer called the tty group ID.
|
||||
This grouping is used to arbitrate between multiple jobs
|
||||
contending for the same terminal (see csh(1), and tty(4)).
|
||||
|
||||
SEE ALSO
|
||||
intro(3), perror(3)
|
||||
|
||||
|
||||
LIST OF SYSTEM CALLS
|
||||
Name Appears on Page Description
|
||||
|
||||
_exit exit(2) terminate a process
|
||||
accept accept(2) accept a connection on a socket
|
||||
access access(2) determine accessibility of file
|
||||
acct acct(2) turn accounting on or off
|
||||
adjtime adjtime(2) correct the time to allow synchronization of the system clock
|
||||
async_daemon nfssvc(2) NFS daemons
|
||||
bind bind(2) bind a name to a socket
|
||||
brk brk(2) change data segment size
|
||||
chdir chdir(2) change current working directory
|
||||
chmod chmod(2) change mode of file
|
||||
chown chown(2) change owner and group of a file
|
||||
chroot chroot(2) change root directory
|
||||
close close(2) delete a descriptor
|
||||
connect connetc(2) initiate a connection on a socket
|
||||
creat creat(2) create a new file
|
||||
dup dup(2) duplicate a descriptor
|
||||
dup2 dup(2) duplicate a descriptor
|
||||
execve execve(2) execute a file
|
||||
fchmod chmod(2) change mode of file
|
||||
fchown chown(2) change owner and group of a file
|
||||
fcntl fcntl(2) file control
|
||||
flock flock(2) apply or remove an advisory lock on an open file
|
||||
fork fork(2) create a new process
|
||||
fstat stat(2) get file status
|
||||
fsync fsync(2) synchronize a file's in-core state with that on disk
|
||||
ftruncate truncate(2) truncate a file to a specified length
|
||||
getdirentries getdirentries(2) gets directory entries in a filesystem independent format
|
||||
getdomainname getdomainname(2) get name of current domain
|
||||
getdtablesize getdtablesize(2) get descriptor table size
|
||||
getegid getgid(2) get group identity
|
||||
geteuid getuid(2) get effective user identity
|
||||
getgid getgid(2) get group identity
|
||||
getgroups getgroups(2) get group access list
|
||||
gethostid gethostid(2) get unique identifier of current host
|
||||
gethostname gethostname(2) get name of current host
|
||||
getitimer getitimer(2) get value of interval timer
|
||||
getpagesize getpagesizename(2) get system page size
|
||||
getpeername getpeername(2) get name of connected peer
|
||||
getpgrp setpgrp(2V) set and/or return the process group of a process
|
||||
getpid getpid(2) get parent process identification
|
||||
getppid getpid(2) get process identification
|
||||
getpriority getpriority(2) get program scheduling priority
|
||||
getrlimit getrlimit(2) control maximum system resource consumption
|
||||
getrusage getrusage(2) get information about resource utilization
|
||||
getsockname getsockname(2) get socket name
|
||||
getsockopt getsockopt(2) get options on sockets
|
||||
gettimeofday gettimeofday(2) get date and time
|
||||
getuid getuid(2) get user identity
|
||||
ioctl ioctl(2) control device
|
||||
kill kill(2) send signal to a process
|
||||
killpg killpg(2) send signal to a process group
|
||||
link link(2) make a hard link to a file
|
||||
listen listen(2) listen for connections on a socket
|
||||
lseek lseek(2) move read/write pointer
|
||||
lstat stat(2) get file status
|
||||
mkdir mkdir(2) make a directory file
|
||||
mknod mknod(2) make a special file
|
||||
mmap mmap(2) map or unmap pages of memory
|
||||
mount mount(2) mount file system
|
||||
msgctl msgctl(2) message control operations
|
||||
msgget msgget(2) get message queue
|
||||
msgop msgop(2) message operations
|
||||
msgrcv msgop(2) message operations
|
||||
msgsnd msgop(2) message operations
|
||||
munmap munmap(2) map or unmap pages of memory
|
||||
nfssvc nfssvc(2) NFS daemons
|
||||
open open(2V) open or create a file for reading or writing
|
||||
pipe pipe(2) create an interprocess communication channel
|
||||
profil profil(2) execution time profile
|
||||
ptrace ptrace(2) process trace
|
||||
quotactl quotactl(2) manipulate disk quotas
|
||||
read read(2V) read input
|
||||
readlink readlink(2) read value of a symbolic link
|
||||
readv read(2V) read input
|
||||
reboot reboot(2) reboot system or halt processor
|
||||
recv recv(2) receive a message from a socket
|
||||
recvfrom recv(2) receive a message from a socket
|
||||
recvmsg recv(2) receive a message from a socket
|
||||
rename rename(2) change the name of a file
|
||||
rmdir rmdir(2) remove a directory file
|
||||
sbrk brk(2) change data segment size
|
||||
select select(2) synchronous I/O multiplexing
|
||||
semctl semctl(2) semaphore control operations
|
||||
semget semget(2) get set of semaphores
|
||||
semop semop(2) semaphore operations
|
||||
send send(2) send a message from a socket
|
||||
sendmsg send(2) send a message from a socket
|
||||
sendto send(2) send a message from a socket
|
||||
setdomainname getdomainname(2) set name of current domain
|
||||
setgroups getgroups(2) set group access list
|
||||
sethostname gethostname(2) set name of current host
|
||||
setitimer getitimer(2) set value of interval timer
|
||||
setpgrp setpgrp(2V) set and/or return the process group of a process
|
||||
setpriority getpriority(2) set program scheduling priority
|
||||
setregid setregid(2) set real and effective group IDs
|
||||
setreuid setreuid(2) set real and effective user IDs
|
||||
setrlimit getrlimit(2) control maximum system resource consumption
|
||||
setsockopt getsockopt(2) set options on sockets
|
||||
settimeofday gettimeofday(2) set date and time
|
||||
shmat shmop(2) shared memory operations
|
||||
shmctl shmctl(2) shared memory control operations
|
||||
shmdt shmop(2) shared memory operations
|
||||
shmget shmget(2) get shared memory segment
|
||||
shmop shmop(2) shared memory operations
|
||||
shutdown shutdown(2) shut down part of a full-duplex connection
|
||||
sigblock sigblock(2) block signals
|
||||
sigpause sigpause(2) atomically release blocked signals and wait for interrupt
|
||||
sigsetmask sigsetmask(2) set current signal mask
|
||||
sigstack sigstack(2) set and/or get signal stack context
|
||||
sigvec sigvec(2) software signal facilities
|
||||
socket socket(2) create an endpoint for communication
|
||||
socketpair socketpair(2) create a pair of connected sockets
|
||||
stat stat(2) get file status
|
||||
statfs statfs(2) get file system statistics
|
||||
swapon swapon(2) add a swap device for interleaved paging/swapping
|
||||
symlink symlink(2) make symbolic link to a file
|
||||
sync sync(2) update super-block
|
||||
syscall syscall(2) indirect system call
|
||||
tell lseek(2) locate read/write pointer
|
||||
truncate truncate(2) truncate a file to a specified length
|
||||
umask umask(2) set file creation mode mask
|
||||
uname uname(2V) get name of current UNIX system
|
||||
unlink unlink(2) remove directory entry
|
||||
unmount umount(2) remove a file system
|
||||
utimes utimes(2) set file times
|
||||
vadvise vadvise(2) give advice to paging system
|
||||
vfork vfork(2) spawn new process in a virtual memory efficient way
|
||||
vhangup vhangup(2) virtually ``hangup'' the current control terminal
|
||||
wait wait(2) wait for process to terminate or stop
|
||||
wait3 wait(2) wait for process to terminate or stop
|
||||
write write(2V) write output
|
||||
writev write(2V) write output
|
||||
330
doc/kcc/calls.open
Executable file
330
doc/kcc/calls.open
Executable file
@@ -0,0 +1,330 @@
|
||||
|
||||
|
||||
|
||||
OPEN(2V) SYSTEM CALLS OPEN(2V)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
open - open or create a file for reading or writing
|
||||
|
||||
SYNOPSIS
|
||||
#include <sys/file.h>
|
||||
|
||||
int open(path, flags [ , mode ] )
|
||||
char *path;
|
||||
int flags, mode;
|
||||
|
||||
DESCRIPTION
|
||||
path points to the pathname of a file. open opens the named
|
||||
file for reading and/or writing, as specified by the flags
|
||||
argument, and returns a descriptor for that file. The flags
|
||||
argument may indicate the file is to be created if it does
|
||||
not already exist (by specifying the O_CREAT flag), in which
|
||||
case the file is created with mode mode as described in
|
||||
chmod(2) and modified by the process' umask value (see
|
||||
umask(2)). If the path is a null string, the kernel maps
|
||||
this null pathname to ., the current directory. flags
|
||||
values are constructed by ORing flags from the following
|
||||
list (only one of the first three flags below may be used):
|
||||
|
||||
O_RDONLY Open for reading only.
|
||||
|
||||
O_WRONLY Open for writing only.
|
||||
|
||||
O_RDWR Open for reading and writing.
|
||||
|
||||
O_NDELAY When opening a FIFO with O_RDONLY or O_WRONLY set:
|
||||
|
||||
If O_NDELAY is set:
|
||||
|
||||
An open for reading-only will return without
|
||||
delay. An open for writing-only will return
|
||||
an error if no process currently has the file
|
||||
open for reading.
|
||||
|
||||
If O_NDELAY is clear:
|
||||
|
||||
An open for reading-only will block until a
|
||||
process opens the file for writing. An open
|
||||
for writing-only will block until a process
|
||||
opens the file for reading.
|
||||
|
||||
When opening a file associated with a communication
|
||||
line:
|
||||
|
||||
If O_NDELAY is set:
|
||||
|
||||
The open will return without waiting for car-
|
||||
rier. The first time the process attempts to
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OPEN(2V) SYSTEM CALLS OPEN(2V)
|
||||
|
||||
|
||||
|
||||
perform I/O on the open file it will block
|
||||
(not currently implemented).
|
||||
|
||||
If O_NDELAY is clear:
|
||||
|
||||
The open will block until carrier is present.
|
||||
|
||||
O_APPEND If set, the file pointer will be set to the end of
|
||||
the file prior to each write.
|
||||
|
||||
O_CREAT If the file exists, this flag has no effect. Oth-
|
||||
erwise, the owner ID of the file is set to the
|
||||
effective user ID of the process, the group ID of
|
||||
the file is set to the group ID of the directory in
|
||||
which the file is created, and the low-order 12
|
||||
bits of the file mode are set to the value of mode
|
||||
modified as follows (see creat(2)):
|
||||
|
||||
All bits set in the file mode creation mask of
|
||||
the process are cleared. See umask(2).
|
||||
|
||||
The ``save text image after execution'' bit of
|
||||
the mode is cleared. See chmod(2).
|
||||
|
||||
O_TRUNC If the file exists, its length is truncated to 0
|
||||
and the mode and owner are unchanged.
|
||||
|
||||
O_EXCL If O_EXCL and O_CREAT are set, open will fail if
|
||||
the file exists. This can be used to implement a
|
||||
simple exclusive access locking mechanism. If
|
||||
O_EXCL is set and the last component of the path-
|
||||
name is a symbolic link, the open will fail even if
|
||||
the symbolic link points to a non-existent name.
|
||||
|
||||
The file pointer used to mark the current position within
|
||||
the file is set to the beginning of the file.
|
||||
|
||||
The new descriptor is set to remain open across execve sys-
|
||||
tem calls; see close(2) and fcntl(2).
|
||||
|
||||
There is a system enforced limit on the number of open file
|
||||
descriptors per process, whose value is returned by the
|
||||
getdtablesize(2) call.
|
||||
|
||||
SYSTEM V DESCRIPTION
|
||||
If the O_NDELAY flag is set on an open, that flag is set for
|
||||
that file descriptor (see fcntl) and may affect subsequent
|
||||
reads and writes. See read(2V) and write(2V).
|
||||
|
||||
RETURN VALUE
|
||||
The value -1 is returned if an error occurs, and external
|
||||
variable errno is set to indicate the cause of the error.
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OPEN(2V) SYSTEM CALLS OPEN(2V)
|
||||
|
||||
|
||||
|
||||
Otherwise a non-negative numbered file descriptor for the
|
||||
new open file is returned.
|
||||
|
||||
ERRORS
|
||||
Open fails if:
|
||||
|
||||
ENOTDIR A component of the path prefix of path is not
|
||||
a directory.
|
||||
|
||||
EINVAL path contains a character with the high-order
|
||||
bit set.
|
||||
|
||||
ENAMETOOLONG The length of a component of path exceeds 255
|
||||
characters, or the length of path exceeds
|
||||
1023 characters.
|
||||
|
||||
ENOENT O_CREAT is not set and the named file does
|
||||
not exist.
|
||||
|
||||
ENOENT A component of the path prefix of path does
|
||||
not exist.
|
||||
|
||||
ELOOP Too many symbolic links were encountered in
|
||||
translating path.
|
||||
|
||||
EACCES Search permission is denied for a component
|
||||
of the path prefix of path.
|
||||
|
||||
EACCES The required permissions (for reading and/or
|
||||
writing) are denied for the file named by
|
||||
path.
|
||||
|
||||
EACCES The file referred to by path does not exist,
|
||||
O_CREAT is specified, and the directory in
|
||||
which it is to be created does not permit
|
||||
writing.
|
||||
|
||||
EISDIR The named file is a directory, and the argu-
|
||||
ments specify it is to be opened for writing.
|
||||
|
||||
ENXIO O_NDELAY is set, the named file is a FIFO,
|
||||
O_WRONLY is set, and no process has the file
|
||||
open for reading.
|
||||
|
||||
EMFILE The system limit for open file descriptors
|
||||
per process has already been reached.
|
||||
|
||||
ENFILE The system file table is full.
|
||||
|
||||
ENOSPC The file does not exist, O_CREAT is speci-
|
||||
fied, and the directory in which the entry
|
||||
for the new file is being placed cannot be
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OPEN(2V) SYSTEM CALLS OPEN(2V)
|
||||
|
||||
|
||||
|
||||
extended because there is no space left on
|
||||
the file system containing the directory.
|
||||
|
||||
ENOSPC The file does not exist, O_CREAT is speci-
|
||||
fied, and there are no free inodes on the
|
||||
file system on which the file is being
|
||||
created.
|
||||
|
||||
EDQUOT The file does not exist, O_CREAT is speci-
|
||||
fied, and the directory in which the entry
|
||||
for the new file is being placed cannot be
|
||||
extended because the user's quota of disk
|
||||
blocks on the file system containing the
|
||||
directory has been exhausted.
|
||||
|
||||
EDQUOT The file does not exist, O_CREAT is speci-
|
||||
fied, and the user's quota of inodes on the
|
||||
file system on which the file is being
|
||||
created has been exhausted.
|
||||
|
||||
EROFS The named file does not exist, O_CREAT is
|
||||
specified, and the file system on which it is
|
||||
to be created is a read-only file system.
|
||||
|
||||
EROFS The named file resides on a read-only file
|
||||
system, and the file is to be opened for
|
||||
writing.
|
||||
|
||||
ENXIO The file is a character special or block spe-
|
||||
cial file, and the associated device does not
|
||||
exist.
|
||||
|
||||
EINTR A signal was caught during the open system
|
||||
call.
|
||||
|
||||
ETXTBSY The file is a pure procedure (shared text)
|
||||
file that is being executed and the open call
|
||||
requests write access.
|
||||
|
||||
EIO An I/O error occurred while reading from or
|
||||
writing to the file system.
|
||||
|
||||
EFAULT path points outside the process's allocated
|
||||
address space.
|
||||
|
||||
EEXIST O_EXCL and O_CREAT were both specified and
|
||||
the file exists.
|
||||
|
||||
EOPNOTSUPP An attempt was made to open a socket (not
|
||||
currently implemented).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
OPEN(2V) SYSTEM CALLS OPEN(2V)
|
||||
|
||||
|
||||
|
||||
SEE ALSO
|
||||
chmod(2), close(2), dup(2), fcntl(2), lseek(2), read(2V),
|
||||
write(2V), umask(2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 5
|
||||
|
||||
|
||||
|
||||
198
doc/kcc/calls.read
Executable file
198
doc/kcc/calls.read
Executable file
@@ -0,0 +1,198 @@
|
||||
|
||||
|
||||
|
||||
READ(2V) SYSTEM CALLS READ(2V)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
read, readv - read input
|
||||
|
||||
SYNOPSIS
|
||||
cc = read(d, buf, nbytes)
|
||||
int cc, d;
|
||||
char *buf;
|
||||
int nbytes;
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
cc = readv(d, iov, iovcnt)
|
||||
int cc, d;
|
||||
struct iovec *iov;
|
||||
int iovcnt;
|
||||
|
||||
DESCRIPTION
|
||||
read attempts to read nbytes of data from the object refer-
|
||||
enced by the descriptor d into the buffer pointed to by buf.
|
||||
readv performs the same action, but scatters the input data
|
||||
into the iovcnt buffers specified by the members of the iov
|
||||
array: iov[0], iov[1], ..., iov[iovcnt-1].
|
||||
|
||||
For readv, the iovec structure is defined as
|
||||
|
||||
struct iovec {
|
||||
caddr_t iov_base;
|
||||
int iov_len;
|
||||
};
|
||||
|
||||
Each iovec entry specifies the base address and length of an
|
||||
area in memory where data should be placed. readv will
|
||||
always fill an area completely before proceeding to the
|
||||
next.
|
||||
|
||||
On objects capable of seeking, the read starts at a position
|
||||
given by the pointer associated with d (see lseek(2)). Upon
|
||||
return from read, the pointer is incremented by the number
|
||||
of bytes actually read.
|
||||
|
||||
Objects that are not capable of seeking always read from the
|
||||
current position. The value of the pointer associated with
|
||||
such an object is undefined.
|
||||
|
||||
Upon successful completion, read and readv return the number
|
||||
of bytes actually read and placed in the buffer. The system
|
||||
guarantees to read the number of bytes requested if the
|
||||
descriptor references a normal file which has that many
|
||||
bytes left before the end-of-file, but in no other case.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.4 Last change: 25 July 1986 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
READ(2V) SYSTEM CALLS READ(2V)
|
||||
|
||||
|
||||
|
||||
If the returned value is 0, then end-of-file has been
|
||||
reached.
|
||||
|
||||
When attempting to read from a descriptor associated with an
|
||||
empty pipe, socket, or FIFO:
|
||||
|
||||
If O_NDELAY is set, the read will return a -1 and errno
|
||||
will be set to EWOULDBLOCK.
|
||||
|
||||
If O_NDELAY is clear, the read will block until data is
|
||||
written to the pipe or the file is no longer open for
|
||||
writing.
|
||||
|
||||
When attempting to read from a descriptor associated with a
|
||||
tty that has no data currently available:
|
||||
|
||||
If O_NDELAY is set, the read will return a -1 and errno
|
||||
will be set to EWOULDBLOCK.
|
||||
|
||||
If O_NDELAY is clear, the read will block until data
|
||||
becomes available.
|
||||
|
||||
If O_NDELAY is set, and less data are available than are
|
||||
requested by the read or readv, only the data that are
|
||||
available are returned, and the count indicates how many
|
||||
bytes of data were actually read.
|
||||
|
||||
SYSTEM V DESCRIPTION
|
||||
When an attempt is made to read a descriptor which is in
|
||||
no-delay mode, and there is no data currently available,
|
||||
read will return a 0 instead of returning a -1 and setting
|
||||
errno to EWOULDBLOCK. Note that this is indistinguishable
|
||||
from end-of-file.
|
||||
|
||||
RETURN VALUE
|
||||
If successful, the number of bytes actually read is
|
||||
returned. Otherwise, a -1 is returned and the global vari-
|
||||
able errno is set to indicate the error.
|
||||
|
||||
ERRORS
|
||||
read and readv will fail if one or more of the following are
|
||||
true:
|
||||
|
||||
EBADF d is not a valid file descriptor open for
|
||||
reading.
|
||||
|
||||
EISDIR d refers to a directory which is on a file
|
||||
system mounted using the NFS.
|
||||
|
||||
EFAULT buf points outside the allocated address
|
||||
space.
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.4 Last change: 25 July 1986 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
READ(2V) SYSTEM CALLS READ(2V)
|
||||
|
||||
|
||||
|
||||
EIO An I/O error occurred while reading from or
|
||||
writing to the file system.
|
||||
|
||||
EINTR A read from a slow device was interrupted
|
||||
before any data arrived by the delivery of a
|
||||
signal.
|
||||
|
||||
EINVAL The pointer associated with d was negative.
|
||||
|
||||
EWOULDBLOCK The file was marked for non-blocking I/O, and
|
||||
no data were ready to be read. In addition,
|
||||
readv may return one of the following errors:
|
||||
|
||||
EINVAL Iovcnt was less than or equal to 0, or
|
||||
greater than 16.
|
||||
|
||||
EINVAL One of the iov_len values in the iov array
|
||||
was negative.
|
||||
|
||||
EINVAL The sum of the iov_len values in the iov
|
||||
array overflowed a 32-bit integer.
|
||||
|
||||
EFAULT Part of iov points outside the process's
|
||||
allocated address space.
|
||||
|
||||
SEE ALSO
|
||||
dup(2), fcntl(2), open(2), pipe(2), select(2), socket(2),
|
||||
socketpair(2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.4 Last change: 25 July 1986 3
|
||||
|
||||
|
||||
|
||||
198
doc/kcc/calls.stat
Executable file
198
doc/kcc/calls.stat
Executable file
@@ -0,0 +1,198 @@
|
||||
|
||||
|
||||
|
||||
STAT(2) SYSTEM CALLS STAT(2)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
stat, lstat, fstat - get file status
|
||||
|
||||
SYNOPSIS
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
stat(path, buf)
|
||||
char *path;
|
||||
struct stat *buf;
|
||||
|
||||
lstat(path, buf)
|
||||
char *path;
|
||||
struct stat *buf;
|
||||
|
||||
fstat(fd, buf)
|
||||
int fd;
|
||||
struct stat *buf;
|
||||
|
||||
DESCRIPTION
|
||||
_s_t_a_t obtains information about the file named by _p_a_t_h.
|
||||
Read, write or execute permission of the named file is not
|
||||
required, but all directories listed in the path name lead-
|
||||
ing to the file must be searchable.
|
||||
|
||||
_l_s_t_a_t is like _s_t_a_t except in the case where the named file
|
||||
is a symbolic link, in which case _l_s_t_a_t returns information
|
||||
about the link, while _s_t_a_t returns information about the
|
||||
file the link references.
|
||||
|
||||
_f_s_t_a_t obtains the same information about an open file refer-
|
||||
enced by the argument descriptor, such as would be obtained
|
||||
by an _o_p_e_n call.
|
||||
|
||||
_b_u_f is a pointer to a _s_t_a_t structure into which information
|
||||
is placed concerning the file. The contents of the struc-
|
||||
ture pointed to by _b_u_f include the following members:
|
||||
|
||||
dev_t st_dev; /* device inode resides on */
|
||||
ino_t st_ino; /* this inode's number */
|
||||
u_short st_mode;/* protection */
|
||||
short st_nlink;/* number of hard links to the file */
|
||||
short st_uid; /* user ID of owner */
|
||||
short st_gid; /* group ID of owner */
|
||||
dev_t st_rdev;/* the device type, for inode that is device */
|
||||
off_t st_size;/* total size of file, in bytes */
|
||||
time_t st_atime;/* file last access time */
|
||||
time_t st_mtime;/* file last modify time */
|
||||
time_t st_ctime;/* file last status change time */
|
||||
long st_blksize;/* optimal blocksize for file system i/o ops */
|
||||
long st_blocks;/* actual number of blocks allocated */
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
STAT(2) SYSTEM CALLS STAT(2)
|
||||
|
||||
|
||||
|
||||
st_atime Time when file data was last read or modified.
|
||||
Changed by the following system calls: _m_k_n_o_d(2),
|
||||
_u_t_i_m_e_s(2), _r_e_a_d(2V), _w_r_i_t_e(2V), and _t_r_u_n_c_a_t_e(2).
|
||||
For reasons of efficiency, st_atime is not set
|
||||
when a directory is searched, although this
|
||||
would be more logical.
|
||||
|
||||
st_mtime Time when data was last modified. It is not set
|
||||
by changes of owner, group, link count, or mode.
|
||||
Changed by the following system calls: _m_k_n_o_d(2),
|
||||
_u_t_i_m_e_s(2), _w_r_i_t_e(2V).
|
||||
|
||||
st_ctime Time when file status was last changed. It is
|
||||
set both both by writing and changing the i-
|
||||
node. Changed by the following system calls:
|
||||
_c_h_m_o_d(2) _c_h_o_w_n(2), _l_i_n_k(2), _m_k_n_o_d(2), _r_e_n_a_m_e(2),
|
||||
_u_n_l_i_n_k(2), _u_t_i_m_e_s(2), _w_r_i_t_e(2V), _t_r_u_n_c_a_t_e(2).
|
||||
|
||||
The status information word _s_t__m_o_d_e has bits:
|
||||
#define S_IFMT 0170000/* type of file */
|
||||
#define S_IFIFO 0010000/* fifo special */
|
||||
#define S_IFCHR 0020000/* character special */
|
||||
#define S_IFDIR 0040000/* directory */
|
||||
#define S_IFBLK 0060000/* block special */
|
||||
#define S_IFREG 0100000/* regular file */
|
||||
#define S_IFLNK 0120000/* symbolic link */
|
||||
#define S_IFSOCK 0140000/* socket */
|
||||
#define S_ISUID 0004000/* set user id on execution */
|
||||
#define S_ISGID 0002000/* set group id on execution */
|
||||
#define S_ISVTX 0001000/* save swapped text even after use */
|
||||
#define S_IREAD 0000400/* read permission, owner */
|
||||
#define S_IWRITE 0000200/* write permission, owner */
|
||||
#define S_IEXEC 0000100/* execute/search permission, owner */
|
||||
|
||||
The mode bits 0000070 and 0000007 encode group and others
|
||||
permissions (see _c_h_m_o_d(2)).
|
||||
|
||||
RETURN VALUE
|
||||
Upon successful completion a value of 0 is returned. Other-
|
||||
wise, a value of -1 is returned and _e_r_r_n_o is set to indicate
|
||||
the error.
|
||||
|
||||
ERRORS
|
||||
_s_t_a_t and _l_s_t_a_t will fail if one or more of the following are
|
||||
true:
|
||||
|
||||
ENOTDIR A component of the path prefix of _p_a_t_h is not
|
||||
a directory.
|
||||
|
||||
EINVAL _p_a_t_h contains a character with the high-order
|
||||
bit set.
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
STAT(2) SYSTEM CALLS STAT(2)
|
||||
|
||||
|
||||
|
||||
ENAMETOOLONG The length of a component of _p_a_t_h exceeds 255
|
||||
characters, or the length of _p_a_t_h exceeds
|
||||
1023 characters.
|
||||
|
||||
ENOENT The file referred to by _p_a_t_h does not exist.
|
||||
|
||||
EACCES Search permission is denied for a component
|
||||
of the path prefix of _p_a_t_h.
|
||||
|
||||
ELOOP Too many symbolic links were encountered in
|
||||
translating _p_a_t_h.
|
||||
|
||||
EFAULT _b_u_f or _p_a_t_h points to an invalid address.
|
||||
|
||||
EIO An I/O error occurred while reading from or
|
||||
writing to the file system.
|
||||
|
||||
_f_s_t_a_t will fail if one or both of the following are true:
|
||||
|
||||
EBADF _f_d is not a valid open file descriptor.
|
||||
|
||||
EFAULT _b_u_f points to an invalid address.
|
||||
|
||||
EIO An I/O error occurred while reading from or
|
||||
writing to the file system.
|
||||
|
||||
CAVEAT
|
||||
The fields in the stat structure currently marked _s_t__s_p_a_r_e_1,
|
||||
_s_t__s_p_a_r_e_2, and _s_t__s_p_a_r_e_3 are present in preparation for
|
||||
inode time stamps expanding to 64 bits. This, however, can
|
||||
break certain programs which depend on the time stamps being
|
||||
contiguous (in calls to _u_t_i_m_e_s(2)).
|
||||
|
||||
SEE ALSO
|
||||
chmod(2), chown(2), readlink(2), utimes(2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 3
|
||||
|
||||
|
||||
|
||||
198
doc/kcc/calls.write
Executable file
198
doc/kcc/calls.write
Executable file
@@ -0,0 +1,198 @@
|
||||
|
||||
|
||||
|
||||
WRITE(2V) SYSTEM CALLS WRITE(2V)
|
||||
|
||||
|
||||
|
||||
NAME
|
||||
write, writev - write output
|
||||
|
||||
SYNOPSIS
|
||||
cc = write(d, buf, nbytes)
|
||||
int cc, d;
|
||||
char *buf;
|
||||
int nbytes;
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
cc = writev(d, iov, iovcnt)
|
||||
int cc, d;
|
||||
struct iovec *iov;
|
||||
int iovcnt;
|
||||
|
||||
DESCRIPTION
|
||||
_w_r_i_t_e attempts to write _n_b_y_t_e_s of data to the object refer-
|
||||
enced by the descriptor _d from the buffer pointed to by _b_u_f.
|
||||
_w_r_i_t_e_v performs the same action, but gathers the output data
|
||||
from the _i_o_v_c_n_t buffers specified by the members of the _i_o_v
|
||||
array: iov[0], iov[1], ..., iov[iovcnt-1].
|
||||
|
||||
For _w_r_i_t_e_v, the _i_o_v_e_c structure is defined as
|
||||
|
||||
struct iovec {
|
||||
caddr_t iov_base;
|
||||
int iov_len;
|
||||
};
|
||||
|
||||
Each _i_o_v_e_c entry specifies the base address and length of an
|
||||
area in memory from which data should be written. _w_r_i_t_e_v
|
||||
will always write a complete area before proceeding to the
|
||||
next.
|
||||
|
||||
On objects capable of seeking, the _w_r_i_t_e starts at a posi-
|
||||
tion given by the pointer associated with _d, see _l_s_e_e_k(2).
|
||||
Upon return from _w_r_i_t_e, the pointer is incremented by the
|
||||
number of bytes actually written.
|
||||
|
||||
Objects that are not capable of seeking always write from
|
||||
the current position. The value of the pointer associated
|
||||
with such an object is undefined.
|
||||
|
||||
If the O_APPEND flag of the file status flags is set, the
|
||||
file pointer will be set to the end of the file prior to
|
||||
each write.
|
||||
|
||||
If the real user is not the super-user, then _w_r_i_t_e clears
|
||||
the set-user-id bit on a file. This prevents penetration of
|
||||
system security by a user who "captures" a writable set-
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
WRITE(2V) SYSTEM CALLS WRITE(2V)
|
||||
|
||||
|
||||
|
||||
user-id file owned by the super-user.
|
||||
|
||||
When using non-blocking I/O on objects that are subject to
|
||||
flow control, such as sockets, pipes (or FIFOs), or termi-
|
||||
nals, _w_r_i_t_e and _w_r_i_t_e_v may write fewer bytes than requested;
|
||||
the return value must be noted, and the remainder of the
|
||||
operation should be retried when possible. If such an
|
||||
object's buffers are full, so that it cannot accept any
|
||||
data, then _w_r_i_t_e and _w_r_i_t_e_v will return -1 and set _e_r_r_n_o to
|
||||
EWOULDBLOCK. Otherwise, they will block until space becomes
|
||||
available.
|
||||
|
||||
SYSTEM V DESCRIPTION
|
||||
A _w_r_i_t_e (but not a _w_r_i_t_e_v) on an object that cannot accept
|
||||
any data will return a count of 0, rather than returning-1
|
||||
and setting _e_r_r_n_o to EWOULDBLOCK.
|
||||
|
||||
RETURN VALUE
|
||||
Upon successful completion the number of bytes actually wri-
|
||||
ten is returned. Otherwise a -1 is returned and the global
|
||||
variable _e_r_r_n_o is set to indicate the error.
|
||||
|
||||
ERRORS
|
||||
_w_r_i_t_e and _w_r_i_t_e_v will fail and the file pointer will remain
|
||||
unchanged if one or more of the following are true:
|
||||
|
||||
EBADF _d is not a valid descriptor open for writing.
|
||||
|
||||
EPIPE An attempt is made to write to a pipe that is
|
||||
not open for reading by any process (or to a
|
||||
socket of type SOCK_STREAM that is connected
|
||||
to a peer socket.) Note: an attempted write
|
||||
of this kind will also cause you to recieve a
|
||||
SIGPIPE signal from the kernel. If you've
|
||||
not made a special provision to catch or
|
||||
ignore this signal, your process will die.
|
||||
|
||||
EFBIG An attempt was made to write a file that
|
||||
exceeds the process's file size limit or the
|
||||
maximum file size.
|
||||
|
||||
EFAULT Part of _i_o_v or data to be written to the file
|
||||
points outside the process's allocated
|
||||
address space.
|
||||
|
||||
a signal whose.SM SV_INTERRUPT
|
||||
The call is forced to terminate prematurely due to the arrival of
|
||||
bit in sv_flags is set (see _s_i_g_v_e_c(2)).
|
||||
_s_i_g_n_a_l(3V), in the System V compatibility
|
||||
library, sets this bit for any signal it
|
||||
catches.
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
WRITE(2V) SYSTEM CALLS WRITE(2V)
|
||||
|
||||
|
||||
|
||||
EINVAL The pointer associated with _d was negative.
|
||||
|
||||
ENOSPC There is no free space remaining on the file
|
||||
system containing the file.
|
||||
|
||||
EDQUOT The user's quota of disk blocks on the file
|
||||
system containing the file has been
|
||||
exhausted.
|
||||
|
||||
EIO An I/O error occurred while reading from or
|
||||
writing to the file system.
|
||||
|
||||
EWOULDBLOCK The file was marked for non-blocking I/O, and
|
||||
no data could be written immediately.
|
||||
|
||||
In addition, _w_r_i_t_e_v may return one of the following errors:
|
||||
|
||||
EINVAL _I_o_v_c_n_t was less than or equal to 0, or
|
||||
greater than 16.
|
||||
|
||||
EINVAL One of the _i_o_v__l_e_n values in the _i_o_v array
|
||||
was negative.
|
||||
|
||||
EINVAL The sum of the _i_o_v__l_e_n values in the _i_o_v
|
||||
array overflowed a 32-bit integer.
|
||||
|
||||
SEE ALSO
|
||||
fcntl(2), lseek(2), open(2V), pipe(2), select(2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sun Release 3.2 Last change: 16 July 1986 3
|
||||
|
||||
|
||||
|
||||
1526
doc/kcc/cc.doc
Executable file
1526
doc/kcc/cc.doc
Executable file
File diff suppressed because it is too large
Load Diff
123
doc/kcc/coding.doc
Executable file
123
doc/kcc/coding.doc
Executable file
@@ -0,0 +1,123 @@
|
||||
KCC Runtime Library Coding
|
||||
|
||||
This file is oriented towards KCC implementors and describes
|
||||
some general rules for writing C library functions, along with a more
|
||||
detailed explanation of certain crucial files in the library.
|
||||
|
||||
The source for all library routines is kept in <xx.LIB> where
|
||||
"xx" depends on your system; on the distribution it is usually something
|
||||
like "KCC-4". Since that doesn't matter here, it will be left out of
|
||||
any filenames mentioned.
|
||||
|
||||
<.LIB*> Runtime library sources: Documented in:
|
||||
<.LIB> General-purpose library routines. (LIBC.DOC)
|
||||
<.LIB.STDIO> Standard I/O package routines. (LIBC.DOC)
|
||||
<.LIB.MATH> Math library routines. (LIBC.DOC)
|
||||
<.LIB.USYS> Unix simulation routines. (USYS.DOC)
|
||||
<.LIB.NETWORK> A stab at a couple BSD net routines. (LIBC.DOC)
|
||||
<.LIB.PML> Unused "portable math library" routines.
|
||||
<.LIB.TEST> Unused testing routines.
|
||||
|
||||
Guidelines for writing C library modules:
|
||||
|
||||
ALWAYS #include "c-env.h" before anything else, unless the
|
||||
code is truly portable and completely in C. Note this is "c-env.h",
|
||||
not <c-env.h>, so that it is easy to test variations.
|
||||
|
||||
All source files for KCC and the LIBC routines should refer to
|
||||
their header files with "" instead of <>, so that different versions
|
||||
of the .H files can be tested easily in the source directory before
|
||||
installation in the system-wide standard location. Normal compilation
|
||||
can simply point to the standard include-file location with the -I
|
||||
switch. However, note that user programs, unlike the library sources,
|
||||
should always use <>.
|
||||
|
||||
Keep all versions of a function together in the same file,
|
||||
rather than having a different file for each version depending on the
|
||||
system. Just conditionalize any system-dependent code appropriately.
|
||||
|
||||
If trying to assemble for an unsupported system or CPU, invoke
|
||||
the #error preprocessor command to cause a compilation error with an
|
||||
appropriate message. Alternatively, if it is important that a
|
||||
function symbol exist even though it is unsupported, you can code for
|
||||
a function that always fails with an error printout to stderr.
|
||||
|
||||
In general each specific library function should have its own
|
||||
individual file, although several functions can be collected in the
|
||||
same file if they are really tightly bound together. Any routine that
|
||||
needs to use a system call should consider using #asm for efficiency,
|
||||
instead of the jsys() or syscal() functions. (This is not normally
|
||||
recommended, but since library routines are heavily used and rarely
|
||||
modified, it's somewhat more acceptable.)
|
||||
|
||||
|
||||
ASSEMBLER HACKERS:
|
||||
.FAI or .MAC source modules should never exist. Functions which
|
||||
require assembly code should use the #asm or asm() feature of KCC.
|
||||
See the KCC user documentation for details on this.
|
||||
Use $ or % for runtime-only externals, switches, and macros,
|
||||
to avoid possible conflict with C symbols. Remember "_" in a C symbol is
|
||||
equivalent to "." in an assembler symbol.
|
||||
The C runtime support has the following symbol conventions:
|
||||
$$$xxx Major module entry name.
|
||||
$$xxxx Global symbol value, internal to runtimes.
|
||||
$xxxxx Global label, internal to runtimes.
|
||||
%xxxxx Macro-type instruction.
|
||||
%%xxxx Miscellaneous macro function.
|
||||
|
||||
USYS routines:
|
||||
If writing a UNIX system-call simulation routine (which should
|
||||
go into <.USYS>), there are additional things to be careful of, and the
|
||||
file USYS.DOC should be consulted.
|
||||
|
||||
IMPORTANT FILES:
|
||||
|
||||
C-ENV.H - C Environment defs. Contains all system/CPU configuration defs.
|
||||
Copy kept in standard include dir.
|
||||
|
||||
Should be included by every LIBC routine which has any system
|
||||
or environment dependencies. Different versions of this file exist
|
||||
for different systems/machines/configurations. Can also be included
|
||||
by user programs. IFNDEFs allow testing temporary changes by using
|
||||
the -D switch, although this should be done in conjunction with the
|
||||
appropriate -x= switches.
|
||||
|
||||
|
||||
CPU.C - Load-time CPU definitions for target machine, determined by C-ENV.H.
|
||||
Entry point: $$$CPU (a dummy)
|
||||
|
||||
This module is part of the C library and defines the values for
|
||||
several symbols which depend on the specific processor that the program
|
||||
is being loaded for. The primary usefulness of this module is that it
|
||||
allows the user to defer until load time the decision of whether to build
|
||||
a program for extended or non-extended operation. It also sets the right
|
||||
symbols to ensure that all loaded modules are compatible with the CPU type
|
||||
being loaded for.
|
||||
|
||||
CRT.C - Standard C Run Time support for KCC.
|
||||
Entry point: $$$CRT (a dummy)
|
||||
Globals: $START Startup
|
||||
__EXIT Exit
|
||||
_END,_ETEXT,_EDATA,_EALLOC Hack: Unix simul (shd move)
|
||||
$RET,$RETF,$RETZ,$RETT,$RETP,$RETN Return points
|
||||
$ZERO Handy zero constant
|
||||
$ADJBP ADJBP simulation
|
||||
$Bxxxx Various byte-pointer tables
|
||||
All C programs start here. CRT is responsible for setting up
|
||||
the C environment so that C code can execute properly. It specifically
|
||||
does not do anything about setting up a UNIX environment; that is up to
|
||||
whatever it is loaded with. When the C environment is ready, it calls
|
||||
the routine _runtm() which should perform any remaining setup and then
|
||||
call main(). Normally this routine is found in URT.C, the Unix-simulation
|
||||
Run Time module.
|
||||
|
||||
|
||||
URT.C - UNIX-simulation Run Time support (in <.LIB.USYS>)
|
||||
Entry points: _RUNTM EXIT .EXIT ERRNO
|
||||
|
||||
This module is written in C, and is called by CRT once the C
|
||||
environment is set up. URT then sets up the UNIX simulation
|
||||
environment, parsing the command line and setting up stdin, stdout,
|
||||
and stderr. When ready, it calls the user's main() function with the
|
||||
parsed command line as a normal "argc,argv" array of char pointers.
|
||||
|
||||
469
doc/kcc/codsig.doc
Executable file
469
doc/kcc/codsig.doc
Executable file
@@ -0,0 +1,469 @@
|
||||
UN*X SIGNAL SIMULATION - IMPLEMENTATION NOTES
|
||||
|
||||
This file documents some of the unholy and intimate details of
|
||||
how the KCC USYS library routines simulate the Un*x signal mechanism.
|
||||
It does not explain everything. To seriously understand what is going
|
||||
on, you need to read the exhaustive comments in the source files
|
||||
(SIGVEC.C and <signal.h>) as well as the user-oriented file
|
||||
SIGNAL.DOC.
|
||||
|
||||
|
||||
KCC Implementation:
|
||||
|
||||
We try to implement 4.3BSD, since with that the older, cruder
|
||||
mechanisms can be emulated also.
|
||||
|
||||
ITS has a very powerful software interrupt system and can
|
||||
readily handle the BSD scheme. T20 has more trouble. T10 as far as
|
||||
known is simply out of it altogether. This document is primarily about
|
||||
the T20 implementation (the only one currently existing).
|
||||
|
||||
First, a note on what "a/synchronous" means:
|
||||
|
||||
A SYNCHRONOUS interrupt is one that happens at a specific PC
|
||||
due to the instruction at that location. Typical examples: illegal
|
||||
instruction interrupts (which can include JSYS calls), floating-point
|
||||
exceptions. For these types of interrupts the PC is significant and
|
||||
it or the contents it points to may need to be checked to determine
|
||||
what to do, because simply continuing the process at that PC will
|
||||
very likely just generate another such interrupt.
|
||||
An ASYNCHRONOUS interrupt is one that may happen at ANY time,
|
||||
regardless of place; these are generated by events external to the
|
||||
program. Typical examples: TTY input interrupts, timer interrupts.
|
||||
For these, the PC is unimportant except that it should be preserved
|
||||
and restored if the interrupt handler wishes to continue whatever was
|
||||
interrupted.
|
||||
|
||||
No UN*X C signal handler has the capability of returning from
|
||||
handling a synchronous interrupt. In fact there is no mechanism
|
||||
provided for a signal handler to find out what its return PC is.
|
||||
(it's possible, with trickery, but I've never seen an example).
|
||||
4.3BSD (as opposed to 4.2 or any other Un*x) now makes this possible
|
||||
by providing the handler with a pointer to a saved-context structure!
|
||||
|
||||
Note that some signal handlers return to normal code by
|
||||
means of longjmp(); this is particularly true for alarm() handlers.
|
||||
ANSI specifies that longjmp should restore the environment properly
|
||||
even from within a signal handler, but is not required to do anything
|
||||
meaningful if called from a nested signal handler. KCC supports this
|
||||
use of longjmp().
|
||||
|
||||
T20 Problems:
|
||||
|
||||
(1) T20 PSIs have 3 priority levels. While interrupting at
|
||||
one level, no other interrupts at that level can be serviced (although
|
||||
they will be deferred). This is unlike UN*X where signals and their
|
||||
handlers are all completely independent of each other.
|
||||
|
||||
(2) The T20 return address may be a "monitor address" which
|
||||
indicates that a JSYS was interrupted before it completed. This can
|
||||
only be continued by the first DEBRK at that interrupt level; anything
|
||||
else aborts that JSYS, with unknown consequences.
|
||||
To clarify: if the return PC does not have the user-mode bit set,
|
||||
then it was interrupted out of a JSYS. The PC address however refers to
|
||||
the user address space, and points to the JSYS return location (that is,
|
||||
one greater than the location of the JSYS call.) As far as I can tell
|
||||
from examination of the monitor code, a JSYS which is interrupted just
|
||||
as it is about to return will have already changed the PC to user mode,
|
||||
so the fact of a monitor-mode PC should always imply that there is still
|
||||
something left which the JSYS hasn't yet finished doing. Unfortunately,
|
||||
the fact that IIC% itself interrupts with a monitor-mode PC implies that
|
||||
this analysis is bogus and that the PSI system is even more losing than
|
||||
could possibly be expected.
|
||||
|
||||
Doing a DEBRK back to this place will complete the JSYS.
|
||||
Doing a DEBRK anywhere else (or turning on the user-mode bit) will
|
||||
abort it and the monitor forgets the saved context. It isn't clear
|
||||
whether re-starting the JSYS, by backing up the PC by one, will do the
|
||||
right things; the ACs may not have been properly adjusted. Given the
|
||||
usual history of T20/10X, they probably haven't. This is the biggest
|
||||
problem, but can be coped with if user code is careful. I think.
|
||||
IIC% should NOT be restarted! SIN% and probably SOUT% appear
|
||||
to update their ACs and can be restarted.
|
||||
|
||||
It is possible to execute a signal handler entirely within an
|
||||
interrupt level even if the handler uses longjmp(), if longjmp conspires
|
||||
to do a DEBRK when jumping back to the previous context. So the main
|
||||
problem with handling interrupts in this way is the lock-out of other
|
||||
interrupts.
|
||||
|
||||
FINAL PLAN:
|
||||
|
||||
Key aspect: all T20 PSI interrupts are handled IMMEDIATELY
|
||||
and DEBRK'd as soon as possible. The time spent at interrupt
|
||||
level is absolutely minimal, and no signal handlers will
|
||||
be called at interrupt level unless specifically (and non-portably)
|
||||
requested.
|
||||
|
||||
The UN*X signal mechanism is primarily implemented by
|
||||
the PSI handling code, including the BSD signal block mask, rather
|
||||
than by trying to use the monitor's PSI Jsys calls.
|
||||
|
||||
No USYS (Un*x System call simulation) routine should be interrupted.
|
||||
If an internal JSYS is interrupted then that system call should
|
||||
return -1 with errno set to EINTR. Otherwise things run through
|
||||
to completion and the signal takes effect just before returning
|
||||
a normal return value.
|
||||
|
||||
************************************************************************
|
||||
NOTE!!!!! THE DETAILS OUTLINED IN THE REST OF THIS FILE ARE NOT
|
||||
NECESSARILY COMPLETE!!! Read the sources also, namely:
|
||||
SIGVEC.C - main source, PSI handlers
|
||||
SIGDAT.C - additional important source
|
||||
JSYS.C - jsys() function
|
||||
************************************************************************
|
||||
|
||||
Global variables:
|
||||
|
||||
int _sigusys; /* Positive if within critical USYS code */
|
||||
unsigned int _sigpendmask; /* 36-bit mask of pending signals */
|
||||
/* PSI can add to this during _sigusys. */
|
||||
unsigned int _sigblockmask; /* 36-bit mask saying which signals to block */
|
||||
/* PSI cannot change this during _sigusys. */
|
||||
|
||||
|
||||
BSD signal block mask:
|
||||
This is implemented softwarily, by having the
|
||||
PSI code check the mask itself and so forth, thus implementing
|
||||
whatever notion of blocking is needed, rather than trying to defer the
|
||||
actual PSIs themselves. This doesn't actually turn off the PSI
|
||||
channels, and it is in theory possible there might be runaway
|
||||
interrupts, but this seems unlikely. It cannot happen with
|
||||
synchronous interrupts, and the asynchronous ones all seem fairly
|
||||
sporadic. Installing the default action or no handler will still
|
||||
result in turning off the relevant PSI channel.
|
||||
|
||||
If a PSI is triggered for a signal which is currently handled by
|
||||
SIG_DFL (default) or SIG_IGN (ignored) then the actions are
|
||||
straightforward. Actually no PSI should ever arrive for a SIG_DFL
|
||||
handler.
|
||||
|
||||
If a PSI comes in for which a user signal handler is defined,
|
||||
there are four cases that must be checked for:
|
||||
(1) USYS code, user-mode PC - Simple deferred case.
|
||||
(2) USYS code, JSYS-mode PC - Complex but all planned for.
|
||||
(3) User code, user-mode PC - Simple immediate case.
|
||||
(4) User code, JSYS-mode PC - Complex and unpredictable; worst!!
|
||||
|
||||
In general, user-mode PCs are simple. For JSYS-mode PCs things are
|
||||
more complex. In fact, much of the hair in jsys() is due to the need
|
||||
to coordinate its activities with those of the PSI handling system.
|
||||
There is one special case: an illegal instruction interrupt (.ICILI)
|
||||
is ALWAYS delivered with the PC claiming JSYS mode, regardless of
|
||||
whether the offending instruction was a failing JSYS or a bad word
|
||||
value. To handle this screw-up, the PSI handler checks
|
||||
.ICILI interrupts specially and turns back on the user-mode PC bit if
|
||||
the bad instruction was not a JSYS. This simplifies things for the
|
||||
rest of the code.
|
||||
|
||||
(1) USYS code, user-mode PC - Simple deferred case.
|
||||
If we are in USYS code we cannot call a handler. What we do
|
||||
is set the signal's bit in _sigpendmask (for pending ints) and do a
|
||||
simple DEBRK right back to the place interrupted from, so the USYS
|
||||
code can run on to completion. Special checking is required for
|
||||
synchronous interrupts, since those usually cannot be continued.
|
||||
If the interrupt is .ICAOV or .ICFOV we can simply continue. Otherwise
|
||||
we must fail with an error message.
|
||||
|
||||
(2) USYS code, JSYS-mode PC - Complex but all planned for.
|
||||
Again, synchronous interrupts are a problem. For a JSYS-mode
|
||||
synchronous interrupt we can only continue if the PC was within the
|
||||
jsys() routine, in which case we can cause the jsys() call to abort
|
||||
(whether or not it was marked as interruptible). Otherwise, our only
|
||||
recourse is to halt the process with an error message.
|
||||
The important thing about asynchronous interrupts is that
|
||||
because the code interrupted from was USYS code, we can always be
|
||||
assured that whatever form the JSYS invocation took, both the USYS
|
||||
code and the PSI code agree on how the interrupt will be handled.
|
||||
The pending signal bit is always set; no handler is ever invoked
|
||||
from within inside USYS code. Since we always do an immediate DEBRK%, we
|
||||
always have the option of either fully continuing a JSYS or of aborting it.
|
||||
The USYS code has four different ways of invoking a JSYS:
|
||||
Asynch Synch
|
||||
(a) in-line with ERJMP Continue <imposs, fail w/err>
|
||||
(b) in-line without ERJMP Continue fail with err msg
|
||||
(c) jsys() with int flag do intret <imposs, but do intret>
|
||||
(d) jsys() without flag Continue <imposs, but do intret>
|
||||
|
||||
The interesting case here is (c) where an asynchronous interrupt
|
||||
causes the PSI code to turn on the user-mode bit and then DEBRK% to a
|
||||
specific interrupt return location within jsys(). Otherwise, execution
|
||||
merely continues.
|
||||
A synchronous interrupt within jsys() is very unlikely,
|
||||
because jsys() always has an ERJMP following a jsys invocation; also,
|
||||
any reasonable USYS assembler code should have ERJMP to handle
|
||||
expected errors. But if one happens, then:
|
||||
b: halt process with error message.
|
||||
a: should not happen, but halt with error msg anyway.
|
||||
c,d: fail with an "interrupted" return value.
|
||||
This is also not supposed to happen, but a reading of the
|
||||
T20 page fault code seems to indicate it is possible for a
|
||||
PSI to happen regardless of whether an ERJMP exists.
|
||||
|
||||
(3) User code, user-mode PC - Simple immediate case.
|
||||
This is the simple, straightforward case.
|
||||
We simply DEBRK to the signal handler, after saving all stuff on stack
|
||||
such that if the handler returns, control returns to interrupted point.
|
||||
Note that for synchronous interrupts that have the CF_OPC flag, the saved
|
||||
PC is that of the guilty instruction, so that continuation will simply
|
||||
generate another interrupt if the handler failed to remedy the problem!
|
||||
|
||||
(4) User code, JSYS-mode PC
|
||||
This is the biggest problem.
|
||||
Would be nice to only DEBRK when signal handler returns, cuz then
|
||||
the JSYS could be continued. But having the priority level stuck will
|
||||
prevent other signals from being handled, and longjmp() would have to
|
||||
test for needing to hack DEBRK% itself. If at all possible we want
|
||||
to avoid running signal handlers at interrupt level.
|
||||
So we evidently have to do the same thing as for a user-mode
|
||||
PC, and just call the signal handler with the DEBRK%.
|
||||
Users can use the interruptable flag bit for jsys() calls, and this
|
||||
will work. Otherwise, if there was any way of knowing whether it
|
||||
was safe to re-start a JSYS then we could back up the PC to do this,
|
||||
but as far as is known there isn't any guaranteed method. So "random"
|
||||
JSYS calls that don't go through the jsys() facility are subject to
|
||||
being aborted without any error indication.
|
||||
|
||||
Continuation actions for user code, JSYS-mode PC:
|
||||
Asynch Synch
|
||||
(a) in-line with ERJMP Restart <imposs, but take ERJMP>
|
||||
(b) in-line without ERJMP Restart Restart
|
||||
(c) jsys() with int flag do intret <imposs, but take intret>
|
||||
(d) jsys() without flag Restart <imposs, but take intret>
|
||||
|
||||
There is one exception to the "Restart" action: if the JSYS was IIC% then
|
||||
we simply "continue" (at the next instruction).
|
||||
|
||||
USYS interrupt handling:
|
||||
|
||||
We need some macros or functions, one to suspend interrupts at
|
||||
the start of critical USYS code, and another to reactivate them once
|
||||
the critical code is done. May also need one which checks for pending
|
||||
interrupts. Hard part is how to handle an interruptible invocation of
|
||||
jsys() such that no signal gets missed between the test for pending
|
||||
signals and actual execution of the JSYS. The best way seems to be
|
||||
for the PSI code to know about the address range of critical code in
|
||||
jsys().
|
||||
|
||||
USYS_BEG(); - Suspends all signals; used by USYS code to tell
|
||||
PSI stuff that a usys call is being executed.
|
||||
#define USYS_BEG() (++_sigusys)
|
||||
|
||||
USYS_END(); - Reactivates all signals; used by USYS code to tell
|
||||
PSI stuff that it's OK to handle signals now, and checks to
|
||||
see if there are any pending signals that should be handled.
|
||||
NOTE: the signal suspension is lifted BEFORE we test for pending
|
||||
signals; if a signal happens after the lift but before the
|
||||
_sigpendmask test, the worst that happens is we call
|
||||
_sigtrigpend() unnecessarily.
|
||||
If the ordering was reversed then we might
|
||||
get a signal after the _sigpendmask test but before lifting
|
||||
the suspension; that signal would never be serviced.
|
||||
#define USYS_END() { if (--_sigusys <= 0 && _sigpendmask) \
|
||||
_sigtrigpend(); }
|
||||
|
||||
USYS_RET(val); - Reactivates all signals; used by USYS code to tell
|
||||
PSI stuff that a usys call is finished and about to return.
|
||||
Also must check for pending signals and dispatch to handler if any.
|
||||
NOTE: the return value is computed into a temporary location
|
||||
so it cannot change regardless of what a signal handler does.
|
||||
#define USYS_RET(val) { int tmpret = (val); \
|
||||
USYS_END(); \
|
||||
return tmpret; }
|
||||
|
||||
USYS_INTRET(-1); - same as above, when USYS code knows that a jsys() has
|
||||
been interrupted and is returning for this reason. No test
|
||||
of _sigpendmask is needed. We set errno last in an attempt to avoid
|
||||
having its value changed by the signal handler; of course another
|
||||
signal could happen anytime after errno is set and before it is
|
||||
checked by the user program, but that is a problem with this
|
||||
stupid mechanism on UN*X too.
|
||||
#define USYS_INTRET(val) { --_sigusys; _sigtrigpend(); \
|
||||
errno = EINTR; \
|
||||
return val; } /* Should always be -1 */
|
||||
|
||||
USYS_SIGTST() - Tests for pending signals. Needed?
|
||||
#define USYS_SIGTST() (_sigpendmask)
|
||||
|
||||
USYS code cautions:
|
||||
The USYS routines need to be careful to always invoke the
|
||||
signal macros appropriately. But a more important (and more subtle)
|
||||
problem is that they also have to be careful of calling on other
|
||||
library routines!
|
||||
UN*X code assumes, of course, that a system call is executed
|
||||
entirely within the kernel, and has no effect on anything in the process
|
||||
address space other than things explicitly requested by the call. This
|
||||
means that our USYS code must have the same non-effect; the routines
|
||||
can only call those library functions which are fully re-entrant and
|
||||
change no static data.
|
||||
The problem is worse for those USYS calls invoked by a signal
|
||||
handler. In particular, if any USYS routine calls malloc() then it
|
||||
runs the risk of enormous unexpected screwage if the main user code
|
||||
happened to be in the middle of a malloc call! Of course the user's
|
||||
signal handler itself could call malloc() with similar bad consequences, but
|
||||
in this case the user has control over what is going on, and presumably
|
||||
knows what is going on.
|
||||
|
||||
PSI code:
|
||||
|
||||
All signal PSIs happen at level 2. If we are so unfortunate as to
|
||||
get a panic PSI within the PSI code, this will cause process
|
||||
termination, but the PSI code will be extremely minimal and should not
|
||||
cause any problems.
|
||||
Levels 1 and 3 can be reserved for the user, thus giving
|
||||
flexibility of using a level either higher or lower than the Un*x
|
||||
signal facility; some mechanism would have to be figured out, though
|
||||
(see next page).
|
||||
|
||||
When a PSI interrupt happens:
|
||||
Monitor saves PC in predefined table, jumps to PSI handler.
|
||||
Save an AC or two for checking.
|
||||
If SIG_DFL (default) was in effect, we shouldn't be getting this
|
||||
PSI at all.
|
||||
If SIG_IGN was in effect and PSI was enabled for this signal
|
||||
then the PSI handler will be a do-nothing that just
|
||||
DEBRK%s immediately.
|
||||
Otherwise, we must have a handler of some type. "psisig" is the
|
||||
location of the PSI handler for such signals. It distinguishes
|
||||
between interrupts from USYS code and user code, as well as
|
||||
whether the PC is a monitor (JSYS) or user-mode PC.
|
||||
If the handler is invoked, this is done with a DEBRK%.
|
||||
|
||||
More on extensions to sigvec():
|
||||
|
||||
For additional flexibility, the "sigvec" structure can be extended
|
||||
to include additional parameters. Existence of a new bit in sv_flags
|
||||
would indicate that the additional structure members are significant.
|
||||
|
||||
The things we'd like to be able to specify, independently of each other:
|
||||
SV_XINTLEV: ON If handler should run at interrupt level.
|
||||
SV_XASMHAN: ON If handler is special assembler routine (ACs not saved,
|
||||
no args given). Otherwise, normal C handler.
|
||||
SV_XOS: ON If the OS structure should be checked for:
|
||||
(1) Exact PSI channel # to use for this signal (0 = existing).
|
||||
(2) What PSI level to use (0 = existing).
|
||||
(3) .TICxx code (plus 1) to ATI% to this channel (0 = none).
|
||||
|
||||
Some of those are interdependent:
|
||||
Specification of a positive .TIC code always replaces any existing
|
||||
code by the new one, and use of -1 always clears any existing code. If
|
||||
the value is 0, however, then the meaning depends on whether a channel #
|
||||
was specified. If the channel # was given, 0 is the same as -1. Otherwise,
|
||||
if no channel # was given, then 0 means leave any existing code alone.
|
||||
If the handler is an assembly routine, then it MUST run at interrupt
|
||||
level. Thus, it is an error to specify SV_XASMHAN without SV_XINTLEV.
|
||||
|
||||
Currently only SV_XINTLEV is implemented. It should work to use
|
||||
longjmp() within handlers called with this flag!
|
||||
|
||||
Fixing up jsys():
|
||||
|
||||
The jsys() function has been fixed up so that it understands
|
||||
which calls take what kinds of returns, and can guarantee the
|
||||
following return values:
|
||||
-1: interrupted
|
||||
0: error (return error code in acs[0])
|
||||
1,2,3: success, returned at that location.
|
||||
|
||||
The calls SIBE, SOBE, SOBF are weird. Not clear how to distinguish
|
||||
an error return from a "normal" +1 or +2 return. Same applies to SKPIR.
|
||||
GFRKH and GFRKS have both +1, +2, and Illeg-Instr PSIs.
|
||||
|
||||
Last remaining ambiguities are for the +3 returns, of which only 3
|
||||
exist: ERSTR, GACTF, and STDIR (10X only). STDIR and GACTF are
|
||||
simple as only the successes need to be distinguished. ERSTR is hard as
|
||||
there are two different error returns.
|
||||
STDIR (10X only) - all 3 returns counted as success. Error happens
|
||||
if illegal instruction interrupt. Can distinguish success
|
||||
returns by value 1,2,3.
|
||||
GACTF - Returns 2 or 3 for success, 0 for failure (+1 return).
|
||||
ERSTR - We'll have to fudge this one:
|
||||
Return 0 for interrupt or +1 failure return.
|
||||
Return 2 for the +2 failure return.
|
||||
Return 3 for the +3 full winnage return.
|
||||
|
||||
So, for those three calls, the caller has to check the exact return value
|
||||
and cannot just assume a positive return value means winnage.
|
||||
|
||||
The jsys() code needs to distinguish skipping from
|
||||
non-skipping calls in order to return the right stuff.
|
||||
|
||||
Normally skips Non-skip
|
||||
JSYS <E> JSYS <E>
|
||||
ERJMP ret0 ERJMP ret0
|
||||
JRST ret2 JRST ret1
|
||||
JRST ret3
|
||||
|
||||
For 10X the normally-skipped ERJMP would have to be replaced by a
|
||||
ERJMPA ret0, and the PSI handler made to know about this. Different
|
||||
code sequences may be needed for the weirdos like SIBE/SOBE/SOBF.
|
||||
|
||||
Rather than keeping a global table indexed by JSYS value, it would be
|
||||
possible to have the jsys-number argument to jsys() carry some flags
|
||||
with it in the high-order bits which indicated what sort of jsys it
|
||||
was, or what actions jsys() should carry out. The jsys-name macro
|
||||
definitions in <jsys.h> can include those flags. This also makes it
|
||||
easy for user programs to examine the flags as well, and they can be
|
||||
used in #if preprocessor tests. This would involve putting the table
|
||||
into UNV.C or whatever program is used to generate the <jsys.h> type
|
||||
files from MONSYM.UNV.
|
||||
|
||||
JSYS-related PSI handling:
|
||||
|
||||
Some special handling is needed for interrupts from JSYS calls
|
||||
and from within jsys(). This is discussed in more detail in a previous
|
||||
part of this documentation.
|
||||
|
||||
_SIGTRIGPEND discussion:
|
||||
Once _sigusys is turned off, any signals which arrived during the
|
||||
call execution (but were suspended because _sigusys was on) need to be
|
||||
triggered, and this is the function of _sigtrigpend().
|
||||
If user handlers never expect to run at interrupt level then we
|
||||
could "trigger" these signals entirely within our own software, without
|
||||
fiddling with the T20 PSI system. However, to be most general it is best
|
||||
if actual PSIs are triggered -- this can be done with IIC%.
|
||||
While we are checking the pending signal mask, we have to be
|
||||
careful, because if an asynchronous signal happens just after the code
|
||||
has decided to trigger that signal, but before doing so, then
|
||||
the handler could be called twice. We need to ensure that incoming
|
||||
PSIs/signals are not serviced for the signals in _sigpendmask, even though
|
||||
_sigusys must be off.
|
||||
One straightforward method of solving this is to use DIR% to
|
||||
temporarily disable the PSI system:
|
||||
DIR% ; Suspend PSIs
|
||||
<determine bits to give IIC>
|
||||
IIC% ; Initiate PSIs on chans
|
||||
EIR% ; Allow PSIs to take effect
|
||||
|
||||
However, the overhead of additional monitor calls is a little
|
||||
annoying. We could also solve this in our software by having the PSI
|
||||
code NOT service an interrupt if _sigpendmask already indicates a
|
||||
signal instance is outstanding. Thus, _sigtrigpend() can proceed to
|
||||
trigger signals on just those bits in _sigpendmask without fear that
|
||||
an asynchronous interrupt will wrest away control in the middle; if a PSI
|
||||
does happen for one of those bits, it will see that it is already set in
|
||||
the mask and will simply DEBRK% right back.
|
||||
Note that the only place that _sigpendmask bits are turned off
|
||||
is within the PSI code just before jumping to a handler.
|
||||
There's a BUG in this scheme, though: how does the signal handler
|
||||
know when an interrupt on an already outstanding signal should be ignored,
|
||||
and when it should be handled? _sigtrigpend() is doing an IIC% which
|
||||
causes an interrupt indistinguishable from the real thing! So, to patch
|
||||
this up, the PSI code needs to check the PC and see whether it's at the
|
||||
IIC% in _sigtrigpend(); if it is, then it's OK to handle the signal.
|
||||
|
||||
A third solution might be possible such that IIC% is
|
||||
unnecessary too. If the handler for a signal happens to want
|
||||
interrupt-level processing (as this would be a special feature, most
|
||||
handlers won't) then IIC% could be used anyway. This seems unlikely
|
||||
however since at SOME point PSIs need to be turned off so that
|
||||
bits can be tested and set without fear of having them changed out from
|
||||
under, and normally it's the PSI code itself that has this security because
|
||||
it is running at interrupt level. After all, we need to turn the bit in
|
||||
_sigpendmask off just before jumping to the handler.
|
||||
Another idea: don't worry about calling it twice, after all
|
||||
the interrupt did happen at least twice?
|
||||
Bad thought: not good to permit interrupts during sigtrigpend
|
||||
because some of them might want to change things about the signal system,
|
||||
by calling sigsetmask(), sigvec(), etc! Much safer to just prohibit
|
||||
any handler calls whatsoever.
|
||||
59
doc/kcc/codsys.doc
Executable file
59
doc/kcc/codsys.doc
Executable file
@@ -0,0 +1,59 @@
|
||||
CODSYS.DOC - Information on writing USYS routines.
|
||||
|
||||
Writing USYS routines:
|
||||
|
||||
USYS Header Files
|
||||
|
||||
<sys/usysio.h> T20 Defs for USYS I/O routines.
|
||||
<sys/usysig.h> T20 Defs for USYS Signal stuff.
|
||||
<sys/usytty.h> T20 Defs for USYS TTY stuff.
|
||||
|
||||
In order to implement signal handling correctly, we have to ensure
|
||||
that no USYS routine has control wrested away from it, leaving internal
|
||||
data in an inconsistent state. For this reason certain rules
|
||||
must be followed:
|
||||
|
||||
[1] At the START of a USYS routine, invoke the macro USYS_BEG().
|
||||
This and other USYS_ macros are defined in <sys/usysig.h>.
|
||||
|
||||
[2] When RETURNING from a USYS routine, invoke one of the following macros:
|
||||
USYS_RET(val); Return a local variable or constant value.
|
||||
USYS_RETVOLATILE(val); Return a volatile (global or function) value.
|
||||
USYS_RETERR(err); Return -1, setting errno to "err".
|
||||
USYS_RETINT(); Return -1, setting errno to EINTR.
|
||||
|
||||
Each of the USYS_RETxxx macros serves as a "return" statement, and
|
||||
each takes care to process any pending signals. If a signal occurred
|
||||
during the USYS routine, it is deferred until the USYS_RETxxx happens,
|
||||
and is then handled just before returning to the user's program. The
|
||||
reason for distinguishing RETVOLATILE from simple RET is because the
|
||||
former case must save the return value in a temporary local-scope
|
||||
location while any pending interrupts are processed. Otherwise, by the
|
||||
time the actual return took place, the return value may have changed from
|
||||
what it should have been!
|
||||
|
||||
Non-interference:
|
||||
USYS routines are assumed not to interfere in any way with
|
||||
non-USYS library functions. Thus, it is very, VERY bad for a USYS
|
||||
routine to call a C library function which changes static data; the
|
||||
user program will not be expecting this. Note that signal handlers
|
||||
must be able to execute system calls, and any normal C library
|
||||
function could be interrupted. malloc(), in particular, cannot be
|
||||
used by a USYS routine for this reason!
|
||||
|
||||
JSYS calls:
|
||||
When making a JSYS call, "fast" and "slow" calls need to be
|
||||
distinguished. "fast" calls are those which never block or hang, and
|
||||
for which no asynchronous PSI interrupts are expected to happen;
|
||||
"slow" calls are those which have the potential to hang for indefinite
|
||||
amounts of time, and should be considered interruptible. If using a
|
||||
"slow" call, the JSYS_INTERRUPTABLE flag should be added to the
|
||||
JSYS-number argument in the call to jsys(). The latter will return -1
|
||||
if the call was interrupted, and in this case the USYS routine should
|
||||
return with USYS_RETINT().
|
||||
Things are actually a little more complicated than this, as
|
||||
certain calls such as read() and write() must check to see whether they
|
||||
should really be interrupted or if the signal handler permits them to
|
||||
continue what they were doing. This is done by invoking USYS_END() and
|
||||
examining its return value to see what happened. Look at the existing
|
||||
code for read(), write(), and ioctl() for examples.
|
||||
128
doc/kcc/humble.doc
Executable file
128
doc/kcc/humble.doc
Executable file
@@ -0,0 +1,128 @@
|
||||
-*-Text-*-
|
||||
|
||||
HUMBLE - Functions for hacking inferiors.
|
||||
|
||||
|
||||
#include <sys/humble.h>
|
||||
|
||||
The header file for using the humble package.
|
||||
|
||||
|
||||
int j_create()
|
||||
|
||||
Creates an inferior, returns an FD or -1 if failure
|
||||
|
||||
This FD can be used just like any other file FD. It can even be used to do
|
||||
I/O, although that is of limited utility. Conversely, a file FD obtained
|
||||
from open() (by opening "USR:COMSAT IV" for example) will work with the
|
||||
rest of the functions in the humble package, you don't have to use
|
||||
j_create(). Although in that case it is kind of hard to control the
|
||||
details of opening the USR: device.
|
||||
|
||||
Possible errors:
|
||||
- Already have 8 inferiors.
|
||||
- This job has no free channels.
|
||||
- The system has no free job slots.
|
||||
|
||||
|
||||
int j_kill(fd)
|
||||
int fd;
|
||||
|
||||
Kills the specified inferior. Just like close() except it actually
|
||||
destroys the job. Can only be applied to the last open FD. (Although I
|
||||
don't see much advantage to dup'ing a job FD, it will work...)
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- Not the last open FD.
|
||||
|
||||
|
||||
int j_read(fd, addr, buf, count)
|
||||
int fd, addr, *buf, count;
|
||||
|
||||
Copies COUNT words into BUF from the inferior starting at ADDR. Normally
|
||||
returns 0. If error, it returns the number of words left to be written.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD, negative count, negative or huge address.
|
||||
- Tried to read nonexistent memory.
|
||||
|
||||
|
||||
int j_write(fd, addr, buf, count)
|
||||
int fd, addr, *buf, count;
|
||||
|
||||
Copies COUNT words from BUF into the inferior starting at ADDR. Creating
|
||||
memory if it doesn't exist. Normally returns 0. If error it returns the
|
||||
number of words left to be written.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD, negative count, negative or huge address.
|
||||
- System doesn't currently have enough virtual address space.
|
||||
- Can't write into a foreign job.
|
||||
|
||||
|
||||
int j_dump(job_fd, file_fd)
|
||||
int job_fd, file_fd;
|
||||
|
||||
Writes a PDUMP file for the job on the freshly opened file.
|
||||
Returns 0 if success and -1 if failure.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- File FD isn't open to DSK.
|
||||
- DSK or directory full, etc.
|
||||
|
||||
|
||||
int j_load(job_fd, file_fd)
|
||||
int job_fd, file_fd;
|
||||
|
||||
Loads a PDUMP or SBLK file into the job from the freshly opened file.
|
||||
Returns 0 if success and -1 if failure.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- File FD isn't open to DSK.
|
||||
- File is in the wrong format.
|
||||
|
||||
|
||||
int j_vread(fd, var, loc)
|
||||
int fd, var, *loc;
|
||||
|
||||
Read a user variable. Returns 0 if it wins, -1 if failure.
|
||||
VAR is a user variable specifier. LOC is where to store the result.
|
||||
|
||||
The header file humble.h defines the macro SIXBIT so that user variable
|
||||
specifiers can be easily constructed. SIXBIT("USTP") returns the integer
|
||||
that is the sixbit of "USTP". Other specifiers acceptable to .CALL USRVAR
|
||||
will work as well.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- No such user variable.
|
||||
|
||||
|
||||
int j_vwrite(fd, var, val)
|
||||
int fd, var, val;
|
||||
|
||||
Write a user variable. Returns 0 if it wins, -1 if failure.
|
||||
VAR is a user variable specifier. VAL is the new value.
|
||||
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- No such user variable.
|
||||
- Can't write into this job.
|
||||
|
||||
|
||||
int j_atty(fd)
|
||||
int fd;
|
||||
|
||||
Allow an inferior to make use of the TTY. Returns 0 if it wins, -1
|
||||
if failure.
|
||||
Possible errors:
|
||||
- Not a job FD.
|
||||
- Job isn't an inferior.
|
||||
|
||||
|
||||
int j_dtty()
|
||||
|
||||
Devour the TTY. Always returns 0. Can't possibly fail!
|
||||
143
doc/kcc/instal.doc
Executable file
143
doc/kcc/instal.doc
Executable file
@@ -0,0 +1,143 @@
|
||||
INSTALLING KCC ON A TOPS-20 SYSTEM
|
||||
|
||||
KCC is normally distributed over the Internet via FTP from
|
||||
SRI-NIC.ARPA, but can also be obtained on tape. This file describes
|
||||
the basics of installing KCC for each, but you should read everything
|
||||
regardless of which medium you are using.
|
||||
|
||||
TAPE INSTALLATION:
|
||||
|
||||
The TOPS-20 tape consists of a single DUMPER saveset with
|
||||
several directories. They are organized into a single tree with the
|
||||
top-level directory named "KCCDIST" or "KCC-n" or whatever; for
|
||||
purposes of discussion we'll assume the fictitious name "KCC-n". You
|
||||
can either retrieve all files at once, or extract only those necessary
|
||||
to install a working copy of KCC.
|
||||
|
||||
Retrieving all files:
|
||||
Create a directory, such as KCCDIST, to hold the distribution.
|
||||
This will contain the following:
|
||||
|
||||
<KCC-n> General information files, in particular:
|
||||
CC.EXE The KCC compiler.
|
||||
AGREE.TXT Ethical issues.
|
||||
INSTAL.DOC Installation info; what you are reading now.
|
||||
NEWS.TXT News about this version.
|
||||
|
||||
C: => <KCC-n.INCLUDE> Runtime library and include files.
|
||||
CC.DOC KCC user documentation.
|
||||
<KCC-n.INCLUDE.SYS> More include files, Un*x oriented.
|
||||
|
||||
<KCC-n.FAIL> FAIL assembler source, binary, and manual.
|
||||
<KCC-n.KCC> KCC compiler sources and auxiliary files.
|
||||
<KCC-n.LIB*> Runtime library sources:
|
||||
<KCC-n.LIB> General-purpose library routines.
|
||||
<KCC-n.LIB.STDIO> Standard I/O package routines.
|
||||
<KCC-n.LIB.MATH> Math library routines.
|
||||
<KCC-n.LIB.USYS> Unix simulation routines.
|
||||
<KCC-n.LIB.NETWORK> A stab at a couple BSD net routines.
|
||||
<KCC-n.LIB.PML> Unused "portable math library" routines.
|
||||
<KCC-n.LIB.TEST> Unused testing routines.
|
||||
|
||||
|
||||
Installing a working KCC:
|
||||
|
||||
To install a working copy of KCC, you should create a
|
||||
directory to hold the runtime library and include files, and define
|
||||
the logical name C: to point to it. This may be the same directory as
|
||||
the one you restored the tape to (i.e. <KCC-n.INCLUDE>), or it may be
|
||||
a different place. This directory should also have a subdirectory
|
||||
called SYS to hold certain other include files.
|
||||
Read the NEWS.TXT file for any special news about this version
|
||||
of the distribution. Then define C:, copy CC.EXE to your site's SYS:
|
||||
directory, and you're all set.
|
||||
To summarize, these are the files you need:
|
||||
|
||||
<KCC-n>CC.EXE
|
||||
C: => <KCC-n.INCLUDE>*.*.0 Runtime library and include files.
|
||||
<KCC-n.INCLUDE.SYS>*.*.0 More include files, Un*x oriented.
|
||||
|
||||
Be sure to read the General Notes farther on in this file.
|
||||
|
||||
FTP transfer notes:
|
||||
|
||||
If you are fortunate enough to have Internet access, I
|
||||
recommend that you use FTP (File Transfer Protocol) to get copies of
|
||||
any KCC files that you need.
|
||||
|
||||
Connect to SRI-NIC.ARPA, and use the FTP anonymous login
|
||||
convention (username "anonymous", password your real name) to log in.
|
||||
The complete distribution is available in the directory tree defined
|
||||
by the logical name KCCDIST:, which is organized exactly as described
|
||||
in the previous (tape installation) section. You can retrieve any of
|
||||
the files or directories mentioned as needed.
|
||||
NOTE: the exact directory name which KCCDIST: points to will
|
||||
vary! It may be <KCCDIST>, or <KCC-n>, or something else, so be
|
||||
prepared to modify the given filenames appropriately.
|
||||
|
||||
BETA-TEST Versions:
|
||||
|
||||
For those interested in serving as "beta test" sites and
|
||||
living dangerously, it is possible to acquire the very latest binaries
|
||||
by transferring the following files:
|
||||
SYS:CC.EXE Latest KCC.
|
||||
C:*.*.0 Latest runtime library and include files.
|
||||
C:<KCC.SYS>*.*.0 Latest Un*x-emulation include files.
|
||||
|
||||
Since KCC and the library are still evolving steadily, you will almost
|
||||
certainly get something newer and better. Just be aware that you also
|
||||
have the following risks:
|
||||
(1) The binaries may contain new bugs.
|
||||
(2) The new versions may be incompatible (this will cause linker
|
||||
error messages to alert you, however).
|
||||
(3) The new sources will not be available until things stabilize
|
||||
enough for a new distribution to be made.
|
||||
|
||||
General Notes:
|
||||
|
||||
It is wise to retain the file version numbers during
|
||||
installation, since that is how KCC versions are numbered; a higher
|
||||
file version number means a more recent version of KCC.
|
||||
|
||||
C:CC.DOC contains user documentation. More internal details
|
||||
may be available at various places in the directory tree, in files
|
||||
named *.DOC.
|
||||
|
||||
KCC as distributed will invoke the FAIL assembler by
|
||||
default, rather than MACRO, because FAIL is much faster. If you do
|
||||
not have FAIL, you may wish to install it also. The .EXE binary,
|
||||
.FAI source, and line-printer style manual (FAIL.MANUAL) are included.
|
||||
If you don't want to try this, or for other reasons prefer to use
|
||||
MACRO, then you will want to either recompile KCC with the CCSITE.H
|
||||
file changed to reflect your preferences, or you can patch the "tgasm"
|
||||
variable in CC.EXE to have the value 1.
|
||||
|
||||
|
||||
MONITOR/EXEC Modifications:
|
||||
|
||||
There are certain modifications to the TOPS-20 Monitor and Exec
|
||||
which KCC can make use of, if they are available. They are:
|
||||
(1) Monitor: the PIP: device, to support pipes.
|
||||
(2) Exec: PRARG% protocol to support "&" background processing.
|
||||
(3) Exec: COMPIL-class command support.
|
||||
|
||||
Many sites already have these modifications, but if you don't, you
|
||||
should be able to obtain them from their origin at Stanford; contact
|
||||
Stu Grossman <Grossman@SIERRA.STANFORD.EDU>. Note that they are not
|
||||
necessary, either to use KCC or run the C programs it compiles.
|
||||
|
||||
The COMPIL-class command change is simple enough to be described here:
|
||||
|
||||
The EXEC modifications to make its COMPILE/LOAD/etc commands
|
||||
work with KCC can be found in the Stanford version of the EXEC
|
||||
in the EXECCS module:
|
||||
|
||||
In the LANGUAGE macro definition, add:
|
||||
L (DDT,C,CC,KCC) ;KCC
|
||||
Immediately after the instruction at BSRC1, add:
|
||||
CAIN P4,LT.C
|
||||
RET
|
||||
Immediately after the instruction at PUTDF, add:
|
||||
CAIN P4,LT.C
|
||||
SKIPA ; If KCC, always use native mode.
|
||||
|
||||
1230
doc/kcc/itskcc.mail
Executable file
1230
doc/kcc/itskcc.mail
Executable file
File diff suppressed because it is too large
Load Diff
70
doc/kcc/jobdat.txt
Executable file
70
doc/kcc/jobdat.txt
Executable file
@@ -0,0 +1,70 @@
|
||||
|
||||
JOBDAT as of 9 Jan 78:
|
||||
.JBUUO 40 User's UUO data location; opcode and EA stored here
|
||||
.JB41 41 User's UUO trap address; contains instruction to go
|
||||
to user's trap routine (usually JSR or PUSHJ)
|
||||
.JBERR 42 LH: unused RH: accumulated error count
|
||||
.JBREL 44 LH: 0 RH: highest lowseg address
|
||||
.JBBLT 45 three locations used by the loader and monitor
|
||||
.JBDDT 74 LH: Last addres of DDT RH: Starting address of DDT
|
||||
if 0, DDT is not loaded
|
||||
.JBHRL 115 LH: length of hiseg RH: highest legal address in
|
||||
hiseg, 0 => no hiseg
|
||||
.JBSYM 116 LH: Negative length of RH: Base address of symbol table
|
||||
symbol table
|
||||
.JBUSY 117 Same format as .JBSYM, pointer to undefined symbol table
|
||||
.JBSA 120 LH: Initial .JBFF value RH: Start address
|
||||
.JBFF 121 LH: 0 RH: Address of first free location
|
||||
in lowseg; set to .JBSA<18,18>
|
||||
by RESET UUO
|
||||
.JBREN 124 LH: Unused RH: REENTER start address
|
||||
.JBAPR 125 LH: 0 RH: Trap address for APR traps
|
||||
.JBCNI 126 APR status from CONI when APR trap taken
|
||||
.JBTPC 127 PC of next instruction when APR trap taken
|
||||
.JBOPC 130 Previous .JOBPC saved by DDT, REENTER, START or CSTART
|
||||
In some cases this value points to the erroneous UUO,
|
||||
see the reference manual.
|
||||
.JBCHN 131 LH: 0 or first free loc RH: Address of first location
|
||||
after FORTRAN IV after first FORTRAN IV
|
||||
program BLOCK DATA program
|
||||
.JBCOR 133 LH: Highest location RH: User core argument on
|
||||
in lowseg loaded last GET or SAVE command
|
||||
with nonzero data
|
||||
.JBINT 134 LH: reserved RH: 0 or address of error
|
||||
intercept block
|
||||
.JBVER 137 Version number: in octal, it is given as
|
||||
gVVVmm,,eeeeee
|
||||
where
|
||||
g is the group who last modified the program:
|
||||
0 - DEC development
|
||||
1 - DEC
|
||||
2,3,4 - Customers
|
||||
5,6,7 - Customer's users
|
||||
Mostly CMU ignores this field
|
||||
|
||||
VVV major version number, in octal
|
||||
mm minor version number.
|
||||
00 => no minor version
|
||||
01 => A
|
||||
02 => B etc.
|
||||
eeeeee edit level
|
||||
prints as (eeeeee)
|
||||
|
||||
e.g., the .JBVER version number 103402,,4556
|
||||
would print to the VERSION command as 34B(4556)-1
|
||||
NOTE: if the program has ONLY a high segment, .JBHVR must be set also!
|
||||
|
||||
For jobs with only a high segment, the vestigial job data area
|
||||
is defined as the first '10 locations of the high segment, and
|
||||
the fields are (relative to .JBHGH, usually 400000):
|
||||
|
||||
.JBHSA 0 Copy of .JBSA
|
||||
.JBH41 1 Copy of .JB41
|
||||
.JBHCR 2 Copy of .JBCOR
|
||||
.JBHRN 3 LH: restores LH of .JBHRL
|
||||
RH: restores RH of .JBREN
|
||||
.JBHVR 4 Copy of .JBVER
|
||||
.JBHNM 5 High-segment name set on a SAVE (sixbit)
|
||||
.JBHSM 6 Pointer to highsegment symbols, if any
|
||||
7 Reserved
|
||||
.JBHDA 10 First free location after vestigial job data area
|
||||
2749
doc/kcc/kcc.xmail
Executable file
2749
doc/kcc/kcc.xmail
Executable file
File diff suppressed because it is too large
Load Diff
934
doc/kcc/libc.doc
Executable file
934
doc/kcc/libc.doc
Executable file
@@ -0,0 +1,934 @@
|
||||
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.
|
||||
269
doc/kcc/libtmx.doc
Executable file
269
doc/kcc/libtmx.doc
Executable file
@@ -0,0 +1,269 @@
|
||||
NAME
|
||||
time_parse - parse free-format date/time string
|
||||
|
||||
SYNOPSIS
|
||||
#include <timex.h>
|
||||
|
||||
int time_parse(char *str, struct tmx *tmx, char **endptr);
|
||||
|
||||
struct tmx {
|
||||
struct tm tm; /* See ctime(3) for definition */
|
||||
struct tmz tmz; /* See time_lzone(3X) for definition */
|
||||
char *tmx_err; /* NULL or pointer to error message */
|
||||
int tmx_flags; /* Flags for possible future uses */
|
||||
};
|
||||
#define TMX_NULL (-1) /* Unspecified items are given this value */
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
time_parse() accepts a null-terminated date/time string,
|
||||
"str", and parses it to fill out the specified TMX structure, "tmx".
|
||||
If "endptr" is not null, it is always set to point to the remainder
|
||||
(if any) of the string not consumed by time_parse(). The "time_make()"
|
||||
function can be used to derive a UNIX time word of type "time_t" from the
|
||||
resulting TMX structure.
|
||||
|
||||
The integer return value is used to help indicate overall
|
||||
success or failure. A negative value means that the parse stopped due
|
||||
to conflicting specifications or ambiguous keywords, which usually
|
||||
means an error; otherwise, the value is the number of non-break tokens
|
||||
successfully scanned, which may be 0. Whenever the parse did not
|
||||
reach the end of the string for whatever reason, the char pointer
|
||||
"tmx_err" will be non-NULL and will point to a short constant message
|
||||
string describing the reason.
|
||||
|
||||
INPUT
|
||||
|
||||
"time_parse()" is intended to parse all reasonable date and/or
|
||||
time formats, specifically including everything that the TOPS-20/TENEX
|
||||
IDTNC JSYS will accept. The function is actually much more flexible
|
||||
than this since it will tolerate most cases of arbitrarily ordered,
|
||||
delimited, and duplicated items; it makes use of contextual clues to
|
||||
heuristically determine the meaning of numerical tokens.
|
||||
|
||||
The string is parsed into tokens which are either numbers or
|
||||
keywords, separated by punctuation break characters. Keywords may be
|
||||
in any case and need only have enough of the word to uniquely identify
|
||||
it. Whitespace serves to delimit tokens but is otherwise ignored.
|
||||
The parse will stop when it encounters a keyword which cannot be
|
||||
identified (unknown or ambiguous), or encounters a character that is
|
||||
not one of the valid date/time punctuation chars: "()-,/:." plus space
|
||||
and tab. It will also stop if the only plausible interpretation of
|
||||
a token leads to a clash with already parsed values.
|
||||
For maximum flexibility, the parsing is deliberately as
|
||||
forgiving as possible, and will accept ANY construct as long as it can
|
||||
make some sense out of it, regardless of how bizarre the string looks
|
||||
to a human. It is guaranteed to correctly parse all strings which are
|
||||
"well formatted", but it cannot be used to enforce a specific syntax
|
||||
and its interpretation of some inherently ambiguous strings may not be
|
||||
what the user expects.
|
||||
|
||||
The following are examples of acceptable formats (most taken
|
||||
from the TOPS-20/TENEX documentation). They are shown as dates and
|
||||
times; a string may have only one of these, or it may have both in
|
||||
either order, and sometimes their tokens can intermingle.
|
||||
Dates Times
|
||||
6-Feb-76 12:34:56 or 1234:56 or 123456
|
||||
Feb-6-76 12:34 or 1234
|
||||
Feb 6 76 16:30 or 1630 or 4:30pm
|
||||
Feb 6, 1976 1:23 or 123 or 0123
|
||||
6 Feb 76 1:56AM
|
||||
6.2.1976 1:56-EST or 1:56 EST or 0156AM EST
|
||||
2/6/76 NOON
|
||||
1976-02-06 12:00AM or 12 AM or 12-am or MIDNIGHT
|
||||
Wedn Febru 6 1976 5-STD or 0500-STANDARD
|
||||
1976 We Fe 6 12:30-DAYLIGHT
|
||||
|
||||
Combined:
|
||||
Fri Nov 13 13:08:02 PDT 1981 (output of ctime())
|
||||
Monday, May 24, 1987 3:22:23am-PST (03:22:23) (output of T20 daytime)
|
||||
Wed 2 Dec 87 09:18:44 PST (RFC822 format)
|
||||
10-Nov-52 12:34-CDT
|
||||
2:25 AM, December 25, 2025
|
||||
Tues-PDT,(1988)8PM..AugUS 8 Tu (free-format example)
|
||||
|
||||
Note that any USA timezone abbreviation is allowed, plus GMT, UT,
|
||||
and whatever else has been added to the keyword table.
|
||||
|
||||
DIAGNOSTICS
|
||||
To summarize all possible return situations:
|
||||
|
||||
Value tmx_err **endptr Meaning
|
||||
< 0 set start of bad token Parse stopped due to clashing specs
|
||||
or ambiguous keyword.
|
||||
>= 0 NULL '\0' String was completely parsed.
|
||||
>= 0 set start of invalid token String was not completely parsed.
|
||||
(if isalpha(**endptr) is
|
||||
true, this is an unknown
|
||||
keyword)
|
||||
|
||||
Return-value:
|
||||
The exact quantity expressed by a positive return
|
||||
value is not useful for most purposes; it represents the number of
|
||||
valid numerical or alpha (keyword) tokens that the scan parsed. This
|
||||
often but not always corresponds to the number of entries in "tmx"
|
||||
that were set. A zero return value always indicates that the scan
|
||||
halted before finding any such valid tokens, and nothing in the "tmx"
|
||||
structure was set.
|
||||
|
||||
tmx_err:
|
||||
The "tmx_err" member of "tmx" will be NULL if the parse scanned
|
||||
the entire string, otherwise it will be set. Note that the setting of
|
||||
this variable, as well as the sign of the return value, does not
|
||||
necessarily reflect either success or failure; it is up to the
|
||||
application program to interpret the results.
|
||||
|
||||
endptr:
|
||||
The "endptr" return value provides another way to see what
|
||||
terminated the scan, since it points to the first character of
|
||||
whatever token stopped it. This will be '\0' at the end of the
|
||||
string, and if **endptr is an alpha character then the token was an
|
||||
unidentified or ambiguous keyword.
|
||||
|
||||
tmx:
|
||||
NOTE!! Although a "tm" structure is included in the "tmx"
|
||||
structure, the values it contains are not completely consistent with
|
||||
the way "tm" structures are used by the C library functions. There
|
||||
are two differences:
|
||||
|
||||
(1) If a structure member was not specified by the date/time string,
|
||||
it is given the value TMX_NULL, defined in <timex.h>, which matches
|
||||
no valid value for any member. In particular the "tm.tm_yday"
|
||||
member will always be set to TMX_NULL since there is no standard
|
||||
convention for specifying it in a text string.
|
||||
|
||||
(2) The "tm.tm_year" member is set to whatever year value the
|
||||
string specifies. This may be 87, or 1987, or any other number.
|
||||
This conflicts with the C library interpretation where 0 is the
|
||||
year 1900.
|
||||
|
||||
In fact, time_parse() can be used to merely initialize a
|
||||
"tmx" structure, by invoking it like this:
|
||||
time_parse((char *)0, &tmx, (char *)0);
|
||||
The time_make() function can be used to completely
|
||||
canonicalize the structure so that the "tm" substructure is then
|
||||
acceptable to the standard C library functions.
|
||||
|
||||
It is important to remember that time_parse() does not, in
|
||||
general, attempt to verify the correctness of the resulting "tmx"
|
||||
structure. Cross-checking is limited primarily to ensuring that duplicate
|
||||
specifications are identical, e.g. if the weekday is seen twice, it
|
||||
must have the same value or the parse fails. time_make() will perform
|
||||
the necessary content checking to derive a valid "time_t" time.
|
||||
|
||||
SEE ALSO
|
||||
time_make(3X), time_lzone(3X), ctime(3), time(2)
|
||||
|
||||
AUTHOR
|
||||
Ken Harrenstien, SRI International
|
||||
<KLH@SRI-NIC.ARPA> 415/859-6552
|
||||
|
||||
NAME
|
||||
time_make - derive a "time_t" time value from a parsed time
|
||||
|
||||
SYNOPSIS
|
||||
#include <timex.h>
|
||||
|
||||
time_t time_make(struct tmx *tmx);
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"time_make" can be considered the inverse of "localtime"; it
|
||||
takes a broken-down time description and returns a UNIX-format time
|
||||
value of type "time_t". Note that it works only on "tmx" structures,
|
||||
not "tm" structures.
|
||||
|
||||
It is possible to have unspecified (TMX_NULL) values in the
|
||||
structure, which time_make() will attempt to default reasonably:
|
||||
|
||||
Member Default value if unspecified
|
||||
tm.tm_year Current year.
|
||||
tm.tm_mon 0 (Jan) if year specified, else current month.
|
||||
tm.tm_mday 1 if month specified, else current mday.
|
||||
tm.tm_hour 0
|
||||
tm.tm_min 0
|
||||
tm.tm_sec 0
|
||||
tmz.tm_secwest tmz.tm_minwest * 60
|
||||
tmz.tm_minwest local timezone
|
||||
tm.tm_isdst 0 if timezone not local. If local,
|
||||
applies local DST algorithm.
|
||||
|
||||
For example, "July 10" will default the year to its current
|
||||
value (e.g. 1987), and the time to 00:00:00. Just giving "1980" will
|
||||
produce "Jan 1, 1980 00:00:00".
|
||||
The timezone, which is specified by tmz.tm_secwest, defaults
|
||||
to tmz.tm_minwest*60 which in turn defaults to the local timezone. A
|
||||
value of 1 for either variable is interpreted as an explicit request to
|
||||
use the local timezone.
|
||||
If tm.tm_isdst is set to 0, daylight savings time (DST) is never
|
||||
applied. If set to 1 (to represent USA DST) then DST is always applied
|
||||
(by subtracting one hour). If not specified, no DST is applied unless
|
||||
the timezone is that of the local timezone, in which case DST is applied
|
||||
if appropriate (determined by consulting localtime()).
|
||||
|
||||
The "tm.tm_yday" (day of year) entry is not used to compute
|
||||
the time unless neither the month nor day are specified. The
|
||||
"tm.tm_wday" (day of week) entry is never used. However, specifying
|
||||
either of these values will cause them to be checked, and time_make()
|
||||
will fail if the values conflict with the other date specifications.
|
||||
|
||||
DIAGNOSTICS
|
||||
-1 is returned on failure, which is usually due to a parameter
|
||||
being out of range. A failure return will always set "tmx_err" in the
|
||||
tmx structure to point to a short constant error message. This variable
|
||||
is cleared to NULL for a successful return.
|
||||
|
||||
SEE ALSO
|
||||
time_parse(3X), time_lzone(3X), ctime(3), time(2)
|
||||
|
||||
AUTHOR
|
||||
Ken Harrenstien, SRI International
|
||||
<KLH@SRI-NIC.ARPA> 415/859-6552
|
||||
|
||||
NAME
|
||||
time_lzone - get local timezone information
|
||||
time_tzset - set local timezone information from system
|
||||
|
||||
SYNOPSIS
|
||||
#include <timex.h>
|
||||
|
||||
int time_lzone(struct tmz *tmz);
|
||||
|
||||
int time_tzset(void);
|
||||
|
||||
struct tmz {
|
||||
long tmz_secwest; /* Secs west of GMT (-12/+12 hrs) */
|
||||
int tmz_minwest; /* Same, in mins. (tmz_secwest/60) */
|
||||
int tmz_dsttype; /* DST type if any (0 = none, 1 = USA) */
|
||||
char *tmz_name; /* Standard timezone name */
|
||||
char *tmz_dname; /* DST timezone name (if any) */
|
||||
};
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"time_lzone()" fills out the structure pointed to. It
|
||||
does this by copying the contents of the static area indicated by
|
||||
time_tzset(), which it calls if necessary.
|
||||
|
||||
"time_tzset()" attempts to get the local timezone information
|
||||
from the system or environment (this is system dependent) and uses
|
||||
this to set (or re-initialize) its static TMZ structure. If
|
||||
successful, a pointer to this structure is returned; if it could not
|
||||
be initialized, NULL is returned. It is not necessary to invoke this
|
||||
function explicitly unless the program has some reason to believe that
|
||||
the timezone may have changed during execution.
|
||||
|
||||
SEE ALSO
|
||||
time_make(3X), time_parse(3X), ctime(3), time(2)
|
||||
|
||||
BUGS
|
||||
Time zones are a big mess, especially on Unix where there are
|
||||
several incompatible (and unportable) methods of tracking them.
|
||||
These functions attempt to standardize the information more sensibly.
|
||||
|
||||
AUTHOR
|
||||
Ken Harrenstien, SRI International
|
||||
<KLH@SRI-NIC.ARPA> 415/859-6552
|
||||
|
||||
24
doc/kcc/libtrm.doc
Executable file
24
doc/kcc/libtrm.doc
Executable file
@@ -0,0 +1,24 @@
|
||||
libtrm is the library for fancy terminal stuff. currently, libtrm
|
||||
only contains trmcap, the package for slurping in termcap entries,
|
||||
returning requested portions, creating cursor movement strings, and so
|
||||
forth. for full trmcap documentation see termcap(3X); for termcap
|
||||
entry documentation see termcap(5);
|
||||
|
||||
trmcap contains these functions:
|
||||
|
||||
int tgetent(bp, name); get entry for terminal name into buf bp
|
||||
int tgetnum(cap); get the numeric value of capability cap
|
||||
int tgetflag(cap); returns 1 if the given cap is present, else 0
|
||||
char *tgetstr(cap, area); return string value for capability cap
|
||||
char *tgoto(cm, h, v); return cursor addressing string to get to h,v
|
||||
void tputs(string, nlines, outfun);
|
||||
output string with padding. see man page.
|
||||
char *tparam(string, outstring, len, arg0, arg1, arg2, arg3);
|
||||
expand termcap entry into outstring
|
||||
|
||||
hideous global constants which trmcap defines:
|
||||
|
||||
short ospeed; output speed of the terminal
|
||||
char PC; character to use for padding to terminal?
|
||||
char *BC; pointer to "bc" capability in termcap entry
|
||||
char *UP; pointer to "up" capability in termcap entry
|
||||
205
doc/kcc/news.txt
Executable file
205
doc/kcc/news.txt
Executable file
@@ -0,0 +1,205 @@
|
||||
03/17/87 KCC 560, LIBC 124: <2,,1> Binary KCC update
|
||||
|
||||
A copy of CC.EXE.560 is included which fixes a number of
|
||||
annoying bugs that users encountered with KCC 557. The sources are
|
||||
still those for 557, however. The library is unchanged.
|
||||
|
||||
03/06/87 KCC 557, LIBC 124: <2,,1> Third formal distribution snapshot
|
||||
|
||||
IMPORTANT: this version of KCC is incompatible with previous
|
||||
versions! The way that structures are returned from functions has
|
||||
changed, and the layout of "char" and "short" objects in structures has
|
||||
also changed. In order to enforce this, the symbol $$CVER has been
|
||||
updated, and any attempt to load .REL modules which have been produced
|
||||
by incompatible versions of KCC will cause LINK to complain with an
|
||||
error message similar to this:
|
||||
|
||||
%LNKMDS Multiply-defined global symbol $$CVER
|
||||
Detected in module PRINTF from file C:LIBC.REL
|
||||
Defined value = 1000001, this value = 2000001
|
||||
|
||||
This is easily remedied by re-compiling old modules. Fortunately, no
|
||||
further incompatible changes are expected to be necessary.
|
||||
|
||||
Nothing has really changed from the user's viewpoint. However,
|
||||
there are several new features available, and some inefficiencies
|
||||
corrected. The noteworthy changes are listed below, very briefly;
|
||||
as usual, CC.DOC should be consulted for more complete and informative
|
||||
details.
|
||||
|
||||
KCC: ---------------------------------------------------------------
|
||||
|
||||
KCC - Bug fixes:
|
||||
A multitude of minor bug fixes too trivial to mention, almost
|
||||
all having to do with incorrectly optimized code. One that wasn't
|
||||
trivial was that {char c, *cp = &c;} used to produce an (int *)!
|
||||
|
||||
KCC - Incompatible changes:
|
||||
* "shorts" are now 18 bits long (halfwords), with sizeof(short) == 2.
|
||||
* The mechanism for returning structure values from functions
|
||||
is different. This is an internal change, invisible to the user, which
|
||||
is much more efficient than the previous method.
|
||||
* Structure members of type "char" and "short" are now packed
|
||||
differently (more compactly). Any structure using these types will be
|
||||
laid out differently in storage.
|
||||
* Integer narrowing and widening is now done properly in all
|
||||
situations. This may cause incorrectly written code to behave
|
||||
differently.
|
||||
* Implicit arithmetic conversions now follow the ANSI
|
||||
value-preserving rules rather than the old K&R and H&S
|
||||
unsigned-preserving rules. Ambiguous code may behave differently.
|
||||
* "float" values are no longer automatically converted to "double",
|
||||
except for function arguments. This conforms to the ANSI draft.
|
||||
* The "signed" keyword (introduced by ANSI) has been implemented.
|
||||
* "volatile" and "const" (also new from ANSI) are now reserved
|
||||
words (but unimplemented).
|
||||
|
||||
KCC - Extension: New data types:
|
||||
5 new data types have been introduced, which act like "char"
|
||||
but with different byte sizes. You can now manipulate signed or
|
||||
unsigned bytes of 6, 7, 8, 9, or 18 bits. This is non-portable and
|
||||
intended strictly for PDP-10 machine-dependent code where efficiency
|
||||
is desirable.
|
||||
|
||||
KCC - Efficiency improvements:
|
||||
The change to the structure handling mechanism falls in this
|
||||
category. Structure copies used to always take two subroutine calls
|
||||
and two copies; they now use a single in-line BLT (or a series of
|
||||
single-word moves, whichever is best), and are much faster than
|
||||
element-by-element copying.
|
||||
KCC's constant initialization code has been improved to the point
|
||||
where almost all constants are now initialized at load time rather than
|
||||
at run time; a similar mechanism eliminates the code that used to generate
|
||||
string constant pointers. You will see a significant difference with code
|
||||
that uses many string literals; both startup time and program size are
|
||||
reduced.
|
||||
KCC's pointer arithmetic for byte pointers is MUCH better.
|
||||
Pointer comparison and subtraction formerly used subroutine calls and
|
||||
many, many instructions; both now use a handful of in-line
|
||||
instructions and some magic numbers.
|
||||
There are no more calls to internal run-time subroutines.
|
||||
All of the operations which used to require this are now compiled
|
||||
in-line, including double-int and int-double conversion, pointer
|
||||
operations, and structure copying.
|
||||
|
||||
KCC - unsigned and signed data:
|
||||
KCC now fully supports "unsigned int" operations. Some code
|
||||
that uses unsigned integers will now compile differently. Division in
|
||||
particular needs many more instructions. Any integer type, "char" in
|
||||
particular, may be declared as "signed" and will behave accordingly.
|
||||
|
||||
KCC - Switch changes:
|
||||
-L=<str> Passes <str> in the command string to the linking loader.
|
||||
-v=<fs> (Verbosity) has been expanded; see CC.DOC. -v alone prints out
|
||||
everything, including the loader command string.
|
||||
-l Libraries loaded with the -l switch are now loaded in /SEARCH
|
||||
mode (they evidently weren't before).
|
||||
|
||||
KCC - Miscellaneous
|
||||
-d=sym now produces a *.CYM file instead of *.SYM, to avoid
|
||||
conflicts with LINK output files.
|
||||
-P=ansi+kcc is now the default. The effects are minor and documented
|
||||
in CC.DOC. The three new ANSI keywords of "signed", "const", and "volatile"
|
||||
are recognized, although only the first has any real effect.
|
||||
|
||||
|
||||
LIBC: ---------------------------------------------------------------
|
||||
|
||||
More minor bug fixes to the LIBC stdio routines.
|
||||
|
||||
open() now attempts to track down and expand logical device
|
||||
names completely (thus performing what the monitor should be doing but
|
||||
isn't). Thus, open("X:subdir/filename.ext",0) will work even if X is
|
||||
a search path. Previously only the first device/directory could be tried.
|
||||
This permits KCC #includes to work with C: defined as a search path.
|
||||
|
||||
malloc() no longer allocates pages 770-777 (non-extended) or
|
||||
37770-37777 (extended), so that obsolete forms of DDT can be mapped therein.
|
||||
|
||||
12/07/86 KCC 537, LIBC 93: <1,,1> Informal distribution snapshot
|
||||
Various additional bug fixes.
|
||||
There may be some stray files and other cruft as this was made just
|
||||
so that Systems Concepts could get the latest stuff; some things haven't
|
||||
been checked out.
|
||||
|
||||
10/21/86 KCC 534
|
||||
Fixed a register allocation bug which got tickled by very large
|
||||
floating-point expressions.
|
||||
LIBC: fixed a minor scanf bug. Fixed system/vfork/exit to work properly.
|
||||
|
||||
09/28/86 KCC 533, LIBC 14: <1,,1> Second formal distribution snapshot
|
||||
|
||||
This is called a "snapshot" to emphasize that while the sources
|
||||
in this distribution should be consistent and working, the compiler and
|
||||
library are still under active development to remove known quirks and
|
||||
deficiencies, and have already changed.
|
||||
As before, all .REL files must be recompiled; the STDIO
|
||||
structures are different and there are new C runtime hooks. Most
|
||||
importantly, the symbol $$CVER is now defined in every module
|
||||
(currently it is <1,,1>) so as to detect any future conflicts when
|
||||
loading modules that were incompatibly compiled.
|
||||
Various change notes follow. For all of them, see the CC.DOC
|
||||
file for more details.
|
||||
|
||||
KCC: ---------------------------------------------------------------
|
||||
|
||||
KCC - Command line
|
||||
There are several new switches, and the way KCC interprets
|
||||
filenames is slightly different. A file with a .REL extension is
|
||||
always ignored, but is passed on to the loader. A file without any
|
||||
extension is special if the -q switch is given; it is only compiled if
|
||||
the .C source is more recent than the .REL binary.
|
||||
New switches:
|
||||
-A Specify nonstandard assembler header file (old meaning of -H)
|
||||
-H Specify nonstandard path for #include <> files.
|
||||
-i Loader: load program to run with extended addressing.
|
||||
-L Loader: nonstandard path for library files.
|
||||
-l Loader: search specified library
|
||||
-o Loader: specify .EXE filename.
|
||||
-P Set portability level.
|
||||
-q Compile extension-less files conditionally.
|
||||
|
||||
KCC - General
|
||||
There are no real changes in code generation. A couple of
|
||||
over-optimization bugs were fixed, and a couple of other optimizations
|
||||
added.
|
||||
KCC now generates its own assembler header based on the target
|
||||
CPU, assembler, and system; the file C-HDR.FAI no longer exists.
|
||||
Two more KCC extensions were added: the `ident` quoting syntax,
|
||||
and the asm() in-line code mechanism. #asm and #endasm must now appear
|
||||
only within a function body.
|
||||
KCC identifiers are now unique up to 31 characters, as per the
|
||||
ANSI draft (external symbols are still only unique up to 6).
|
||||
The runtime variable $EXADF no longer exists. The decision on
|
||||
whether to run extended is now made at load time, either with the -i switch
|
||||
or by loading C:LIBCKX as the first module.
|
||||
|
||||
LIBC: --------------------------------------------------------------
|
||||
|
||||
LIBC - CHAR
|
||||
ispunct() was "fixed" to exclude space. CARM claims space is
|
||||
included, but neither ANSI nor BSD does so. We assume this is a mistake
|
||||
in CARM.
|
||||
|
||||
LIBC - STRING
|
||||
The routines memchr, memcmp, memcpy, memset were added from ANSI.
|
||||
|
||||
LIBC - STORAGE
|
||||
free(), malloc(), and realloc() now behave as per ANSI when given
|
||||
NULL or zero as arguments.
|
||||
|
||||
LIBC - STDIO
|
||||
The "update" mode is now supported for streams. In addition
|
||||
to this, the library implements the ANSI concept of text vs binary
|
||||
streams. The 'R' specification was flushed; 'b', '7', '8', '9', 'C',
|
||||
and "C-" were added.
|
||||
|
||||
LIBC - other
|
||||
system() was added.
|
||||
|
||||
07/26/86 KCC 512, CLIB 225: First formal distribution version.
|
||||
|
||||
If you already had a version of KCC on your system, you will need
|
||||
to recompile any .REL modules generated by the old version, because the
|
||||
new KCC uses a different STDIO package. .EXE files do not need to be
|
||||
recompiled.
|
||||
302
doc/kcc/port.doc
Executable file
302
doc/kcc/port.doc
Executable file
@@ -0,0 +1,302 @@
|
||||
INSTALLING AND PORTING KCC
|
||||
|
||||
This file tries to document various things about porting KCC to other
|
||||
systems; including how to bring up new versions on systems which already have
|
||||
KCC.
|
||||
|
||||
A "port" involves two major things: the KCC compiler itself, and
|
||||
the C library (LIBC). They are interdependent, and since the compiler is used
|
||||
to compile itself, things have to be done carefully.
|
||||
|
||||
KCC supports all CPUs: KA, KI, KS, KL, KX. System is irrelevant.
|
||||
LIBC supports only TOPS-20. There is partial (but not complete)
|
||||
support for TOPS-10, WAITS, and ITS.
|
||||
|
||||
The usual situations are these:
|
||||
|
||||
(1) Installing KCC and the library for the first time.
|
||||
(2) Installing a new version of the C library or KCC.
|
||||
(3) Using KCC as a cross-compiler for another CPU or system.
|
||||
(4) Porting KCC and the library to a different CPU or system.
|
||||
|
||||
Other references:
|
||||
For (1) see the distribution INSTAL.DOC file.
|
||||
The KCC USER.DOC section about cross-compiling.
|
||||
The C library file LIBC.DOC.
|
||||
|
||||
Building and installing a compatible new version of KCC/LIBC for your current
|
||||
system:
|
||||
|
||||
If the new version has exactly the same site-dependent parameters
|
||||
(C-ENV.H and CCSITE.H) then you can simply install the new binary, without
|
||||
bothering to recompile from the sources.
|
||||
|
||||
If your site-dependent parameters are different from that of the
|
||||
distributed KCC then you will need to recompile from the sources. To do
|
||||
this,
|
||||
1. Make sure that the C-ENV.H in the KCC source directory is correct
|
||||
(or, if it doesn't exist, that the version in the include directory
|
||||
is correct). Ditto your CCSITE.H or whatever is different.
|
||||
2. On TOPS-20, simply invoke CC.MIC, as in "DO CC". Or do it by hand.
|
||||
Then install the resulting NCC.EXE on your system as "CC".
|
||||
|
||||
NOTE: if the new version of KCC makes some changes in its runtime
|
||||
assumptions, you may need to change some other things. The most that may be
|
||||
required is to follow the cross-compilation procedure as if porting to a new
|
||||
system. If you know what is going on, you may be able to get by with less
|
||||
than a full new installation.
|
||||
|
||||
Using KCC as a cross-compiler:
|
||||
|
||||
This assumes you want to set things up on your source system so
|
||||
that you can compile programs into binaries which can then be moved to
|
||||
a target system and executed there. This can sometimes be useful if the
|
||||
target system is not really able to run KCC itself for whatever reason.
|
||||
Also, we assume that the source system is a TOPS-20, since KCC is fully
|
||||
supported for that system and the existence of logical names makes things
|
||||
easier.
|
||||
|
||||
[1] Set up a new directory to serve as the standard include (and library)
|
||||
directory for the target system's files. For the sake of the following
|
||||
discussion, call this directory NC:.
|
||||
|
||||
[2] Install in NC: an appropriately editted copy of C-ENV.H.
|
||||
In particular, CPU_xxx and SYS_xxx must be set properly.
|
||||
|
||||
[3] Build a program called, for example, XCC which passes its arguments on
|
||||
to an invoked CC with the addition of appropriate switches.
|
||||
See the program TCC.C in the KCC source directory for a sample;
|
||||
this program runs on TOPS-20 and compiles code for TENEX.
|
||||
The following switches should be set:
|
||||
-L to specify the library directory path (NC:)
|
||||
-H to specify the standard include file directory path (NC:)
|
||||
-x to specify the target CPU, system, and assembler
|
||||
And others such as -A if necessary.
|
||||
|
||||
[4] Use XCC to recompile and rebuild the entire C library. Install the
|
||||
new LIBC.REL in NC:.
|
||||
|
||||
[5] That's it. KCC does not need to be rebuilt, since XCC will simply
|
||||
invoke KCC with the appropriate switches set. Whenever making
|
||||
a program to run on the target machine, just use XCC.
|
||||
|
||||
KCC/LIBC Cross-compilation (using logical names):
|
||||
|
||||
These are the complete steps to follow when building a new KCC and
|
||||
LIBC for another CPU or system. You may be able to get by with doing less,
|
||||
if you know what is going on and what the changes are. You may have to
|
||||
do more, if the new CPU or system is not fully supported.
|
||||
|
||||
This procedure for cross-compiling KCC/LIBC for a different CPU/system
|
||||
relies on TOPS-20 logical names, and assumes that the logical name C: is used
|
||||
by the source machine's KCC to refer to both the standard include directory
|
||||
and the library directory. If some other logical name is used, substitute
|
||||
that for C: in the following discussion.
|
||||
|
||||
[0] Redefine C: to be a search path pointing FIRST to a "new" standard
|
||||
directory, and SECOND to KCC's standard directory (normally
|
||||
this is the system-wide logical name C:).
|
||||
This requires the user to:
|
||||
@define C: <new-dir>, C:
|
||||
|
||||
[1] Edit C:C-ENV.H for new configuration; write out to C: (new dir).
|
||||
In particular make sure that the SYS_xxx and CPU_xxx defaults are set.
|
||||
Make sure that any local copies of C-ENV.H (in the KCC or LIBC
|
||||
source directories) are identical.
|
||||
The same applies to any other .H files that need to be changed; new
|
||||
versions should be put in C: (new dir) and local copies made identical
|
||||
or flushed.
|
||||
|
||||
[2] Connect to the LIBC source directory.
|
||||
Delete all .REL files (@DEL *.REL,<.*>*.REL)
|
||||
|
||||
[3] Rebuild entire library with the LIBC.MIC file (@DO LIBC).
|
||||
Edit LIBC.MIC beforehand to add any -x= switches that are necessary,
|
||||
for example -x=ki, -x=klx. These switches should match with
|
||||
the definitions in C-ENV.H!!!
|
||||
|
||||
[4] Install new LIBC.REL into C: (@COPY LIBC.REL.0 C:*.*.*)
|
||||
|
||||
[5] Also install the new LIBCKX.REL file into C:. This is necessary in
|
||||
order to allow loading of extended-addressing programs. If your
|
||||
machine does not support extended addressing, of course, you can
|
||||
ignore this file.
|
||||
|
||||
--- At this point the new library is ready! ---
|
||||
|
||||
[6] Build a new KCC:
|
||||
Connect to the KCC source directory.
|
||||
Make sure that the site-dependent defaults in CCSITE.H are okay.
|
||||
Other parameters can be changed in CCPARM.H if necessary.
|
||||
Make sure that the local copy of C-ENV.H is either flushed or
|
||||
is the same as the version in the new C:.
|
||||
|
||||
[7] Delete all the old .REL files (@DEL *.REL).
|
||||
[8] Compile and load all the C modules with the CC.MIC file (@DO CC).
|
||||
Edit CC.MIC beforehand to add any -x= switches that are necessary,
|
||||
for example -x=ki, -x=klx.
|
||||
This will automatically load up some library routines from the new
|
||||
LIBC. You now have a binary KCC for the target system.
|
||||
|
||||
[9] To install on your own system:
|
||||
you can replace the old C: by new C: in either of two ways:
|
||||
A. (quick) Copy all new C: files over to old C:
|
||||
Then undefine your job-wide C:.
|
||||
B. (cautious) Copy all remaining files from old C: to new C:.
|
||||
Test it out. If no problems, then revise the system-wide
|
||||
logical name. If problems, swap the names back.
|
||||
|
||||
[10] To install on another system:
|
||||
On target system, set up the include directory.
|
||||
Copy all files from new C: to target (.H files plus LIBC.REL),
|
||||
then all remaining files from old C: to target.
|
||||
Copy the new CC binary to whereever the target's system progs live.
|
||||
If desired, copy the LIBC and KCC sources too.
|
||||
|
||||
Cross-compilation without logical names:
|
||||
|
||||
This is a little harder because the source and target directories have
|
||||
to be more explicitly specified. In the following discussion, the strings OLD
|
||||
and NEW are assumed to represent the paths for the old (existing) standard
|
||||
directory, and the new directory where the new .H files and library will be
|
||||
written and stored.
|
||||
|
||||
[1] Edit C-ENV.H for new configuration; write out to NEW.
|
||||
In particular make sure that the SYS_xxx and CPU_xxx defaults are set.
|
||||
Make sure that any local copies of C-ENV.H (in the KCC or LIBC
|
||||
source directories) are identical.
|
||||
The same applies to any other .H files that need to be changed; new
|
||||
versions should be put in NEW (new dir) and local copies made identical
|
||||
or flushed.
|
||||
|
||||
[2] Connect to the LIBC source directory.
|
||||
Delete all .REL files.
|
||||
|
||||
[3] Rebuild entire library. The LIBC.MIC file shows which files need
|
||||
to be compiled and loaded into a library.
|
||||
All compilations should be of this form:
|
||||
CC -c -LNEWLIB -INEW -IOLD -x=ki module.C
|
||||
Where:
|
||||
"-x=ki" illustrates how a specific CPU must be selected.
|
||||
"module" is the library module being compiled.
|
||||
"NEWLIB" is the path for library modules in NEW, e.g. -LC:LIB=.REL
|
||||
The need to specify this is an unfortunate artifact of
|
||||
the way library load requests are inserted into the code.
|
||||
|
||||
[4] Build all the .REL files together into a library; the first two
|
||||
files must be CPU.REL and CRT.REL. Move this file into the NEW
|
||||
directory.
|
||||
|
||||
--- Now start building the new KCC ---
|
||||
|
||||
[5] Build a new KCC:
|
||||
Connect to the KCC source directory.
|
||||
Make sure that the site-dependent defaults in CCSITE.H are okay.
|
||||
In particular make sure that LIBPREFIX and LIBPOSTFIX match
|
||||
what was given in the -LNEWLIB switch while compiling LIBC.
|
||||
Other parameters can be changed in CCPARM.H if necessary.
|
||||
Make sure that the local copy of C-ENV.H is either flushed or
|
||||
is the same as the version in NEW.
|
||||
|
||||
[6] Delete all the old .REL files.
|
||||
[7] Compile and load all the C modules specified by the CC.MIC file.
|
||||
Use the same form as for compiling the LIBC modules, including
|
||||
the -L, -I, -x, and -A switches.
|
||||
You will then have a binary KCC suitable for the target system.
|
||||
|
||||
[8] To install on your own system:
|
||||
you can replace OLD by NEW in either of two ways:
|
||||
A. (quick) Copy all NEW files over to OLD. Install the KCC binary.
|
||||
B. (cautious) Copy all remaining files from OLD to NEW.
|
||||
Test it out. If OK, install the KCC binary.
|
||||
|
||||
[9] To install on another system:
|
||||
On target system, set up the include directory.
|
||||
Copy all files from NEW to target (.H files plus LIBC.REL),
|
||||
then all remaining files from OLD to target.
|
||||
Copy the new CC binary to whereever the target's system progs live.
|
||||
If desired, copy the LIBC and KCC sources too.
|
||||
|
||||
Thoughts on future port to ITS:
|
||||
|
||||
Main problem is that the only linking loader available on ITS is
|
||||
STINK, which only understands STINK format .REL files. There may be
|
||||
an old version of the DEC linker available, but this is non-supported
|
||||
and painful to use. Finally, MIDAS can produce either STINK or DECREL format;
|
||||
the ITS version of FAIL can do the same. This gives us only three
|
||||
possibilities, in increasing order of generality:
|
||||
(1) Use ITS FAIL, producing STINK format.
|
||||
(2) Make KCC produce MIDAS output. Use MIDAS, with STINK format.
|
||||
(3) Make STINK understand DECREL format. Use MIDAS or FAIL.
|
||||
|
||||
Note that if KCC is ever improved to bypass the assembler phase by
|
||||
outputting .REL files directly, it will either have to also know about
|
||||
STINK format, or STINK will have to know about DECREL format. The latter
|
||||
is most general.
|
||||
|
||||
Actual porting:
|
||||
|
||||
Approach 1: build a KCC elsewhere, dump in old DECSAV format. FTP over
|
||||
and convert to SBLK executable format.
|
||||
Approach 2: generate complete set of .FAI files and then FTP them.
|
||||
Run ITS FAIL to generate STINK format rels,
|
||||
then STINK them together to produce KCC and CLIB.
|
||||
Approach 3: generate complete set of .MID files and FTP them.
|
||||
Run MIDAS and then STINK the results together.
|
||||
Approach 4: generate complete set of .REL files and FTP them.
|
||||
Modify STINK to understand DECREL format, load files with STINK.
|
||||
|
||||
Fixing KCC to produce valid MIDAS output will require:
|
||||
(1) Modifying KCC to produce common assembler subset. Can do.
|
||||
(2) Modifying the syntax of all assembler runtimes. This is
|
||||
the real problem. Only hope for dealing with this reasonably
|
||||
is to change everything to use new #ASM feature; then KCC
|
||||
can conditionalize the syntax depending on system.
|
||||
|
||||
Library routines required by KCC:
|
||||
|
||||
(this list can be generated by loading all .REL modules and then
|
||||
giving the /UNDEF switch to LINK)
|
||||
|
||||
$$$CPU 0
|
||||
$$$CRT 0 ; * C Runtime stuff, in CRT.C
|
||||
$BPCNT 413166
|
||||
$BYTE 517604
|
||||
$DFIX 437543
|
||||
$NSPOP 472623
|
||||
$NSPUS 472615
|
||||
$START 403165
|
||||
$SUBBP 413303
|
||||
$ZERO 463273
|
||||
|
||||
Sys-dependent routines
|
||||
.CPUTM 403072 ; * All systems supported
|
||||
EXIT 441516 ; *
|
||||
GETPID 517376 ; * CCASMB for temp files
|
||||
JSYS 517315 ; T20 - CCASMB for PRARG%
|
||||
PFORK 517675 ; T20,10X - CCASMB for asm/link invoke
|
||||
****> UNLINK 517225 ; T20,10X,ITS - CC to flush asm files
|
||||
; Needs LOOKUP+RENAME for T10/WAITS
|
||||
STDIO ; * STDIO stuff. Should not be sys-dep
|
||||
.SIOS 0
|
||||
FCLOSE 517443
|
||||
FFLUSH 517666
|
||||
FGETC 517212
|
||||
FOPEN 517417
|
||||
FPRINT 516663
|
||||
FPUTC 515464
|
||||
FPUTS 517440
|
||||
FWRITE 516627
|
||||
SPRINT 517407
|
||||
UNGETC 412045
|
||||
Stg alloc ; * Depends on S/BRK, all sys supported.
|
||||
FREE 442156
|
||||
MALLOC 517154
|
||||
REALLO 517235
|
||||
STRING ; * (no sys-dep stuff)
|
||||
STRCAT 414767
|
||||
STRCMP 417712
|
||||
STRCPY 517371
|
||||
STRLEN 517335
|
||||
Misc library
|
||||
QSORT 457226 ; * (no sys-dep stuff)
|
||||
240
doc/kcc/signal.doc
Executable file
240
doc/kcc/signal.doc
Executable file
@@ -0,0 +1,240 @@
|
||||
KCC UN*X SIGNAL SIMULATION
|
||||
|
||||
This file provides some user-oriented information on how to
|
||||
use the KCC simulation of the Un*x signal mechanism.
|
||||
|
||||
Unfortunately, there is no single consistent signal mechanism
|
||||
used by all UN*X-type systems. The currently known schemes fall into
|
||||
three basic categories:
|
||||
|
||||
(1) Traditional: V7, SYS V, ANSI. [signal()]
|
||||
(2) Better: 4.2 BSD / SUN [signal(), sigvec(), sig*()]
|
||||
KCC=> (3) Best: 4.3 BSD [signal(), sigvec(), sig*()]
|
||||
|
||||
Attributes:
|
||||
Handler reset Signal mask Calls restarted
|
||||
(1) yes no no
|
||||
(2) no yes no
|
||||
KCC=> (3) no yes yes
|
||||
|
||||
Handler Reset:
|
||||
In traditional Un*x implementations, the call of a signal handler
|
||||
automatically resets that signal's handler to SIG_DFL (default handling,
|
||||
normally termination). The handler has to do invoke signal() again if
|
||||
it wishes to catch additional signals. 4.3BSD and KCC do not do this
|
||||
reset.
|
||||
|
||||
Signal mask:
|
||||
BSD introduced a signal mask which allows signals to be kept
|
||||
pending until the mask no longer blocks them from being handled.
|
||||
Whenever a handler is called, the corresponding bit in its mask (at
|
||||
least) is always set; thus there is no need to reset the handler to
|
||||
SIG_DFL. This is much more robust as there is no gap during which
|
||||
quickly repeated asynchronous signals can mistakenly kill a process.
|
||||
BSD added a number of new calls to handle this mask. They are
|
||||
sigvec (general-purpose replacement for signal), sigsetmask, sigblock, and
|
||||
sigpause. KCC implements all of these.
|
||||
|
||||
Call restart:
|
||||
In both (1) and (2) a signal during certain system calls would
|
||||
cause those calls to return -1 with errno set to EINTR. In 4.3BSD this
|
||||
was changed so that normally such calls are restarted automatically when
|
||||
a signal handler returns. A flag bit with sigvec() allows the old action
|
||||
of EINTR to still be taken. A new call, sigreturn(), was added to permit
|
||||
true context restoration. KCC implements this too.
|
||||
|
||||
More on system call interruption:
|
||||
On Un*x signals may only interrupt the following calls:
|
||||
read(), write() - slow devices only (never DSK:)
|
||||
wait()
|
||||
ioctl() on a slow device (esp. TTY:)
|
||||
any call that locks an inode - open(), creat()?
|
||||
Calls which are not restarted by 4.3BSD if interrupted:
|
||||
pause(), sigpause()
|
||||
|
||||
KCC permits only the above USYS calls to be interrupted. For all
|
||||
but pause() and sigpause(), the calls will be restarted automatically
|
||||
unless specifically requested by the SV_INTERRUPT bit in a sigvec call.
|
||||
|
||||
Changing the signal mechanism:
|
||||
To accomodate cases where it is difficult to change the user
|
||||
code (e.g. during initial stages of porting some software), the signal
|
||||
mechanism can be changed from 4.3BSD to 4.2BSD or V7/SYSV by including
|
||||
the following code in the module where "main" is defined:
|
||||
|
||||
#define _URTSUD_DEFAULT_SIGS _URTSUD_xxx_SIGS
|
||||
#include <urtsud.h>
|
||||
|
||||
where "xxx" is one of SYSV, BSD42, or BSD43.
|
||||
|
||||
For additional information more detailed than that provided in this
|
||||
file, consult the files CODSIG.DOC and SIGVEC.C in the source directory.
|
||||
|
||||
KCC-supported signals:
|
||||
|
||||
/--------------- (A)synchronous or (S)ynchronous.
|
||||
| /------------ (P)anic channel or not.
|
||||
| | /--- Only seen for (J)SYS or (U)ser; * = both.
|
||||
Code: [AS][P-][O-][JU*]
|
||||
\------- O means if interrupt PC is user-mode, the
|
||||
PC is that of the offending instruction and
|
||||
not the next one (as for all other cases).
|
||||
|
||||
Signal PSI Code
|
||||
|
||||
SIGINT x A--* TTY Interrupt (interactive)
|
||||
SIGQUIT x A--* TTY Quit (interactive)
|
||||
SIGALRM x A--* Alarm Clock (TIMER%)
|
||||
|
||||
SIGCHLD .ICIFT A--* Inferior fork termination
|
||||
SIGFPE .ICFOV S--U Floating Point overflow
|
||||
SIGFPE .ICAOV S--U Arithmetic overflow
|
||||
SIGSEGV .ICPOV SP-U PDL overflow
|
||||
SIGILL .ICILI SP-* Illegal Instruction
|
||||
SIGBUS .ICIRD SPO* Illegal memory read
|
||||
SIGBUS .ICIWR SPO* Illegal memory write
|
||||
SIGPIPE .ICDAE SPO* Device or data error
|
||||
SIGXFSZ .ICQTA SPO* Quota exceeded
|
||||
SIGXFSZ .ICMSE SPO* Machine resources exhausted
|
||||
|
||||
SIGT20EOF .ICEOF S--J EOF condition on input
|
||||
SIGT20NXP .ICNXP S-O* Ref to non-ex page
|
||||
|
||||
If a panic signal occurs during execution of a USYS call then
|
||||
the program will be halted with an error message, even if a handler is
|
||||
defined for that signal. It is possible to ignore panic signals with
|
||||
SIG_IGN although this is unwise.
|
||||
The default action (SIG_DFL) for a particular signal varies.
|
||||
As long as a signal is not set to anything, its action remains
|
||||
whatever the TOPS-20 system action is; panic signals will cause the
|
||||
process to be halted, and all other signals are ignored. If a signal is
|
||||
explicitly set to SIG_DFL then its default action will become whatever
|
||||
the Un*x default action is. See the include file <signal.h> for a listing
|
||||
of all signals with their default actions.
|
||||
A "core" file is never made, since this is unnecessary and unhelpful
|
||||
on TOPS-20/TENEX.
|
||||
|
||||
Use of SIGINT and SIGQUIT:
|
||||
|
||||
At startup there are no interrupt characters. That is,
|
||||
t_intrc and t_quitc of the "tchars" ioctl structure are both -1.
|
||||
Simply setting these characters does not cause either to generate
|
||||
signals unless the signal handler has been explicitly set to something
|
||||
by signal(). If explicitly set to SIG_DFL then the signal will
|
||||
terminate the process, since this is the default Un*x action.
|
||||
|
||||
These interrupt characters can only be some form of control character,
|
||||
including DEL.
|
||||
|
||||
Signal Handlers:
|
||||
|
||||
When a signal handler is invoked, it is called with the following
|
||||
arguments:
|
||||
void sighandler(sig, chn, scp)
|
||||
int sig; /* Signal # */
|
||||
int chn; /* PSI channel # (T20/10X) */
|
||||
struct sigcontext *scp; /* Pointer to context */
|
||||
|
||||
Since more than one PSI channel is mapped into a single signal, the
|
||||
"chn" variable allows the handler to distinguish between them if
|
||||
necessary. The signal context structure is defined in <signal.h> and
|
||||
contains the complete context of the signal, including the interrupt
|
||||
PC and flags, saved ACs, and old signal mask. Code which references
|
||||
this structure is not portable to machines other than the PDP-10, but
|
||||
at this level things are non-portable anyway.
|
||||
|
||||
Returning from the handler will resume the process where it was
|
||||
interrupted. longjmp() to some other location will work as long as the
|
||||
signal handlers are not nested.
|
||||
|
||||
WARNING:
|
||||
Any time you write a signal handler routine, you must be aware
|
||||
of what you might be interrupting and how the handler actions may
|
||||
affect the rest of the program. There are too many subtleties to go
|
||||
into more than a few of the important aspects here. For example,
|
||||
while it should be okay to use USYS calls within the handler (the
|
||||
interrupt system ensures that these are treated as atomic), it is
|
||||
almost NEVER okay to invoke any library routine which alters static
|
||||
data, such as "ctime". In particular, none of the storage allocation
|
||||
facilities such as "malloc" should be called, because the program might
|
||||
have been interrupted out of a call to malloc, and the data structures
|
||||
will be in an inconsistent state. It is also risky to use any of
|
||||
the standard I/O library routines, for similar reasons.
|
||||
|
||||
WARNING:
|
||||
The signal code goes to a great deal of trouble to ensure that
|
||||
if a user program JSYS is interrupted, it can be continued on return
|
||||
from the handler. But the TOPS-20/TENEX PSI scheme is so complex and
|
||||
messed up that it is impossible to guarantee that this will always
|
||||
work. To be COMPLETELY safe, you can use the jsys() facility, which will
|
||||
never permit its JSYS to be interrupted unless the JSYS_OKINT flag is
|
||||
set, and even then will provide you with a definite indication that
|
||||
a signal was handled.
|
||||
|
||||
|
||||
Additional notes:
|
||||
|
||||
What "a/synchronous" means:
|
||||
|
||||
A SYNCHRONOUS interrupt is one that happens at a specific PC
|
||||
due to the instruction at that location. Typical examples: illegal
|
||||
instruction interrupts (which can include JSYS calls), floating-point
|
||||
exceptions, and illegal memory references. For these types of
|
||||
interrupts the PC is significant and it or the contents it points to
|
||||
may need to be checked to determine what to do, because simply
|
||||
continuing the process at that PC will very likely just generate
|
||||
another such interrupt.
|
||||
|
||||
An ASYNCHRONOUS interrupt is one that may happen at ANY time,
|
||||
regardless of place; these are generated by events external to the
|
||||
program. Typical examples: TTY input interrupts, timer interrupts.
|
||||
For these, the PC is unimportant except that it should be preserved
|
||||
and restored if the interrupt handler wishes to continue whatever was
|
||||
interrupted.
|
||||
|
||||
No UN*X C signal handler has the capability of returning from
|
||||
handling a synchronous interrupt. In fact there is no mechanism
|
||||
provided for a signal handler to find out what its return PC is.
|
||||
(it's possible, with trickery, but I've never seen an example).
|
||||
4.3BSD (as opposed to 4.2 or any other Un*x) now makes this possible
|
||||
by providing the handler with a pointer to a saved-context structure!
|
||||
|
||||
Note that some signal handlers return to normal code by
|
||||
means of longjmp(); this is particularly true for alarm() handlers.
|
||||
ANSI specifies that longjmp should restore the environment properly
|
||||
even from within a signal handler, but is not required to do anything
|
||||
meaningful if called from a nested signal handler. KCC supports this
|
||||
use of longjmp().
|
||||
|
||||
Extensions to sigvec():
|
||||
|
||||
For additional flexibility, the "sigvec" structure has been
|
||||
extended to include additional parameters. Some new flags in sv_flags
|
||||
are used to indicate when the additional structure members are
|
||||
significant.
|
||||
|
||||
The things that can be specified, independently of each other:
|
||||
SV_XINTLEV: ON If handler should run at interrupt level.
|
||||
SV_XASMHAN: ON If handler is special assembler routine (ACs not saved,
|
||||
no args given). Otherwise, normal C handler.
|
||||
SV_XOS: ON If the sigvec structure should be checked for:
|
||||
(1) Exact PSI channel # to use for this signal (0 = existing).
|
||||
(2) What PSI level to use (0 = existing).
|
||||
(3) .TICxx code (plus 1) to ATI% to this channel (0 = none).
|
||||
|
||||
Not all of the flags work yet:
|
||||
|
||||
Currently only SV_XINTLEV is implemented. It works to use
|
||||
longjmp() within handlers called with this flag!
|
||||
|
||||
SV_XASMHAN is not yet used. If added, it will be an error to
|
||||
specify SV_XASMHAN without SV_XINTLEV; that is, if the handler is an
|
||||
assembly routine, then it MUST run at interrupt level.
|
||||
|
||||
SV_XOS is not yet used. If added, specification of a positive
|
||||
.TIC code will always replace any existing code by the new one, and
|
||||
use of -1 will always clear any existing code. If the value is 0,
|
||||
however, then the meaning depends on whether a channel # was
|
||||
specified. If the channel # was given, 0 is the same as -1.
|
||||
Otherwise, if no channel # was given, then 0 means leave any existing
|
||||
code alone.
|
||||
450
doc/kcc/usys.doc
Executable file
450
doc/kcc/usys.doc
Executable file
@@ -0,0 +1,450 @@
|
||||
USYS.DOC - KCC Un*x System-call simulation
|
||||
|
||||
This file documents various things about the USYS library routines,
|
||||
which are intended to provide simulation and support for Un*x system
|
||||
call functions.
|
||||
|
||||
Specifications for the interfaces were taken from the March
|
||||
1984 4.2BSD Unix Programmer's Manual (UPM), plus the 4.3BSD man pages,
|
||||
and all code here works as described in those references unless
|
||||
otherwise documented.
|
||||
|
||||
Implementors should also read the CODSYS.DOC file in the
|
||||
source directory.
|
||||
|
||||
Contents:
|
||||
Intro - listing format
|
||||
Summary of USYS routines
|
||||
Definitions
|
||||
Individual Routine Descriptions (as needed)
|
||||
|
||||
Library function listing format:
|
||||
|
||||
Name Module Port-status Comments
|
||||
(routine name) (source file) (see below)
|
||||
|
||||
Port-status code:
|
||||
E = file #includes "c-env.h" for environment config.
|
||||
<sys> - runs on the given sys, one of: T20,10X,T10,WAITS,ITS.
|
||||
*10 = portable to all PDP-10 OS (T20,10X,T10,WAITS,ITS)
|
||||
* = fully portable (either no OS-dependent stuff, or a
|
||||
fully-portable conditional exists)
|
||||
|
||||
Comments:
|
||||
"U" means the call is USYS_macro enclosed and cannot be
|
||||
interrupted by signals.
|
||||
"-" means it isn't enclosed
|
||||
(this better be cuz interrupts don't affect the call!)
|
||||
"I" means it is interruptible (i.e. can return EINTR error).
|
||||
"IC" means interrupts may be continued within the call.
|
||||
|
||||
USYS function summary: Src: lib/usys/
|
||||
|
||||
Name Module Port-status Comments
|
||||
|
||||
access ACCESS T20,10X U 10X only partial.
|
||||
alarm ALARM T20 U
|
||||
brk SBRK *10 U
|
||||
chdir CHDIR T20,10X U
|
||||
chmod CHMOD T20,10X U
|
||||
chown CHOWN T20,10X U
|
||||
close CLOSE T20,10X,ITS U
|
||||
creat OPEN T20,10X U
|
||||
dup DUP *10 U
|
||||
dup2 DUP *10 U
|
||||
errno (data) URT *10 -
|
||||
exec[lv][ep] FORK T20,10X U
|
||||
exit EXIT *10 -
|
||||
fchmod CHMOD T20,10X U
|
||||
fchown CHOWN T20,10X U
|
||||
fcntl FCNTL *10 U
|
||||
fork FORKEX T20,10X U
|
||||
forkexec FORKEX T20,10X U KCC-specific routine.
|
||||
fstat STAT T20,10X U (also: xfstat)
|
||||
ftime TIME *10 -
|
||||
geteuid GETUID T20,10X U
|
||||
getpid GETPID *10 U see format note.
|
||||
gettimeofday TIME *10 -
|
||||
getuid GETUID T20,10X U
|
||||
gtty SGTTY T20 U
|
||||
ioctl IOCTL T20 UIC Partial.
|
||||
kill SIGVEC T20,10X U
|
||||
lseek LSEEK T20,10X U
|
||||
open OPEN T20,10X U (Uses BSD flags; mode not supported)
|
||||
pause PAUSE *10 -I Always returns with EINTR
|
||||
pipe PIPE T20 U (monitor must have PIP: device)
|
||||
psignal PSIGNA *10 -
|
||||
raise SIGVEC T20,10X U (ANSI function, not syscall)
|
||||
read READ T20,10X U
|
||||
rename RENAME T20,10X U
|
||||
sbrk SBRK *10 U
|
||||
sigblock SIGVEC T20,10X U
|
||||
signal SIGNAL T20,10X U
|
||||
sigpause SIGVEC T20,10X UI Always returns with EINTR
|
||||
sigreturn SIGVEC T20,10X U
|
||||
sigsetmask SIGVEC T20,10X U
|
||||
sigstack SIGVEC T20,10X U
|
||||
sigvec SIGVEC T20,10X U
|
||||
sleep SLEEP *10 -I (returns no value)
|
||||
stat STAT T20,10X U (also: xstat)
|
||||
stty SGTTY T20 U
|
||||
tell LSEEK T20,10X U
|
||||
time TIME *10 - (also: tadl_xxx routines)
|
||||
times TIMES *10 -
|
||||
unlink UNLINK T20,10X,ITS U (10X doesn't expunge)
|
||||
utime UTIME T20,10X U
|
||||
vfork FORK T20,10X U
|
||||
wait WAIT T20,10X UIC
|
||||
write WRITE T20,10X,ITS UIC
|
||||
_exit EXIT *10 U
|
||||
_runtm URT *10 (internal) C programs start here.
|
||||
_urtsud (data) URTSUD *10 (internal) Runtime startup defs.
|
||||
|
||||
DEFINITIONS:
|
||||
|
||||
The UPM introduction contains some definitions which provide
|
||||
a convenient way to start describing how the KCC simulations differ from
|
||||
Un*x; some concepts are supported and others are not.
|
||||
|
||||
Process ID (PID): Supported, see long description.
|
||||
Parent Process ID: Supported, see long description.
|
||||
|
||||
Process Group ID: not implemented
|
||||
TTY Group ID: not implemented
|
||||
|
||||
Real User ID: Supported.
|
||||
The user ID on T20/10X is the "user number".
|
||||
|
||||
Real Group ID: not implemented
|
||||
Effective UID, GID, and Access Groups: not implemented
|
||||
Super-user: not implemented
|
||||
Special Processes: not implemented
|
||||
|
||||
File Descriptor (FD): Supported.
|
||||
Small non-negative integers in the range 0 to 63 inclusive.
|
||||
FDs 0, 1, and 2 correspond to standard input, output, and error output.
|
||||
On T20/10X these are initially set to the JFNs .PRIIN, .PRIOU, .CTTRM.
|
||||
You can obtain the JFN for a FD by using the fcntl() call.
|
||||
|
||||
File Name: Supported.
|
||||
On T20/10X, up to 39 chars per component. Must be 7-bit ASCII.
|
||||
Can quote with ^V.
|
||||
|
||||
Path Name: Supported.
|
||||
Un*x style / paths are permitted, where foo/ is taken to mean foo
|
||||
is a subdirectory of the current directory.
|
||||
|
||||
If the monitor worked right, a filespec of the form "C:foo/bar.h" could
|
||||
be turned into "C:<.foo>bar.h", assuming standard-type relative
|
||||
directory fixes, and we would win. But no. Instead, we have to do
|
||||
the work manually: the logical device is recursively expanded until
|
||||
an end device-directory pair is found, at which point the file
|
||||
lookup is tried. If it fails, the expansion/traversal continues.
|
||||
|
||||
Directory: Supported.
|
||||
<.> and <..> work on some T20 systems (Stanford mods).
|
||||
|
||||
Root Directory and Current Working Directory:
|
||||
A directory of the form "/foo" is taken to mean "<foo>".
|
||||
The notion of a current working directory is supported.
|
||||
|
||||
File Access Permissions:
|
||||
Each set of T20/10X owner, group, and world access bits
|
||||
corresponds to a set of Un*x owner, group, and other bits.
|
||||
Un*x T20/10X
|
||||
04 040 Read access
|
||||
02 020 Write access
|
||||
01 010 Execute access
|
||||
- 04 Append access
|
||||
- 02 Directory listing access
|
||||
- 01 -
|
||||
Thus, a call such as "chmod(foo.bar, 0644)" will set the T20/10X
|
||||
protection of "foo.bar" to 604040.
|
||||
There is no way a user program can either read or set the last
|
||||
three T20/10X protection bits, except by doing a CHFDB% itself.
|
||||
Finally, there is no T20/10X counterpart to the set-UID or set-GID
|
||||
bits.
|
||||
|
||||
Sockets and Address Families: not implemented (yet!)
|
||||
|
||||
ERRORS:
|
||||
|
||||
The global "errno" is set by all failing USYS calls.
|
||||
The standard UN*X error numbers from <errno.h> are used where possible,
|
||||
although a few T20-specific error codes have been defined. See <errno.h>
|
||||
for details.
|
||||
There is currently no easy way to find out what TOPS-20/TENEX
|
||||
error (if any) caused errno to be set. The best one can do is find the
|
||||
most recent error for the process with GETER%. Perhaps someday this will
|
||||
be improved.
|
||||
|
||||
Exceptions:
|
||||
ftime, time, gettimeofday, times
|
||||
getpid
|
||||
_exit (never returns)
|
||||
|
||||
PROCESS ID (PID): Long Description
|
||||
|
||||
PID values are generated by:
|
||||
(1) getpid() - self process ID. This must not change over
|
||||
the lifetime of the process!
|
||||
(2) fork() - to identify the child process.
|
||||
(3) wait() - to identify the child process that stopped.
|
||||
This should match the value returned by fork().
|
||||
|
||||
PID values are used by:
|
||||
(1) kill() - to send signals to self, child, or parent.
|
||||
(It is rare to send them anywhere else.)
|
||||
(2) Code that checks the return value of wait().
|
||||
(3) Code that generates unique filenames, port numbers, or the like
|
||||
which should not conflict with those of any other
|
||||
active process.
|
||||
|
||||
For ITS, TOPS-10, and WAITS the PID is simply the job #, a
|
||||
small positive integer; zero and negative PIDs will never be seen, as
|
||||
job 0 is the monitor itself and no system can support 2**35 jobs.
|
||||
|
||||
However, TENEX (and hence TOPS-20) has never had a notion of a
|
||||
unique process identifier, except internally inside the monitor; this
|
||||
fork ID is simply not accessible to the user. Fork handles are all
|
||||
relative, in an obscene attempt to prevent programs from referencing
|
||||
any process they shouldn't. This makes it impossible to implement
|
||||
getpid() in a straightforward way. The subterfuge I have resorted to
|
||||
is as follows:
|
||||
|
||||
T20 PID = <IPCF PID>,,<frk #><job #>
|
||||
<IPCF PID> - Left half of a PID generated by MUTIL% for process
|
||||
This is guaranteed by system to be unique.
|
||||
<frk #> - low 9 bits of relative fork handle, in 0777000.
|
||||
<job #> - low 9 bits of job number, in 0777.
|
||||
|
||||
getpid() remembers the value generated on first call and
|
||||
returns that thereafter. This satisfies the uniqueness and constancy
|
||||
criterion, as well as being efficient.
|
||||
fork() and wait() convert the relative fork handles from
|
||||
CFORK% and GFRKS% to a child PID with a zero LH but with the other
|
||||
fields set. Since relative fork handles are from 400000 to 400777, we
|
||||
only need the low 9 bits.
|
||||
fork() in the new child process copies the saved getpid()
|
||||
value, if any; this is its parent's PID and may be used by kill(). The
|
||||
saved value is then cleared so if the child calls getpid() it will generate
|
||||
its own unique value.
|
||||
kill() checks its PID argument first against the saved
|
||||
getpid() value to see if a signal is being sent to itself. If not it then
|
||||
sees whether it matches that of its parent (if any) and sends a signal
|
||||
to .FHSUP if so. Otherwise, if the LH is 0 it assumes the signal is
|
||||
being sent to a child, and generates the appropriate relative fork
|
||||
handle from the 9 bits in the PID value. Note: There is no good way
|
||||
to identify "miscellaneous" signals generated by another process (PSIs
|
||||
on the "CHNmisc" channel); only those PSIs uniquely mapped to a single
|
||||
signal can be successfully sent between processes.
|
||||
|
||||
This scheme fails only if PIDs are somehow passed from one
|
||||
process to another either via pipe, file, or vfork() shared memory, since
|
||||
the result of a child's getpid() won't match what its parent's fork()
|
||||
returned. But this should practically never happen.
|
||||
|
||||
TENEX:
|
||||
On TENEX, which doesn't have IPCF, we just use GFRKS% to
|
||||
locate our fork within the job fork structure and hope the resulting
|
||||
number, which we stick in the LH, doesn't change. At least TENEX
|
||||
doesn't have extended addressing either so we can munch the GFRKS%
|
||||
data on the stack.
|
||||
|
||||
OPEN() - Some I/O details:
|
||||
|
||||
The open() call has several additional flags which are intended to
|
||||
help specify the proper actions on TOPS-20/TENEX systems, since the
|
||||
defaults assumed by open() may not always be correct.
|
||||
|
||||
Standard BSD flags:
|
||||
O_RDONLY open for reading only
|
||||
O_WRONLY open for writing only
|
||||
O_RDWR open for reading and writing
|
||||
O_NDELAY do not block on open (not supported)
|
||||
O_APPEND append on each write
|
||||
O_CREAT create file if it does not exist
|
||||
O_TRUNC truncate size to 0
|
||||
O_EXCL error if create and file exists
|
||||
|
||||
KCC-specific flags (not portable)
|
||||
O_BINARY Open in binary (9-bit byte) mode
|
||||
O_CONVERTED Force LF-conversion
|
||||
O_UNCONVERTED Force NO LF-conversion
|
||||
O_BSIZE_7 Force 7-bit bytesize
|
||||
O_BSIZE_8 Force 8-bit bytesize
|
||||
O_BSIZE_9 Force 9-bit bytesize
|
||||
|
||||
TOPS-20 and TENEX specific flags
|
||||
O_T20_WILD Allow wildcards on GTJFN%
|
||||
O_T20_WROLD For writes, do NOT use GJ%FOU
|
||||
O_T20_SYS_LOG logical device is system-wide!
|
||||
O_T20_THAWED Open file for thawed access
|
||||
|
||||
The BSD flags behave as per the UPM documentation, and the T20
|
||||
flags are fairly straightforward. The KCC flags however are more subtle;
|
||||
they affect the characteristics of the I/O that will be done, rather than
|
||||
how a file will be found or created. The two decisions that must be made
|
||||
are: (1) Bytesize, and (2) LF-conversion. These are explained below.
|
||||
|
||||
BYTESIZE:
|
||||
The decision of which bytesize to use for I/O is somewhat
|
||||
complicated. The bytesize on UN*X is always 8 bits, but on PDP-10s it
|
||||
can be anything from 0 to 36 bits. The algorithm we use is as follows:
|
||||
If a byte size (one of 7, 8, or 9) is explicitly requested, use that.
|
||||
Otherwise, for a new file, use 9 if O_BINARY, else 7.
|
||||
for an old file, use the file's bytesize.
|
||||
A size of 0 or 36 is treated as for a new file.
|
||||
Any other size is simply used. If this is not
|
||||
one of 7, 8, or 9 then the results are unpredictable.
|
||||
|
||||
LF-CONVERSION:
|
||||
UN*X text files use the convention that a LF alone is a
|
||||
"newline", whereas PDP-10 systems use CRLF together. Thus, the normal
|
||||
mode of I/O uses LF-conversion, wherein read() converts a input CRLF
|
||||
sequence to LF, and write() converts an output LF to CRLF. The algorithm
|
||||
used to determine whether LF-conversion should be done is:
|
||||
Conversion is normally only done if the bytesize is 7.
|
||||
Any other size implies NO conversion.
|
||||
However, this default can be overriden by certain flags:
|
||||
If O_CONVERTED is set, conversion is ALWAYS done.
|
||||
If O_UNCONVERTED or O_BINARY is set, conversion is NEVER done.
|
||||
|
||||
LSEEK() - Problems with LF-conversion
|
||||
|
||||
lseek() deals only with system-level file pointers. When no
|
||||
LF-conversion is being done, this corresponds exactly to the UN*X notion
|
||||
of a file position, namely the # of bytes offset from the start of the file,
|
||||
and it is possible to create your own file positions arithmetically.
|
||||
|
||||
However, when LF-conversion is being done then this is not possible;
|
||||
the position returned by lseek will correspond to the system's position,
|
||||
rather than to the number of bytes fed through read() or write(). In this
|
||||
case you can only lseek to a position previously returned by lseek() itself.
|
||||
(Note that 0 is a special case that always works). Typically the pointer
|
||||
returned will be larger than the number of bytes read or written thus far,
|
||||
since the system is aware of the CR's in the file even though the C program
|
||||
isn't.
|
||||
|
||||
STAT() - file status information
|
||||
|
||||
This section describes the correspondence between the components
|
||||
of the stat() structure (as defined for Un*x) and the TOPS-20 file system
|
||||
information.
|
||||
|
||||
struct stat
|
||||
{
|
||||
dev_t st_dev; /* The .DVxxx device type */
|
||||
ino_t st_ino; /* .FBADR - Disk address of file index blk */
|
||||
unsigned int st_mode; /* Un*x-style mode bits */
|
||||
int st_nlink; /* 1 (always) */
|
||||
int st_uid; /* T20: User #, 10X: directory # */
|
||||
int st_gid; /* 0 (always, for now) */
|
||||
dev_t st_rdev; /* 0 (always, for now) */
|
||||
off_t st_size; /* .FBSIZ - size in bytes (any bytesize) */
|
||||
time_t st_atime; /* .FBREF - last ref (Un*x format time) */
|
||||
int st_spare1;
|
||||
time_t st_mtime; /* .FBWRT - last write (Un*x format time) */
|
||||
int st_spare2;
|
||||
time_t st_ctime; /* .FBCRE - last mod (Un*x format time) */
|
||||
int st_spare3;
|
||||
long st_blksize; /* # bytes in a page (derived from FB%BSZ) */
|
||||
long st_blocks; /* # pages in file (FB%PGC of .FBBYV) */
|
||||
long st_spare4[2];
|
||||
};
|
||||
|
||||
|
||||
FORKEXEC() - New KCC-specific call
|
||||
|
||||
This call is intended to combine the functions of fork() and
|
||||
exec() so that a user program that wants to perform the very common
|
||||
procedure of first calling fork() and then having the child call exec()
|
||||
can now simply use forkexec() and accomplish the same thing much faster.
|
||||
|
||||
The calling sequence is simply:
|
||||
#include <frkxec.h>
|
||||
int forkexec(fxp);
|
||||
struct frkxec *fxp;
|
||||
|
||||
See the include file for details on the contents of the frkxec
|
||||
structure and the flags that can be provided.
|
||||
|
||||
All of the exec*() functions call forkexec() with FX_NOFORK set.
|
||||
|
||||
TTY Handling:
|
||||
|
||||
The library supports many (though not all) of the Un*x TTY
|
||||
functions. The primary means of getting information about the TTY and
|
||||
setting TTY parameters is with the ioctl() call. All 4.3BSD TTY-related
|
||||
ioctl functions are recognized, although not all are completely supported.
|
||||
In particular, all requests to "get" data structures will always return
|
||||
as much information as is available; attempting to "set" some elements of
|
||||
these structures may or may not work, as described in the following comments.
|
||||
|
||||
IOCTL function comments:
|
||||
|
||||
FIONREAD - Get # bytes to read on FD. Supported.
|
||||
|
||||
TIOCGETP - Get sgttyb parameters, same as V6/V7 gtty(). Supported.
|
||||
TIOCSETP - Set sgttyb parameters, same as V6/V7 stty(). Supported.
|
||||
sg_ispeed, sg_ospeed Can read and set.
|
||||
sg_erase Cannot set to anything but DEL (fails if you try).
|
||||
sg_kill Cannot set to anything but ^U (fails if you try).
|
||||
sg_flags The following flags are used:
|
||||
RAW, CRMOD, ECHO, CBREAK
|
||||
All other flags are ignored, esp. LCASE and TANDEM.
|
||||
|
||||
TIOCSETN - V7: same as TIOCSETP, but without flushing TTY input. Supported.
|
||||
TIOCEXCL - V7: set exclusive use of tty (not implemented).
|
||||
TIOCNXCL - V7: reset exclusive use of tty (not implemented).
|
||||
TIOCHPCL - V7: Hang up on last close (not implemented).
|
||||
TIOCFLUSH - V7: Flush TTY input and output buffers. Supported.
|
||||
|
||||
All other functions are for BSD4.3.
|
||||
|
||||
TIOCSTI - Simulate terminal input. Supported.
|
||||
TIOCSBRK - Set break bit. (not implemented)
|
||||
TIOCCBRK - Clear break bit. (not implemented)
|
||||
TIOCSDTR - Set data terminal ready. (not implemented)
|
||||
TIOCCDTR - Clear data terminal ready. (not implemented)
|
||||
TIOCGPGRP - Get pgrp of tty. (not implemented)
|
||||
TIOCSPGRP - Set pgrp of tty. (not implemented)
|
||||
|
||||
TIOCGETC - Get special characters (tchars). Supported.
|
||||
TIOCSETC - Set special characters (tchars). Supported (sort of).
|
||||
t_intrc and t_quitc (for SIGINT and SIGQUIT) are initially -1 but
|
||||
can be set to any control character. Note that because
|
||||
chars are unsigned, the initial value when converted to
|
||||
an integer is 0777, not -1!
|
||||
No other elements of tchars can be set to anything but what they
|
||||
already are:
|
||||
t_stopc = ^S, t_startc = ^Q, t_eofc = ^Z, t_brkc = -1
|
||||
|
||||
|
||||
TIOCLBIS - Set bits in local mode word. (not implemented)
|
||||
TIOCLBIC - Clear bits in local mode word. (not implemented)
|
||||
TIOCLGET - Get local mode mask. (not implemented)
|
||||
TIOCLSET - Set local mode mask. (not implemented)
|
||||
|
||||
TIOCSLTC - Set local special chars (ltchars). Supported.
|
||||
TIOCGLTC - Get local special chars (ltchars). Supported (sort of).
|
||||
None of these chars can be set to anything but what they already are:
|
||||
t_suspc = ^C, t_dsuspc = ^C, t_rprntc = ^R, t_flushc = ^O,
|
||||
t_werasc = ^W, t_lnextc = ^V
|
||||
|
||||
TIOCGETD - Get line discipline. Supported.
|
||||
TIOCSETD - Set line discipline. Supported (sort of).
|
||||
The line discipline is always NTTYDISC and cannot be set otherwise.
|
||||
|
||||
TIOCGWINSZ - Get window size info. Supported.
|
||||
TIOCSWINSZ - Set window size info. Supported.
|
||||
ws_col and ws_row correspond to the terminal's width and height.
|
||||
Both can be read and set.
|
||||
ws_xpixel and wx_ypixel are initially 0 but can be set and then read.
|
||||
|
||||
Signals:
|
||||
|
||||
Signals are complicated, both on Un*x and T20/10X. The KCC
|
||||
implementation by default attempts to support the 4.3BSD signal
|
||||
mechanism, which uses a variety of system calls. For those planning
|
||||
to use signals, the file SIGNAL.DOC should be consulted.
|
||||
59
src/c/c.defs
Executable file
59
src/c/c.defs
Executable file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
|
||||
C Standard Definitions
|
||||
|
||||
*/
|
||||
|
||||
# define ITS ITS
|
||||
|
||||
/* data types */
|
||||
|
||||
|
||||
struct _filespec {int dev, fn1, fn2, dir;};
|
||||
# define filespec struct _filespec
|
||||
|
||||
# define channel int
|
||||
|
||||
struct _cal {int year, month, day, hour, minute, second;};
|
||||
# define cal struct _cal
|
||||
|
||||
struct _tag {int *pc, *fp, *ap, *sp;};
|
||||
# define tag struct _tag
|
||||
|
||||
|
||||
/* common values */
|
||||
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
|
||||
# define OPENLOSS -1 /* returned by COPEN if lose */
|
||||
# define EOF_VALUE 0 /* returned by CGETC if EOF */
|
||||
|
||||
/* C interrupts */
|
||||
|
||||
# define INT_DEFAULT 0
|
||||
# define INT_IGNORE 1
|
||||
|
||||
# define realt_interrupt 0
|
||||
# define mpv_interrupt 1
|
||||
# define ioc_interrupt 2
|
||||
# define ilopr_interrupt 3
|
||||
# define mar_interrupt 4
|
||||
# define utrap_interrupt 5
|
||||
# define pure_interrupt 6
|
||||
# define wiro_interrupt 7
|
||||
|
||||
# define sys_down_interrupt 8
|
||||
# define clock_interrupt 9
|
||||
# define timer_interrupt 10
|
||||
# define pdlov_interrupt 11
|
||||
# define ttyi_interrupt 12
|
||||
# define cli_interrupt 13
|
||||
# define overflow 14
|
||||
# define float_overflow 15
|
||||
|
||||
# define channel0_interrupt 16
|
||||
# define inferior0_interrupt 32
|
||||
|
||||
# define ctrls_interrupt 41
|
||||
# define ctrlg_interrupt 42
|
||||
7
src/c/clib.stinkr
Executable file
7
src/c/clib.stinkr
Executable file
@@ -0,0 +1,7 @@
|
||||
; xfile for loading basic C library
|
||||
; this file must be loaded first
|
||||
; segment 0 must start at 100
|
||||
|
||||
s 100,n,p,n
|
||||
i sinit
|
||||
l c;[crel] >
|
||||
15
src/c/ctype.h
Executable file
15
src/c/ctype.h
Executable file
@@ -0,0 +1,15 @@
|
||||
#define _U 01
|
||||
#define _L 02
|
||||
#define _A 03
|
||||
#define _N 04
|
||||
#define _S 010
|
||||
|
||||
extern char _ctype[];
|
||||
|
||||
#define isalpha(c) (_ctype[c]&_A)
|
||||
#define isupper(c) (_ctype[c]&_U)
|
||||
#define islower(c) (_ctype[c]&_L)
|
||||
#define isdigit(c) (_ctype[c]&_N)
|
||||
#define isspace(c) (_ctype[c]&_S)
|
||||
#define toupper(c) ((c)-'a'+'A')
|
||||
#define tolower(c) ((c)-'A'+'a')
|
||||
61
src/c/nc.insert
Executable file
61
src/c/nc.insert
Executable file
@@ -0,0 +1,61 @@
|
||||
; C;NC INSERT
|
||||
|
||||
; THIS FILE IS NEEDED TO ASSEMBLE MIDAS PROGRAMS PRODUCED BY
|
||||
; THE C COMPILER AS WELL AS HAND-CODED MIDAS PROGRAMS DESIGNED
|
||||
; TO BE LOADED WITH C PROGRAMS
|
||||
|
||||
RELOCATABLE
|
||||
.INSRT SYSENG;MULSEG INSERT
|
||||
.MSEG 200000',600000',700000'
|
||||
|
||||
IF1,[
|
||||
.MLLIT==1
|
||||
|
||||
A=1
|
||||
B=2
|
||||
C=3
|
||||
D=4
|
||||
P=15.
|
||||
.CCALL=1_27.
|
||||
GO=JRST
|
||||
|
||||
EQUALS ENTRY .GLOBAL
|
||||
EQUALS EXTERN .GLOBAL
|
||||
|
||||
DEFINE .IDATA
|
||||
.SEG 0
|
||||
TERMIN
|
||||
|
||||
DEFINE .UDATA
|
||||
.SEG 1
|
||||
TERMIN
|
||||
|
||||
DEFINE .CODE
|
||||
.SEG 2
|
||||
TERMIN
|
||||
|
||||
DEFINE .PDATA
|
||||
.SEG 3
|
||||
TERMIN
|
||||
|
||||
; STACK HACKING FOR VARIABLE REFERENCES
|
||||
|
||||
%P==0
|
||||
DEFINE PPUSH [A]
|
||||
PUSH P,A
|
||||
%P==%P+1
|
||||
TERMIN
|
||||
DEFINE PPOP [A]
|
||||
POP P,A
|
||||
%P==%P-1
|
||||
TERMIN
|
||||
DEFINE CCALL N,F
|
||||
.CCALL N,F
|
||||
%P==%P-N
|
||||
TERMIN
|
||||
|
||||
];END IF1
|
||||
|
||||
IF2,[IFDEF FS1,[
|
||||
.KILL %A,%P,A,B,C,D,P,GO,.CCALL
|
||||
]]
|
||||
21
src/c/stdio.h
Executable file
21
src/c/stdio.h
Executable file
@@ -0,0 +1,21 @@
|
||||
/* STDIO.H for DEC20 implementation */
|
||||
|
||||
/* actual code is in <C.LIB>C20STD.C */
|
||||
|
||||
# define BUFSIZ 512 /* this number is irrelevant */
|
||||
# define FILE int /* the actual structure is irrelevant */
|
||||
# define NULL 0 /* null file pointer for error return */
|
||||
# define EOF (-1) /* returned on end of file */
|
||||
|
||||
# define peekchar pkchar /* rename to avoid name conflict */
|
||||
# define fopen flopen /* " */
|
||||
# define getc fgetc /* " */
|
||||
# define getchar fgeth /* " */
|
||||
# define fprintf ffprintf /* " */
|
||||
# define calloc fcalloc /* " */
|
||||
|
||||
# define feof ceof /* direct translation */
|
||||
# define putc cputc /* " */
|
||||
# define fputc cputc /* " */
|
||||
|
||||
extern FILE *stdin, *stdout, *stderr;
|
||||
104
src/kcc_sy/fsdefs.h
Executable file
104
src/kcc_sy/fsdefs.h
Executable file
@@ -0,0 +1,104 @@
|
||||
/* -*-C-*-
|
||||
* ITS filesystem definitions
|
||||
*
|
||||
* Defines the format of binary MFDs and UFDs for use by C programs.
|
||||
*/
|
||||
|
||||
/*
|
||||
** MFD INFO
|
||||
*/
|
||||
|
||||
/* RANDOM INFO IN MFD */
|
||||
|
||||
#define MDNUM 0 /* ASCENDING DIR NUM */
|
||||
#define MDNAMP 1 /* PNTR TO ORG OF USER NAME BLOCK AREA */
|
||||
#define MDYEAR 2 /* CURRENT YEAR */
|
||||
#define MPDOFF 3 /* DE-CORIOLIS CLOCK OFFSET */
|
||||
#define MPDWDK 4 /* PREFERRED WRITING DISK (PHYSICAL DRIVE #) */
|
||||
#define MDCHK 5 /* THIS WORD MUST BE M.F.D. (FOR CHECKING) */
|
||||
#define MDNUDS 6 /* NUMBER USER DIRECTORIES (FOR CHECKING ONLY) */
|
||||
#define LMIBLK 7 /* TOTAL STG USED BY HACKS LIKE THIS */
|
||||
|
||||
/* USER NAME BLKS FROM C(MDNAMP) TO END */
|
||||
|
||||
#define LMNBLK 2 /* # WDS/BLK */
|
||||
#define MNUNAM 0 /* 6BIT USER NAME */
|
||||
|
||||
/*
|
||||
** UFD INFO
|
||||
*/
|
||||
|
||||
#define UFDBYT 6 /* SIZE OF BYTES */
|
||||
#define UFDBPW (36 / UFDBYT) /* NUMBER OF BYTES PER WORD */
|
||||
|
||||
/* RANDOM INFO IN UFD */
|
||||
|
||||
#define UDESCP 0 /* FS PNTR TO DESC AREA */
|
||||
#define UDNAMP 1 /* PNTR TO ORG OF NAME AREA */
|
||||
#define UDNAME 2 /* USER NAME (FOR CHECKING) */
|
||||
#define UDBLKS 3 /* LEFT HALF HAS AMOUNT OF SPACE ALLOCATED (NOT */
|
||||
/* USED CURRENTLY BY SYSTEM), RIGHT HALF HAS */
|
||||
/* NUMBER OF BLOCKS USED. */
|
||||
#define UDALLO 4 /* IF NONZERO, LEFT HALF HAS DISK NUMBER, RIGHT */
|
||||
/* HALF HAS AMOUNT OF SPACE ALLOCATED */
|
||||
#define UDDESC 11 /* FIRST LOC AVAIL FOR DESC */
|
||||
|
||||
/* UFD DESCRIPTORS
|
||||
** 0 => FREE 1-UDTKMX => TAKE NEXT N
|
||||
** UDTKMX+1 THRU UDWPH-1 => SKIP N-UDTKMX AND TAKE ONE
|
||||
** UDWPH => WRITE-PLACE-HOLDER
|
||||
** 040 BIT SET => LOAD ADDRESS. LOWER 5 BITS PLUS NEXT NXLBYT (2)
|
||||
** CHARS (17 BITS IN ALL)
|
||||
** 040 BIT & 020 BIT => "FUNNY" BLOCK IF DMDSK. WHAT IS THIS, ANYWAY?
|
||||
** END BY 0
|
||||
**
|
||||
** IF LINK DESCR
|
||||
** 6 CHAR OR UNTIL ; = SYS NAME. MUST HAVE NO CHAR = 0 IN THIS OR
|
||||
** NEXT 2 NAMES
|
||||
** NEXT CHAR QUOTED BY : (FOR NAMES WITH : OR ;)
|
||||
** NEXT CHAR N1
|
||||
** NEXT CHAR N2
|
||||
** END BY 0
|
||||
*/
|
||||
|
||||
#define UDTKMX 12 /* HIGHEST "TAKE N" CODE */
|
||||
#define UDWPH 31 /* PLACE HOLDER ON WRITE (OR NULL FILE) */
|
||||
#define UDSKMX (UDWPH - UDTKMX - 1) /* # BLOCKS THAT CAN BE SKIPPED */
|
||||
#define NXLBYT 2 /* # ADDITIONAL BYTES FOR LOAD ADDR */
|
||||
|
||||
/* NAME AREA DATA */
|
||||
|
||||
#define LUNBLK 5 /* WDS/NAME BLK */
|
||||
#define UNFN1 0 /* FIRST FN */
|
||||
#define UNFN2 1 /* SECOND FN */
|
||||
#define UNRNDM 2 /* ALL KINDS OF RANDOM INFO */
|
||||
#define UNDSCP 0001500000000 /* PNTR TO DESC */
|
||||
#define UNPKN 0150500000000 /* PACK # */
|
||||
#define UNLINK 01000000 /* LINK BIT */
|
||||
#define UNREAP 02000000 /* IF 1, DONT REAP FILE */
|
||||
#define UNWRIT 04000000 /* OPEN FOR WRITING */
|
||||
#define UNMARK 010000000 /* GC MARK BIT */
|
||||
#define UNCDEL 020000000 /* DEL WHEN CLOSED */
|
||||
#define DELBTS 020000000 /* DELETED -- IGNORE */
|
||||
#define UNIGFL 024000000 /* BITS TO IGNORE FILE */
|
||||
#define UNWRDC 0301200000000 /* WORD COUNT OF LAST BLOCK MOD 2000 */
|
||||
#define UNDUMP 0400000000000 /* HAS BEEN DUMPED */
|
||||
#define UNDATE 3 /* DATE ETC. */
|
||||
#define UNTIM 0002200000000 /* COMPACTED TIME OF CREATION */
|
||||
#define UNYMD 0222000000000 /* Y,M,D OF CREATION */
|
||||
#define UNMON 0270400000000 /* MONTH */
|
||||
#define UNDAY 0220500000000 /* DAY */
|
||||
#define UNYRB 0330700000000 /* YEAR */
|
||||
#define UNREF 4 /* REFERENCE DATE SAME AS LEFT HALF OF UNDATE */
|
||||
#define UNREFD 0222000000000 /* REFERENCE DATE */
|
||||
#define UNAUTH 0111100000000 /* MFD INDEX OF AUTHOR, ALL 1=> NO */
|
||||
/* DIRECTORY */
|
||||
#define UNBYTE 0001100000000 /* FILE BYTE SIZE AND LENGTH INFO. */
|
||||
/* LET S=BITS PER BYTE, C=COUNT OF UNUSED BYTES
|
||||
** IN LAST WD
|
||||
** 400+100xS+C S=1 TO 3 C=0 TO 35.
|
||||
** 200+20xS+C S=4 TO 7 C=0 TO 8
|
||||
** 44+4xS+C S=8 TO 18. C=0 TO 3
|
||||
** 44-S S=19. TO 36. C=0
|
||||
** NOTE THAT OLD FILES HAVE UNBYTE=0 => S=36.
|
||||
*/
|
||||
11
src/kcc_sy/humble.h
Executable file
11
src/kcc_sy/humble.h
Executable file
@@ -0,0 +1,11 @@
|
||||
/* -*-C-*-
|
||||
* HUMBLE header file
|
||||
*/
|
||||
|
||||
extern int j_create(), j_kill();
|
||||
extern int j_read(), j_write();
|
||||
extern int j_dump(), j_load();
|
||||
extern int j_vread(), j_vwrite();
|
||||
extern int j_atty(), j_dtty();
|
||||
|
||||
#define SIXBIT(name) (* ((int *) ((_KCCtype_char6 *) name)))
|
||||
Reference in New Issue
Block a user