Annotation of 43BSDReno/contrib/jove/extend.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: #include "jove.h"
                      9: #include "fp.h"
                     10: #include "termcap.h"
                     11: #include "ctype.h"
                     12: #include "chars.h"
                     13: #include "disp.h"
                     14: #include "re.h"
                     15: 
                     16: #if defined(JOB_CONTROL) || defined(IPROCS)
                     17: # include <signal.h>
                     18: #endif
                     19: 
                     20: #ifdef MAC
                     21: # include "mac.h"
                     22: #else
                     23: # ifdef        STDARGS
                     24: #  include <stdarg.h>
                     25: # else
                     26: #  include <varargs.h>
                     27: # endif
                     28: #endif
                     29: 
                     30: #ifdef MSDOS
                     31: # include <process.h>
                     32: #endif
                     33: 
                     34: private void
                     35:        DefAutoExec proto((struct data_obj *(*proc)()));
                     36: 
                     37: private int
                     38:        match proto((char **, char *));
                     39: 
                     40: int    InJoverc = 0;
                     41: 
                     42: /* Auto execute code */
                     43: 
                     44: #define NEXECS 20
                     45: 
                     46: private struct {
                     47:        char    *a_pattern;
                     48:        data_obj        *a_cmd;
                     49: } AutoExecs[NEXECS];   /* must be initialized by system to 0 */
                     50: 
                     51: private int    ExecIndex = 0;
                     52: 
                     53: /* Command auto-execute. */
                     54: 
                     55: void
                     56: CAutoExec()
                     57: {
                     58:        DefAutoExec(findcom);
                     59: }
                     60: 
                     61: /* Macro auto-execute. */
                     62: 
                     63: void
                     64: MAutoExec()
                     65: {
                     66:        DefAutoExec(findmac);
                     67: }
                     68: 
                     69: private void
                     70: DefAutoExec(proc)
                     71: #if defined(MAC) || defined(IBMPC)
                     72: data_obj       *(*proc)();
                     73: #else
                     74: data_obj       *(*proc) proto((char *));
                     75: #endif
                     76: {
                     77:        data_obj        *d;
                     78:        char    *pattern;
                     79:        int     i;
                     80: 
                     81:        if (ExecIndex >= NEXECS)
                     82:                complain("Too many auto-executes, max %d.", NEXECS);
                     83:        if ((d = (*proc)(ProcFmt)) == 0)
                     84:                return;
                     85:        pattern = do_ask("\r\n", (int (*) proto((int))) 0, (char *) 0, ": %f %s ",
                     86:                d->Name);
                     87:        for (i = 0; i < ExecIndex; i++) {
                     88:            if (AutoExecs[i].a_cmd == d) {
                     89:                char    *ipat = AutoExecs[i].a_pattern;
                     90: 
                     91:                if ((pattern == NULL || ipat == NULL)?
                     92:                    (pattern == ipat) : (strcmp(pattern, ipat) == 0))
                     93:                        return;         /* eliminate duplicates */
                     94:            }
                     95:        }
                     96:        AutoExecs[ExecIndex].a_pattern = copystr(pattern);
                     97:        AutoExecs[ExecIndex].a_cmd = d;
                     98:        ExecIndex += 1;
                     99: }
                    100: 
                    101: /* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
                    102:    same kind of file (i.e., match the same pattern) or OLD is 0 and it
                    103:    matches, OR if the pattern is 0 (none was specified) then, we execute
                    104:    the command associated with that kind of file. */
                    105: 
                    106: void
                    107: DoAutoExec(new, old)
                    108: register char  *new,
                    109:                *old;
                    110: {
                    111:        register int    i;
                    112: 
                    113:        set_arg_value(1);
                    114:        for (i = 0; i < ExecIndex; i++)
                    115:                if ((AutoExecs[i].a_pattern == 0) ||
                    116:                    ((new != 0 && LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
                    117:                     (old == 0 || !LookingAt(AutoExecs[i].a_pattern, old, 0))))
                    118:                        ExecCmd(AutoExecs[i].a_cmd);
                    119: }
                    120: 
                    121: int
                    122: addgetc()
                    123: {
                    124:        int     c;
                    125: 
                    126:        if (!InJoverc) {
                    127:                Asking = strlen(mesgbuf);
                    128:                c = getch();
                    129:                Asking = 0;
                    130:                add_mess("%p ", c);
                    131:        } else {
                    132:                c = getch();
                    133:                if (c == '\n')
                    134:                        return EOF;     /* this isn't part of the sequence */
                    135:                else if (c == '\\') {
                    136:                        if ((c = getch()) == LF)
                    137:                                complain("[Premature end of line]");
                    138:                } else if (c == '^') {
                    139:                        if ((c = getch()) == '?')
                    140:                                c = RUBOUT;
                    141:                        else if (isalpha(c) || strchr("@[\\]^_", c))
                    142:                                c = CTL(c);
                    143:                        else
                    144:                                complain("[Unknown control character]");
                    145:                }
                    146:        }
                    147:        return c;
                    148: }
                    149: 
                    150: void
                    151: Extend()
                    152: {
                    153:        data_obj        *d;
                    154: 
                    155:        if ((d = findcom(": ")) != NULL)
                    156:                ExecCmd(d);
                    157: }
                    158: 
                    159: /* Read a positive integer from CP.  It must be in base BASE, and
                    160:    complains if it isn't.  If allints is nonzero, all the characters
                    161:    in the string must be integers or we return -1; otherwise we stop
                    162:    reading at the first nondigit. */
                    163: 
                    164: int
                    165: chr_to_int(cp, base, allints, result)
                    166: register char  *cp;
                    167: int    base,
                    168:        allints;
                    169: register int   *result;
                    170: {
                    171:        register int    c;
                    172:        int     value = 0,
                    173:                sign;
                    174: 
                    175:        if ((c = *cp) == '-') {
                    176:                sign = -1;
                    177:                cp += 1;
                    178:        } else
                    179:                sign = 1;
                    180:        while ((c = *cp++) != '\0') {
                    181:                if (!isdigit(c)) {
                    182:                        if (allints == YES)
                    183:                                return INT_BAD;
                    184:                        break;
                    185:                }
                    186:                c = c - '0';
                    187:                if (c >= base)
                    188:                        complain("You must specify in base %d.", base);
                    189:                value = value * base + c;
                    190:        }
                    191:        *result = value * sign;
                    192:        return INT_OKAY;
                    193: }
                    194: 
                    195: int
                    196: ask_int(prompt, base)
                    197: char   *prompt;
                    198: int    base;
                    199: {
                    200:        char    *val = ask((char *) 0, prompt);
                    201:        int     value;
                    202: 
                    203:        if (chr_to_int(val, base, YES, &value) == INT_BAD)
                    204:                complain("That's not a number!");
                    205:        return value;
                    206: }
                    207: 
                    208: void
                    209: vpr_aux(vp, buf)
                    210: register const struct variable *vp;
                    211: char   *buf;
                    212: {
                    213:        switch (vp->v_flags & V_TYPEMASK) {
                    214:        case V_BASE10:
                    215:                swritef(buf, "%d", *((int *) vp->v_value));
                    216:                break;
                    217: 
                    218:        case V_BASE8:
                    219:                swritef(buf, "%o", *((int *) vp->v_value));
                    220:                break;
                    221: 
                    222:        case V_BOOL:
                    223:                swritef(buf, (*((int *) vp->v_value)) ? "on" : "off");
                    224:                break;
                    225: 
                    226:        case V_STRING:
                    227:        case V_FILENAME:
                    228:                swritef(buf, "%s", vp->v_value);
                    229:                break;
                    230: 
                    231:        case V_CHAR:
                    232:                swritef(buf, "%p", *((int *) vp->v_value));
                    233:                break;
                    234:        }
                    235: }
                    236: 
                    237: void
                    238: PrVar()
                    239: {
                    240:        struct variable *vp;
                    241:        char    prbuf[256];
                    242: 
                    243:        if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
                    244:                return;
                    245:        vpr_aux(vp, prbuf);
                    246:        s_mess(": %f %s => %s", vp->Name, prbuf);
                    247: }
                    248: 
                    249: void
                    250: SetVar()
                    251: {
                    252:        struct variable *vp;
                    253:        char    *prompt;
                    254: 
                    255:        if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
                    256:                return;
                    257:        prompt = sprint(": %f %s ", vp->Name);
                    258: 
                    259:        switch (vp->v_flags & V_TYPEMASK) {
                    260:        case V_BASE10:
                    261:        case V_BASE8:
                    262:            {
                    263:                int     value;
                    264: 
                    265:                value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10)
                    266:                                          ? 10 : 8);
                    267:                *((int *) vp->v_value) = value;
                    268:                break;
                    269:            }
                    270: 
                    271:        case V_BOOL:
                    272:            {
                    273:                char    *def = *((int *) vp->v_value) ? "off" : "on",
                    274:                        *on_off;
                    275:                int     value;
                    276: 
                    277:                on_off = ask(def, prompt);
                    278:                if (casecmp(on_off, "on") == 0)
                    279:                        value = ON;
                    280:                else if (casecmp(on_off, "off") == 0)
                    281:                        value = OFF;
                    282:                else
                    283:                        complain("Boolean variables must be ON or OFF.");
                    284:                *((int *) vp->v_value) = value;
                    285: #ifdef MAC
                    286:                MarkVar(vp,-1,0);       /* mark the menu item */
                    287: #endif
                    288:                s_mess("%s%s", prompt, value ? "on" : "off");
                    289:                break;
                    290:            }
                    291: 
                    292:        case V_FILENAME:
                    293:            {
                    294:                char    fbuf[FILESIZE];
                    295: 
                    296:                (void) ask_file(prompt, (char *) vp->v_value, fbuf);
                    297:                strcpy((char *) vp->v_value, fbuf);
                    298:                break;
                    299:            }
                    300: 
                    301:        case V_STRING:
                    302:            {
                    303:                char    *str;
                    304: 
                    305:                /* Do_ask() so you can set string to "" if you so desire. */
                    306:                str = do_ask("\r\n", (int (*) proto((int))) 0, (char *) vp->v_value,
                    307:                        prompt);
                    308:                if (str == 0)
                    309:                        str = NullStr;
                    310:                strcpy(vp->v_value, str);
                    311:                /* ... and hope there is enough room. */
                    312:                break;
                    313:            }
                    314:        case V_CHAR:
                    315:                f_mess(prompt);
                    316:                *((int *) vp->v_value) = addgetc();
                    317:                break;
                    318: 
                    319:        }
                    320:        if (vp->v_flags & V_MODELINE)
                    321:                UpdModLine = YES;
                    322:        if (vp->v_flags & V_CLRSCREEN) {
                    323: #ifdef IBMPC
                    324:                setcolor(Fgcolor, Bgcolor);
                    325: #endif /* IBMPC */
                    326:                ClAndRedraw();
                    327:        }
                    328:        if (vp->v_flags & V_TTY_RESET)
                    329:                tty_reset();
                    330: }
                    331: 
                    332: /* Command completion - possible is an array of strings, prompt is
                    333:    the prompt to use, and flags are ... well read jove.h.
                    334: 
                    335:    If flags are RET_STATE, and the user hits <return> what they typed
                    336:    so far is in the Minibuf string. */
                    337: 
                    338: private char   **Possible;
                    339: private int    comp_value,
                    340:                comp_flags;
                    341: 
                    342: int
                    343: aux_complete(c)
                    344: int    c;
                    345: {
                    346:        int     command,
                    347:                i;
                    348: 
                    349:        if (comp_flags & CASEIND) {
                    350:                char    *lp;
                    351: 
                    352:                for (lp = linebuf; *lp != '\0'; lp++)
                    353: #if (defined(IBMPC) || defined(MAC))
                    354:                        lower(lp);
                    355: #else
                    356:                        if (isupper(*lp))
                    357:                                *lp = tolower(*lp);
                    358: #endif
                    359:        }
                    360:        switch (c) {
                    361:        case EOF:
                    362:                comp_value = -1;
                    363:                return 0;
                    364: 
                    365:        case '\r':
                    366:        case '\n':
                    367:                command = match(Possible, linebuf);
                    368:                if (command >= 0) {
                    369:                        comp_value = command;
                    370:                        return 0;       /* tells ask to stop */
                    371:                }
                    372:                if (eolp() && bolp()) {
                    373:                        comp_value = NULLSTRING;
                    374:                        return 0;
                    375:                }
                    376:                if (comp_flags & RET_STATE) {
                    377:                        comp_value = command;
                    378:                        return 0;
                    379:                }
                    380:                if (InJoverc)
                    381:                        complain("[\"%s\" unknown]", linebuf);
                    382:                rbell();
                    383:                break;
                    384: 
                    385:        case '\t':
                    386:        case ' ':
                    387:            {
                    388:                int     minmatch = 1000,
                    389:                        maxmatch = 0,
                    390:                        numfound = 0,
                    391:                        lastmatch = -1,
                    392:                        len = strlen(linebuf);
                    393: 
                    394:                for (i = 0; Possible[i] != 0; i++) {
                    395:                        int     this_len;
                    396: 
                    397:                        this_len = numcomp(Possible[i], linebuf);
                    398:                        maxmatch = max(maxmatch, this_len);
                    399:                        if (this_len >= len) {
                    400:                                if (numfound)
                    401:                                        minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
                    402:                                else
                    403:                                        minmatch = strlen(Possible[i]);
                    404:                                numfound += 1;
                    405:                                lastmatch = i;
                    406:                                if (strcmp(linebuf, Possible[i]) == 0)
                    407:                                        break;
                    408:                        }
                    409:                }
                    410: 
                    411:                if (numfound == 0) {
                    412:                        rbell();
                    413:                        if (InJoverc)
                    414:                                complain("[\"%s\" unknown]", linebuf);
                    415:                        /* If we're not in the .joverc then
                    416:                           let's do something helpful for the
                    417:                           user. */
                    418:                        if (maxmatch < len) {
                    419:                                char    *cp;
                    420: 
                    421:                                cp = linebuf + maxmatch;
                    422:                                *cp = 0;
                    423:                                Eol();
                    424:                        }
                    425:                        break;
                    426:                }
                    427:                if (c != '\t' && numfound == 1) {
                    428:                        comp_value = lastmatch;
                    429:                        return 0;
                    430:                }
                    431:                null_ncpy(linebuf, Possible[lastmatch], (size_t) minmatch);
                    432:                Eol();
                    433:                if (minmatch == len)    /* No difference */
                    434:                        rbell();
                    435:                break;
                    436:            }
                    437: 
                    438:        case '?':
                    439:                {
                    440:                int     len;
                    441: 
                    442:                if (InJoverc)
                    443:                        complain((char *) 0);
                    444:                /* kludge: in case we're using UseBuffers, in which case
                    445:                   linebuf gets written all over */
                    446:                strcpy(Minibuf, linebuf);
                    447:                len = strlen(Minibuf);
                    448:                TOstart("Completion", TRUE);    /* for now ... */
                    449:                for (i = 0; Possible[i]; i++)
                    450:                        if (numcomp(Possible[i], Minibuf) >= len) {
                    451:                                Typeout(Possible[i]);
                    452:                                if (TOabort != 0)
                    453:                                        break;
                    454:                        }
                    455: 
                    456:                TOstop();
                    457:                }
                    458:                break;
                    459:        }
                    460:        return !FALSE;
                    461: }
                    462: 
                    463: int
                    464: complete(possible, prompt, flags)
                    465: register char  *possible[];
                    466: char   *prompt;
                    467: int    flags;
                    468: {
                    469:        /* protect static "Possible" from being overwritten due to recursion */
                    470:        if (InRealAsk)
                    471:                complain((char *) NULL);
                    472: 
                    473:        Possible = possible;
                    474:        comp_flags = flags;
                    475:        (void) do_ask("\r\n \t?", aux_complete, NullStr, prompt);
                    476:        return comp_value;
                    477: }
                    478: 
                    479: private int
                    480: match(choices, what)
                    481: register char  **choices,
                    482:                *what;
                    483: {
                    484:        register size_t len;
                    485:        int     i,
                    486:                found = 0,
                    487:                save,
                    488:                exactmatch = -1;
                    489: 
                    490:        len = strlen(what);
                    491:        if (len == 0)
                    492:                return NULLSTRING;
                    493:        for (i = 0; choices[i]; i++) {
                    494:                if (strncmp(what, choices[i], len) == 0) {
                    495:                        if (strcmp(what, choices[i]) == 0)
                    496:                                exactmatch = i;
                    497:                        save = i;
                    498:                        found += 1;     /* found one */
                    499:                }
                    500:        }
                    501: 
                    502:        if (found == 0)
                    503:                save = ORIGINAL;
                    504:        else if (found > 1) {
                    505:                if (exactmatch != -1)
                    506:                        save = exactmatch;
                    507:                else
                    508:                        save = AMBIGUOUS;
                    509:        }
                    510: 
                    511:        return save;
                    512: }
                    513: 
                    514: void
                    515: Source()
                    516: {
                    517:        extern char     *getenv();
                    518:        char    *com,
                    519:                buf[FILESIZE];
                    520: 
                    521: #ifndef MSDOS
                    522:        swritef(buf, "%s/.joverc", HomeDir);
                    523: #else /* MSDOS */
                    524:        if (com = getenv("JOVERC"))
                    525:                strcpy(buf, com);
                    526:        else
                    527:                strcpy(buf, Joverc);
                    528: #endif /* MSDOS */
                    529:        com = ask_file((char *) 0, buf, buf);
                    530:        if (joverc(buf) == 0)
                    531:                complain(IOerr("read", com));
                    532: }
                    533: 
                    534: void
                    535: BufPos()
                    536: {
                    537:        register Line   *lp = curbuf->b_first;
                    538:        register int    i,
                    539:                        dotline;
                    540:        long    dotchar,
                    541:                nchars;
                    542: 
                    543:        for (i = nchars = 0; lp != 0; i++, lp = lp->l_next) {
                    544:                if (lp == curline) {
                    545:                        dotchar = nchars + curchar;
                    546:                        dotline = i + 1;
                    547:                }
                    548:                nchars += length(lp) + (lp->l_next != 0); /* include the NL */
                    549:        }
                    550: 
                    551:        s_mess("[\"%s\" line %d/%d, char %D/%D (%d%%), cursor = %d/%d]",
                    552:               filename(curbuf), dotline, i, dotchar, nchars,
                    553:               (nchars == 0) ? 100 : (int) (((long) dotchar * 100) / nchars),
                    554:               calc_pos(linebuf, curchar),
                    555:               calc_pos(linebuf, (int)strlen(linebuf)));
                    556: }
                    557: 
                    558: #define IF_UNBOUND     (-1)
                    559: #define IF_TRUE                1
                    560: #define IF_FALSE       (!IF_TRUE)
                    561: 
                    562: #ifndef MAC
                    563: private int
                    564: do_if(cmd)
                    565: char   *cmd;
                    566: {
                    567: #ifdef MSDOS
                    568:        int status;
                    569: #else
                    570:        int     pid,
                    571:                status;
                    572: #endif /* MSDOS */
                    573: #ifndef MSDOS
                    574: 
                    575:        switch (pid = fork()) {
                    576:        case -1:
                    577:                complain("[Fork failed: if]");
                    578:                /*NOTREACHED*/
                    579: 
                    580:        case 0:
                    581:            {
                    582: #endif /* MSDOS */
                    583:                char    *args[12],
                    584:                        *cp = cmd,
                    585:                        **ap = args;
                    586: 
                    587:                *ap++ = cmd;
                    588:                for (;;) {
                    589:                        if ((cp = strchr(cp, ' ')) == 0)
                    590:                                break;
                    591:                        *cp++ = '\0';
                    592:                        *ap++ = cp;
                    593:                }
                    594:                *ap = 0;
                    595: 
                    596: #ifndef MSDOS
                    597:                close(0);       /*      we want reads to fail */
                    598:                /* close(1);     but not writes or ioctl's
                    599:                close(2);    */
                    600: #else /* MSDOS */
                    601:        if ((status = spawnvp(0, args[0], args)) < 0)
                    602:                complain("[Spawn failed: if]");
                    603: #endif /* MSDOS */
                    604: 
                    605: #ifndef MSDOS
                    606:                (void) execvp(args[0], (const char **)args);
                    607:                _exit(-10);     /* signals exec error (see below) */
                    608:            }
                    609:        }
                    610: #ifdef IPROCS
                    611:        SigHold(SIGCHLD);
                    612: #endif
                    613:        dowait(pid, &status);
                    614: #ifdef IPROCS
                    615:        SigRelse(SIGCHLD);
                    616: #endif
                    617:        if (status == -10)
                    618:                complain("[Exec failed]");
                    619:        if (status < 0)
                    620:                complain("[Exit %d]", status);
                    621: #endif /* MSDOS */
                    622:        return (status == 0);   /* 0 means successful */
                    623: }
                    624: #endif /* MAC */
                    625: 
                    626: int
                    627: joverc(file)
                    628: char   *file;
                    629: {
                    630:        char    buf[LBSIZE],
                    631:                lbuf[LBSIZE];
                    632:        int     lnum = 0,
                    633:                eof = FALSE;
                    634:        jmp_buf savejmp;
                    635:        int     IfStatus = IF_UNBOUND;
                    636:        File    *fp;
                    637: 
                    638:        fp = open_file(file, buf, F_READ, NO, YES);
                    639:        if (fp == NIL)
                    640:                return NO;      /* joverc returns an integer */
                    641: 
                    642:        /* Catch any errors, here, and do the right thing with them,
                    643:           and then restore the error handle to whoever did a setjmp
                    644:           last. */
                    645: 
                    646:        InJoverc += 1;
                    647:        push_env(savejmp);
                    648:        if (setjmp(mainjmp)) {
                    649:                Buffer  *savebuf = curbuf;
                    650: 
                    651:                SetBuf(do_select((Window *) 0, "RC errors"));
                    652:                ins_str(sprint("%s:%d:%s\t%s\n", pr_name(file, YES), lnum, lbuf, mesgbuf), NO);
                    653:                unmodify();
                    654:                SetBuf(savebuf);
                    655:                Asking = 0;
                    656:        }
                    657:        if (!eof) do {
                    658:                eof = (f_gets(fp, lbuf, sizeof lbuf) == EOF);
                    659:                lnum += 1;
                    660:                if (lbuf[0] == '#')             /* a comment */
                    661:                        continue;
                    662: #ifndef MAC
                    663:                if (casencmp(lbuf, "if", (size_t)2) == 0) {
                    664:                        char    cmd[128];
                    665: 
                    666:                        if (IfStatus != IF_UNBOUND)
                    667:                                complain("[Cannot have nested if's]");
                    668:                        if (LookingAt("if[ \t]*\\(.*\\)$", lbuf, 0) == 0)
                    669:                                complain("[If syntax error]");
                    670:                        putmatch(1, cmd, sizeof cmd);
                    671:                        IfStatus = do_if(cmd) ? IF_TRUE : IF_FALSE;
                    672:                        continue;
                    673:                } else if (casencmp(lbuf, "else", (size_t)4) == 0) {
                    674:                        if (IfStatus == IF_UNBOUND)
                    675:                                complain("[Unexpected `else']");
                    676:                        IfStatus = !IfStatus;
                    677:                        continue;
                    678:                } else if (casencmp(lbuf, "endif", (size_t)5) == 0) {
                    679:                        if (IfStatus == IF_UNBOUND)
                    680:                                complain("[Unexpected `endif']");
                    681:                        IfStatus = IF_UNBOUND;
                    682:                        continue;
                    683:                }
                    684: #endif
                    685:                if (IfStatus == IF_FALSE)
                    686:                        continue;
                    687:                (void) strcat(lbuf, "\n");
                    688:                Inputp = lbuf;
                    689:                while (*Inputp == ' ' || *Inputp == '\t')
                    690:                        Inputp += 1;    /* skip white space */
                    691:                Extend();
                    692:        } while (!eof);
                    693: 
                    694:        f_close(fp);
                    695:        pop_env(savejmp);
                    696:        Inputp = 0;
                    697:        Asking = 0;
                    698:        InJoverc -= 1;
                    699:        if (IfStatus != IF_UNBOUND)
                    700:                complain("[Missing endif]");
                    701:        return 1;
                    702: }

unix.superglobalmegacorp.com

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