Annotation of 43BSD/contrib/B/src/bed/sugg.c, revision 1.1.1.1

1.1       root        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

unix.superglobalmegacorp.com

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