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

1.1       root        1: /*************************************************************************
                      2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
                      3:  * provided to you without charge for use only on a licensed Unix        *
                      4:  * system.  You may copy JOVE provided that this notice is included with *
                      5:  * the copy.  You may not sell copies of this program or versions        *
                      6:  * modified for use on microcomputer systems, unless the copies are      *
                      7:  * included with a Unix system distribution and the source is provided.  *
                      8:  *************************************************************************/
                      9: 
                     10: #include "jove.h"
                     11: #include "io.h"
                     12: #include "termcap.h"
                     13: #include "ctype.h"
                     14: #ifdef JOB_CONTROL
                     15: #      include <signal.h>
                     16: #endif
                     17: 
                     18: #include <varargs.h>
                     19: 
                     20: int    InJoverc = 0;
                     21: 
                     22: extern int     getch(),
                     23:                getchar();
                     24: 
                     25: /* Auto execute code */
                     26: 
                     27: #define NEXECS 20
                     28: 
                     29: private struct {
                     30:        char    *a_pattern;
                     31:        data_obj        *a_cmd;
                     32: } AutoExecs[NEXECS] = {0};
                     33: 
                     34: private int    ExecIndex = 0;
                     35: 
                     36: /* Command auto-execute. */
                     37: 
                     38: CAutoExec()
                     39: {
                     40:        DefAutoExec(findcom);
                     41: }
                     42: 
                     43: /* Macro auto-execute. */
                     44: 
                     45: MAutoExec()
                     46: {
                     47:        DefAutoExec(findmac);
                     48: }
                     49: 
                     50: /* VARARGS0 */
                     51: 
                     52: DefAutoExec(proc)
                     53: data_obj       *(*proc)();
                     54: {
                     55:        data_obj        *d;
                     56:        char    *pattern;
                     57:        int     i;
                     58: 
                     59:        if (ExecIndex >= NEXECS)
                     60:                complain("Too many auto-executes, max %d.", NEXECS);
                     61:        if ((d = (*proc)(ProcFmt)) == 0)
                     62:                return;
                     63:        pattern = ask((char *) 0, ": %f %s ", d->Name);
                     64:        for (i = 0; i < ExecIndex; i++)
                     65:                if ((AutoExecs[i].a_cmd == d) &&
                     66:                    (strcmp(pattern, AutoExecs[i].a_pattern) == 0))
                     67:                        return;         /* Eliminate duplicates. */
                     68:        AutoExecs[ExecIndex].a_pattern = copystr(pattern);
                     69:        AutoExecs[ExecIndex].a_cmd = d;
                     70:        ExecIndex++;
                     71: }
                     72: 
                     73: /* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
                     74:    same kind of file (i.e., match the same pattern) or OLD is 0 and it
                     75:    matches, we execute the command associated with that kind of file. */
                     76:  
                     77: DoAutoExec(new, old)
                     78: register char  *new,
                     79:                *old;
                     80: {
                     81:        register int    i;
                     82: 
                     83:        exp_p = 1;
                     84:        exp = 1;        /* So minor modes don't toggle.  We always want
                     85:                           them on. */
                     86:        if (new == 0)
                     87:                return;
                     88:        for (i = 0; i < ExecIndex; i++)
                     89:                if ((LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
                     90:                    (old == 0 || !LookingAt(AutoExecs[i].a_pattern, old, 0)))
                     91:                        ExecCmd(AutoExecs[i].a_cmd);
                     92: }
                     93: 
                     94: BindAKey()
                     95: {
                     96:        BindSomething(findcom);
                     97: }
                     98: 
                     99: BindMac()
                    100: {
                    101:        BindSomething(findmac);
                    102: }
                    103: 
                    104: extern int     EscPrefix(),
                    105:                CtlxPrefix(),
                    106:                MiscPrefix();
                    107: 
                    108: data_obj **
                    109: IsPrefix(cp)
                    110: data_obj       *cp;
                    111: {
                    112:        int     (*proc)();
                    113: 
                    114:        if (cp == 0 || (cp->Type & TYPEMASK) != FUNCTION)
                    115:                return 0;
                    116:        proc = ((struct cmd *) cp)->c_proc;
                    117:        if (proc == EscPrefix)
                    118:                return pref1map;
                    119:        if (proc == CtlxPrefix)
                    120:                return pref2map;
                    121:        if (proc == MiscPrefix)
                    122:                return miscmap;
                    123:        return 0;
                    124: }
                    125: 
                    126: unbind_aux(c)
                    127: {
                    128:        if (c == CR || c == LF)
                    129:                return FALSE;   /* tells do_ask to return */
                    130:        Insert(c);
                    131:        return !FALSE;
                    132: }
                    133: 
                    134: UnbindC()
                    135: {
                    136:        char    *keys;
                    137:        data_obj        **map = mainmap;
                    138: 
                    139:        keys = do_ask("\r\n\01\02\03\04\05\06\010\011\013\014\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", unbind_aux, (char *) 0, ProcFmt);
                    140:        if (keys == 0)
                    141:                return;
                    142:        for (;;) {
                    143:                if (keys[1] == '\0')
                    144:                        break;
                    145:                if ((map = IsPrefix(map[*keys])) == 0)
                    146:                        break;
                    147:                keys++;
                    148:        }
                    149:        if (keys[1] != 0)
                    150:                complain("That's not a legitimate key sequence.");
                    151:        map[keys[0]] = 0;
                    152: }
                    153:                
                    154: addgetc()
                    155: {
                    156:        int     c;
                    157: 
                    158:        if (!InJoverc)
                    159:                Asking = strlen(mesgbuf);
                    160:        c = getch();
                    161:        if (InJoverc) {
                    162:                if (c == '\n')
                    163:                        return EOF;     /* this isn't part of the sequence */
                    164:                else if (c == '\\') {
                    165:                        if ((c = getch()) == LF)
                    166:                                complain("[Premature end of line]");
                    167:                } else if (c == '^') {
                    168:                        if ((c = getch()) == '?')
                    169:                                c = RUBOUT;
                    170:                        else if (isalpha(c) || index("[\\]^_", c))
                    171:                                c = c - '@';
                    172:                        else
                    173:                                complain("[Unknown control character]");
                    174:                }
                    175:        }
                    176: 
                    177:        Asking = 0;
                    178:        add_mess("%p ", c);
                    179: 
                    180:        return c;
                    181: }
                    182: 
                    183: BindWMap(map, lastkey, cmd)
                    184: data_obj       **map,
                    185:                *cmd;
                    186: {
                    187:        data_obj        **nextmap;
                    188:        int     c;
                    189: 
                    190:        c = addgetc();
                    191:        if (c == EOF) {
                    192:                if (lastkey == EOF)
                    193:                        complain("[Empty key sequence]");
                    194:                complain("[Premature end of key sequence]");
                    195:        } else {
                    196:                if (nextmap = IsPrefix(map[c]))
                    197:                        BindWMap(nextmap, c, cmd);
                    198:                else
                    199:                        map[c] = cmd;
                    200:        }
                    201: }
                    202: 
                    203: /* VARARGS0 */
                    204: 
                    205: BindSomething(proc)
                    206: data_obj       *(*proc)();
                    207: {
                    208:        data_obj        *d;
                    209: 
                    210:        if ((d = (*proc)(ProcFmt)) == 0)
                    211:                return;
                    212:        s_mess(": %f %s ", d->Name);
                    213:        BindWMap(mainmap, EOF, d);
                    214: }
                    215: 
                    216: /* Describe key */
                    217: 
                    218: DescWMap(map, key)
                    219: data_obj       **map;
                    220: {
                    221:        data_obj        *cp = map[key],
                    222:                        **prefp;
                    223: 
                    224:        if (cp == 0)
                    225:                add_mess("is unbound.");
                    226:        else if (prefp = IsPrefix(cp))
                    227:                DescWMap(prefp, addgetc());
                    228:        else
                    229:                add_mess("is bound to %s.", cp->Name);
                    230: }
                    231: 
                    232: KeyDesc()
                    233: {
                    234:        s_mess(ProcFmt);
                    235:        DescWMap(mainmap, addgetc());
                    236: }
                    237: 
                    238: DescCom()
                    239: {
                    240:        data_obj        *dp;
                    241:        char    pattern[100],
                    242:                doc_type[40],
                    243:                *file = CMD_DB;
                    244:        File    *fp;
                    245: 
                    246:        if (!strcmp(LastCmd->Name, "describe-variable"))
                    247:                dp = (data_obj *) findvar(ProcFmt);
                    248:        else
                    249:                dp = (data_obj *) findcom(ProcFmt);
                    250: 
                    251:        if (dp == 0)
                    252:                return;
                    253:        fp = open_file(file, iobuff, F_READ, COMPLAIN, QUIET);
                    254:        Placur(ILI, 0);
                    255:        flusho();
                    256:        sprintf(pattern, "^:entry \"%s\" \"\\([^\"]*\\)\"", dp->Name);
                    257:        TOstart("Help", TRUE);
                    258:        for (;;) {
                    259:                if (f_gets(fp, genbuf, LBSIZE) == EOF) {
                    260:                        Typeout("There is no documentation for \"%s\".", dp->Name);
                    261:                        goto outahere;
                    262:                }
                    263:                if ((strncmp(genbuf, ":entry", 6) == 0) && LookingAt(pattern, genbuf, 0))
                    264:                        break;
                    265:        }
                    266:        /* found it ... let's print it */
                    267:        putmatch(1, doc_type, sizeof doc_type);
                    268:        if (strcmp("Variable", doc_type) == 0)
                    269:                Typeout(dp->Name);
                    270:        else if (strcmp("Command", doc_type) == 0) {
                    271:                char    binding[128];
                    272: 
                    273:                find_binds((struct cmd *) dp, binding);
                    274:                if (blnkp(binding))
                    275:                        Typeout("To invoke %s, type \"ESC X %s<cr>\".",
                    276:                                dp->Name,
                    277:                                dp->Name);
                    278:                else
                    279:                        Typeout("Type \"%s\" to invoke %s.", binding, dp->Name);
                    280:        }
                    281:        Typeout("");
                    282:        while (f_gets(fp, genbuf, LBSIZE) != EOF)
                    283:                if (strncmp(genbuf, ":entry", 6) == 0)
                    284:                        goto outahere;
                    285:                else
                    286:                        Typeout("%s", genbuf);
                    287: outahere:
                    288:        f_close(fp);
                    289:        TOstop();
                    290: }
                    291: 
                    292: DescBindings()
                    293: {
                    294:        extern int      Typeout();
                    295: 
                    296:        TOstart("Key Bindings", TRUE);
                    297:        DescMap(mainmap, NullStr);
                    298:        TOstop();
                    299: }
                    300: 
                    301: DescMap(map, pref)
                    302: data_obj       **map;
                    303: char   *pref;
                    304: {
                    305:        int     c1,
                    306:                c2 = 0,
                    307:                numbetween;
                    308:        char    keydescbuf[40];
                    309:        data_obj        **prefp;
                    310: 
                    311:        for (c1 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
                    312:                c2 = c1;
                    313:                if (map[c1] == 0)
                    314:                        continue;
                    315:                while (++c2 < 0200 && map[c1] == map[c2])
                    316:                        ;
                    317:                c2--;
                    318:                numbetween = c2 - c1;
                    319:                if (numbetween == 1)
                    320:                        sprintf(keydescbuf, "%s {%p,%p}", pref, c1, c2);
                    321:                else if (numbetween == 0)
                    322:                        sprintf(keydescbuf, "%s %p", pref, c1);
                    323:                else
                    324:                        sprintf(keydescbuf, "%s [%p-%p]", pref, c1, c2);
                    325:                if (prefp = IsPrefix(map[c1]))
                    326:                        DescMap(prefp, keydescbuf);
                    327:                else
                    328:                        Typeout("%-14s%s", keydescbuf, map[c1]->Name);
                    329:        }
                    330: }
                    331: 
                    332: private
                    333: find_binds(cp, buf)
                    334: struct cmd     *cp;
                    335: char   *buf;
                    336: {
                    337:        char    *endp;
                    338: 
                    339:        buf[0] = '\0';
                    340:        fb_aux(cp, mainmap, (char *) 0, buf);
                    341:        endp = buf + strlen(buf) - 2;
                    342:        if ((endp > buf) && (strcmp(endp, ", ") == 0))
                    343:                *endp = '\0';
                    344: }
                    345: 
                    346: private
                    347: fb_aux(cp, map, prefix, buf)
                    348: register data_obj      *cp,
                    349:                        **map;
                    350: char   *buf,
                    351:        *prefix;
                    352: {
                    353:        int     c1,
                    354:                c2;
                    355:        char    *bufp = buf + strlen(buf),
                    356:                prefbuf[20];
                    357:        data_obj        **prefp;
                    358: 
                    359:        for (c1 = c2 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
                    360:                c2 = c1;
                    361:                if (map[c1] == cp) {
                    362:                        while (++c2 < 0200 && map[c1] == map[c2])
                    363:                                ;
                    364:                        c2--;
                    365:                        if (prefix)
                    366:                                sprintf(bufp, "%s ", prefix);
                    367:                        bufp += strlen(bufp);
                    368:                        switch (c2 - c1) {
                    369:                        case 0:
                    370:                                sprintf(bufp, "%p, ", c1);
                    371:                                break;
                    372:        
                    373:                        case 1:
                    374:                                sprintf(bufp, "{%p,%p}, ", c1, c2);
                    375:                                break;
                    376:        
                    377:                        default:
                    378:                                sprintf(bufp, "[%p-%p], ", c1, c2);
                    379:                                break;
                    380:                        }
                    381:                }
                    382:                if (prefp = IsPrefix(map[c1])) {
                    383:                        sprintf(prefbuf, "%p", c1);
                    384:                        fb_aux(cp, prefp, prefbuf, bufp);
                    385:                }
                    386:                bufp += strlen(bufp);
                    387:        }
                    388: }
                    389: 
                    390: Apropos()
                    391: {
                    392:        register struct cmd     *cp;
                    393:        register struct macro   *m;
                    394:        register struct variable        *v;
                    395:        char    *ans;
                    396:        int     anyfs = 0,
                    397:                anyvs = 0,
                    398:                anyms = 0;
                    399:        char    buf[256];
                    400: 
                    401:        ans = ask((char *) 0, ": %f (keyword) ");
                    402:        TOstart("Help", TRUE);
                    403:        for (cp = commands; cp->Name != 0; cp++)
                    404:                if (sindex(ans, cp->Name)) {
                    405:                        if (anyfs == 0) {
                    406:                                Typeout("Commands");
                    407:                                Typeout("--------");
                    408:                        }
                    409:                        find_binds(cp, buf);
                    410:                        if (buf[0])
                    411:                                Typeout(": %-30s(%s)", cp->Name, buf);
                    412:                        else
                    413:                                Typeout(": %s", cp->Name);
                    414:                        anyfs++;
                    415:                }
                    416:        if (anyfs)
                    417:                Typeout(NullStr);
                    418:        for (v = variables; v->Name != 0; v++)
                    419:                if (sindex(ans, v->Name)) {
                    420:                        if (anyvs == 0) {
                    421:                                Typeout("Variables");
                    422:                                Typeout("---------");
                    423:                        }
                    424:                        anyvs++;
                    425:                        vpr_aux(v, buf);
                    426:                        Typeout(": set %-26s%s", v->Name, buf);
                    427:                }
                    428:        if (anyvs)
                    429:                Typeout(NullStr);
                    430:        for (m = macros; m != 0; m = m->m_nextm)
                    431:                if (sindex(ans, m->Name)) {
                    432:                        if (anyms == 0) {
                    433:                                Typeout("Macros");
                    434:                                Typeout("------");
                    435:                        }
                    436:                        anyms++;
                    437:                        find_binds((data_obj *) m, buf);
                    438:                        if (buf[0])
                    439:                                Typeout(": %-30s(%s)", m->Name, buf);
                    440:                        else
                    441:                                Typeout(": %-30s%s", "execute-macro", m->Name);
                    442:                }
                    443:        TOstop();
                    444: }
                    445: 
                    446: Extend()
                    447: {
                    448:        data_obj        *d;
                    449: 
                    450:        if (d = findcom(": "))
                    451:                ExecCmd(d);
                    452: }
                    453: 
                    454: /* Read a positive integer from CP.  It must be in base BASE, and
                    455:    complains if it isn't.  If allints is nonzero, all the characters
                    456:    in the string must be integers or we return -1; otherwise we stop
                    457:    reading at the first nondigit. */
                    458: 
                    459: chr_to_int(cp, base, allints)
                    460: register char  *cp;
                    461: {
                    462:        register int    c;
                    463:        int     value = 0;
                    464: 
                    465:        while (c = *cp++) {
                    466:                if (!isdigit(c)) {
                    467:                        if (allints)
                    468:                                return -1;
                    469:                        break;
                    470:                }
                    471:                c = c - '0';
                    472:                if (c >= base)
                    473:                        complain("You must specify in base %d.", base);
                    474:                value = value * base + c;
                    475:        }
                    476:        return value;
                    477: }
                    478: 
                    479: ask_int(prompt, base)
                    480: char   *prompt;
                    481: int    base;
                    482: {
                    483:        char    *val = ask((char *) 0, prompt);
                    484:        int     value = chr_to_int(val, base, 1);
                    485: 
                    486:        if (value < 0)
                    487:                complain("That's not a number!");
                    488:        return value;
                    489: }
                    490: 
                    491: private
                    492: vpr_aux(vp, buf)
                    493: register struct variable       *vp;
                    494: char   *buf;
                    495: {
                    496:        switch (vp->v_flags & V_TYPEMASK) {
                    497:        case V_BASE10:
                    498:                sprintf(buf, "%d", *(vp->v_value));
                    499:                break;
                    500: 
                    501:        case V_BASE8:
                    502:                sprintf(buf, "%o", *(vp->v_value));
                    503:                break;
                    504: 
                    505:        case V_BOOL:
                    506:                sprintf(buf, (*(vp->v_value)) ? "on" : "off");
                    507:                break;
                    508: 
                    509:        case V_STRING:
                    510:                sprintf(buf, "%s", (char *) vp->v_value);
                    511:                break;
                    512: 
                    513:        case V_CHAR:
                    514:                sprintf(buf, "%p", *(vp->v_value));
                    515:                break;
                    516:        }
                    517: }
                    518: 
                    519: PrVar()
                    520: {
                    521:        struct variable *vp;
                    522:        char    prbuf[256];
                    523: 
                    524:        if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
                    525:                return;
                    526:        vpr_aux(vp, prbuf);
                    527:        s_mess(": %f %s => %s", vp->Name, prbuf);
                    528: }
                    529: 
                    530: SetVar()
                    531: {
                    532:        struct variable *vp;
                    533:        char    *prompt;
                    534: 
                    535:        if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
                    536:                return;
                    537:        prompt = sprint(": %f %s ", vp->Name);
                    538: 
                    539:        switch (vp->v_flags & V_TYPEMASK) {
                    540:        case V_BASE10:
                    541:        case V_BASE8:
                    542:            {
                    543:                int     value;
                    544: 
                    545:                value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10)
                    546:                                          ? 10 : 8);
                    547:                *(vp->v_value) = value;
                    548:                break;
                    549:            }
                    550: 
                    551:        case V_BOOL:
                    552:            {
                    553:                char    *def = *(vp->v_value) ? "off" : "on",
                    554:                        *on_off;
                    555:                int     value;
                    556: 
                    557:                on_off = ask(def, prompt);
                    558:                if (casecmp(on_off, "on") == 0)
                    559:                        value = ON;
                    560:                else if (casecmp(on_off, "off") == 0)
                    561:                        value = OFF;
                    562:                else
                    563:                        complain("Boolean variables must be ON or OFF.");
                    564:                *(vp->v_value) = value;
                    565:                s_mess("%s%s", prompt, value ? "on" : "off");
                    566:                break;
                    567:            }
                    568: 
                    569:        case V_STRING:
                    570:            {
                    571:                char    *str;
                    572: 
                    573:                /* Do_ask() so if you want you can set string to
                    574:                   "" if you so desire. */
                    575:                str = do_ask("\r\n", (int (*)()) 0, (char *) vp->v_value, prompt);
                    576:                if (str == 0)
                    577:                        str = NullStr;
                    578:                strcpy((char *) vp->v_value, str);
                    579:                /* ... and hope there is enough room. */
                    580:                break;
                    581:            }
                    582:        case V_CHAR:
                    583:                f_mess(prompt);
                    584:                *(vp->v_value) = addgetc();
                    585:                break;          
                    586: 
                    587:        }
                    588:        if (vp->v_flags & V_MODELINE)
                    589:                UpdModLine++;
                    590:        if (vp->v_flags & V_CLRSCREEN)
                    591:                ClAndRedraw();
                    592:        if (vp->v_flags & V_TTY_RESET)
                    593:                tty_reset();
                    594: }
                    595:                        
                    596: /* Command completion - possible is an array of strings, prompt is
                    597:    the prompt to use, and flags are ... well read jove.h.
                    598: 
                    599:    If flags are RET_STATE, and the user hits <return> what they typed
                    600:    so far is in the Minibuf string. */
                    601: 
                    602: private char   **Possible;
                    603: private int    comp_value,
                    604:                comp_flags;
                    605: 
                    606: aux_complete(c)
                    607: {
                    608:        int     command,
                    609:                length,
                    610:                i;
                    611: 
                    612:        switch (c) {
                    613:        case EOF:
                    614:                comp_value = -1;
                    615:                return 0;
                    616: 
                    617:        case '\r':
                    618:        case '\n':
                    619:                command = match(Possible, linebuf);
                    620:                if (command >= 0) {
                    621:                        comp_value = command;
                    622:                        return 0;       /* tells ask to stop */
                    623:                }
                    624:                if (eolp() && bolp()) {
                    625:                        comp_value = NULLSTRING;
                    626:                        return 0;
                    627:                }
                    628:                if (comp_flags == RET_STATE) switch (command) {
                    629:                        case UNIQUE:
                    630:                        case ORIGINAL:
                    631:                        case NULLSTRING:
                    632:                                comp_value = command;
                    633:                                return 0;
                    634: 
                    635:                        default:
                    636:                                break;
                    637:                }
                    638:                if (InJoverc)
                    639:                        complain("[\"%s\" unknown]", linebuf);
                    640:                rbell();
                    641:                break;
                    642: 
                    643:        case '\t':
                    644:        case ' ':
                    645:            {
                    646:                int     minmatch = 1000,
                    647:                        maxmatch = 0,
                    648:                        numfound = 0,
                    649:                        lastmatch = -1,
                    650:                        length = strlen(linebuf);
                    651: 
                    652:                for (i = 0; Possible[i] != 0; i++) {
                    653:                        int     this_len;
                    654: 
                    655:                        this_len = numcomp(Possible[i], linebuf);
                    656:                        maxmatch = max(maxmatch, this_len);
                    657:                        if (this_len >= length) {
                    658:                                if (numfound)
                    659:                                        minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
                    660:                                else
                    661:                                        minmatch = strlen(Possible[i]);
                    662:                                numfound++;
                    663:                                lastmatch = i;
                    664:                                if (strcmp(linebuf, Possible[i]) == 0)
                    665:                                        break;
                    666:                        }
                    667:                }
                    668: 
                    669:                if (numfound == 0) {
                    670:                        rbell();
                    671:                        if (InJoverc)
                    672:                                complain("[\"%s\" unknown]", linebuf);
                    673:                        /* If we're not in the .joverc then
                    674:                           let's do something helpful for the
                    675:                           user. */
                    676:                        if (maxmatch < length) {
                    677:                                char    *cp;
                    678: 
                    679:                                cp = linebuf + maxmatch;
                    680:                                *cp = 0;
                    681:                                Eol();
                    682:                        }
                    683:                        break;
                    684:                }
                    685:                if (c != '\t' && numfound == 1) {
                    686:                        comp_value = lastmatch;
                    687:                        return 0;
                    688:                }
                    689:                null_ncpy(linebuf, Possible[lastmatch], minmatch);
                    690:                Eol();
                    691:                if (minmatch == length) /* No difference */
                    692:                        rbell();
                    693:                break;
                    694:            }
                    695: 
                    696:        case '?':
                    697:                if (InJoverc)
                    698:                        complain((char *) 0);
                    699:                /* kludge: in case we're using UseBuffers, in which case
                    700:                   linebuf gets written all over */
                    701:                strcpy(Minibuf, linebuf);
                    702:                length = strlen(Minibuf);
                    703:                TOstart("Completion", TRUE);    /* for now ... */
                    704:                for (i = 0; Possible[i]; i++)
                    705:                        if (numcomp(Possible[i], Minibuf) >= length) {
                    706:                                Typeout(Possible[i]);
                    707:                                if (TOabort != 0)
                    708:                                        break;
                    709:                        }
                    710: 
                    711:                TOstop();
                    712:                break;
                    713:        }
                    714:        return !FALSE;
                    715: }
                    716: 
                    717: complete(possible, prompt, flags)
                    718: register char  *possible[];
                    719: char   *prompt;
                    720: {
                    721:        Possible = possible;
                    722:        comp_flags = flags;
                    723:        (void) do_ask("\r\n \t?", aux_complete, NullStr, prompt);
                    724:        return comp_value;
                    725: }
                    726: 
                    727: match(choices, what)
                    728: register char  **choices,
                    729:                *what;
                    730: {
                    731:        register int    len;
                    732:        int     i,
                    733:                found = 0,
                    734:                save,
                    735:                exactmatch = -1;
                    736: 
                    737:        len = strlen(what);
                    738:        if (len == 0)
                    739:                return NULLSTRING;
                    740:        for (i = 0; choices[i]; i++) {
                    741:                if (strncmp(what, choices[i], len) == 0) {
                    742:                        if (strcmp(what, choices[i]) == 0)
                    743:                                exactmatch = i;
                    744:                        save = i;
                    745:                        found++;        /* Found one. */
                    746:                }
                    747:        }
                    748: 
                    749:        if (found == 0)
                    750:                save = ORIGINAL;
                    751:        else if (found > 1) {
                    752:                if (exactmatch != -1)
                    753:                        save = exactmatch;
                    754:                else
                    755:                        save = AMBIGUOUS;
                    756:        }
                    757: 
                    758:        return save;
                    759: }
                    760: 
                    761: Source()
                    762: {
                    763:        char    *com,
                    764:                buf[FILESIZE];
                    765: 
                    766:        sprintf(buf, "%s/.joverc", getenv("HOME"));
                    767:        com = ask_file(buf, buf);
                    768:        if (joverc(buf) == NIL)
                    769:                complain(IOerr("read", com));
                    770: }
                    771: 
                    772: BufPos()
                    773: {
                    774:        register Line   *lp = curbuf->b_first;
                    775:        register int    i,
                    776:                        dotline;
                    777: 
                    778:        for (i = 0; lp != 0; i++, lp = lp->l_next)
                    779:                if (lp == curline)
                    780:                        dotline = i + 1;
                    781: 
                    782:        s_mess("\"%s\" line %d of %d --%d%%--, column %d of %d.",
                    783:                        filename(curbuf),
                    784:                        dotline,
                    785:                        i,
                    786:                        (int) (((long) dotline * 100) / i),
                    787:                        1 + calc_pos(linebuf, curchar),
                    788:                        1 + calc_pos(linebuf, strlen(linebuf)));
                    789: }
                    790: 
                    791: #define IF_UNBOUND     -1
                    792: #define IF_TRUE                1
                    793: #define IF_FALSE       !IF_TRUE
                    794: 
                    795: do_if(cmd)
                    796: char   *cmd;
                    797: {
                    798:        int     pid,
                    799:                status;
                    800: 
                    801:        switch (pid = fork()) {
                    802:        case -1:
                    803:                complain("[Fork failed: if]");
                    804: 
                    805:        case 0:
                    806:            {
                    807:                char    *args[12],
                    808:                        *cp = cmd,
                    809:                        **ap = args;
                    810: 
                    811:                *ap++ = cmd;
                    812:                for (;;) {
                    813:                        if ((cp = index(cp, ' ')) == 0)
                    814:                                break;
                    815:                        *cp++ = '\0';
                    816:                        *ap++ = cp;
                    817:                }
                    818:                *ap = 0;
                    819: 
                    820:                close(0);       /*      we want reads to fail */
                    821:                /* close(1);     but not writes or ioctl's
                    822:                close(2);    */
                    823: 
                    824:                (void) execvp(args[0], args);
                    825:                _exit(-10);     /* signals exec error (see below) */
                    826:            }
                    827:        }
                    828: #ifdef IPROCS
                    829:        sighold(SIGCHLD);
                    830: #endif
                    831:        dowait(pid, &status);
                    832: #ifdef IPROCS
                    833:        sigrelse(SIGCHLD);
                    834: #endif
                    835:        if (status == -10)
                    836:                complain("[Exec failed]");
                    837:        if (status < 0)
                    838:                complain("[Exit %d]", status);
                    839:        return (status == 0);   /* 0 means successful */
                    840: }
                    841: 
                    842: joverc(file)
                    843: char   *file;
                    844: {
                    845:        char    buf[LBSIZE],
                    846:                lbuf[128];
                    847:        int     lnum = 0,
                    848:                eof = FALSE;
                    849:        jmp_buf savejmp;
                    850:        int     IfStatus = IF_UNBOUND;
                    851:        File    *fp;
                    852: 
                    853:        fp = open_file(file, buf, F_READ, !COMPLAIN, QUIET);
                    854:        if (fp == NIL)
                    855:                return NIL;
                    856: 
                    857:        /* Catch any errors, here, and do the right thing with them,
                    858:           and then restore the error handle to whoever did a setjmp
                    859:           last. */
                    860: 
                    861:        push_env(savejmp);
                    862:        if (setjmp(mainjmp)) {
                    863:                Buffer  *savebuf = curbuf;
                    864: 
                    865:                SetBuf(do_select((Window *) 0, "RC errors"));
                    866:                ins_str(sprint("%s:%d:%s\t%s\n", pr_name(file), lnum, lbuf, mesgbuf), NO);
                    867:                unmodify();
                    868:                SetBuf(savebuf);
                    869:                Asking = 0;
                    870:        }
                    871:        InJoverc = 1;
                    872:        if (!eof) do {
                    873:                eof = (f_gets(fp, lbuf, sizeof lbuf) == EOF);
                    874:                lnum++;
                    875:                if (casencmp(lbuf, "if", 2) == 0) {
                    876:                        char    cmd[128];
                    877: 
                    878:                        if (IfStatus != IF_UNBOUND)
                    879:                                complain("[Cannot have nested if's]");
                    880:                        if (LookingAt("if[ \t]*\\(.*\\)$", lbuf, 0) == 0)
                    881:                                complain("[If syntax error]");
                    882:                        putmatch(1, cmd, sizeof cmd);
                    883:                        IfStatus = do_if(cmd) ? IF_TRUE : IF_FALSE;
                    884:                        continue;
                    885:                } else if (casencmp(lbuf, "else", 4) == 0) {
                    886:                        if (IfStatus == IF_UNBOUND)
                    887:                                complain("[Unexpected `else']");
                    888:                        IfStatus = !IfStatus;
                    889:                        continue;
                    890:                } else if (casencmp(lbuf, "endif", 5) == 0) {
                    891:                        if (IfStatus == IF_UNBOUND)
                    892:                                complain("[Unexpected `endif']");
                    893:                        IfStatus = IF_UNBOUND;
                    894:                        continue;
                    895:                }
                    896:                if (IfStatus == IF_FALSE)
                    897:                        continue;
                    898:                (void) strcat(lbuf, "\n");
                    899:                Inputp = lbuf;
                    900:                while (*Inputp == ' ' || *Inputp == '\t')
                    901:                        Inputp++;       /* skip white space */
                    902:                Extend();
                    903:        } while (!eof);
                    904: 
                    905:        f_close(fp);
                    906:        pop_env(savejmp);
                    907:        Inputp = 0;
                    908:        Asking = 0;
                    909:        InJoverc = 0;
                    910:        if (IfStatus != IF_UNBOUND)
                    911:                complain("[Missing endif]");
                    912:        return !NIL;
                    913: }

unix.superglobalmegacorp.com

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