# 2.11BSD#431 - /usr/src/new/jove/extend.c

##### Functions

    Apropos           X
    BindAKey          X
    BindMac           X
    BindSomething     X
    BindWMap          X
    BufPos            X
    CAutoExec         X
    DefAutoExec       X
    DescBindings      X
    DescCom           X
    DescMap           X
    DescWMap          X
    DoAutoExec        X
    Extend            X
    IsPrefix          X
    KeyDesc           X
    MAutoExec         X
    PrVar             X
    SetVar            X
    Source            X
    UnbindC           X
    addgetc           X
    ask_int           X
    aux_complete      X
    chr_to_int        X
    complete          X
    do_if             X
    fb_aux            X
    find_binds        X
    joverc            X
    match             X
    vpr_aux           X

##### Variables

    ExecIndex         X
    InJoverc          X
    Possible          X
    comp_flags        X
    comp_value        X
    private           X

##### Macros

    IF_FALSE          X
    IF_TRUE           X
    IF_UNBOUND        X
    NEXECS            X
    private           X

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

#### Defined functions

Apropos defined in line 463; used 4 times

- in /usr/src/new/jove/externs.h line 187, 795
- in /usr/src/new/jove/funcdefs.c line 23, 281

BindAKey defined in line 130; used 4 times

- in /usr/src/new/jove/externs.h line 194, 802
- in /usr/src/new/jove/funcdefs.c line 35, 297

BindMac defined in line 136; used 4 times

- in /usr/src/new/jove/externs.h line 195, 803
- in /usr/src/new/jove/funcdefs.c line 36, 298

BindSomething defined in line 246; used 4 times

- in line 133, 139
- in /usr/src/new/jove/externs.h line 197, 805

BindWMap defined in line 216; used 4 times

- in line 231, 259
- in /usr/src/new/jove/externs.h line 198, 806

BufPos defined in line 891; used 4 times

- in /usr/src/new/jove/externs.h line 216, 824
- in /usr/src/new/jove/funcdefs.c line 37, 302

CAutoExec defined in line 67; used 4 times

- in /usr/src/new/jove/externs.h line 218, 826
- in /usr/src/new/jove/funcdefs.c line 239, 282

DefAutoExec defined in line 83; used 4 times

- in line 70, 78
- in /usr/src/new/jove/externs.h line 234, 842

DescBindings defined in line 353; used 4 times

- in /usr/src/new/jove/externs.h line 248, 856
- in /usr/src/new/jove/funcdefs.c line 93, 343

DescCom defined in line 286; used 5 times

- in /usr/src/new/jove/externs.h line 249, 857
- in /usr/src/new/jove/funcdefs.c line 94, 344-346(2)

DescMap defined in line 365; used 4 times

- in line 359, 395
- in /usr/src/new/jove/externs.h line 250, 858

DescWMap defined in line 264; used 4 times

- in line 274, 283
- in /usr/src/new/jove/externs.h line 251, 859

DoAutoExec defined in line 115; used 3 times

- in /usr/src/new/jove/buf.c line 600
- in /usr/src/new/jove/externs.h line 263, 871

Extend defined in line 520; used 5 times

- in line 1047
- in /usr/src/new/jove/externs.h line 283, 891
- in /usr/src/new/jove/funcdefs.c line 103, 383

IsPrefix defined in line 146; used 9 times

- in line 178, 230, 273, 394, 455
- in /usr/src/new/jove/externs.h line 137, 745
- in /usr/src/new/jove/iproc.c line 398
- in /usr/src/new/jove/macros.c line 352

KeyDesc defined in line 279; used 4 times

- in /usr/src/new/jove/externs.h line 311, 919
- in /usr/src/new/jove/funcdefs.c line 81, 345

MAutoExec defined in line 75; used 4 times

- in /usr/src/new/jove/externs.h line 321, 929
- in /usr/src/new/jove/funcdefs.c line 240, 283

PrVar defined in line 605; used 4 times

- in /usr/src/new/jove/externs.h line 342, 950
- in /usr/src/new/jove/funcdefs.c line 212, 482

SetVar defined in line 617; used 4 times

- in /usr/src/new/jove/externs.h line 380, 988
- in /usr/src/new/jove/funcdefs.c line 186, 536

Source defined in line 872; used 4 times

- in /usr/src/new/jove/externs.h line 388, 996
- in /usr/src/new/jove/funcdefs.c line 195, 549

UnbindC defined in line 168; used 4 times

- in /usr/src/new/jove/externs.h line 406, 1014
- in /usr/src/new/jove/funcdefs.c line 16, 568

addgetc defined in line 187; used 8 times

- in line 224, 274, 283, 683
- in /usr/src/new/jove/externs.h line 63, 670
- in /usr/src/new/jove/iproc.c line 392
- in /usr/src/new/jove/mac.c line 1987

ask_int defined in line 563; used 6 times

- in line 633
- in /usr/src/new/jove/externs.h line 67, 674
- in /usr/src/new/jove/mac.c line 1963
- in /usr/src/new/jove/misc.c line 298, 305

aux_complete defined in line 709; used 3 times

- in line 833
- in /usr/src/new/jove/externs.h line 68, 675

chr_to_int defined in line 534; used 7 times

- in line 571
- in /usr/src/new/jove/buf.c line 499
- in /usr/src/new/jove/externs.h line 74, 681
- in /usr/src/new/jove/jove.c line 837, 853
- in /usr/src/new/jove/proc.c line 140

complete defined in line 826; used 6 times

- in /usr/src/new/jove/buf.c line 195
- in /usr/src/new/jove/externs.h line 75, 682
- in /usr/src/new/jove/funcdefs.c line 675
- in /usr/src/new/jove/macros.c line 416
- in /usr/src/new/jove/vars.c line 126

do_if defined in line 920; used 3 times

- in line 1027
- in /usr/src/new/jove/externs.h line 76, 683

fb_aux defined in line 415; used 4 times

- in line 33-38(2), 409, 457

find_binds defined in line 401; used 5 times

- in line 34-39(2), 334, 483, 511

joverc defined in line 982; used 6 times

- in line 887
- in /usr/src/new/jove/externs.h line 97, 704
- in /usr/src/new/jove/jove.c line 1246-1252(3)

match defined in line 837; used 3 times

- in line 734
- in /usr/src/new/jove/externs.h line 104, 711

vpr_aux defined in line 576; used 4 times

- in line 35-40(2), 499, 613

#### Defined variables

ExecIndex defined in line 63; used 6 times

- in line 95, 101-107(4), 123

InJoverc defined in line 49; used 7 times

- in line 192, 747, 780, 806, 1002, 1054
- in /usr/src/new/jove/macros.c line 325

Possible defined in line 705; used 12 times

- in line 734, 761-773(6), 798, 813-815(3), 831

comp_flags defined in line 707; used 3 times

- in line 716, 743, 832

comp_value defined in line 706; used 6 times

- in line 729, 736-744(3), 795, 834

private defined in line 705; never used

#### Defined macros

IF_FALSE defined in line 917; used 2 times

- in line 1027, 1041

IF_TRUE defined in line 916; used 2 times

- in line 917, 1027

IF_UNBOUND defined in line 915; used 6 times

- in line 991, 1022, 1030-1037(3), 1055

NEXECS defined in line 56; used 3 times

- in line 61, 95-96(2)

private defined in line 45; used 10 times

- in line 27-37(3), 44, 58-63(2), 401, 415, 576, 706

Last modified: 1988-08-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2816 |