xref: /csrg-svn/old/dbx/library.c (revision 46995)
121606Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
542683Sbostic  * %sccs.include.redist.c%
621606Sdist  */
79666Slinton 
821606Sdist #ifndef lint
9*46995Sbostic static char sccsid[] = "@(#)library.c	5.5 (Berkeley) 03/05/91";
1038105Sbostic #endif /* not lint */
1116611Ssam 
129666Slinton /*
139666Slinton  * General purpose routines.
149666Slinton  */
159666Slinton 
169666Slinton #include <stdio.h>
179666Slinton #include <errno.h>
189666Slinton #include <signal.h>
199666Slinton 
209666Slinton #define public
219666Slinton #define private static
229666Slinton #define and &&
239666Slinton #define or ||
249666Slinton #define not !
259666Slinton #define ord(enumcon)	((int) enumcon)
269666Slinton #define nil(type)	((type) 0)
279666Slinton 
2816611Ssam typedef int integer;
2916611Ssam typedef enum { FALSE, TRUE } boolean;
309666Slinton typedef char *String;
319666Slinton typedef FILE *File;
329666Slinton typedef String Filename;
339666Slinton 
349666Slinton #undef FILE
359666Slinton 
369666Slinton String cmdname;			/* name of command for error messages */
379666Slinton Filename errfilename;		/* current file associated with error */
389666Slinton short errlineno;		/* line number associated with error */
399666Slinton 
409666Slinton /*
419666Slinton  * Definitions for doing memory allocation.
429666Slinton  */
439666Slinton 
449666Slinton extern char *malloc();
459666Slinton 
469666Slinton #define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))
479666Slinton #define dispose(p)	{ free((char *) p); p = 0; }
489666Slinton 
499666Slinton /*
509666Slinton  * Macros for doing freads + fwrites.
519666Slinton  */
529666Slinton 
539666Slinton #define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)
549666Slinton #define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)
559666Slinton 
569666Slinton /*
579666Slinton  * String definitions.
589666Slinton  */
599666Slinton 
609666Slinton extern String strcpy(), index(), rindex();
619666Slinton extern int strlen();
629666Slinton 
639666Slinton #define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)
649666Slinton #define streq(s1, s2)	(strcmp(s1, s2) == 0)
659666Slinton 
6633321Sdonn typedef int IntFunc();
679666Slinton 
6833321Sdonn IntFunc *onsyserr();
6933321Sdonn 
709666Slinton typedef struct {
7133321Sdonn     IntFunc *func;
7233321Sdonn } ErrInfo;
739666Slinton 
7433321Sdonn #define ERR_IGNORE ((IntFunc *) 0)
7533321Sdonn #define ERR_CATCH  ((IntFunc *) 1)
769666Slinton 
779666Slinton /*
789666Slinton  * Call a program.
799666Slinton  *
809666Slinton  * Four entries:
819666Slinton  *
829666Slinton  *	call, callv - call a program and wait for it, returning status
839666Slinton  *	back, backv - call a program and don't wait, returning process id
849666Slinton  *
859666Slinton  * The command's standard input and output are passed as FILE's.
869666Slinton  */
879666Slinton 
889666Slinton 
8916611Ssam #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
909666Slinton #define BADEXEC 127	/* exec fails */
919666Slinton 
929666Slinton #define ischild(pid)    ((pid) == 0)
939666Slinton 
949666Slinton /* VARARGS3 */
call(name,in,out,args)959666Slinton public int call(name, in, out, args)
969666Slinton String name;
979666Slinton File in;
989666Slinton File out;
999666Slinton String args;
1009666Slinton {
1019666Slinton     String *ap, *argp;
1029666Slinton     String argv[MAXNARGS];
1039666Slinton 
1049666Slinton     argp = &argv[0];
1059666Slinton     *argp++ = name;
1069666Slinton     ap = &args;
1079666Slinton     while (*ap != nil(String)) {
1089666Slinton 	*argp++ = *ap++;
1099666Slinton     }
1109666Slinton     *argp = nil(String);
1119666Slinton     return callv(name, in, out, argv);
1129666Slinton }
1139666Slinton 
1149666Slinton /* VARARGS3 */
back(name,in,out,args)1159666Slinton public int back(name, in, out, args)
1169666Slinton String name;
1179666Slinton File in;
1189666Slinton File out;
1199666Slinton String args;
1209666Slinton {
1219666Slinton     String *ap, *argp;
1229666Slinton     String argv[MAXNARGS];
1239666Slinton 
1249666Slinton     argp = &argv[0];
1259666Slinton     *argp++ = name;
1269666Slinton     ap = &args;
1279666Slinton     while (*ap != nil(String)) {
1289666Slinton 	*argp++ = *ap++;
1299666Slinton     }
1309666Slinton     *argp = nil(String);
1319666Slinton     return backv(name, in, out, argv);
1329666Slinton }
1339666Slinton 
callv(name,in,out,argv)1349666Slinton public int callv(name, in, out, argv)
1359666Slinton String name;
1369666Slinton File in;
1379666Slinton File out;
1389666Slinton String *argv;
1399666Slinton {
1409666Slinton     int pid, status;
1419666Slinton 
1429666Slinton     pid = backv(name, in, out, argv);
1439666Slinton     pwait(pid, &status);
1449666Slinton     return status;
1459666Slinton }
1469666Slinton 
backv(name,in,out,argv)1479666Slinton public int backv(name, in, out, argv)
1489666Slinton String name;
1499666Slinton File in;
1509666Slinton File out;
1519666Slinton String *argv;
1529666Slinton {
1539666Slinton     int pid;
1549666Slinton 
1559666Slinton     fflush(stdout);
1569666Slinton     if (ischild(pid = fork())) {
1579666Slinton 	fswap(0, fileno(in));
1589666Slinton 	fswap(1, fileno(out));
1599666Slinton 	onsyserr(EACCES, ERR_IGNORE);
1609666Slinton 	execvp(name, argv);
1619666Slinton 	_exit(BADEXEC);
1629666Slinton     }
1639666Slinton     return pid;
1649666Slinton }
1659666Slinton 
1669666Slinton /*
1679666Slinton  * Swap file numbers so as to redirect standard input and output.
1689666Slinton  */
1699666Slinton 
fswap(oldfd,newfd)1709666Slinton private fswap(oldfd, newfd)
1719666Slinton int oldfd;
1729666Slinton int newfd;
1739666Slinton {
1749666Slinton     if (oldfd != newfd) {
1759666Slinton 	close(oldfd);
1769666Slinton 	dup(newfd);
1779666Slinton 	close(newfd);
1789666Slinton     }
1799666Slinton }
1809666Slinton 
1819666Slinton /*
1829666Slinton  * Invoke a shell on a command line.
1839666Slinton  */
1849666Slinton 
1859666Slinton #define DEF_SHELL	"csh"
1869666Slinton 
shell(s)1879666Slinton public shell(s)
1889666Slinton String s;
1899666Slinton {
1909666Slinton     extern String getenv();
1919666Slinton     String sh;
1929666Slinton 
1939666Slinton     if ((sh = getenv("SHELL")) == nil(String)) {
1949666Slinton 	sh = DEF_SHELL;
1959666Slinton     }
1969666Slinton     if (s != nil(String) and *s != '\0') {
1979666Slinton 	call(sh, stdin, stdout, "-c", s, 0);
1989666Slinton     } else {
1999666Slinton 	call(sh, stdin, stdout, 0);
2009666Slinton     }
2019666Slinton }
2029666Slinton 
2039666Slinton /*
2049666Slinton  * Wait for a process the right way.  We wait for a particular
2059666Slinton  * process and if any others come along in between, we remember them
2069666Slinton  * in case they are eventually waited for.
2079666Slinton  *
2089666Slinton  * This routine is not very efficient when the number of processes
2099666Slinton  * to be remembered is large.
21014394Slinton  *
21114394Slinton  * To deal with a kernel idiosyncrasy, we keep a list on the side
21214394Slinton  * of "traced" processes, and do not notice them when waiting for
21314394Slinton  * another process.
2149666Slinton  */
2159666Slinton 
2169666Slinton typedef struct pidlist {
2179666Slinton     int pid;
2189666Slinton     int status;
2199666Slinton     struct pidlist *next;
2209666Slinton } Pidlist;
2219666Slinton 
22214394Slinton private Pidlist *pidlist, *ptrclist, *pfind();
2239666Slinton 
ptraced(pid)22414394Slinton public ptraced(pid)
22514394Slinton int pid;
22614394Slinton {
22714394Slinton     Pidlist *p;
22814394Slinton 
22914394Slinton     p = alloc(1, Pidlist);
23014394Slinton     p->pid = pid;
23114394Slinton     p->next = ptrclist;
23214394Slinton     ptrclist = p;
23314394Slinton }
23414394Slinton 
unptraced(pid)23514394Slinton public unptraced(pid)
23614394Slinton int pid;
23714394Slinton {
23814394Slinton     register Pidlist *p, *prev;
23914394Slinton 
24014394Slinton     prev = nil(Pidlist *);
24114394Slinton     p = ptrclist;
24214394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
24314394Slinton 	prev = p;
24414394Slinton 	p = p->next;
24514394Slinton     }
24614394Slinton     if (p != nil(Pidlist *)) {
24714394Slinton 	if (prev == nil(Pidlist *)) {
24814394Slinton 	    ptrclist = p->next;
24914394Slinton 	} else {
25014394Slinton 	    prev->next = p->next;
25114394Slinton 	}
25214394Slinton 	dispose(p);
25314394Slinton     }
25414394Slinton }
25514394Slinton 
isptraced(pid)25616611Ssam private boolean isptraced(pid)
25714394Slinton int pid;
25814394Slinton {
25914394Slinton     register Pidlist *p;
26014394Slinton 
26114394Slinton     p = ptrclist;
26214394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
26314394Slinton 	p = p->next;
26414394Slinton     }
26516611Ssam     return (boolean) (p != nil(Pidlist *));
26614394Slinton }
26714394Slinton 
pwait(pid,statusp)2689666Slinton public pwait(pid, statusp)
2699666Slinton int pid, *statusp;
2709666Slinton {
27114393Slinton     Pidlist *p;
27214393Slinton     int pnum, status;
2739666Slinton 
27414393Slinton     p = pfind(pid);
27514393Slinton     if (p != nil(Pidlist *)) {
27614393Slinton 	*statusp = p->status;
27714393Slinton 	dispose(p);
27814394Slinton     } else {
27914394Slinton 	pnum = wait(&status);
28014394Slinton 	while (pnum != pid and pnum >= 0) {
28114394Slinton 	    if (not isptraced(pnum)) {
28214394Slinton 		p = alloc(1, Pidlist);
28314394Slinton 		p->pid = pnum;
28414394Slinton 		p->status = status;
28514394Slinton 		p->next = pidlist;
28614394Slinton 		pidlist = p;
28714394Slinton 	    }
28814394Slinton 	    pnum = wait(&status);
2899666Slinton 	}
29014394Slinton 	if (pnum < 0) {
29114394Slinton 	    p = pfind(pid);
29214394Slinton 	    if (p == nil(Pidlist *)) {
29314394Slinton 		panic("pwait: pid %d not found", pid);
29414394Slinton 	    }
29514394Slinton 	    *statusp = p->status;
29614394Slinton 	    dispose(p);
29714394Slinton 	} else {
29814394Slinton 	    *statusp = status;
29914394Slinton 	}
30014393Slinton     }
3019666Slinton }
3029666Slinton 
3039666Slinton /*
3049666Slinton  * Look for the given process id on the pidlist.
3059666Slinton  *
3069666Slinton  * Unlink it from list if found.
3079666Slinton  */
3089666Slinton 
pfind(pid)3099666Slinton private Pidlist *pfind(pid)
3109666Slinton int pid;
3119666Slinton {
3129666Slinton     register Pidlist *p, *prev;
3139666Slinton 
3149666Slinton     prev = nil(Pidlist *);
3159666Slinton     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
3169666Slinton 	if (p->pid == pid) {
3179666Slinton 	    break;
3189666Slinton 	}
3199666Slinton 	prev = p;
3209666Slinton     }
3219666Slinton     if (p != nil(Pidlist *)) {
3229666Slinton 	if (prev == nil(Pidlist *)) {
3239666Slinton 	    pidlist = p->next;
3249666Slinton 	} else {
3259666Slinton 	    prev->next = p->next;
3269666Slinton 	}
3279666Slinton     }
3289666Slinton     return p;
3299666Slinton }
3309666Slinton 
3319666Slinton /*
3329666Slinton  * System call error handler.
3339666Slinton  *
3349666Slinton  * The syserr routine is called when a system call is about to
3359666Slinton  * set the c-bit to report an error.  Certain errors are caught
3369666Slinton  * and cause the process to print a message and immediately exit.
3379666Slinton  */
3389666Slinton 
3399666Slinton extern int sys_nerr;
3409666Slinton extern char *sys_errlist[];
3419666Slinton 
3429666Slinton /*
3439666Slinton  * Before calling syserr, the integer errno is set to contain the
3449666Slinton  * number of the error.  The routine "_mycerror" is a dummy which
3459666Slinton  * is used to force the loader to get my version of cerror rather
3469666Slinton  * than the usual one.
3479666Slinton  */
3489666Slinton 
3499666Slinton extern int errno;
3509666Slinton extern _mycerror();
3519666Slinton 
3529666Slinton /*
35316611Ssam  * Initialize error information, setting defaults for handling errors.
3549666Slinton  */
3559666Slinton 
35633321Sdonn private ErrInfo *errinfo;
3579666Slinton 
initErrInfo()35816611Ssam private initErrInfo ()
35916611Ssam {
36016611Ssam     integer i;
36116611Ssam 
36233321Sdonn     errinfo = alloc(sys_nerr, ErrInfo);
36316611Ssam     for (i = 0; i < sys_nerr; i++) {
36416611Ssam 	errinfo[i].func = ERR_CATCH;
36516611Ssam     }
36616611Ssam     errinfo[0].func = ERR_IGNORE;
36716611Ssam     errinfo[EPERM].func = ERR_IGNORE;
36816611Ssam     errinfo[ENOENT].func = ERR_IGNORE;
36916611Ssam     errinfo[ESRCH].func = ERR_IGNORE;
37016611Ssam     errinfo[EBADF].func = ERR_IGNORE;
37116611Ssam     errinfo[ENOTTY].func = ERR_IGNORE;
37216611Ssam     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
37316611Ssam }
37416611Ssam 
syserr()3759666Slinton public syserr()
3769666Slinton {
37733321Sdonn     register ErrInfo *e;
3789666Slinton 
37916611Ssam     if (errno < 0 or errno > sys_nerr) {
38016611Ssam 	fatal("errno %d", errno);
38116611Ssam     } else {
38233321Sdonn 	if (errinfo == nil(ErrInfo *)) {
38316611Ssam 	    initErrInfo();
38416611Ssam 	}
38516611Ssam 	e = &(errinfo[errno]);
38616611Ssam 	if (e->func == ERR_CATCH) {
3879666Slinton 	    fatal(sys_errlist[errno]);
38816611Ssam 	} else if (e->func != ERR_IGNORE) {
38916611Ssam 	    (*e->func)();
3909666Slinton 	}
3919666Slinton     }
3929666Slinton }
3939666Slinton 
3949666Slinton /*
39516611Ssam  * Catcherrs' purpose is to initialize the errinfo table, get this module
39616611Ssam  * loaded, and make sure my cerror is loaded (only applicable when this is
39716611Ssam  * in a library).
3989666Slinton  */
3999666Slinton 
catcherrs()4009666Slinton public catcherrs()
4019666Slinton {
4029666Slinton     _mycerror();
40316611Ssam     initErrInfo();
4049666Slinton }
4059666Slinton 
4069666Slinton /*
40718221Slinton  * Turn off the error catching mechanism completely by having all errors
40818221Slinton  * ignored.  This is most useful between a fork and an exec.
40918221Slinton  */
41018221Slinton 
nocatcherrs()41118221Slinton public nocatcherrs()
41218221Slinton {
41318221Slinton     integer i;
41418221Slinton 
41518221Slinton     for (i = 0; i < sys_nerr; i++) {
41618221Slinton 	errinfo[i].func = ERR_IGNORE;
41718221Slinton     }
41818221Slinton }
41918221Slinton 
42018221Slinton /*
42133321Sdonn  * Change the action on receipt of an error, returning the previous action.
4229666Slinton  */
4239666Slinton 
onsyserr(n,f)42433321Sdonn public IntFunc *onsyserr(n, f)
4259666Slinton int n;
42633321Sdonn IntFunc *f;
4279666Slinton {
42833321Sdonn     IntFunc *oldf;
42933321Sdonn 
43033321Sdonn     if (errinfo == nil(ErrInfo *)) {
43116611Ssam 	initErrInfo();
43216611Ssam     }
43333321Sdonn     oldf = errinfo[n].func;
4349666Slinton     errinfo[n].func = f;
43533321Sdonn     return oldf;
4369666Slinton }
4379666Slinton 
4389666Slinton /*
4399666Slinton  * Print the message associated with the given signal.
4409666Slinton  * Like a "perror" for signals.
4419666Slinton  */
4429666Slinton 
44333321Sdonn #ifdef SIGWINCH
4449666Slinton public int sys_nsig = NSIG;
44533321Sdonn #else not 4.3 BSD
44633321Sdonn /*
44733321Sdonn  * This table is correct for 4.2-like systems but will
44833321Sdonn  * be inadequate for System V (which is the sort of
44933321Sdonn  * Unix that needs it!).
45033321Sdonn  */
45133321Sdonn public String sys_siglist[] = {
45233321Sdonn     "no signal",
45333321Sdonn     "hangup",
45433321Sdonn     "interrupt",
45533321Sdonn     "quit",
45633321Sdonn     "illegal instruction",
45733321Sdonn     "trace trap",
45833321Sdonn     "IOT instruction",
45933321Sdonn     "EMT instruction",
46033321Sdonn     "floating point exception",
46133321Sdonn     "kill",
46233321Sdonn     "bus error",
46333321Sdonn     "segmentation violation",
46433321Sdonn     "bad argument to system call",
46533321Sdonn     "broken pipe",
46633321Sdonn     "alarm clock",
46733321Sdonn     "soft kill",
46833321Sdonn     "urgent I/O condition",
46933321Sdonn     "stop signal not from tty",
47033321Sdonn     "stop signal from tty",
47133321Sdonn     "continue",
47233321Sdonn     "child termination",
47333321Sdonn     "stop (tty input)",
47433321Sdonn     "stop (tty output)",
47533321Sdonn     "possible input/output",
47633321Sdonn     "exceeded CPU time limit",
47733321Sdonn     "exceeded file size limit"
47833321Sdonn };
47933321Sdonn public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
4809666Slinton 
psignal(s,n)48116611Ssam public psignal(s, n)
4829666Slinton String s;
48316611Ssam integer n;
4849666Slinton {
48516611Ssam     String msg;
48616611Ssam     integer len;
48718538Sralph     extern String sys_siglist[];
4889666Slinton 
48916611Ssam     if (n >= 0 and n < sys_nsig) {
49016611Ssam 	msg = sys_siglist[n];
49116611Ssam     } else {
49216611Ssam 	msg = "Unknown signal";
4939666Slinton     }
49416611Ssam     len = strlen(s);
49516611Ssam     if (len > 0) {
49616611Ssam 	write(2, s, len);
4979666Slinton 	write(2, ": ", 2);
4989666Slinton     }
49916611Ssam     write(2, msg, strlen(msg));
5009666Slinton     write(2, "\n", 1);
5019666Slinton }
502*46995Sbostic #endif
5039666Slinton 
5049666Slinton /*
5059666Slinton  * Standard error handling routines.
5069666Slinton  */
5079666Slinton 
5089666Slinton private short nerrs;
5099666Slinton private short nwarnings;
5109666Slinton 
5119666Slinton /*
5129666Slinton  * Main driver of error message reporting.
5139666Slinton  */
5149666Slinton 
5159666Slinton /* VARARGS2 */
errmsg(errname,shouldquit,s,a,b,c,d,e,f,g,h,i,j,k,l,m)5169666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5179666Slinton String errname;
51816611Ssam boolean shouldquit;
5199666Slinton String s;
5209666Slinton {
5219666Slinton     fflush(stdout);
5229666Slinton     if (shouldquit and cmdname != nil(String)) {
5239666Slinton 	fprintf(stderr, "%s: ", cmdname);
5249666Slinton     }
5259666Slinton     if (errfilename != nil(Filename)) {
5269666Slinton 	fprintf(stderr, "%s: ", errfilename);
5279666Slinton     }
5289666Slinton     if (errlineno > 0) {
5299666Slinton 	fprintf(stderr, "%d: ", errlineno);
5309666Slinton     }
5319666Slinton     if (errname != nil(String)) {
5329666Slinton 	fprintf(stderr, "%s: ", errname);
5339666Slinton     }
5349666Slinton     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5359666Slinton     putc('\n', stderr);
53633321Sdonn     fflush(stderr);
5379666Slinton     if (shouldquit) {
5389666Slinton 	quit(1);
5399666Slinton     }
5409666Slinton }
5419666Slinton 
5429666Slinton /*
5439666Slinton  * For when printf isn't sufficient for printing the error message ...
5449666Slinton  */
5459666Slinton 
beginerrmsg()5469666Slinton public beginerrmsg()
5479666Slinton {
5489666Slinton     fflush(stdout);
5499666Slinton     if (errfilename != nil(String)) {
5509666Slinton 	fprintf(stderr, "%s: ", errfilename);
5519666Slinton     }
5529666Slinton     if (errlineno > 0) {
5539666Slinton 	fprintf(stderr, "%d: ", errlineno);
5549666Slinton     }
5559666Slinton }
5569666Slinton 
enderrmsg()5579666Slinton public enderrmsg()
5589666Slinton {
5599666Slinton     putc('\n', stderr);
56033321Sdonn     fflush(stderr);
5619666Slinton     erecover();
5629666Slinton }
5639666Slinton 
5649666Slinton /*
5659666Slinton  * The messages are listed in increasing order of seriousness.
5669666Slinton  *
5679666Slinton  * First are warnings.
5689666Slinton  */
5699666Slinton 
5709666Slinton /* VARARGS1 */
warning(s,a,b,c,d,e,f,g,h,i,j,k,l,m)5719666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5729666Slinton String s;
5739666Slinton {
5749666Slinton     nwarnings++;
5759666Slinton     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5769666Slinton }
5779666Slinton 
5789666Slinton /*
5799666Slinton  * Errors are a little worse, they mean something is wrong,
5809666Slinton  * but not so bad that processing can't continue.
5819666Slinton  *
5829666Slinton  * The routine "erecover" is called to recover from the error,
5839666Slinton  * a default routine is provided that does nothing.
5849666Slinton  */
5859666Slinton 
5869666Slinton /* VARARGS1 */
error(s,a,b,c,d,e,f,g,h,i,j,k,l,m)5879666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5889666Slinton String s;
5899666Slinton {
5909666Slinton     extern erecover();
5919666Slinton 
5929666Slinton     nerrs++;
5939666Slinton     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5949666Slinton     erecover();
5959666Slinton }
5969666Slinton 
5979666Slinton /*
5989666Slinton  * Non-recoverable user error.
5999666Slinton  */
6009666Slinton 
6019666Slinton /* VARARGS1 */
fatal(s,a,b,c,d,e,f,g,h,i,j,k,l,m)6029666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6039666Slinton String s;
6049666Slinton {
6059666Slinton     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6069666Slinton }
6079666Slinton 
6089666Slinton /*
6099666Slinton  * Panics indicate an internal program error.
6109666Slinton  */
6119666Slinton 
6129666Slinton /* VARARGS1 */
panic(s,a,b,c,d,e,f,g,h,i,j,k,l,m)6139666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6149666Slinton String s;
6159666Slinton {
6169666Slinton     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6179666Slinton }
6189666Slinton 
numerrors()6199666Slinton short numerrors()
6209666Slinton {
6219666Slinton     short r;
6229666Slinton 
6239666Slinton     r = nerrs;
6249666Slinton     nerrs = 0;
6259666Slinton     return r;
6269666Slinton }
6279666Slinton 
numwarnings()6289666Slinton short numwarnings()
6299666Slinton {
6309666Slinton     short r;
6319666Slinton 
6329666Slinton     r = nwarnings;
6339666Slinton     nwarnings = 0;
6349666Slinton     return r;
6359666Slinton }
6369666Slinton 
6379666Slinton /*
6389666Slinton  * Recover from an error.
6399666Slinton  *
6409666Slinton  * This is the default routine which we aren't using since we have our own.
6419666Slinton  *
6429666Slinton public erecover()
6439666Slinton {
6449666Slinton }
6459666Slinton  *
6469666Slinton  */
6479666Slinton 
6489666Slinton /*
6499666Slinton  * Default way to quit from a program is just to exit.
6509666Slinton  *
6519666Slinton public quit(r)
6529666Slinton int r;
6539666Slinton {
6549666Slinton     exit(r);
6559666Slinton }
6569666Slinton  *
6579666Slinton  */
6589666Slinton 
6599666Slinton /*
6609666Slinton  * Compare n-byte areas pointed to by s1 and s2
6619666Slinton  * if n is 0 then compare up until one has a null byte.
6629666Slinton  */
6639666Slinton 
cmp(s1,s2,n)6649666Slinton public int cmp(s1, s2, n)
6659666Slinton register char *s1, *s2;
6669666Slinton register unsigned int n;
6679666Slinton {
6689666Slinton     if (s1 == nil(char *) || s2 == nil(char *)) {
6699666Slinton 	panic("cmp: nil pointer");
6709666Slinton     }
6719666Slinton     if (n == 0) {
6729666Slinton 	while (*s1 == *s2++) {
6739666Slinton 	    if (*s1++ == '\0') {
6749666Slinton 		return(0);
6759666Slinton 	    }
6769666Slinton 	}
6779666Slinton 	return(*s1 - *(s2-1));
6789666Slinton     } else {
6799666Slinton 	for (; n != 0; n--) {
6809666Slinton 	    if (*s1++ != *s2++) {
6819666Slinton 		return(*(s1-1) - *(s2-1));
6829666Slinton 	    }
6839666Slinton 	}
6849666Slinton 	return(0);
6859666Slinton     }
6869666Slinton }
6879666Slinton 
6889666Slinton /*
6899666Slinton  * Move n bytes from src to dest.
6909666Slinton  * If n is 0 move until a null is found.
6919666Slinton  */
6929666Slinton 
mov(src,dest,n)6939666Slinton public mov(src, dest, n)
6949666Slinton register char *src, *dest;
6959666Slinton register unsigned int n;
6969666Slinton {
6979666Slinton     if (src == nil(char *))
6989666Slinton 	panic("mov: nil source");
6999666Slinton     if (dest == nil(char *))
7009666Slinton 	panic("mov: nil destination");
7019666Slinton     if (n != 0) {
7029666Slinton 	for (; n != 0; n--) {
7039666Slinton 	    *dest++ = *src++;
7049666Slinton 	}
7059666Slinton     } else {
7069666Slinton 	while ((*dest++ = *src++) != '\0');
7079666Slinton     }
7089666Slinton }
70933321Sdonn 
71033321Sdonn #ifdef IRIS /* or in general for 4.2 - System V C library interface */
71133321Sdonn 
bcopy(fromaddr,toaddr,n)71233321Sdonn public bcopy (fromaddr, toaddr, n)
71333321Sdonn char *fromaddr, *toaddr;
71433321Sdonn int n;
71533321Sdonn {
71633321Sdonn     blt(toaddr, fromaddr, n);
71733321Sdonn }
71833321Sdonn 
bzero(addr,n)71933321Sdonn public bzero (addr, n)
72033321Sdonn char *addr;
72133321Sdonn int n;
72233321Sdonn {
72333321Sdonn     register char *p, *q;
72433321Sdonn 
72533321Sdonn     p = addr;
72633321Sdonn     q = p + n;
72733321Sdonn     while (p < q) {
72833321Sdonn 	*p++ = '\0';
72933321Sdonn     }
73033321Sdonn }
73133321Sdonn 
73233321Sdonn #include <string.h>
73333321Sdonn 
index(s,c)73433321Sdonn public char *index (s, c)
73533321Sdonn char *s, c;
73633321Sdonn {
73733321Sdonn     return strchr(s, c);
73833321Sdonn }
73933321Sdonn 
rindex(s,c)74033321Sdonn public char *rindex (s, c)
74133321Sdonn char *s, c;
74233321Sdonn {
74333321Sdonn     return strrchr(s, c);
74433321Sdonn }
74533321Sdonn 
74633321Sdonn #endif
747