Annotation of 43BSDTahoe/new/B/src/bed/sugg.c, revision 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.