# 2.11BSD#431 - /usr/src/new/PORT/B/src/bed/sugg.c

##### Functions

    accsugg           X
    addsugg           X
    checksugg         X
    delsugg           X
    endsugg           X
    getpattern        X
    initsugg          X
    killsugg          X
    newsugg           X
    nextsugg          X
    readsugg          X
    setsugg           X
    subgetpattern     X
    writesugg         X

##### Variables

    ignorefirstcall   X
    lastsugg          X
    nbuiltin          X
    nsugg             X
    suggchanges       X

##### Macros

    MAXNSUGG          X
    SUGGFILE          X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
       2: static char rcsid[] = "$Header: sugg.c,v 2.4 84/10/26 12:10:51 guido Exp $";
       3:
       4: /*
       5:  * B editor -- New suggestion handling module.
       6:  */
       7:
       8: #include "feat.h"
       9:
      10: #ifdef USERSUGG
      11:
      12: #include "b.h"
      13: #include "bobj.h"
      14: #include "node.h"
      15: #include "supr.h"
      16: #include "gram.h"
      17: #include "queu.h"
      18:
      19: #include <ctype.h>
      20:
      21: extern bool dflag;
      22: extern bool edontop;
      23:
      24: extern bool lefttorite;
      25:
      26: #ifndef SUGGFILE
      27: #define SUGGFILE ".Bed_sugg"
      28: #endif
      29:
      30: #define MAXNSUGG 1000
      31:
      32: Hidden value sugg[MAXNSUGG];
      33: Hidden int nsugg;
      34: Hidden int nbuiltin;
      35: Hidden bool suggchanges;
      36: Hidden bool ignorefirstcall; /* Communication between killsugg and setsugg */
      37:
      38: /*
      39:  * Read the suggestion table from file.
      40:  */
      41:
      42: Visible Procedure
      43: initsugg()
      44: {
      45:     char buffer[1000];
      46:     register FILE *fp;
      47:     register c;
      48:
      49:     fp = fopen(SUGGFILE, "r");
      50:     if (!fp) {
      51:         if (dflag) {
      52:             fprintf(stderr, "*** No suggestion file: ");
      53:             perror(SUGGFILE);
      54:         }
      55:         return;
      56:     }
      57:     while (fgets(buffer, sizeof buffer, fp)) {
      58:         if (!index(buffer, '\n')) { /* Skip long line */
      59:             fprintf(stderr,
      60:                 "*** Excessively long suggestion ignored\n");
      61:             while ((c = getc(fp)) != '\n' && c != EOF)
      62:                 ;
      63:         }
      64:         else
      65:             addsugg(buffer, -1);
      66:     }
      67:     fclose(fp);
      68: }
      69:
      70:
      71: /*
      72:  * Make sure a line looks like a suggestion, return No if not.
      73:  * Replace the trailing newline or comment-sign by a zero byte.
      74:  * ***** Should check more thoroughly. *****
      75:  */
      76:
      77: Hidden bool
      78: checksugg(bp)
      79:     string bp;
      80: {
      81:     if (!isascii(*bp) || !isupper(*bp))
      82:         return No;
      83:     while (*bp && *bp != '\n' && *bp != '\\')
      84:         ++bp;
      85:     *bp = 0;
      86:     return Yes;
      87: }
      88:
      89:
      90: /*
      91:  * Procedure to add a suggestion to the suggestion table.
      92:  */
      93:
      94: Visible Procedure
      95: addsugg(str, builtin)
      96:     string str;
      97:     int builtin;
      98: {
      99:     int i;
     100:     int j;
     101:     int len;
     102:     int cmp;
     103:     string suggi;
     104:     int where = (builtin == -1) ? nsugg : nbuiltin;
     105:
     106:     if (!checksugg(str))
     107:         return;
     108:     for (len = 0; str[len] && str[len] != ' '; ++len)
     109:         ;
     110:     for (i = nsugg-1; i >= 0; --i) {
     111:         suggi = Str(sugg[i]);
     112:         cmp = strncmp(str, suggi, len);
     113:         if (cmp < 0)
     114:             continue;
     115:         if (cmp > 0) {
     116:             if (i >= where)
     117:                 where = i+1;
     118:             continue;
     119:         }
     120:         if (suggi[len] && suggi[len] != ' ')
     121:             continue; /* No match, just prefix */
     122:         if (Strequ(str+len, suggi+len))
     123:             return; /* Ignore exact duplicates */
     124:         if (i < nbuiltin)
     125:             return; /* Cannot replace built-in */
     126:         /* Replacement */
     127:         sugg[i] = mk_text(str); /* No use to release the old one... */
     128:                     /* ...its refcount is infinite */
     129:         fix(sugg[i]);
     130:         suggchanges = Yes;
     131:         return;
     132:     }
     133:     /* Insertion */
     134:     if (nsugg >= MAXNSUGG)
     135:         return; /* Table overflow */
     136:     if (builtin == Yes)
     137:         ++nbuiltin;
     138:     for (j = nsugg; j > where; --j)
     139:         sugg[j] = sugg[j-1];
     140:     ++nsugg;
     141:     sugg[where] = mk_text(str);
     142:     fix(sugg[where]);
     143:     suggchanges = Yes;
     144: }
     145:
     146:
     147: /*
     148:  * Procedure to delete a suggestion from the suggestion table.
     149:  * Must supply the whole string as argument.
     150:  */
     151:
     152: Hidden Procedure
     153: delsugg(str)
     154:     string str;
     155: {
     156:     int i;
     157:
     158:     for (i = 0; i < nsugg; ++i) {
     159:         if (Strequ(str, Str(sugg[i]))) {
     160:             --nsugg;
     161:             for (; i < nsugg; ++i)
     162:                 sugg[i] = sugg[i+1];
     163:             suggchanges = Yes;
     164:             return;
     165:         }
     166:     }
     167: }
     168:
     169:
     170: /*
     171:  * Return a suitable suggestion which matches str for len characters.
     172:  * If len > 1, and all of str (even beyond len) equals some table
     173:  * entry, the first matching entry after that is preferred; otherwise,
     174:  * the first matching entry at all is returned.
     175:  * Vnil is returned if no entry matches.
     176:  */
     177:
     178: Hidden node
     179: nextsugg(str, len)
     180:     string str;
     181:     int len;
     182: {
     183:     bool found = !str[len];
     184:     int first = -1;
     185:     int i;
     186:
     187:     for (i = 0; i < nsugg; ++i) {
     188:         if (!Strnequ(str, Str(sugg[i]), len))
     189:             continue;
     190:         if (found)
     191:             return (node) sugg[i];
     192:         if (Strequ(str+len, Str(sugg[i])+len))
     193:             found = Yes;
     194:         if (first < 0)
     195:             first = i;
     196:     }
     197:     if (first >= 0)
     198:         return (node) sugg[first];
     199:     return Nnil;
     200: }
     201:
     202:
     203: /*
     204:  * Procedure to save the suggestion file if it has been changed.
     205:  */
     206:
     207: Visible Procedure
     208: endsugg()
     209: {
     210:     FILE *fp;
     211:     int i;
     212:
     213:     if (!suggchanges)
     214:         return;
     215:     suggchanges = No;
     216:     fp = fopen(SUGGFILE, "w");
     217:     if (!fp) {
     218:         if (dflag) {
     219:             fprintf(stderr, "*** Can't rewrite ");
     220:             perror(SUGGFILE);
     221:         }
     222:         return;
     223:     }
     224:     if (dflag)
     225:         fprintf(stderr, "*** [Rewriting suggestion file]\n");
     226:     for (i = nbuiltin; i < nsugg; ++i)
     227:         fprintf(fp, "%s\n", Str(sugg[i]));
     228:     if (fclose(fp) == EOF) {
     229:         fprintf(stderr, "*** Can't finish writing ");
     230:         perror(SUGGFILE);
     231:         return;
     232:     }
     233: }
     234:
     235:
     236: /*
     237:  * Find a new suggestion or advance in the current one.
     238:  * Interface styled like resuggest: string pointer is advanced here.
     239:  */
     240:
     241: Visible bool
     242: newsugg(ep, pstr, alt_c)
     243:     environ *ep;
     244:     string *pstr;
     245:     int alt_c;
     246: {
     247:     char buffer[1000];
     248:     node n = tree(ep->focus);
     249:     node nn;
     250:     int sym = symbol(n);
     251:     string str;
     252:     string bp;
     253:     bool end;
     254:
     255:     Assert(pstr && *pstr);
     256:     if (sym != Suggestion || ep->mode != VHOLE || ep->s1 != 2)
     257:         return No;
     258:     strncpy(buffer, Str((value)firstchild(n)), sizeof buffer);
     259:     for (str = *pstr, bp = buffer+ep->s2, end = No;
     260:             *str && bp < buffer + sizeof buffer; ++str, ++bp) {
     261:         if (!*bp)
     262:             end = Yes;
     263:         *bp = *str;
     264:     }
     265:     if (end)
     266:         *bp = 0;
     267:     nn = (node)nextsugg(buffer, ep->s2 + 1);
     268:     if (!nn) {
     269:         if (!alt_c)
     270:             return No;
     271:         buffer[ep->s2] = alt_c;
     272:         nn = (node)nextsugg(buffer, ep->s2 + 1);
     273:         if (!nn)
     274:             return No;
     275:     }
     276:     if (nn != firstchild(n)) {
     277:         s_down(ep);
     278:         replace(&ep->focus, nn);
     279:         s_up(ep);
     280:     }
     281:     /* No need to release because its refcount is infinite anyway */
     282:     ++ep->s2;
     283:     if (**pstr == ' ')
     284:         accsugg(ep);
     285:     ++*pstr;
     286:     return Yes;
     287: }
     288:
     289:
     290: /*
     291:  * Kill suggestion -- only the part to the left of the focus is kept.
     292:  */
     293:
     294: Visible Procedure
     295: killsugg(ep)
     296:     environ *ep;
     297: {
     298:     queue q = Qnil;
     299:     char buffer[1000];
     300:     node n = tree(ep->focus);
     301:
     302:     Assert(ep->mode == VHOLE && ep->s1 == 2 && symbol(n) == Suggestion);
     303:     strncpy(buffer, Str((value)firstchild(n)), ep->s2);
     304:     buffer[ep->s2] = 0;
     305:     delfocus(&ep->focus);
     306:     ep->mode = WHOLE;
     307:     ignorefirstcall = Yes;
     308:     ins_string(ep, buffer, &q, 0);
     309:     qrelease(q);
     310:     ignorefirstcall = No;
     311: }
     312:
     313:
     314: /*
     315:  * Place an initial suggestion in a node.
     316:  */
     317:
     318: Visible bool
     319: setsugg(pp, c, ep)
     320:     path *pp;
     321:     char c;
     322:     environ *ep;
     323: {
     324:     char buf[2];
     325:     node n;
     326:
     327:     if (lefttorite)
     328:         return No;
     329:     if (ignorefirstcall) {
     330:         ignorefirstcall = No;
     331:         return No;
     332:     }
     333:     buf[0] = c;
     334:     buf[1] = 0;
     335:     n = (node)nextsugg(buf, 1);
     336:     if (!n)
     337:         return No;
     338:     replace(pp, newnode(1, Suggestion, &n));
     339:     ep->mode = VHOLE;
     340:     ep->s1 = 2;
     341:     ep->s2 = 1;
     342:     return Yes;
     343: }
     344:
     345:
     346: /*
     347:  * Accept a suggestion -- turn it into real nodes.
     348:  */
     349:
     350: Visible Procedure
     351: accsugg(ep)
     352:     environ *ep;
     353: {
     354:     node n = tree(ep->focus);
     355:     int s2 = ep->s2;
     356:     queue q = Qnil;
     357:     environ env;
     358:
     359:     Assert(symbol(n) == Suggestion && ep->mode == VHOLE && ep->s1 == 2);
     360:     stringtoqueue(Str((value)firstchild(n)) + s2, &q);
     361:     killsugg(ep);
     362:     Ecopy(*ep, env);
     363:     if (app_queue(ep, &q))
     364:         Erelease(env);
     365:     else {
     366:         Erelease(*ep);
     367:         Emove(env, *ep);
     368:         qrelease(q);
     369:     }
     370: }
     371:
     372:
     373: /*
     374:  * Procedure called when a unit is read in.
     375:  * It tries to update the suggestion database.
     376:  * It also remembers the suggestion so that it can be removed by writesugg
     377:  * if that finds the unit was deleted.
     378:  */
     379:
     380: Hidden char lastsugg[1000];
     381:
     382: Visible Procedure
     383: readsugg(p)
     384:     path p;
     385: {
     386:     p = pathcopy(p);
     387:     top(&p);
     388:     getpattern(lastsugg, tree(p));
     389:     pathrelease(p);
     390:     addsugg(lastsugg, No);
     391: }
     392:
     393:
     394: /*
     395:  * Procedure called when a unit is saved.
     396:  * It tries to update the suggestion database.
     397:  * If the unit appears empty, the last suggestion passed to readsugg
     398:  * will be deleted.
     399:  */
     400:
     401: Visible Procedure
     402: writesugg(p)
     403:     path p;
     404: {
     405:     p = pathcopy(p);
     406:     top(&p);
     407:     if (width(tree(p)) == 0)
     408:         delsugg(lastsugg);
     409:     else {
     410:         getpattern(lastsugg, tree(p));
     411:         if (lastsugg[0])
     412:             addsugg(lastsugg, No);
     413:     }
     414:     pathrelease(p);
     415: }
     416:
     417:
     418: /*
     419:  * Procedure to find out the suggestion that fits the current unit.
     420:  * Makes the buffer empty if not a HOW'TO unit.
     421:  * ***** Won't work if B-grammar is severely changed! *****
     422:  */
     423:
     424: Hidden Procedure
     425: getpattern(buffer, n)
     426:     string buffer;
     427:     node n;
     428: {
     429:     string *rp = noderepr(n);
     430:
     431:     buffer[0] = 0;
     432:     while (Fw_zero(rp[0])) {
     433:         if (nchildren(n) == 0)
     434:             return;
     435:         n = firstchild(n);
     436:         rp = noderepr(n);
     437:     }
     438:     if (!Strequ(rp[0], "HOW'TO ") || nchildren(n) < 1)
     439:         return;
     440:     subgetpattern(&buffer, firstchild(n));
     441:     *buffer = 0;
     442: }
     443:
     444:
     445: /*
     446:  * Refinement for getpattern to do the work.
     447:  */
     448:
     449: Hidden Procedure
     450: subgetpattern(pbuf, n)
     451:     string *pbuf;
     452:     node n;
     453: {
     454:     string *rp;
     455:     int i;
     456:     int nch;
     457:
     458:     rp = noderepr(n);
     459:     nch = (Type(n) == Tex) ? 0 : nchildren(n);
     460:     for (i = 0; i <= nch; ++i) {
     461:         if (i > 0)
     462:             subgetpattern(pbuf, child(n, i));
     463:         if (Fw_positive(rp[i])) {
     464:             if (islower(rp[i][0]))
     465:                 *(*pbuf)++ = '?';
     466:             else {
     467:                 strcpy(*pbuf, rp[i]);
     468:                 *pbuf += strlen(*pbuf);
     469:             }
     470:         }
     471:     }
     472: }
     473:
     474: #endif USERSUGG

