Annotation of 43BSD/contrib/jove/extend.c, revision 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.