xref: /csrg-svn/old/dbx/library.c (revision 33321)
121606Sdist /*
221606Sdist  * Copyright (c) 1983 Regents of the University of California.
321606Sdist  * All rights reserved.  The Berkeley software License Agreement
421606Sdist  * specifies the terms and conditions for redistribution.
521606Sdist  */
69666Slinton 
721606Sdist #ifndef lint
8*33321Sdonn static char sccsid[] = "@(#)library.c	5.2 (Berkeley) 01/12/88";
921606Sdist #endif not lint
1016611Ssam 
11*33321Sdonn static char rcsid[] = "$Header: library.c,v 1.2 87/03/25 20:50:14 donn Exp $";
1218221Slinton 
139666Slinton /*
149666Slinton  * General purpose routines.
159666Slinton  */
169666Slinton 
179666Slinton #include <stdio.h>
189666Slinton #include <errno.h>
199666Slinton #include <signal.h>
209666Slinton 
219666Slinton #define public
229666Slinton #define private static
239666Slinton #define and &&
249666Slinton #define or ||
259666Slinton #define not !
269666Slinton #define ord(enumcon)	((int) enumcon)
279666Slinton #define nil(type)	((type) 0)
289666Slinton 
2916611Ssam typedef int integer;
3016611Ssam typedef enum { FALSE, TRUE } boolean;
319666Slinton typedef char *String;
329666Slinton typedef FILE *File;
339666Slinton typedef String Filename;
349666Slinton 
359666Slinton #undef FILE
369666Slinton 
379666Slinton String cmdname;			/* name of command for error messages */
389666Slinton Filename errfilename;		/* current file associated with error */
399666Slinton short errlineno;		/* line number associated with error */
409666Slinton 
419666Slinton /*
429666Slinton  * Definitions for doing memory allocation.
439666Slinton  */
449666Slinton 
459666Slinton extern char *malloc();
469666Slinton 
479666Slinton #define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))
489666Slinton #define dispose(p)	{ free((char *) p); p = 0; }
499666Slinton 
509666Slinton /*
519666Slinton  * Macros for doing freads + fwrites.
529666Slinton  */
539666Slinton 
549666Slinton #define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)
559666Slinton #define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)
569666Slinton 
579666Slinton /*
589666Slinton  * String definitions.
599666Slinton  */
609666Slinton 
619666Slinton extern String strcpy(), index(), rindex();
629666Slinton extern int strlen();
639666Slinton 
649666Slinton #define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)
659666Slinton #define streq(s1, s2)	(strcmp(s1, s2) == 0)
669666Slinton 
67*33321Sdonn typedef int IntFunc();
689666Slinton 
69*33321Sdonn IntFunc *onsyserr();
70*33321Sdonn 
719666Slinton typedef struct {
72*33321Sdonn     IntFunc *func;
73*33321Sdonn } ErrInfo;
749666Slinton 
75*33321Sdonn #define ERR_IGNORE ((IntFunc *) 0)
76*33321Sdonn #define ERR_CATCH  ((IntFunc *) 1)
779666Slinton 
789666Slinton /*
799666Slinton  * Call a program.
809666Slinton  *
819666Slinton  * Four entries:
829666Slinton  *
839666Slinton  *	call, callv - call a program and wait for it, returning status
849666Slinton  *	back, backv - call a program and don't wait, returning process id
859666Slinton  *
869666Slinton  * The command's standard input and output are passed as FILE's.
879666Slinton  */
889666Slinton 
899666Slinton 
9016611Ssam #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
919666Slinton #define BADEXEC 127	/* exec fails */
929666Slinton 
939666Slinton #define ischild(pid)    ((pid) == 0)
949666Slinton 
959666Slinton /* VARARGS3 */
969666Slinton public int call(name, in, out, args)
979666Slinton String name;
989666Slinton File in;
999666Slinton File out;
1009666Slinton String args;
1019666Slinton {
1029666Slinton     String *ap, *argp;
1039666Slinton     String argv[MAXNARGS];
1049666Slinton 
1059666Slinton     argp = &argv[0];
1069666Slinton     *argp++ = name;
1079666Slinton     ap = &args;
1089666Slinton     while (*ap != nil(String)) {
1099666Slinton 	*argp++ = *ap++;
1109666Slinton     }
1119666Slinton     *argp = nil(String);
1129666Slinton     return callv(name, in, out, argv);
1139666Slinton }
1149666Slinton 
1159666Slinton /* VARARGS3 */
1169666Slinton public int back(name, in, out, args)
1179666Slinton String name;
1189666Slinton File in;
1199666Slinton File out;
1209666Slinton String args;
1219666Slinton {
1229666Slinton     String *ap, *argp;
1239666Slinton     String argv[MAXNARGS];
1249666Slinton 
1259666Slinton     argp = &argv[0];
1269666Slinton     *argp++ = name;
1279666Slinton     ap = &args;
1289666Slinton     while (*ap != nil(String)) {
1299666Slinton 	*argp++ = *ap++;
1309666Slinton     }
1319666Slinton     *argp = nil(String);
1329666Slinton     return backv(name, in, out, argv);
1339666Slinton }
1349666Slinton 
1359666Slinton public int callv(name, in, out, argv)
1369666Slinton String name;
1379666Slinton File in;
1389666Slinton File out;
1399666Slinton String *argv;
1409666Slinton {
1419666Slinton     int pid, status;
1429666Slinton 
1439666Slinton     pid = backv(name, in, out, argv);
1449666Slinton     pwait(pid, &status);
1459666Slinton     return status;
1469666Slinton }
1479666Slinton 
1489666Slinton public int backv(name, in, out, argv)
1499666Slinton String name;
1509666Slinton File in;
1519666Slinton File out;
1529666Slinton String *argv;
1539666Slinton {
1549666Slinton     int pid;
1559666Slinton 
1569666Slinton     fflush(stdout);
1579666Slinton     if (ischild(pid = fork())) {
1589666Slinton 	fswap(0, fileno(in));
1599666Slinton 	fswap(1, fileno(out));
1609666Slinton 	onsyserr(EACCES, ERR_IGNORE);
1619666Slinton 	execvp(name, argv);
1629666Slinton 	_exit(BADEXEC);
1639666Slinton     }
1649666Slinton     return pid;
1659666Slinton }
1669666Slinton 
1679666Slinton /*
1689666Slinton  * Swap file numbers so as to redirect standard input and output.
1699666Slinton  */
1709666Slinton 
1719666Slinton private fswap(oldfd, newfd)
1729666Slinton int oldfd;
1739666Slinton int newfd;
1749666Slinton {
1759666Slinton     if (oldfd != newfd) {
1769666Slinton 	close(oldfd);
1779666Slinton 	dup(newfd);
1789666Slinton 	close(newfd);
1799666Slinton     }
1809666Slinton }
1819666Slinton 
1829666Slinton /*
1839666Slinton  * Invoke a shell on a command line.
1849666Slinton  */
1859666Slinton 
1869666Slinton #define DEF_SHELL	"csh"
1879666Slinton 
1889666Slinton public shell(s)
1899666Slinton String s;
1909666Slinton {
1919666Slinton     extern String getenv();
1929666Slinton     String sh;
1939666Slinton 
1949666Slinton     if ((sh = getenv("SHELL")) == nil(String)) {
1959666Slinton 	sh = DEF_SHELL;
1969666Slinton     }
1979666Slinton     if (s != nil(String) and *s != '\0') {
1989666Slinton 	call(sh, stdin, stdout, "-c", s, 0);
1999666Slinton     } else {
2009666Slinton 	call(sh, stdin, stdout, 0);
2019666Slinton     }
2029666Slinton }
2039666Slinton 
2049666Slinton /*
2059666Slinton  * Wait for a process the right way.  We wait for a particular
2069666Slinton  * process and if any others come along in between, we remember them
2079666Slinton  * in case they are eventually waited for.
2089666Slinton  *
2099666Slinton  * This routine is not very efficient when the number of processes
2109666Slinton  * to be remembered is large.
21114394Slinton  *
21214394Slinton  * To deal with a kernel idiosyncrasy, we keep a list on the side
21314394Slinton  * of "traced" processes, and do not notice them when waiting for
21414394Slinton  * another process.
2159666Slinton  */
2169666Slinton 
2179666Slinton typedef struct pidlist {
2189666Slinton     int pid;
2199666Slinton     int status;
2209666Slinton     struct pidlist *next;
2219666Slinton } Pidlist;
2229666Slinton 
22314394Slinton private Pidlist *pidlist, *ptrclist, *pfind();
2249666Slinton 
22514394Slinton public ptraced(pid)
22614394Slinton int pid;
22714394Slinton {
22814394Slinton     Pidlist *p;
22914394Slinton 
23014394Slinton     p = alloc(1, Pidlist);
23114394Slinton     p->pid = pid;
23214394Slinton     p->next = ptrclist;
23314394Slinton     ptrclist = p;
23414394Slinton }
23514394Slinton 
23614394Slinton public unptraced(pid)
23714394Slinton int pid;
23814394Slinton {
23914394Slinton     register Pidlist *p, *prev;
24014394Slinton 
24114394Slinton     prev = nil(Pidlist *);
24214394Slinton     p = ptrclist;
24314394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
24414394Slinton 	prev = p;
24514394Slinton 	p = p->next;
24614394Slinton     }
24714394Slinton     if (p != nil(Pidlist *)) {
24814394Slinton 	if (prev == nil(Pidlist *)) {
24914394Slinton 	    ptrclist = p->next;
25014394Slinton 	} else {
25114394Slinton 	    prev->next = p->next;
25214394Slinton 	}
25314394Slinton 	dispose(p);
25414394Slinton     }
25514394Slinton }
25614394Slinton 
25716611Ssam private boolean isptraced(pid)
25814394Slinton int pid;
25914394Slinton {
26014394Slinton     register Pidlist *p;
26114394Slinton 
26214394Slinton     p = ptrclist;
26314394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
26414394Slinton 	p = p->next;
26514394Slinton     }
26616611Ssam     return (boolean) (p != nil(Pidlist *));
26714394Slinton }
26814394Slinton 
2699666Slinton public pwait(pid, statusp)
2709666Slinton int pid, *statusp;
2719666Slinton {
27214393Slinton     Pidlist *p;
27314393Slinton     int pnum, status;
2749666Slinton 
27514393Slinton     p = pfind(pid);
27614393Slinton     if (p != nil(Pidlist *)) {
27714393Slinton 	*statusp = p->status;
27814393Slinton 	dispose(p);
27914394Slinton     } else {
28014394Slinton 	pnum = wait(&status);
28114394Slinton 	while (pnum != pid and pnum >= 0) {
28214394Slinton 	    if (not isptraced(pnum)) {
28314394Slinton 		p = alloc(1, Pidlist);
28414394Slinton 		p->pid = pnum;
28514394Slinton 		p->status = status;
28614394Slinton 		p->next = pidlist;
28714394Slinton 		pidlist = p;
28814394Slinton 	    }
28914394Slinton 	    pnum = wait(&status);
2909666Slinton 	}
29114394Slinton 	if (pnum < 0) {
29214394Slinton 	    p = pfind(pid);
29314394Slinton 	    if (p == nil(Pidlist *)) {
29414394Slinton 		panic("pwait: pid %d not found", pid);
29514394Slinton 	    }
29614394Slinton 	    *statusp = p->status;
29714394Slinton 	    dispose(p);
29814394Slinton 	} else {
29914394Slinton 	    *statusp = status;
30014394Slinton 	}
30114393Slinton     }
3029666Slinton }
3039666Slinton 
3049666Slinton /*
3059666Slinton  * Look for the given process id on the pidlist.
3069666Slinton  *
3079666Slinton  * Unlink it from list if found.
3089666Slinton  */
3099666Slinton 
3109666Slinton private Pidlist *pfind(pid)
3119666Slinton int pid;
3129666Slinton {
3139666Slinton     register Pidlist *p, *prev;
3149666Slinton 
3159666Slinton     prev = nil(Pidlist *);
3169666Slinton     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
3179666Slinton 	if (p->pid == pid) {
3189666Slinton 	    break;
3199666Slinton 	}
3209666Slinton 	prev = p;
3219666Slinton     }
3229666Slinton     if (p != nil(Pidlist *)) {
3239666Slinton 	if (prev == nil(Pidlist *)) {
3249666Slinton 	    pidlist = p->next;
3259666Slinton 	} else {
3269666Slinton 	    prev->next = p->next;
3279666Slinton 	}
3289666Slinton     }
3299666Slinton     return p;
3309666Slinton }
3319666Slinton 
3329666Slinton /*
3339666Slinton  * System call error handler.
3349666Slinton  *
3359666Slinton  * The syserr routine is called when a system call is about to
3369666Slinton  * set the c-bit to report an error.  Certain errors are caught
3379666Slinton  * and cause the process to print a message and immediately exit.
3389666Slinton  */
3399666Slinton 
3409666Slinton extern int sys_nerr;
3419666Slinton extern char *sys_errlist[];
3429666Slinton 
3439666Slinton /*
3449666Slinton  * Before calling syserr, the integer errno is set to contain the
3459666Slinton  * number of the error.  The routine "_mycerror" is a dummy which
3469666Slinton  * is used to force the loader to get my version of cerror rather
3479666Slinton  * than the usual one.
3489666Slinton  */
3499666Slinton 
3509666Slinton extern int errno;
3519666Slinton extern _mycerror();
3529666Slinton 
3539666Slinton /*
35416611Ssam  * Initialize error information, setting defaults for handling errors.
3559666Slinton  */
3569666Slinton 
357*33321Sdonn private ErrInfo *errinfo;
3589666Slinton 
35916611Ssam private initErrInfo ()
36016611Ssam {
36116611Ssam     integer i;
36216611Ssam 
363*33321Sdonn     errinfo = alloc(sys_nerr, ErrInfo);
36416611Ssam     for (i = 0; i < sys_nerr; i++) {
36516611Ssam 	errinfo[i].func = ERR_CATCH;
36616611Ssam     }
36716611Ssam     errinfo[0].func = ERR_IGNORE;
36816611Ssam     errinfo[EPERM].func = ERR_IGNORE;
36916611Ssam     errinfo[ENOENT].func = ERR_IGNORE;
37016611Ssam     errinfo[ESRCH].func = ERR_IGNORE;
37116611Ssam     errinfo[EBADF].func = ERR_IGNORE;
37216611Ssam     errinfo[ENOTTY].func = ERR_IGNORE;
37316611Ssam     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
37416611Ssam }
37516611Ssam 
3769666Slinton public syserr()
3779666Slinton {
378*33321Sdonn     register ErrInfo *e;
3799666Slinton 
38016611Ssam     if (errno < 0 or errno > sys_nerr) {
38116611Ssam 	fatal("errno %d", errno);
38216611Ssam     } else {
383*33321Sdonn 	if (errinfo == nil(ErrInfo *)) {
38416611Ssam 	    initErrInfo();
38516611Ssam 	}
38616611Ssam 	e = &(errinfo[errno]);
38716611Ssam 	if (e->func == ERR_CATCH) {
3889666Slinton 	    fatal(sys_errlist[errno]);
38916611Ssam 	} else if (e->func != ERR_IGNORE) {
39016611Ssam 	    (*e->func)();
3919666Slinton 	}
3929666Slinton     }
3939666Slinton }
3949666Slinton 
3959666Slinton /*
39616611Ssam  * Catcherrs' purpose is to initialize the errinfo table, get this module
39716611Ssam  * loaded, and make sure my cerror is loaded (only applicable when this is
39816611Ssam  * in a library).
3999666Slinton  */
4009666Slinton 
4019666Slinton public catcherrs()
4029666Slinton {
4039666Slinton     _mycerror();
40416611Ssam     initErrInfo();
4059666Slinton }
4069666Slinton 
4079666Slinton /*
40818221Slinton  * Turn off the error catching mechanism completely by having all errors
40918221Slinton  * ignored.  This is most useful between a fork and an exec.
41018221Slinton  */
41118221Slinton 
41218221Slinton public nocatcherrs()
41318221Slinton {
41418221Slinton     integer i;
41518221Slinton 
41618221Slinton     for (i = 0; i < sys_nerr; i++) {
41718221Slinton 	errinfo[i].func = ERR_IGNORE;
41818221Slinton     }
41918221Slinton }
42018221Slinton 
42118221Slinton /*
422*33321Sdonn  * Change the action on receipt of an error, returning the previous action.
4239666Slinton  */
4249666Slinton 
425*33321Sdonn public IntFunc *onsyserr(n, f)
4269666Slinton int n;
427*33321Sdonn IntFunc *f;
4289666Slinton {
429*33321Sdonn     IntFunc *oldf;
430*33321Sdonn 
431*33321Sdonn     if (errinfo == nil(ErrInfo *)) {
43216611Ssam 	initErrInfo();
43316611Ssam     }
434*33321Sdonn     oldf = errinfo[n].func;
4359666Slinton     errinfo[n].func = f;
436*33321Sdonn     return oldf;
4379666Slinton }
4389666Slinton 
4399666Slinton /*
4409666Slinton  * Print the message associated with the given signal.
4419666Slinton  * Like a "perror" for signals.
4429666Slinton  */
4439666Slinton 
444*33321Sdonn #ifdef SIGWINCH
4459666Slinton public int sys_nsig = NSIG;
446*33321Sdonn #else not 4.3 BSD
447*33321Sdonn /*
448*33321Sdonn  * This table is correct for 4.2-like systems but will
449*33321Sdonn  * be inadequate for System V (which is the sort of
450*33321Sdonn  * Unix that needs it!).
451*33321Sdonn  */
452*33321Sdonn public String sys_siglist[] = {
453*33321Sdonn     "no signal",
454*33321Sdonn     "hangup",
455*33321Sdonn     "interrupt",
456*33321Sdonn     "quit",
457*33321Sdonn     "illegal instruction",
458*33321Sdonn     "trace trap",
459*33321Sdonn     "IOT instruction",
460*33321Sdonn     "EMT instruction",
461*33321Sdonn     "floating point exception",
462*33321Sdonn     "kill",
463*33321Sdonn     "bus error",
464*33321Sdonn     "segmentation violation",
465*33321Sdonn     "bad argument to system call",
466*33321Sdonn     "broken pipe",
467*33321Sdonn     "alarm clock",
468*33321Sdonn     "soft kill",
469*33321Sdonn     "urgent I/O condition",
470*33321Sdonn     "stop signal not from tty",
471*33321Sdonn     "stop signal from tty",
472*33321Sdonn     "continue",
473*33321Sdonn     "child termination",
474*33321Sdonn     "stop (tty input)",
475*33321Sdonn     "stop (tty output)",
476*33321Sdonn     "possible input/output",
477*33321Sdonn     "exceeded CPU time limit",
478*33321Sdonn     "exceeded file size limit"
479*33321Sdonn };
480*33321Sdonn public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
481*33321Sdonn #endif
4829666Slinton 
48316611Ssam public psignal(s, n)
4849666Slinton String s;
48516611Ssam integer n;
4869666Slinton {
48716611Ssam     String msg;
48816611Ssam     integer len;
48918538Sralph     extern String sys_siglist[];
4909666Slinton 
49116611Ssam     if (n >= 0 and n < sys_nsig) {
49216611Ssam 	msg = sys_siglist[n];
49316611Ssam     } else {
49416611Ssam 	msg = "Unknown signal";
4959666Slinton     }
49616611Ssam     len = strlen(s);
49716611Ssam     if (len > 0) {
49816611Ssam 	write(2, s, len);
4999666Slinton 	write(2, ": ", 2);
5009666Slinton     }
50116611Ssam     write(2, msg, strlen(msg));
5029666Slinton     write(2, "\n", 1);
5039666Slinton }
5049666Slinton 
5059666Slinton /*
5069666Slinton  * Standard error handling routines.
5079666Slinton  */
5089666Slinton 
5099666Slinton private short nerrs;
5109666Slinton private short nwarnings;
5119666Slinton 
5129666Slinton /*
5139666Slinton  * Main driver of error message reporting.
5149666Slinton  */
5159666Slinton 
5169666Slinton /* VARARGS2 */
5179666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5189666Slinton String errname;
51916611Ssam boolean shouldquit;
5209666Slinton String s;
5219666Slinton {
5229666Slinton     fflush(stdout);
5239666Slinton     if (shouldquit and cmdname != nil(String)) {
5249666Slinton 	fprintf(stderr, "%s: ", cmdname);
5259666Slinton     }
5269666Slinton     if (errfilename != nil(Filename)) {
5279666Slinton 	fprintf(stderr, "%s: ", errfilename);
5289666Slinton     }
5299666Slinton     if (errlineno > 0) {
5309666Slinton 	fprintf(stderr, "%d: ", errlineno);
5319666Slinton     }
5329666Slinton     if (errname != nil(String)) {
5339666Slinton 	fprintf(stderr, "%s: ", errname);
5349666Slinton     }
5359666Slinton     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5369666Slinton     putc('\n', stderr);
537*33321Sdonn     fflush(stderr);
5389666Slinton     if (shouldquit) {
5399666Slinton 	quit(1);
5409666Slinton     }
5419666Slinton }
5429666Slinton 
5439666Slinton /*
5449666Slinton  * For when printf isn't sufficient for printing the error message ...
5459666Slinton  */
5469666Slinton 
5479666Slinton public beginerrmsg()
5489666Slinton {
5499666Slinton     fflush(stdout);
5509666Slinton     if (errfilename != nil(String)) {
5519666Slinton 	fprintf(stderr, "%s: ", errfilename);
5529666Slinton     }
5539666Slinton     if (errlineno > 0) {
5549666Slinton 	fprintf(stderr, "%d: ", errlineno);
5559666Slinton     }
5569666Slinton }
5579666Slinton 
5589666Slinton public enderrmsg()
5599666Slinton {
5609666Slinton     putc('\n', stderr);
561*33321Sdonn     fflush(stderr);
5629666Slinton     erecover();
5639666Slinton }
5649666Slinton 
5659666Slinton /*
5669666Slinton  * The messages are listed in increasing order of seriousness.
5679666Slinton  *
5689666Slinton  * First are warnings.
5699666Slinton  */
5709666Slinton 
5719666Slinton /* VARARGS1 */
5729666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5739666Slinton String s;
5749666Slinton {
5759666Slinton     nwarnings++;
5769666Slinton     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5779666Slinton }
5789666Slinton 
5799666Slinton /*
5809666Slinton  * Errors are a little worse, they mean something is wrong,
5819666Slinton  * but not so bad that processing can't continue.
5829666Slinton  *
5839666Slinton  * The routine "erecover" is called to recover from the error,
5849666Slinton  * a default routine is provided that does nothing.
5859666Slinton  */
5869666Slinton 
5879666Slinton /* VARARGS1 */
5889666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5899666Slinton String s;
5909666Slinton {
5919666Slinton     extern erecover();
5929666Slinton 
5939666Slinton     nerrs++;
5949666Slinton     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5959666Slinton     erecover();
5969666Slinton }
5979666Slinton 
5989666Slinton /*
5999666Slinton  * Non-recoverable user error.
6009666Slinton  */
6019666Slinton 
6029666Slinton /* VARARGS1 */
6039666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6049666Slinton String s;
6059666Slinton {
6069666Slinton     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6079666Slinton }
6089666Slinton 
6099666Slinton /*
6109666Slinton  * Panics indicate an internal program error.
6119666Slinton  */
6129666Slinton 
6139666Slinton /* VARARGS1 */
6149666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6159666Slinton String s;
6169666Slinton {
6179666Slinton     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6189666Slinton }
6199666Slinton 
6209666Slinton short numerrors()
6219666Slinton {
6229666Slinton     short r;
6239666Slinton 
6249666Slinton     r = nerrs;
6259666Slinton     nerrs = 0;
6269666Slinton     return r;
6279666Slinton }
6289666Slinton 
6299666Slinton short numwarnings()
6309666Slinton {
6319666Slinton     short r;
6329666Slinton 
6339666Slinton     r = nwarnings;
6349666Slinton     nwarnings = 0;
6359666Slinton     return r;
6369666Slinton }
6379666Slinton 
6389666Slinton /*
6399666Slinton  * Recover from an error.
6409666Slinton  *
6419666Slinton  * This is the default routine which we aren't using since we have our own.
6429666Slinton  *
6439666Slinton public erecover()
6449666Slinton {
6459666Slinton }
6469666Slinton  *
6479666Slinton  */
6489666Slinton 
6499666Slinton /*
6509666Slinton  * Default way to quit from a program is just to exit.
6519666Slinton  *
6529666Slinton public quit(r)
6539666Slinton int r;
6549666Slinton {
6559666Slinton     exit(r);
6569666Slinton }
6579666Slinton  *
6589666Slinton  */
6599666Slinton 
6609666Slinton /*
6619666Slinton  * Compare n-byte areas pointed to by s1 and s2
6629666Slinton  * if n is 0 then compare up until one has a null byte.
6639666Slinton  */
6649666Slinton 
6659666Slinton public int cmp(s1, s2, n)
6669666Slinton register char *s1, *s2;
6679666Slinton register unsigned int n;
6689666Slinton {
6699666Slinton     if (s1 == nil(char *) || s2 == nil(char *)) {
6709666Slinton 	panic("cmp: nil pointer");
6719666Slinton     }
6729666Slinton     if (n == 0) {
6739666Slinton 	while (*s1 == *s2++) {
6749666Slinton 	    if (*s1++ == '\0') {
6759666Slinton 		return(0);
6769666Slinton 	    }
6779666Slinton 	}
6789666Slinton 	return(*s1 - *(s2-1));
6799666Slinton     } else {
6809666Slinton 	for (; n != 0; n--) {
6819666Slinton 	    if (*s1++ != *s2++) {
6829666Slinton 		return(*(s1-1) - *(s2-1));
6839666Slinton 	    }
6849666Slinton 	}
6859666Slinton 	return(0);
6869666Slinton     }
6879666Slinton }
6889666Slinton 
6899666Slinton /*
6909666Slinton  * Move n bytes from src to dest.
6919666Slinton  * If n is 0 move until a null is found.
6929666Slinton  */
6939666Slinton 
6949666Slinton public mov(src, dest, n)
6959666Slinton register char *src, *dest;
6969666Slinton register unsigned int n;
6979666Slinton {
6989666Slinton     if (src == nil(char *))
6999666Slinton 	panic("mov: nil source");
7009666Slinton     if (dest == nil(char *))
7019666Slinton 	panic("mov: nil destination");
7029666Slinton     if (n != 0) {
7039666Slinton 	for (; n != 0; n--) {
7049666Slinton 	    *dest++ = *src++;
7059666Slinton 	}
7069666Slinton     } else {
7079666Slinton 	while ((*dest++ = *src++) != '\0');
7089666Slinton     }
7099666Slinton }
710*33321Sdonn 
711*33321Sdonn #ifdef IRIS /* or in general for 4.2 - System V C library interface */
712*33321Sdonn 
713*33321Sdonn public bcopy (fromaddr, toaddr, n)
714*33321Sdonn char *fromaddr, *toaddr;
715*33321Sdonn int n;
716*33321Sdonn {
717*33321Sdonn     blt(toaddr, fromaddr, n);
718*33321Sdonn }
719*33321Sdonn 
720*33321Sdonn public bzero (addr, n)
721*33321Sdonn char *addr;
722*33321Sdonn int n;
723*33321Sdonn {
724*33321Sdonn     register char *p, *q;
725*33321Sdonn 
726*33321Sdonn     p = addr;
727*33321Sdonn     q = p + n;
728*33321Sdonn     while (p < q) {
729*33321Sdonn 	*p++ = '\0';
730*33321Sdonn     }
731*33321Sdonn }
732*33321Sdonn 
733*33321Sdonn #include <string.h>
734*33321Sdonn 
735*33321Sdonn public char *index (s, c)
736*33321Sdonn char *s, c;
737*33321Sdonn {
738*33321Sdonn     return strchr(s, c);
739*33321Sdonn }
740*33321Sdonn 
741*33321Sdonn public char *rindex (s, c)
742*33321Sdonn char *s, c;
743*33321Sdonn {
744*33321Sdonn     return strrchr(s, c);
745*33321Sdonn }
746*33321Sdonn 
747*33321Sdonn #endif
748