home *** CD-ROM | disk | FTP | other *** search
- /* C library - startup, stdio, strings, TOS */
-
- /* max number of args in argv[] */
-
- #define MAXARG 50
-
- /* header file for stdio implementation */
-
- #define MAXBUF 512
- #define MAXIO 6
-
- struct file {
- char mode; /* free or open for read/write */
- char fd; /* GEMTOS file descriptor */
- int idx; /* next slot in buf read/written */
- int len; /* length of the buffer */
- char buf[MAXBUF]; /* i/o buffer */
- };
-
- /* these are the allowed modes */
-
- #define FREE 0
- #define RD 1
- #define WR 2
- #define RDWR 3
-
- /* these should match what's found in stdio.h, except for FILE */
-
- #define FILE struct file
- #define EOF (-1)
- #define NULL (0L)
- #define EOS ((char)0)
-
- /* these are the GEMDOS trap commands */
-
- #define CREATE 0x3C
- #define OPEN 0x3D
- #define CLOSE 0x3E
- #define READ 0x3F
- #define WRITE 0x40
- #define LSEEK 0x42
- #define SETBLK 0x4A
- #define EXIT 0x4C
-
- /*
- * the c runtime start up routine for ttp processes
- *
- * assumes a startup sttp.s of
- * . _bstk 2048
- * . _estk 4
- * taa 7 6
- * lll 4 0
- * sgl _estk
- * lag _estk 7
- * jsr _cttp
- */
-
- _cttp(tpa) long tpa; {
-
- extern int argc;
- extern char *argv[MAXARG];
- extern FILE *stdin, *stdout, *stderr;
- extern FILE _iobuf[1];
-
- char *b, *w, *in, *out, *arge;
- int i;
- long x, *lp;
-
- /* compute size of program, give memory back to TOS */
- lp = tpa;
- x = lp[3] + lp[5] + lp[7] + 0x100;
- if (trap(1, SETBLK, 0, tpa, x))
- exit(-1);
-
- /* parse the command line */
- argc = 1;
- argv[0] = "yc";
- arge = (char *) lp[11];
- b = tpa + 0x81;
- in = out = NULL;
- while (*b) {
- while (*b && *b <= ' ') b++;
- w = b;
- while (*b && *b > ' ') b++;
- if (*b) *b++ = 0;
- if (*w == '<') in = w+1;
- else if (*w == '>') out = w+1;
- else if (argc < MAXARG) argv[argc++] = w;
- }
- argv[argc] = 0L;
-
- /* init stdio */
- for (i = 0; i < MAXIO; i++) {
- _iobuf[i].mode = FREE;
- _iobuf[i].fd = _iobuf[i].idx = _iobuf[i].len = 0;
- }
- stdin = &_iobuf[0];
- stdout = &_iobuf[1];
- stderr = &_iobuf[2];
- stdin->mode = stdout->mode = stderr->mode = RDWR;
- if (in) {
- stdin->fd = i = trap(1, OPEN, in, 0);
- stdin->mode = RD;
- if (i < 0) _cant(in, i);
- }
- if (out) {
- if (*out != '>') { /* create */
- stdout->fd = i = trap(1, CREATE, out, 0);
- }
- else { /* append */
- stdout->fd = i = trap(1, OPEN, ++out, 1);
- if (i >= 0) i = trap(1, LSEEK, 0L, i, 2);
- }
- stdout->mode = WR;
- if (i < 0) _cant(out, i);
- }
-
- /* run the program */
- i = main(argc, argv, arge);
-
- /* close up shop */
- if (in) fclose(stdin);
- if (out) fclose(stdout);
- exit(i);
- }
-
- /* trouble redirecting output */
-
- _cant(s, fd) char *s; {
- _ps("can't redirect ");
- _ps(s);
- _ps("\n\r");
- exit(fd);
- }
-
- _ps(s) char *s; { while (*s) trap(1, 2, *s++); }
-
- /* exit the program */
-
- exit(n) { trap(1, EXIT, n); }
-
- /* data for _cttp or _ctos */
-
- int argc;
- char *argv[MAXARG];
-
- FILE _iobuf[MAXIO], *stdin, *stdout, *stderr;
-
- /* printf's (see below for the guts) */
-
- char *_dopf();
-
- fprintf(fp, fmt, args) FILE *fp; char *fmt; int args; {
- extern char _pfb[256];
- _dopf(_pfb, fmt, &args);
- return fputs(_pfb, fp);
- }
-
- printf(fmt, args) char *fmt; int args; {
- extern char _pfb[256];
- _dopf(_pfb, fmt, &args);
- return fputs(_pfb, stdout);
- }
-
- /*
- * stdio routines
- */
-
- /* return file descriptor of a stream */
-
- fileno(s) FILE *s; { return s->fd; }
-
- /* read a stream */
-
- fread(buf, sz, n, s) char *buf; FILE *s; {
- int r;
- long nn;
- nn = (long) n * (long) sz;
- if ((r = trap(1, READ, s->fd, nn, buf)) < 0)
- r = 0;
- else r = r / sz;
- return r;
- }
-
- /* write on a stream */
-
- fwrite(buf, sz, n, s) char *buf; FILE *s; {
- int r;
- long nn;
- nn = (long) n * (long) sz;
- if ((r = trap(1, WRITE, s->fd, nn, buf)) < 0)
- r = 0;
- else r = r / sz;
- return r;
- }
-
- /* seek and ye shall find */
-
- fseek(s, offset, mode) FILE *s; long offset; {
- lseek(s->fd, offset, mode);
- }
-
- /* close a stream */
-
- fclose(s) FILE *s; {
- if (s != NULL) {
- if (s->mode == WR) fflush(s);
- if (s->fd) trap(1, CLOSE, s->fd);
- s->mode = FREE;
- }
- }
- /* flush out a buffer */
-
- fflush(s) FILE *s; {
- int r;
- if (s->idx > 0)
- r = trap(1, WRITE, s->fd, (long) s->idx, s->buf);
- s->idx = 0;
- return r <= 0 ? EOF : r;
- }
-
- /* get a string from a stream */
-
- char *
- fgets(b, n, f) char *b; int n; FILE *f; {
- int c, i;
- c = getc(f);
- if (c == EOF) return NULL;
- n--;
- for (i = 0; i < n && c != EOF; c = getc(f)) {
- b[i++] = c;
- if (c == '\n') break;
- }
- b[i] = 0;
- return b;
- }
-
- /* open a stream */
-
- FILE *
- fopen(name, mode) char *name, *mode; {
- int i, m, fd, x;
- FILE *s;
- for (i = 0; i < MAXIO && _iobuf[i].mode != FREE; i++)
- ;
- if (i >= MAXIO) return NULL;
- if (*mode == 'w') {
- fd = trap(1, CREATE, name, 0);
- m = WR;
- }
- else if (*mode == 'r') {
- fd = trap(1, OPEN, name, 0);
- m = RD;
- }
- else if (*mode == 'a') {
- if ((fd = trap(1, OPEN, name, 1)) < 0)
- fd = trap(1, CREATE, name, 0);
- else if (trap(1, LSEEK, 0L, fd, 2) < 0L)
- fd = -1;
- m = WR;
- }
- else { /* anything goes here, usually '+' */
- fd = trap(1, OPEN, name, 3);
- m = RDWR;
- }
- if (fd < 0) return NULL;
- s = &_iobuf[i];
- s->len = s->idx = 0;
- s->fd = fd;
- s->mode = m;
- return s;
- }
-
- /* put a string onto the stream */
-
- fputs(s, f) char *s; FILE *f; {
- while (*s) putc(*s++, f);
- }
-
- /* get a string from stdin */
-
- char *
- gets(b) char *b; {
- int c;
- char *r;
- r = b;
- if ((c = getc(stdin)) == EOF) return NULL;
- while (c != '\n' && c != EOF) {
- *b++ = c;
- c = getc(stdin);
- }
- *b = 0;
- return r;
- }
-
- /* get a character from standard input */
-
- getchar() { return getc(stdin); }
-
- /* get a character from a stream */
-
- getc(s) FILE *s; {
- int i, l, c, r;
- if (s == NULL) return EOF;
- if (s->mode == RDWR) {
- l = trap(1, READ, s->fd, (long) 1, s->buf);
- if (l != 1) return EOF;
- i = 0;
- }
- else if (s->mode == RD) {
- i = s->idx;
- while (i >= s->len) {
- l = trap(1, READ, s->fd, (long) MAXBUF, s->buf);
- if (l <= 0) {
- s->idx = s->len = 0;
- return EOF;
- }
- s->len = l;
- i = 0;
- }
- s->idx = i + 1;
- }
- else return EOF;
- c = s->buf[i] & 255;
- if (s->fd == 0 && c == '\r')
- putc(c = '\n', s);
- return c;
- }
-
- /* output characters to a stream */
-
- putchar(c) { putc(c, stdout); }
-
- puts(s) char *s; {
- while (*s) putc(*s++, stdout);
- putc('\n', stdout);
- }
-
- putc(c, s) int c; FILE *s; {
- int i, r;
- if (s == NULL) return EOF;
- r = 0;
- if (s->mode == RDWR) {
- s->buf[0] = c;
- r = trap(1, WRITE, s->fd, (long) 1, s->buf);
- }
- else if (s->mode == WR) {
- if (s->idx == MAXBUF) r = fflush(s);
- s->buf[s->idx] = c;
- s->idx = s->idx + 1;
- }
- else return EOF;
- if (s->fd == 0 && c == '\n') r = putc('\r', s);
- return r <= 0 ? EOF : r;
- }
-
- /*
- * TOS routines
- */
-
- /* duplicate a file descriptor */
-
- dup(fd) { return trap(1, 0x45, fd); }
-
- /* execute a program: mode=0 -> load and go; mode=3 -> load and return */
-
- exec(file, args, env, mode) char *file, *args, *env; int mode; {
- return trap(1, 0x4B, mode, file, args, env);
- }
-
- /* get current directory: drive=0 -> current drive, drive=1 -> A:, etc */
-
- getdir(buf, drive) char *buf; {
- return trap(1, 0x47, buf, drive);
- }
-
- /*
- * list the disk directory
- * pat != NULL - set the DTA buffer, do an SFIRST
- * pat == NULL - do a SNEXT
- */
-
- listdir(pat, buf, mode) char *pat, *buf; {
- if (pat) {
- trap(1, 0x1A, buf);
- return trap(1, 0x4E, pat, mode);
- }
- else return trap(1, 0x4F);
- }
-
- /* seek to a position in a file */
-
- lseek(fd, offset, mode) int fd; long offset; int mode; {
- return trap(1, 0x42, offset, fd, mode);
- }
-
- /* unlink a file */
-
- unlink(name) char *name; { return trap(1, 0x41, name); }
-
- /* close a file */
-
- close(fd) { trap(1, 0x3E, fd); }
-
- /* create a file */
-
- creat(f, m) char *f; {
- return trap(1, 0x3C, f, m);
- }
-
- /* open a file */
-
- open(f, m) char *f; {
- return trap(1, 0x3D, f, m);
- }
-
- /* read a file */
-
- read(fd, buf, sz) int fd, sz; char *buf; {
- return trap(1, 0x3F, fd, (long) sz, buf);
- }
-
- /* unix-like write system call */
-
- write(fd, buf, sz) int fd, sz; char *buf; {
- return trap(1, 0x40, fd, (long) sz, buf);
- }
-
- /*
- * chmod(name, mode)
- * mode = 0x00 - normal file (read/write)
- * 0x01 - read only file
- * 0x02 - hidden file
- * 0x04 - system file
- * 0x08 - file is volume label
- * 0x10 - file is a subdirectory
- * 0x20 - file is written and closed correctly
- */
-
- chmod(name, mode) char *name; int mode; {
- return trap(1, 0x43, name, mode, 0);
- }
-
- /* guts of the printf stuff */
-
- #define MINUSFLG 1
- #define PLUSFLG 2
- #define BLANKFLG 4
- #define POUNDFLG 8
- #define ZEROFLG 16
- #define LONGFLG 32
- #define SIGNFLG 64
- #define LOWERFLG 128
-
- #define MAXINT 32767
-
- char _pfb[256]; /* in case someone needs a buffer */
-
- sprintf(buf, fmt, args) char *buf, *fmt; int args; {
- return _dopf(buf, fmt, &args) - buf;
- }
-
- char *_numcnv();
-
- char *
- _dopf(buf, fmt, i_p) char *buf, *fmt; int *i_p; {
- char c, **s_p, *s;
- long strtol();
- int i, lng, precision, minfldw, flags;
-
- for (c = *fmt; ; c = *++fmt) {
- /* scan to next conversion specification */
- while (c != '%') {
- *buf++ = c;
- if (c == EOS) {
- return buf - 1;
- }
- c = *++fmt;
- }
- c = *++fmt;
- /* scan flags */
- for (flags = 0; ; c = *++fmt) {
- if (c == '-') flags |= MINUSFLG;
- else if (c == '+') flags |= PLUSFLG;
- else if (c == ' ') flags |= BLANKFLG;
- else if (c == '#') flags |= POUNDFLG;
- else break;
- }
- /* scan minimum field width */
- if (c == '*') {
- minfldw = *i_p++;
- c = *++fmt;
- }
- else {
- if (c == '0') flags |= ZEROFLG;
- minfldw = (int)strtol(fmt, &fmt, 10);
- c = *fmt;
- }
- /* scan precision */
- precision = -1;
- if (c == '.') {
- c = *++fmt;
- if (c == '*') {
- precision = *i_p++;
- c = *++fmt;
- }
- else {
- precision = (int)strtol(fmt, &fmt, 10);
- c = *fmt;
- }
- }
- if (c == 'l') {
- flags |= LONGFLG;
- c = *++fmt;
- }
- switch (c) {
- case 'd':
- buf = _numcnv(buf, 10, flags | SIGNFLG, &i_p,
- precision, minfldw);
- break;
- case 'o':
- buf = _numcnv(buf, 8, flags, &i_p, precision, minfldw);
- break;
- case 'u':
- buf = _numcnv(buf, 10, flags, &i_p, precision, minfldw);
- break;
- case 'x':
- flags |= LOWERFLG;
- case 'X':
- buf = _numcnv(buf, 16, flags, &i_p, precision, minfldw);
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- /* someday, floats */
- break;
- case 'c':
- *buf++ = *i_p++;
- break;
- case 's':
- if (precision < 0) precision = MAXINT;
- s_p = (char **)i_p;
- s = *s_p++;
- i_p = (int *)s_p;
- for (lng = 0; s[lng] != EOS && lng < precision; ++lng);
- i = minfldw - lng;
- if ((flags & MINUSFLG) == 0) { /* right justify */
- while (i-- > 0) *buf++ = ' ';
- }
- while (lng--) *buf++ = *s++;
- while (i-- > 0) *buf++ = ' ';
- break;
- case '%':
- default:
- *buf++ = c;
- break;
- }
- }
- }
-
- char *
- _numcnv(buf, base, flags, ip_p, precision, minfldw)
- char *buf;
- unsigned int base;
- int **ip_p;
- {
- char numbuf[20], prefix[5], *s, *p, *strncpy();
- int n, pad, lng, d;
- long value, *l_p;
- unsigned long uvalue;
-
- s = numbuf;
- p = prefix;
- if (flags & LONGFLG) {
- l_p = (long *)*ip_p;
- value = *l_p++;
- *ip_p = (int *)l_p;
- }
- else {
- value = (long)**ip_p;
- *ip_p += 1;
- }
- if (flags & SIGNFLG) {
- if (value < 0) {
- *p++ = '-';
- value = -value;
- }
- else {
- if (flags & PLUSFLG) *p++ = '+';
- else if (flags & BLANKFLG) *p++ = ' ';
- }
- }
- uvalue = (unsigned long) value;
- while (uvalue) {
- d = uvalue % base;
- *s++ = (d < 10) ? d + '0'
- : d - 10 + ((flags & LOWERFLG) ? 'a' : 'A');
- uvalue /= base;
- }
- lng = (int)(s - numbuf);
- n = (int)(p - prefix);
- pad = minfldw - n;
- if (flags & ZEROFLG) precision = minfldw - n;
- if (precision < 0) precision = 1;
- if (flags & POUNDFLG) {
- if (base == 8 && lng >= precision) precision = lng + 1;
- else if (base == 16) {
- *p++ = '0';
- *p++ = flags & LOWERFLG ? 'x' : 'X';
- n += 2;
- precision -= 2;
- }
- }
- pad -= lng > precision ? lng : precision;
- if (pad < 0) pad = 0;
- if ((flags & MINUSFLG) == 0) {
- while (pad--) *buf++ = ' ';
- pad = 0;
- }
- strncpy(buf, prefix, n);
- buf += n;
- while (precision-- > lng) *buf++ = '0';
- while (lng--) *buf++ = *--s;
- while (pad--) *buf++ = ' ';
- return buf;
- }
-
- /* scanf routines */
-
- fscanf(f, fmt, args) FILE *f; char *fmt; int *args; {
- extern char *_sfcp;
- extern FILE *_sffp;
- _sffp = f;
- _sfcp = NULL;
- return _dosf(fmt, &args);
- }
-
- scanf(fmt, args) char *fmt; int *args; {
- extern char *_sfcp;
- extern FILE *_sffp;
- _sffp = stdin;
- _sfcp = NULL;
- return _dosf(fmt, &args);
- }
-
- sscanf(s, fmt, args) char *s; char *fmt; int *args; {
- extern char *_sfcp;
- extern FILE *_sffp;
- _sffp = NULL;
- _sfcp = s;
- return _dosf(fmt, &args);
- }
-
- _dosf(fmt, args) char *fmt; int **args; {
- int assigned, wid, lng, skip, *ip, f, c, m, base;
- long n, *lp;
- char *cp;
- assigned = 0;
- c = _sfget();
- while ((f = *fmt++) && c != EOF) {
- if (f <= ' ') { /* skip spaces */
- while (c <= ' ' && c != EOF)
- c = _sfget();
- }
- else if (f != '%') { /* match character */
- if (c != f)
- return assigned;
- }
- else {
- wid = lng = skip = 0;
- if ((f = *fmt++) == '*') { /* skip assignment */
- skip++;
- f = *fmt++;
- }
- while (f >= '0' && f <= '9') { /* width of value */
- wid = wid * 10 + f - '0';
- f = *fmt++;
- }
- if (f == 'l') { /* long */
- lng++;
- f = *fmt++;
- }
- else if (f == 'h') { /* short */
- f = *fmt++;
- }
- switch (f) { /* conversion spec */
- case '%':
- if (c != '%') return assigned;
- c = _sfget();
- break;
- case 'c':
- if (wid == 0) {
- cp = *args++;
- if (!skip) {
- *cp = c;
- assigned++;
- }
- c = _sfget();
- break;
- }
- case 's':
- cp = *args++;
- while (c <= ' ' && c != EOF)
- c = _sfget();
- while (c > ' ' && c != EOF) {
- if (!skip) *cp++ = c;
- c = _sfget();
- if (--wid == 0) break;
- }
- *cp = 0;
- if (!skip) assigned++;
- break;
- case 'D': case 'X': case 'O':
- lng = 1;
- f = f - 'A' + 'a';
- case 'd': case 'x': case 'o':
- base = (f == 'x' ? 16 : f == 'o' ? 8 : 10);
- n = 0L;
- while (c != EOF && c <= ' ')
- c = _sfget();
- if ((m = _sfnum(c, base)) < 0)
- return assigned;
- do {
- n = n * base + m;
- c = _sfget();
- m = _sfnum(c, base);
- if (--wid == 0) break;
- } while (m >= 0);
- if (!skip) {
- if (lng) {
- lp = *args++;
- *lp = n;
- }
- else {
- ip = *args++;
- *ip = n;
- }
- assigned++;
- }
- break;
- case 'e': case 'f': case 'E': case 'F':
- /* no floats implemented */
- return -2;
- default:
- return assigned;
- }
- }
- }
- return f == 0 ? assigned : EOF;
- }
-
-
- _sfnum(c, base) {
- if (c >= '0' && c <= '9')
- return c - '0';
- else if (base == 16 && c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- else if (base == 16 && c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- else return -1;
- }
-
- _sfget() {
- extern char *_sfcp;
- extern FILE *_sffp;
- if (_sffp) return getc(_sffp);
- if (_sfcp && *_sfcp) return *_sfcp++;
- return EOF;
- }
-
- char *_sfcp; /* char pointer for scanf input string */
- FILE *_sffp; /* FILE pointer for scanf input stream */
-
- /* malloc, free, realloc: dynamic memory allocation */
-
- #define MAXHUNK 512
-
- struct header {
- struct header *next;
- unsigned size;
- };
-
- char *
- malloc(n) unsigned n; {
- extern struct header _base;
- struct header *p, *q;
- long sz;
-
- /* add a header to required size and round up */
- n = n + sizeof(struct header);
- n = (7 + n) & ~7;
-
- /* look for first block big enough in free list */
- p = &_base;
- q = _base.next;
- while (q != NULL && q->size < n) {
- p = q;
- q = q->next;
- }
-
- /* if not enough memory, get more from the system */
- if (q == NULL) {
- sz = (n > MAXHUNK ? n : MAXHUNK);
- q = trap(1, 0x48, sz);
- if (((long)q) < 0) /* no more memory */
- return NULL;
- p->next = q;
- q->size = sz;
- q->next = NULL;
- }
-
- if (q->size > n + sizeof(struct header)) { /* chop it up */
- q->size -= n;
- q = ((long) q) + q->size;
- q->size = n;
- }
- else { /* unlink from free list */
- p->next = q->next;
- }
-
- /* skip over header, hope they don't touch it */
- return ++q;
- }
-
- free(r) struct header *r; {
- extern struct header _base;
- struct header *p, *q, *t;
-
- /* move back to uncover the header */
- r--;
-
- /* find where to insert it */
- p = &_base;
- q = _base.next;
- while (q != NULL && q < r) {
- p = q;
- q = q->next;
- }
-
- /* merge after if possible */
- t = ((long) r) + r->size;
- if (q != NULL && t >= q) {
- r->size += q->size;
- q = q->next;
- }
- r->next = q;
-
- /* merge before if possible, otherwise link it in */
- t = ((long) p) + p->size;
- if (t >= r) {
- p->size += r->size;
- p->next = r->next;
- }
- else p->next = r;
- }
-
- char *
- realloc(r, n) struct header *r; unsigned n; {
- struct header *p, *q;
- long *src, *dst;
- unsigned sz;
-
- p = r - 1;
- sz = (n + sizeof(struct header) + 7) & ~7;
-
- if (p->size > sz) { /* block too big, split in two */
- q = ((long) p) + sz;
- q->size = p->size - sz;
- free(q + 1);
- p->size = sz;
- }
- else if (p->size < sz) { /* block too small, get new one */
- dst = q = malloc(n);
- if (q != NULL) {
- src = r;
- n = p->size - sizeof(struct header);
- while (n > 0) {
- *dst++ = *src++;
- n -= sizeof(long);
- }
- }
- free(r);
- r = q;
- }
- /* else current block will do just fine */
-
- return r;
- }
-
- char *
- calloc(n, sz) unsigned n, sz; {
- char *r, *s;
- unsigned total;
-
- total = n * sz;
- if ((r = s = malloc(total)) != NULL) {
- while (total--)
- *s++ = 0;
- }
- return r;
- }
-
- struct header _base = { NULL, 0 };
-
- /* get options from command line */
-
- extern char *strchr();
- extern char *optarg;
- extern int optind, opterr, optsubind;
-
- getopt(argc, argv, optstr) char *argv[], *optstr; {
- char *o, c;
-
- if (++optind == argc) return EOF;
-
- o = argv[optind];
-
- if (*o == '-') {
- c = o[++optsubind];
- if (c == '-') return EOF;
- optstr = strchr(optstr, c);
- if (optstr == NULL) {
- if (opterr == 0) {
- fprintf(stderr, "unknown option: %s\n", o);
- }
- optsubind = 0;
- return '?';
- }
- if (optstr[1] == ':') {
- optarg = (o[optsubind + 1] != (char)0)
- ? o + optsubind + 1 : argv[++optind];
- optsubind = 0;
- if (optarg == NULL) {
- if (opterr == 0) {
- fprintf(stderr, "missing arg: %s\n", o);
- }
- return '?';
- }
- }
- else if (o[2] != (char)0) {
- optind -= 1;
- }
- return c;
- }
- return EOF;
- }
-
- char *optarg;
- int optind, opterr, optsubind;
-
- /* string routines */
-
- #define MASK(c) ((int)(c) & 0xff)
-
- extern char *_tokptr;
-
- char *
- strcat(s1, s2) char *s1, *s2; {
- char *r;
-
- r = s1;
- if (*s1) while (*++s1);
- while (*s1++ = *s2++);
- return r;
- }
-
- char *
- strncat(s1, s2, n) char *s1, *s2; int n; {
- char *r;
-
- if (n <= 0) return s1;
- r = s1;
- if (*s1) while (*++s1);
- while (n-- && (*s1++ = *s2++));
- while (n-- > 0) *s1++ = EOS;
- return r;
- }
-
- strcmp(s1, s2) char *s1, *s2; {
- while (*s1) {
- if (*s1++ != *s2++)
- return MASK(*--s1) - MASK(*--s2);
- }
- return -MASK(*s2);
- }
-
- strncmp(s1, s2, n) char *s1, *s2; int n; {
- if (n <= 0) return 0;
- while (*s1 && --n) {
- if (*s1++ != *s2++) return MASK(*--s1) - MASK(*--s2);
- }
- return MASK(*s1) - MASK(*s2);
- }
-
- char *
- strcpy(s1, s2) char *s1, *s2; {
- char *r;
-
- r = s1;
- while (*r++ = *s2++);
- return s1;
- }
-
- char *
- strncpy(s1, s2, n) char *s1, *s2; int n; {
- char *r;
-
- if (n <= 0) return s1;
- r = s1;
- while (n && (*r++ = *s2++)) --n;
- while (n--) *r++ = EOS;
- return s1;
- }
-
- strlen(s) char *s; {
- int n;
-
- for (n = 0; *s++; ++n)
- ;
- return n;
- }
-
- char *
- strchr(s, c) char *s; int c; {
- while (*s) if (*s++ == c) return --s;
- return NULL;
- }
-
- char *
- strrchr(s, c) char *s; int c; {
- char *l;
-
- l = NULL;
- while (*s)
- if (*s++ == c)
- l = s - 1;
- return l;
- }
-
- char *
- strpbrk(s1, s2) unsigned char *s1, *s2; {
- int n;
- long bitmap[16];
-
- if (*s1 || *s2) return NULL;
- _setbits(s2, bitmap);
- n = *s1;
- do {
- if (bitmap[n >> 5] & (1 << (n & 31)))
- return s1;
- } while (n = *--s1);
- return NULL;
- }
-
- char *
- strtok(s1, s2) unsigned char *s1, *s2; {
- if (s1 != NULL) _tokptr = s1;
- if (*_tokptr == EOS) return NULL;
- s1 = _tokptr + strspn(_tokptr, s2);
- _tokptr = s1 + strcspn(s1, s2);
- if (_tokptr == s1) return NULL;
- if (*_tokptr != EOS) *_tokptr++ = EOS;
- return s1;
- }
-
- char *_tokptr;
-
- strspn(s1, s2) unsigned char *s1, *s2; {
- long n;
- long bitmap[8];
-
- if ((*s1 == 0) || (*s2 == 0))
- return 0;
- _setbits(s2, bitmap);
- s2 = s1;
- for (n = *s1; bitmap[n >> 5] & (1L << (n & 31)); n = *++s1)
- ;
- return s1 - s2;
- }
-
- strcspn(s1, s2) unsigned char *s1, *s2; {
- long n;
- long bitmap[8];
-
- if ((*s1 == 0) || (*s2 == 0))
- return 0;
- _setbits(s2, bitmap);
- s2 = s1;
- bitmap[0] |= 1L; /* so that eos exits loop */
- for (n = *s1; (bitmap[n >> 5] & (1L << (n & 31))) == 0L; n = *++s1)
- ;
- return s1 - s2;
- }
-
- _setbits(s, m) unsigned char *s; long m[]; {
- unsigned long n;
-
- for (n = 8; n; ) m[--n] = 0L;
- while (n = *s++) {
- m[n >> 5] |= 1L << (n & 31);
- }
- }
-
- long
- strtol(s, p, base) char *s, **p; {
- long r;
- int sign, bn, bcl, bcu, c;
-
- r = 0L;
- sign = 0;
- bn = (base < 11) ? ('0' - 1) + base : '9';
- bcl = ('a' - 10) + base;
- bcu = ('A' - 10) + base;
- while (*s == ' ' || *s == '\t') ++s;
- if (*s == '-') {
- sign = 1;
- ++s;
- }
- if (*s == '0') {
- if ((s[1] == 'x' || s[1] == 'X') && (base == 16)) s += 2;
- }
- for (c = *s ; ; c = *++s) {
- if (c >= '0' && c <= bn)
- c = c - '0';
- else if (c >= 'a' && c < bcl)
- c = c - 'a' + 10;
- else if (c >= 'A' && c < bcu)
- c = c - 'A' + 10;
- else {
- if (p != NULL) *p = s;
- return sign ? -r : r;
- }
- r = r * base + c;
- }
- }
-
- char *
- strlower(s) char *s; {
- char c, *p;
-
- for (p = s; c = *p; ++p)
- if (c >= 'A' && c <= 'Z')
- *p = c - ('A' - 'a');
- return s;
- }
-
- char *
- strupper(s) char *s; {
- char c, *p;
-
- for (p = s; c = *p; ++p)
- if (c >= 'a' && c <= 'z')
- *p = c - ('a' - 'A');
- return s;
- }
-
- memcpy(m1, m2, n) char *m1, *m2; {
- while (n-- > 0)
- *m1++ = *m2++;
- }
-
- /* a UNIX style time command */
-
- extern int _ma[];
-
- long
- time(tloc) long *tloc; {
- int n, hms, y, m, d;
- long t;
-
- n = getdate();
- y = (n >> 9) & 127; m = (n >> 5) & 15; d = n & 31;
- hms = gettime();
- t = (1460 * y) / 4 + ((y % 4) ? 1 : 0) + _ma[m] + d;
- t = 2L * (long)(hms & 31)
- + 60L * (long)((hms >> 5) & 63)
- + 3600L * (24L * t + (long)((hms >> 11) & 31));
- if (tloc != NULL) *tloc = t;
- return t;
- }
-
- getdate() { return trap(1, 0x2A); }
-
- gettime() { return trap(1, 0x2C); }
-
- int _ma[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-
- /* setjmp/longjmp thanks to Bruce Szablak, use setjmp.h! */
-
- setjmp(buf) char **buf; {
- asm( lll 8 0);
- asm( tda 0 0); /* a0 has pointer to buffer */
- asm( tad 6 0); /* d0 has current link pointer */
- asm( sol 0 0 0); /* save clp */
- asm( lol 6 0 0); /* d0 has old link pointer */
- asm( sol 0 4 0); /* save olp */
- asm( lol 6 4 0); /* d0 has return address */
- asm( sol 0 8 0); /* save ret */
- return 0;
- }
-
- longjmp(buf, rc) char **buf; {
- asm( lll 8 0);
- asm( tda 0 0); /* buf in a0 */
- asm( llw 12 0); /* rc in d0 */
- asm( lol 0 0 1); /* current link pointer */
- asm( tda 1 6); /* now in a6 */
- asm( lol 0 4 1); /* old link pointer */
- asm( sll 1 0); /* now on stack */
- asm( lol 0 8 1); /* return address */
- asm( sll 1 4); /* now on stack */
- return; /* longjmp! */
- }
-
- /*
- * stuff for long binary ops (both signed and unsigned)
- * op == 0 for a multiplication request
- * op == 1 for a division
- * op == 2 for a mod operation
- * a and b are the left and right arguments to the binary operator
- *
- * div and mod are done by long division, shift b up until >= a, then
- * back down, subtracting when appropriate
- *
- * mul is done by shifts and adds
- */
-
- #define MUL 0
- #define DIV 1
- #define MOD 2
-
- long
- _lop(op, a, b) int op; long a, b; {
- int neg;
- long result, _ulop();
- neg = 0;
- if (a < 0) {
- neg++;
- a = -a;
- }
- if (b < 0) {
- neg++;
- b = -b;
- }
- result = _ulop(op, a, b);
- return (((op != MOD) && (neg & 1)) ? -result : result);
- }
-
- long
- _ulop(op, xx, yy) int op; unsigned long xx, yy; {
- int i;
- unsigned long result, x, y;
- x = xx;
- y = yy;
- if (op == MUL) {
- result = 0L;
- while (x) {
- if (x & 1L)
- result += y;
- x >>= 1L;
- y <<= 1L;
- }
- }
- else { /* DIV or MOD */
- i = 0;
- result = x > 0x80000000L ? 0x80000000L : x;
- while (y < result) {
- i++;
- y <<= 1L;
- }
- result = 0L;
- while (i) {
- if (x >= y) {
- x -= y;
- result++;
- }
- i--;
- result <<= 1L;
- y >>= 1L;
- }
- if (x >= y) {
- x -= y;
- result++;
- }
- if (op == MOD) result = x;
- }
- return result;
- }
-
-