Annotation of 43BSDTahoe/lib/old_compiler/dbx/library.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)library.c  5.2 (Berkeley) 1/12/88";
                      9: #endif not lint
                     10: 
                     11: static char rcsid[] = "$Header: library.c,v 1.2 87/03/25 20:50:14 donn Exp $";
                     12: 
                     13: /*
                     14:  * General purpose routines.
                     15:  */
                     16: 
                     17: #include <stdio.h>
                     18: #include <errno.h>
                     19: #include <signal.h>
                     20: 
                     21: #define public
                     22: #define private static
                     23: #define and &&
                     24: #define or ||
                     25: #define not !
                     26: #define ord(enumcon)   ((int) enumcon)
                     27: #define nil(type)      ((type) 0)
                     28: 
                     29: typedef int integer;
                     30: typedef enum { FALSE, TRUE } boolean;
                     31: typedef char *String;
                     32: typedef FILE *File;
                     33: typedef String Filename;
                     34: 
                     35: #undef FILE
                     36: 
                     37: String cmdname;                        /* name of command for error messages */
                     38: Filename errfilename;          /* current file associated with error */
                     39: short errlineno;               /* line number associated with error */
                     40: 
                     41: /*
                     42:  * Definitions for doing memory allocation.
                     43:  */
                     44: 
                     45: extern char *malloc();
                     46: 
                     47: #define alloc(n, type) ((type *) malloc((unsigned) (n) * sizeof(type)))
                     48: #define dispose(p)     { free((char *) p); p = 0; }
                     49: 
                     50: /*
                     51:  * Macros for doing freads + fwrites.
                     52:  */
                     53: 
                     54: #define get(fp, var)   fread((char *) &(var), sizeof(var), 1, fp)
                     55: #define put(fp, var)   fwrite((char *) &(var), sizeof(var), 1, fp)
                     56: 
                     57: /*
                     58:  * String definitions.
                     59:  */
                     60: 
                     61: extern String strcpy(), index(), rindex();
                     62: extern int strlen();
                     63: 
                     64: #define strdup(s)              strcpy(malloc((unsigned) strlen(s) + 1), s)
                     65: #define streq(s1, s2)  (strcmp(s1, s2) == 0)
                     66: 
                     67: typedef int IntFunc();
                     68: 
                     69: IntFunc *onsyserr();
                     70: 
                     71: typedef struct {
                     72:     IntFunc *func;
                     73: } ErrInfo;
                     74: 
                     75: #define ERR_IGNORE ((IntFunc *) 0)
                     76: #define ERR_CATCH  ((IntFunc *) 1)
                     77: 
                     78: /*
                     79:  * Call a program.
                     80:  *
                     81:  * Four entries:
                     82:  *
                     83:  *     call, callv - call a program and wait for it, returning status
                     84:  *     back, backv - call a program and don't wait, returning process id
                     85:  *
                     86:  * The command's standard input and output are passed as FILE's.
                     87:  */
                     88: 
                     89: 
                     90: #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
                     91: #define BADEXEC 127    /* exec fails */
                     92: 
                     93: #define ischild(pid)    ((pid) == 0)
                     94: 
                     95: /* VARARGS3 */
                     96: public int call(name, in, out, args)
                     97: String name;
                     98: File in;
                     99: File out;
                    100: String args;
                    101: {
                    102:     String *ap, *argp;
                    103:     String argv[MAXNARGS];
                    104: 
                    105:     argp = &argv[0];
                    106:     *argp++ = name;
                    107:     ap = &args;
                    108:     while (*ap != nil(String)) {
                    109:        *argp++ = *ap++;
                    110:     }
                    111:     *argp = nil(String);
                    112:     return callv(name, in, out, argv);
                    113: }
                    114: 
                    115: /* VARARGS3 */
                    116: public int back(name, in, out, args)
                    117: String name;
                    118: File in;
                    119: File out;
                    120: String args;
                    121: {
                    122:     String *ap, *argp;
                    123:     String argv[MAXNARGS];
                    124: 
                    125:     argp = &argv[0];
                    126:     *argp++ = name;
                    127:     ap = &args;
                    128:     while (*ap != nil(String)) {
                    129:        *argp++ = *ap++;
                    130:     }
                    131:     *argp = nil(String);
                    132:     return backv(name, in, out, argv);
                    133: }
                    134: 
                    135: public int callv(name, in, out, argv)
                    136: String name;
                    137: File in;
                    138: File out;
                    139: String *argv;
                    140: {
                    141:     int pid, status;
                    142: 
                    143:     pid = backv(name, in, out, argv);
                    144:     pwait(pid, &status);
                    145:     return status;
                    146: }
                    147: 
                    148: public int backv(name, in, out, argv)
                    149: String name;
                    150: File in;
                    151: File out;
                    152: String *argv;
                    153: {
                    154:     int pid;
                    155: 
                    156:     fflush(stdout);
                    157:     if (ischild(pid = fork())) {
                    158:        fswap(0, fileno(in));
                    159:        fswap(1, fileno(out));
                    160:        onsyserr(EACCES, ERR_IGNORE);
                    161:        execvp(name, argv);
                    162:        _exit(BADEXEC);
                    163:     }
                    164:     return pid;
                    165: }
                    166: 
                    167: /*
                    168:  * Swap file numbers so as to redirect standard input and output.
                    169:  */
                    170: 
                    171: private fswap(oldfd, newfd)
                    172: int oldfd;
                    173: int newfd;
                    174: {
                    175:     if (oldfd != newfd) {
                    176:        close(oldfd);
                    177:        dup(newfd);
                    178:        close(newfd);
                    179:     }
                    180: }
                    181: 
                    182: /*
                    183:  * Invoke a shell on a command line.
                    184:  */
                    185: 
                    186: #define DEF_SHELL      "csh"
                    187: 
                    188: public shell(s)
                    189: String s;
                    190: {
                    191:     extern String getenv();
                    192:     String sh;
                    193: 
                    194:     if ((sh = getenv("SHELL")) == nil(String)) {
                    195:        sh = DEF_SHELL;
                    196:     }
                    197:     if (s != nil(String) and *s != '\0') {
                    198:        call(sh, stdin, stdout, "-c", s, 0);
                    199:     } else {
                    200:        call(sh, stdin, stdout, 0);
                    201:     }
                    202: }
                    203: 
                    204: /*
                    205:  * Wait for a process the right way.  We wait for a particular
                    206:  * process and if any others come along in between, we remember them
                    207:  * in case they are eventually waited for.
                    208:  *
                    209:  * This routine is not very efficient when the number of processes
                    210:  * to be remembered is large.
                    211:  *
                    212:  * To deal with a kernel idiosyncrasy, we keep a list on the side
                    213:  * of "traced" processes, and do not notice them when waiting for
                    214:  * another process.
                    215:  */
                    216: 
                    217: typedef struct pidlist {
                    218:     int pid;
                    219:     int status;
                    220:     struct pidlist *next;
                    221: } Pidlist;
                    222: 
                    223: private Pidlist *pidlist, *ptrclist, *pfind();
                    224: 
                    225: public ptraced(pid)
                    226: int pid;
                    227: {
                    228:     Pidlist *p;
                    229: 
                    230:     p = alloc(1, Pidlist);
                    231:     p->pid = pid;
                    232:     p->next = ptrclist;
                    233:     ptrclist = p;
                    234: }
                    235: 
                    236: public unptraced(pid)
                    237: int pid;
                    238: {
                    239:     register Pidlist *p, *prev;
                    240: 
                    241:     prev = nil(Pidlist *);
                    242:     p = ptrclist;
                    243:     while (p != nil(Pidlist *) and p->pid != pid) {
                    244:        prev = p;
                    245:        p = p->next;
                    246:     }
                    247:     if (p != nil(Pidlist *)) {
                    248:        if (prev == nil(Pidlist *)) {
                    249:            ptrclist = p->next;
                    250:        } else {
                    251:            prev->next = p->next;
                    252:        }
                    253:        dispose(p);
                    254:     }
                    255: }
                    256: 
                    257: private boolean isptraced(pid)
                    258: int pid;
                    259: {
                    260:     register Pidlist *p;
                    261: 
                    262:     p = ptrclist;
                    263:     while (p != nil(Pidlist *) and p->pid != pid) {
                    264:        p = p->next;
                    265:     }
                    266:     return (boolean) (p != nil(Pidlist *));
                    267: }
                    268: 
                    269: public pwait(pid, statusp)
                    270: int pid, *statusp;
                    271: {
                    272:     Pidlist *p;
                    273:     int pnum, status;
                    274: 
                    275:     p = pfind(pid);
                    276:     if (p != nil(Pidlist *)) {
                    277:        *statusp = p->status;
                    278:        dispose(p);
                    279:     } else {
                    280:        pnum = wait(&status);
                    281:        while (pnum != pid and pnum >= 0) {
                    282:            if (not isptraced(pnum)) {
                    283:                p = alloc(1, Pidlist);
                    284:                p->pid = pnum;
                    285:                p->status = status;
                    286:                p->next = pidlist;
                    287:                pidlist = p;
                    288:            }
                    289:            pnum = wait(&status);
                    290:        }
                    291:        if (pnum < 0) {
                    292:            p = pfind(pid);
                    293:            if (p == nil(Pidlist *)) {
                    294:                panic("pwait: pid %d not found", pid);
                    295:            }
                    296:            *statusp = p->status;
                    297:            dispose(p);
                    298:        } else {
                    299:            *statusp = status;
                    300:        }
                    301:     }
                    302: }
                    303: 
                    304: /*
                    305:  * Look for the given process id on the pidlist.
                    306:  *
                    307:  * Unlink it from list if found.
                    308:  */
                    309: 
                    310: private Pidlist *pfind(pid)
                    311: int pid;
                    312: {
                    313:     register Pidlist *p, *prev;
                    314: 
                    315:     prev = nil(Pidlist *);
                    316:     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
                    317:        if (p->pid == pid) {
                    318:            break;
                    319:        }
                    320:        prev = p;
                    321:     }
                    322:     if (p != nil(Pidlist *)) {
                    323:        if (prev == nil(Pidlist *)) {
                    324:            pidlist = p->next;
                    325:        } else {
                    326:            prev->next = p->next;
                    327:        }
                    328:     }
                    329:     return p;
                    330: }
                    331: 
                    332: /*
                    333:  * System call error handler.
                    334:  *
                    335:  * The syserr routine is called when a system call is about to
                    336:  * set the c-bit to report an error.  Certain errors are caught
                    337:  * and cause the process to print a message and immediately exit.
                    338:  */
                    339: 
                    340: extern int sys_nerr;
                    341: extern char *sys_errlist[];
                    342:  
                    343: /*
                    344:  * Before calling syserr, the integer errno is set to contain the
                    345:  * number of the error.  The routine "_mycerror" is a dummy which
                    346:  * is used to force the loader to get my version of cerror rather
                    347:  * than the usual one.
                    348:  */
                    349: 
                    350: extern int errno;
                    351: extern _mycerror();
                    352: 
                    353: /*
                    354:  * Initialize error information, setting defaults for handling errors.
                    355:  */
                    356: 
                    357: private ErrInfo *errinfo;
                    358: 
                    359: private initErrInfo ()
                    360: {
                    361:     integer i;
                    362: 
                    363:     errinfo = alloc(sys_nerr, ErrInfo);
                    364:     for (i = 0; i < sys_nerr; i++) {
                    365:        errinfo[i].func = ERR_CATCH;
                    366:     }
                    367:     errinfo[0].func = ERR_IGNORE;
                    368:     errinfo[EPERM].func = ERR_IGNORE;
                    369:     errinfo[ENOENT].func = ERR_IGNORE;
                    370:     errinfo[ESRCH].func = ERR_IGNORE;
                    371:     errinfo[EBADF].func = ERR_IGNORE;
                    372:     errinfo[ENOTTY].func = ERR_IGNORE;
                    373:     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
                    374: }
                    375: 
                    376: public syserr()
                    377: {
                    378:     register ErrInfo *e;
                    379: 
                    380:     if (errno < 0 or errno > sys_nerr) {
                    381:        fatal("errno %d", errno);
                    382:     } else {
                    383:        if (errinfo == nil(ErrInfo *)) {
                    384:            initErrInfo();
                    385:        }
                    386:        e = &(errinfo[errno]);
                    387:        if (e->func == ERR_CATCH) {
                    388:            fatal(sys_errlist[errno]);
                    389:        } else if (e->func != ERR_IGNORE) {
                    390:            (*e->func)();
                    391:        }
                    392:     }
                    393: }
                    394: 
                    395: /*
                    396:  * Catcherrs' purpose is to initialize the errinfo table, get this module
                    397:  * loaded, and make sure my cerror is loaded (only applicable when this is
                    398:  * in a library).
                    399:  */
                    400: 
                    401: public catcherrs()
                    402: {
                    403:     _mycerror();
                    404:     initErrInfo();
                    405: }
                    406: 
                    407: /*
                    408:  * Turn off the error catching mechanism completely by having all errors
                    409:  * ignored.  This is most useful between a fork and an exec.
                    410:  */
                    411: 
                    412: public nocatcherrs()
                    413: {
                    414:     integer i;
                    415: 
                    416:     for (i = 0; i < sys_nerr; i++) {
                    417:        errinfo[i].func = ERR_IGNORE;
                    418:     }
                    419: }
                    420: 
                    421: /*
                    422:  * Change the action on receipt of an error, returning the previous action.
                    423:  */
                    424: 
                    425: public IntFunc *onsyserr(n, f)
                    426: int n;
                    427: IntFunc *f;
                    428: {
                    429:     IntFunc *oldf;
                    430: 
                    431:     if (errinfo == nil(ErrInfo *)) {
                    432:        initErrInfo();
                    433:     }
                    434:     oldf = errinfo[n].func;
                    435:     errinfo[n].func = f;
                    436:     return oldf;
                    437: }
                    438: 
                    439: /*
                    440:  * Print the message associated with the given signal.
                    441:  * Like a "perror" for signals.
                    442:  */
                    443: 
                    444: #ifdef SIGWINCH
                    445: public int sys_nsig = NSIG;
                    446: #else not 4.3 BSD
                    447: /*
                    448:  * This table is correct for 4.2-like systems but will
                    449:  * be inadequate for System V (which is the sort of
                    450:  * Unix that needs it!).
                    451:  */
                    452: public String sys_siglist[] = {
                    453:     "no signal",
                    454:     "hangup",
                    455:     "interrupt",
                    456:     "quit",
                    457:     "illegal instruction",
                    458:     "trace trap",
                    459:     "IOT instruction",
                    460:     "EMT instruction",
                    461:     "floating point exception",
                    462:     "kill",
                    463:     "bus error",
                    464:     "segmentation violation",
                    465:     "bad argument to system call",
                    466:     "broken pipe",
                    467:     "alarm clock",
                    468:     "soft kill",
                    469:     "urgent I/O condition",
                    470:     "stop signal not from tty",
                    471:     "stop signal from tty",
                    472:     "continue",
                    473:     "child termination",
                    474:     "stop (tty input)",
                    475:     "stop (tty output)",
                    476:     "possible input/output",
                    477:     "exceeded CPU time limit",
                    478:     "exceeded file size limit"
                    479: };
                    480: public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
                    481: #endif
                    482: 
                    483: public psignal(s, n)
                    484: String s;
                    485: integer n;
                    486: {
                    487:     String msg;
                    488:     integer len;
                    489:     extern String sys_siglist[];
                    490: 
                    491:     if (n >= 0 and n < sys_nsig) {
                    492:        msg = sys_siglist[n];
                    493:     } else {
                    494:        msg = "Unknown signal";
                    495:     }
                    496:     len = strlen(s);
                    497:     if (len > 0) {
                    498:        write(2, s, len);
                    499:        write(2, ": ", 2);
                    500:     }
                    501:     write(2, msg, strlen(msg));
                    502:     write(2, "\n", 1);
                    503: }
                    504: 
                    505: /*
                    506:  * Standard error handling routines.
                    507:  */
                    508: 
                    509: private short nerrs;
                    510: private short nwarnings;
                    511: 
                    512: /*
                    513:  * Main driver of error message reporting.
                    514:  */
                    515: 
                    516: /* VARARGS2 */
                    517: private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    518: String errname;
                    519: boolean shouldquit;
                    520: String s;
                    521: {
                    522:     fflush(stdout);
                    523:     if (shouldquit and cmdname != nil(String)) {
                    524:        fprintf(stderr, "%s: ", cmdname);
                    525:     }
                    526:     if (errfilename != nil(Filename)) {
                    527:        fprintf(stderr, "%s: ", errfilename);
                    528:     }
                    529:     if (errlineno > 0) {
                    530:        fprintf(stderr, "%d: ", errlineno);
                    531:     }
                    532:     if (errname != nil(String)) {
                    533:        fprintf(stderr, "%s: ", errname);
                    534:     }
                    535:     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    536:     putc('\n', stderr);
                    537:     fflush(stderr);
                    538:     if (shouldquit) {
                    539:        quit(1);
                    540:     }
                    541: }
                    542: 
                    543: /*
                    544:  * For when printf isn't sufficient for printing the error message ...
                    545:  */
                    546: 
                    547: public beginerrmsg()
                    548: {
                    549:     fflush(stdout);
                    550:     if (errfilename != nil(String)) {
                    551:        fprintf(stderr, "%s: ", errfilename);
                    552:     }
                    553:     if (errlineno > 0) {
                    554:        fprintf(stderr, "%d: ", errlineno);
                    555:     }
                    556: }
                    557: 
                    558: public enderrmsg()
                    559: {
                    560:     putc('\n', stderr);
                    561:     fflush(stderr);
                    562:     erecover();
                    563: }
                    564: 
                    565: /*
                    566:  * The messages are listed in increasing order of seriousness.
                    567:  *
                    568:  * First are warnings.
                    569:  */
                    570: 
                    571: /* VARARGS1 */
                    572: public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    573: String s;
                    574: {
                    575:     nwarnings++;
                    576:     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    577: }
                    578: 
                    579: /*
                    580:  * Errors are a little worse, they mean something is wrong,
                    581:  * but not so bad that processing can't continue.
                    582:  *
                    583:  * The routine "erecover" is called to recover from the error,
                    584:  * a default routine is provided that does nothing.
                    585:  */
                    586: 
                    587: /* VARARGS1 */
                    588: public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    589: String s;
                    590: {
                    591:     extern erecover();
                    592: 
                    593:     nerrs++;
                    594:     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    595:     erecover();
                    596: }
                    597: 
                    598: /*
                    599:  * Non-recoverable user error.
                    600:  */
                    601: 
                    602: /* VARARGS1 */
                    603: public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    604: String s;
                    605: {
                    606:     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    607: }
                    608: 
                    609: /*
                    610:  * Panics indicate an internal program error.
                    611:  */
                    612: 
                    613: /* VARARGS1 */
                    614: public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    615: String s;
                    616: {
                    617:     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    618: }
                    619: 
                    620: short numerrors()
                    621: {
                    622:     short r;
                    623: 
                    624:     r = nerrs;
                    625:     nerrs = 0;
                    626:     return r;
                    627: }
                    628: 
                    629: short numwarnings()
                    630: {
                    631:     short r;
                    632: 
                    633:     r = nwarnings;
                    634:     nwarnings = 0;
                    635:     return r;
                    636: }
                    637: 
                    638: /*
                    639:  * Recover from an error.
                    640:  *
                    641:  * This is the default routine which we aren't using since we have our own.
                    642:  *
                    643: public erecover()
                    644: {
                    645: }
                    646:  *
                    647:  */
                    648: 
                    649: /*
                    650:  * Default way to quit from a program is just to exit.
                    651:  *
                    652: public quit(r)
                    653: int r;
                    654: {
                    655:     exit(r);
                    656: }
                    657:  *
                    658:  */
                    659: 
                    660: /*
                    661:  * Compare n-byte areas pointed to by s1 and s2
                    662:  * if n is 0 then compare up until one has a null byte.
                    663:  */
                    664: 
                    665: public int cmp(s1, s2, n)
                    666: register char *s1, *s2;
                    667: register unsigned int n;
                    668: {
                    669:     if (s1 == nil(char *) || s2 == nil(char *)) {
                    670:        panic("cmp: nil pointer");
                    671:     }
                    672:     if (n == 0) {
                    673:        while (*s1 == *s2++) {
                    674:            if (*s1++ == '\0') {
                    675:                return(0);
                    676:            }
                    677:        }
                    678:        return(*s1 - *(s2-1));
                    679:     } else {
                    680:        for (; n != 0; n--) {
                    681:            if (*s1++ != *s2++) {
                    682:                return(*(s1-1) - *(s2-1));
                    683:            }
                    684:        }
                    685:        return(0);
                    686:     }
                    687: }
                    688: 
                    689: /*
                    690:  * Move n bytes from src to dest.
                    691:  * If n is 0 move until a null is found.
                    692:  */
                    693: 
                    694: public mov(src, dest, n)
                    695: register char *src, *dest;
                    696: register unsigned int n;
                    697: {
                    698:     if (src == nil(char *))
                    699:        panic("mov: nil source");
                    700:     if (dest == nil(char *))
                    701:        panic("mov: nil destination");
                    702:     if (n != 0) {
                    703:        for (; n != 0; n--) {
                    704:            *dest++ = *src++;
                    705:        }
                    706:     } else {
                    707:        while ((*dest++ = *src++) != '\0');
                    708:     }
                    709: }
                    710: 
                    711: #ifdef IRIS /* or in general for 4.2 - System V C library interface */
                    712: 
                    713: public bcopy (fromaddr, toaddr, n)
                    714: char *fromaddr, *toaddr;
                    715: int n;
                    716: {
                    717:     blt(toaddr, fromaddr, n);
                    718: }
                    719: 
                    720: public bzero (addr, n)
                    721: char *addr;
                    722: int n;
                    723: {
                    724:     register char *p, *q;
                    725: 
                    726:     p = addr;
                    727:     q = p + n;
                    728:     while (p < q) {
                    729:        *p++ = '\0';
                    730:     }
                    731: }
                    732: 
                    733: #include <string.h>
                    734: 
                    735: public char *index (s, c)
                    736: char *s, c;
                    737: {
                    738:     return strchr(s, c);
                    739: }
                    740: 
                    741: public char *rindex (s, c)
                    742: char *s, c;
                    743: {
                    744:     return strrchr(s, c);
                    745: }
                    746: 
                    747: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.