#### Defined functions

accsugg defined in line 350; used 2 times

- in line 284
- in /usr/src/new/PORT/B/src/bed/demo.c line 484

addsugg defined in line 94; used 4 times

- in line 65, 390, 412
- in /usr/src/new/PORT/B/src/bed/gram.c line 243

checksugg defined in line 77; used 1 times

- in line 106

delsugg defined in line 152; used 1 times

- in line 408

endsugg defined in line 207; used 1 times

- in /usr/src/new/PORT/B/src/bed/main.c line 190

getpattern defined in line 424; used 2 times

- in line 388, 410

initsugg defined in line 42; used 1 times

- in /usr/src/new/PORT/B/src/bed/main.c line 165

killsugg defined in line 294; used 3 times

- in line 361
- in /usr/src/new/PORT/B/src/bed/demo.c line 485
- in /usr/src/new/PORT/B/src/bed/que2.c line 528

newsugg defined in line 241; used 1 times

- in /usr/src/new/PORT/B/src/bed/que2.c line 525

nextsugg defined in line 178; used 3 times

- in line 267-272(2), 335

readsugg defined in line 382; used 1 times

- in /usr/src/new/PORT/B/src/bed/demo.c line 243

setsugg defined in line 318; used 1 times

- in /usr/src/new/PORT/B/src/bed/inse.c line 42

subgetpattern defined in line 449; used 2 times

- in line 440, 462

writesugg defined in line 401; used 2 times

- in /usr/src/new/PORT/B/src/bed/demo.c line 254, 680

#### Defined variables

ignorefirstcall defined in line 36; used 4 times

- in line 307-310(2), 329-330(2)

lastsugg defined in line 380; used 6 times

- in line 388-390(2), 408-412(4)

nbuiltin defined in line 34; used 4 times

- in line 104, 124, 137, 226

nsugg defined in line 33; used 10 times

- in line 104, 110, 134-140(3), 158-161(3), 187, 226

rcsid defined in line 2; never used
suggchanges defined in line 35; used 5 times

- in line 130, 143, 163, 213-215(2)

#### Defined macros

MAXNSUGG defined in line 30; used 2 times

- in line 32, 134

SUGGFILE defined in line 27; used 6 times

- in line 26, 49-53(2), 216-220(2), 230

Last modified: 1985-08-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1397 |