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

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
                      2: static char rcsid[] = "$Header: que2.c,v 2.3 84/07/23 13:02:38 guido Exp $";
                      3: 
                      4: /*
                      5:  * B editor -- Manipulate queues of nodes, higher levels.
                      6:  */
                      7: 
                      8: #include <ctype.h>
                      9: 
                     10: #include "b.h"
                     11: #include "feat.h"
                     12: #include "bobj.h"
                     13: #include "node.h"
                     14: #include "supr.h"
                     15: #include "queu.h"
                     16: #include "gram.h"
                     17: #include "tabl.h"
                     18: 
                     19: 
                     20: extern bool lefttorite;
                     21:        /* Set by edit() to signal we parse purely left-to-right */
                     22: extern bool dflag; /* Debug mode even if NDEBUG on */
                     23: 
                     24: 
                     25: /*
                     26:  * Insert a queue of nodes at the focus
                     27:  * (which had better be some kind of a hole).
                     28:  * The nodes may also be a text, in which case the individual characters
                     29:  * are inserted.
                     30:  * Extensive changes to the parse tree may occur, and the node may be
                     31:  * broken up in its constituent parts (texts and other nodes) which
                     32:  * are then inserted individually.
                     33:  */
                     34: 
                     35: Visible bool
                     36: ins_queue(ep, pq, pq2)
                     37:        register environ *ep;
                     38:        register queue *pq;
                     39:        register queue *pq2;
                     40: {
                     41:        register bool ok = Yes;
                     42:        register node n;
                     43:        register queue oldq2;
                     44:        environ saveenv;
                     45:        int oldindentation = focindent(ep);
                     46:        int indentation = oldindentation;
                     47: 
                     48:        leftvhole(ep);
                     49:        while (ok && !emptyqueue(*pq)) {
                     50:                n = queuebehead(pq);
                     51:                if (Type(n) == Tex) {
                     52:                        ok = ins_string(ep, Str((value) n), pq2, 0);
                     53:                        switch (Str((value) n)[Length((value) n) - 1]) { /* Last char */
                     54:                        case '\t':
                     55:                                ++indentation;
                     56:                                break;
                     57:                        case '\b':
                     58:                                --indentation;
                     59:                                break;
                     60:                        case '\n':
                     61:                                while (focindent(ep) > indentation) {
                     62:                                        if (!ins_newline(ep))
                     63:                                                break;
                     64:                                }
                     65:                                break;
                     66:                        }
                     67:                }
                     68:                else {
                     69:                        Ecopy(*ep, saveenv);
                     70:                        oldq2 = qcopy(*pq2);
                     71:                        if (!ins_node(&saveenv, n, pq2)) {
                     72:                                Erelease(saveenv);
                     73:                                qrelease(*pq2);
                     74:                                *pq2 = oldq2;
                     75:                                if (symbol(n) == Hole)
                     76:                                        ok = ins_string(ep, "?", pq2, 0);
                     77:                                else
                     78:                                        splitnode(n, pq);
                     79:                        }
                     80:                        else {
                     81:                                Erelease(*ep);
                     82:                                Emove(saveenv, *ep);
                     83:                                qrelease(oldq2);
                     84:                        }
                     85:                }
                     86:                noderelease(n);
                     87:        }
                     88:        if (!ok)
                     89:                qshow(*pq, "ins_queue");
                     90:        qrelease(*pq);
                     91:        for (indentation = focindent(ep);
                     92:                indentation > oldindentation; --indentation)
                     93:                stringtoqueue("\b", pq2); /* Pass on indentation to outer level */
                     94:        return ok;
                     95: }
                     96: 
                     97: 
                     98: /*
                     99:  * Subroutine to insert a queue to the right of the focus
                    100:  * without affecting the focus position.
                    101:  */
                    102: 
                    103: Visible bool
                    104: app_queue(ep, pq)
                    105:        environ *ep;
                    106:        queue *pq;
                    107: {
                    108:        int where;
                    109:        static int markbit = 1; /* To properly handle recursive calls */
                    110: 
                    111:        if (emptyqueue(*pq))
                    112:                return Yes;
                    113:        where = focoffset(ep);
                    114:        markbit <<= 1;
                    115:        markpath(&ep->focus, markbit);
                    116:        if (!ins_queue(ep, pq, pq)) {
                    117:                markbit >>= 1;
                    118:                return No;
                    119:        }
                    120:        firstmarked(&ep->focus, markbit) || Abort();
                    121:        unmkpath(&ep->focus, markbit);
                    122:        markbit >>= 1;
                    123:        ep->spflag = No;
                    124:        fixfocus(ep, where);
                    125:        return Yes;
                    126: }
                    127: 
                    128: 
                    129: /*
                    130:  * Advance to next thing after current position.
                    131:  */
                    132: 
                    133: Visible bool
                    134: move_on(ep)
                    135:        register environ *ep;
                    136: {
                    137:        register node n;
                    138:        register string *rp;
                    139:        register int sym;
                    140:        register int ich = ichild(ep->focus);
                    141: 
                    142:        if (!up(&ep->focus))
                    143:                return No;
                    144:        higher(ep);
                    145:        n = tree(ep->focus);
                    146:        rp = noderepr(n);
                    147:        if (Fw_positive(rp[ich])) {
                    148:                ep->mode = FHOLE;
                    149:                ep->s1 = 2*ich + 1;
                    150:                ep->s2 = 0;
                    151:                if (ep->spflag) {
                    152:                        ep->spflag = No;
                    153:                        if (rp[ich][0] == ' ') {
                    154:                                ++ep->s2;
                    155:                                if (fwidth(rp[ich]) > 1)
                    156:                                        return Yes;
                    157:                        }
                    158:                        else
                    159:                                return Yes;
                    160:                }
                    161:                else
                    162:                        return Yes;
                    163:        }
                    164:        if (ich < nchildren(n)) {
                    165:                s_downi(ep, ich+1);
                    166:                sym = symbol(tree(ep->focus));
                    167:                if (sym == Hole || sym == Optional)
                    168:                        ep->mode = WHOLE;
                    169:                else
                    170:                        ep->mode = ATBEGIN;
                    171:                return Yes;
                    172:        }
                    173:        ep->mode = ATEND;
                    174:        return Yes;
                    175: }
                    176: 
                    177: 
                    178: /*
                    179:  * Like move_on but moves through fixed texts, skipping only spaces
                    180:  * and empty strings.
                    181:  * <<<<< This code is a dinosaur and should be revised. >>>>>
                    182:  */
                    183: 
                    184: Visible bool
                    185: fix_move(ep)
                    186:        register environ *ep;
                    187: {
                    188:        register int ich;
                    189:        register int i;
                    190:        register string *rp;
                    191:        register string cp;
                    192: 
                    193:        Assert(ep->mode == FHOLE);
                    194: 
                    195:        ich = ep->s1/2;
                    196:        rp = noderepr(tree(ep->focus));
                    197:        cp = rp[ich];
                    198:        if (cp) {
                    199:                i = ep->s2;
                    200:                Assert(i <= Fwidth(cp));
                    201:                if (cp[i] == ' ') {
                    202:                        do {
                    203:                                ++i;
                    204:                        } while (cp[i] == ' ');
                    205:                }
                    206:                if (cp[i] == '\b' || cp[i] == '\t') {
                    207:                        ++i;
                    208:                        Assert(!cp[i]);
                    209:                }
                    210:                else if (cp[i]) {
                    211:                        if (i == ep->s2)
                    212:                                return No;
                    213:                        ep->s2 = i;
                    214:                        return Yes;
                    215:                }
                    216:        }
                    217: 
                    218:        if (ich >= nchildren(tree(ep->focus)))
                    219:                ep->mode = ATEND;
                    220:        else {
                    221:                s_downi(ep, ich+1);
                    222:                if (symbol(tree(ep->focus)) == Hole
                    223:                        || symbol(tree(ep->focus)) == Optional)
                    224:                        ep->mode = WHOLE;
                    225:                else
                    226:                        ep->mode = ATBEGIN;
                    227:        }
                    228:        return Yes;
                    229: }
                    230: 
                    231: 
                    232: /*
                    233:  * Insert a node in the parse tree.
                    234:  */
                    235: 
                    236: Hidden bool
                    237: ins_node(ep, n, pq)
                    238:        register environ *ep;
                    239:        register node n;
                    240:        register queue *pq;
                    241: {
                    242:        register int sym;
                    243:        register node nn;
                    244:        register markbits x;
                    245:        string *rp;
                    246: 
                    247:        if (symbol(n) == Optional)
                    248:                return Yes;
                    249: 
                    250:        for (;;) {
                    251:                switch (ep->mode) {
                    252: 
                    253:                case FHOLE:
                    254:                        if (ep->s2 < lenitem(ep) || !fix_move(ep))
                    255:                                return No;
                    256:                        continue;
                    257: 
                    258:                case VHOLE:
                    259:                        if (ep->s2 < lenitem(ep) || !move_on(ep))
                    260:                                return No;
                    261:                        continue;
                    262: 
                    263:                case ATBEGIN:
                    264:                        sym = symbol(tree(ep->focus));
                    265:                        if (sym == Optional || sym == Hole) {
                    266:                                ep->mode = WHOLE;
                    267:                                continue;
                    268:                        }
                    269:                        x = marks(tree(ep->focus));
                    270:                        if (joinnodes(&ep->focus, n, tree(ep->focus), No)) {
                    271:                                if (x) {
                    272:                                        s_downi(ep, 2);
                    273:                                        markpath(&ep->focus, x);
                    274:                                        s_up(ep);
                    275:                                }
                    276:                                s_down(ep);
                    277:                                ep->mode = ATEND;
                    278:                                leftvhole(ep);
                    279:                                return Yes;
                    280:                        }
                    281:                        nn = tree(ep->focus);
                    282:                        rp = noderepr(nn);
                    283:                        if (nchildren(nn) >= 1 && Fw_zero(rp[0])) {
                    284:                                sym = symbol(firstchild(nn));
                    285:                                if (sym == Hole || sym == Optional) {
                    286:                                        s_down(ep);
                    287:                                        if (fitnode(&ep->focus, n)) {
                    288:                                                ep->mode = ATEND;
                    289:                                                leftvhole(ep);
                    290:                                                return Yes;
                    291:                                        }
                    292:                                        s_up(ep);
                    293:                                }
                    294:                        }
                    295:                        nn = nodecopy(nn);
                    296:                        if (!fitnode(&ep->focus, n)) {
                    297:                                addtoqueue(pq, nn);
                    298:                                noderelease(nn);
                    299:                                delfocus(&ep->focus);
                    300:                                ep->mode = WHOLE;
                    301:                                continue;
                    302:                        }
                    303:                        if (downrite(&ep->focus)) {
                    304:                                if (Type(tree(ep->focus)) != Tex) {
                    305:                                        sym = symbol(tree(ep->focus));
                    306:                                        if (sym == Hole || sym == Optional) {
                    307:                                                if (fitnode(&ep->focus, nn)) {
                    308:                                                        noderelease(nn);
                    309:                                                        nn = Nnil;
                    310:                                                }
                    311:                                        }
                    312:                                }
                    313:                                else
                    314:                                        up(&ep->focus);
                    315:                        }
                    316:                        if (nn) {
                    317:                                addtoqueue(pq, nn);
                    318:                                noderelease(nn);
                    319:                        }
                    320:                        ep->mode = ATEND;
                    321:                        leftvhole(ep);
                    322:                        return Yes;
                    323: 
                    324:                case WHOLE:
                    325:                        sym = symbol(tree(ep->focus));
                    326:                        Assert(sym == Optional || sym == Hole);
                    327:                        do {
                    328:                                higher(ep); /* Only for second time around */
                    329:                                if (fitnode(&ep->focus, n)) {
                    330:                                        ep->mode = ATEND;
                    331:                                        leftvhole(ep);
                    332:                                        return Yes;
                    333:                                }
                    334:                        } while (resttoqueue(&ep->focus, pq));
                    335:                        ep->mode = ATEND;
                    336:                        /* Fall through */
                    337:                case ATEND:
                    338:                        do {
                    339:                                higher(ep); /* Only for second time around */
                    340:                                if (joinnodes(&ep->focus, tree(ep->focus), n, ep->spflag)) {
                    341:                                        ep->spflag = No;
                    342:                                        leftvhole(ep);
                    343:                                        return Yes;
                    344:                                }
                    345:                        } while (resttoqueue(&ep->focus, pq)
                    346:                                || move_on(ep) && ep->mode == ATEND);
                    347:                        return No;
                    348: 
                    349:                default:
                    350:                        return No;
                    351: 
                    352:                }
                    353:        }
                    354: }
                    355: 
                    356: 
                    357: /*
                    358:  * Insert a string in the parse tree.
                    359:  */
                    360: 
                    361: #define NEXT (++str, alt_c = 0)
                    362: 
                    363: Visible bool
                    364: ins_string(ep, str, pq, alt_c)
                    365:        register environ *ep;
                    366:        /*auto*/ string str;
                    367:        register queue *pq;
                    368:        int alt_c;
                    369: {
                    370:        register node nn;
                    371:        auto value v;
                    372:        char buf[1024];
                    373:        register string repr;
                    374:        string oldstr;
                    375:        register int sym;
                    376:        register int len;
                    377:        bool interactive = alt_c != 0;
                    378: 
                    379:        if (alt_c < 0)
                    380:                alt_c = 0;
                    381:        while (*str) {
                    382:                switch (*str) {
                    383: 
                    384:                case '\n':
                    385:                        if (!ins_newline(ep))
                    386:                                return No;
                    387:                        /* Fall through */
                    388:                case '\t':
                    389:                case '\b':
                    390:                        NEXT;
                    391:                        continue;
                    392: 
                    393:                }
                    394:                switch (ep->mode) {
                    395: 
                    396:                case ATBEGIN:
                    397:                        nn = tree(ep->focus);
                    398:                        if (Type(nn) == Tex) {
                    399:                                ep->s1 = 2*ichild(ep->focus);
                    400:                                ep->s2 = 0;
                    401:                                ep->mode = VHOLE;
                    402:                                s_up(ep);
                    403:                                continue;
                    404:                        }
                    405:                        sym = symbol(nn);
                    406:                        if (sym != Optional && sym != Hole) {
                    407:                                if (fwidth(noderepr(nn)[0]) == 0) {
                    408:                                        if (down(&ep->focus))
                    409:                                                break;
                    410:                                }
                    411:                                addtoqueue(pq, nn);
                    412:                                delfocus(&ep->focus);
                    413:                        }
                    414:                        ep->mode = WHOLE;
                    415:                        /* Fall through */
                    416:                case WHOLE:
                    417:                        nn = tree(ep->focus);
                    418:                        sym = symbol(nn);
                    419:                        Assert(sym == Hole || sym == Optional);
                    420:                        while ((len = fitstring(&ep->focus, str, alt_c)) == 0) {
                    421:                                if (sym == Optional) {
                    422:                                        if (!move_on(ep)) {
                    423:                                                if (*str == ' ')
                    424:                                                        NEXT;
                    425:                                                else
                    426:                                                        return No;
                    427:                                        }
                    428:                                        break;
                    429:                                }
                    430:                                if (!interactive && *str == '?') {
                    431:                                        NEXT;
                    432:                                        ep->mode = ATEND;
                    433:                                        break;
                    434:                                }
                    435:                                if (resttoqueue(&ep->focus, pq))
                    436:                                        higher(ep);
                    437:                                else if (spacefix(ep))
                    438:                                        break;
                    439:                                else if (*str == ' ') {
                    440:                                        NEXT;
                    441:                                        break;
                    442:                                }
                    443:                                else if (interactive)
                    444:                                        return No;
                    445:                                else {
                    446:                                        ep->mode = ATEND;
                    447:                                        break;
                    448:                                }
                    449:                        }
                    450:                        if (len > 0) {
                    451:                                str += len;
                    452:                                alt_c = 0;
                    453:                                fixfocus(ep, len);
                    454:                        }
                    455:                        break;
                    456: 
                    457:                case ATEND:
                    458:                        if (add_string(ep, &str, alt_c)) {
                    459:                                alt_c = 0;
                    460:                                break;
                    461:                        }
                    462:                        len = joinstring(&ep->focus, str, ep->spflag,
                    463:                                alt_c ? alt_c : interactive ? -1 : 0, Yes);
                    464:                        if (len > 0) {
                    465:                                s_downi(ep, 2);
                    466:                                ep->spflag = No;
                    467:                                fixfocus(ep, len);
                    468:                        }
                    469:                        else {
                    470:                                if (resttoqueue(&ep->focus, pq)) {
                    471:                                        higher(ep);
                    472:                                        break;
                    473:                                }
                    474:                                if (move_on(ep))
                    475:                                        break;
                    476:                                if (*str == ' ') {
                    477:                                        NEXT;
                    478:                                        break;
                    479:                                }
                    480:                                return No;
                    481:                        }
                    482:                        str += len;
                    483:                        alt_c = 0;
                    484:                        break;
                    485: 
                    486:                case FHOLE:
                    487:                        nn = tree(ep->focus);
                    488:                        repr = noderepr(nn)[ep->s1/2];
                    489:                        if (ep->s2 >= fwidth(repr)
                    490:                                && (ep->s2 <= 0 || ep->spflag || !isalpha(repr[0])
                    491:                                        || repr[ep->s2-1] == ' ')) { /* At end */
                    492:                                if (ep->s1/2 < nchildren(nn)) {
                    493:                                        s_downi(ep, ep->s1/2 + 1);
                    494:                                        ep->mode = ATBEGIN; /* Of next child */
                    495:                                }
                    496:                                else
                    497:                                        ep->mode = ATEND;
                    498:                                break;
                    499:                        }
                    500:                        if ((*str == ':' || *str == ' ') && *str == repr[ep->s2]) {
                    501:                                /*****
                    502:                                 * Quick hack for insertion of test-suites and refinements:
                    503:                                 *****/
                    504:                                ++ep->s2;
                    505:                                NEXT;
                    506:                                continue;
                    507:                        }
                    508:                        if (!lefttorite)
                    509:                                nosuggtoqueue(ep, pq);
                    510:                        oldstr = str;
                    511:                        if (resuggest(ep, &str, alt_c) || soften(ep, &str, alt_c)) {
                    512:                                if (str > oldstr)
                    513:                                        alt_c = 0;
                    514:                                continue;
                    515:                        }
                    516:                        if (fix_move(ep))
                    517:                                continue;
                    518:                        return No;
                    519: 
                    520:                case VHOLE:
                    521:                        Assert(!(ep->s1&1));
                    522:                        nn = tree(ep->focus);
                    523: #ifdef USERSUGG
                    524:                        if (symbol(nn) == Suggestion) {
                    525:                                if (newsugg(ep, &str, alt_c))
                    526:                                        alt_c = 0;
                    527:                                else
                    528:                                        killsugg(ep);
                    529:                                continue;
                    530:                        }
                    531: #endif USERSUGG
                    532:                        s_downi(ep, ep->s1/2);
                    533:                        v = copy((value) tree(ep->focus));
                    534:                        len = 0;
                    535:                        if (!ep->spflag) {
                    536:                                for (; len < sizeof buf - 1 && str[len]
                    537:                                                && mayinsert(nn, ep->s1/2, !!(ep->s2 + len),
                    538:                                                        str[len]);
                    539:                                        ++len) {
                    540:                                        buf[len] = str[len];
                    541:                                }
                    542:                                if (len <= 0 && alt_c
                    543:                                        && mayinsert(nn, ep->s1/2, !!(ep->s2 + len), alt_c)) {
                    544:                                        buf[0] = alt_c;
                    545:                                        len = 1;
                    546:                                }
                    547:                        }
                    548:                        if (len > 0) { /* Effectuate change */
                    549:                                str += len;
                    550:                                alt_c = 0;
                    551:                                Assert(Type(v) == Tex);
                    552:                                buf[len] = 0;
                    553:                                putintrim(&v, ep->s2, Length(v) - ep->s2, buf);
                    554:                                replace(&ep->focus, (node) v);
                    555:                                s_up(ep);
                    556:                                ep->spflag = No;
                    557:                                ep->s2 += len;
                    558:                        }
                    559:                        else { /* Nothing inserted */
                    560:                                if (ep->s2 == 0) { /* Whole string rejected */
                    561:                                        addtoqueue(pq, (node)v);
                    562:                                        release(v);
                    563:                                        s_up(ep);
                    564:                                        delfocus(&ep->focus);
                    565:                                        ep->mode = WHOLE;
                    566:                                        break;
                    567:                                }
                    568:                                if (ep->s2 < Length(v)) {
                    569:                                        addstringtoqueue(pq, Str(v) + ep->s2);
                    570:                                        putintrim(&v, ep->s2, 0, "");
                    571:                                        replace(&ep->focus, (node) v);
                    572:                                }
                    573:                                else
                    574:                                        release(v);
                    575:                                move_on(ep) || Abort(); /* ==> up, cancelling s_downi! */
                    576:                        }
                    577:                        break;
                    578: 
                    579:                default:
                    580:                        Abort();
                    581: 
                    582:                }
                    583:        }
                    584: 
                    585:        return Yes;
                    586: }
                    587: 
                    588: 
                    589: /*
                    590:  * See if two nodes can be joined in a hole.
                    591:  * 'Spflag' indicates whether a space must be present between the nodes
                    592:  * (required or forbidden).
                    593:  * Either of n1, n2 may actually be the current contents of the hole.
                    594:  */
                    595: 
                    596: Hidden bool
                    597: joinnodes(pp, n1, n2, spflag)
                    598:        path *pp;
                    599:        node n1;
                    600:        node n2;
                    601:        bool spflag;
                    602: {
                    603:        path pa = parent(*pp);
                    604:        int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
                    605:        struct table *tp = &table[sympa];
                    606:        struct classinfo *ci = tp->r_class[ichild(*pp) - 1];
                    607:        classptr cp = ci->c_join;
                    608:        int sym1 = symbol(n1);
                    609:        int sym2 = symbol(n2);
                    610:        int symcp;
                    611:        int symfound = -1;
                    612: 
                    613:        if (!cp)
                    614:                return No;
                    615:        for (; *cp; cp += 2) {
                    616:                if (cp[0] != spflag + 1)
                    617:                        continue;
                    618:                symcp = cp[1];
                    619:                tp = &table[symcp];
                    620:                if (isinclass(sym1, tp->r_class[0])
                    621:                        && isinclass(sym2, tp->r_class[1])) {
                    622:                        symfound = symcp;
                    623:                        break;
                    624:                }
                    625:        }
                    626: 
                    627:        if (symfound < 0)
                    628:                return No;
                    629:        n1 = nodecopy(n1);
                    630:        n2 = nodecopy(n2); /* 'Cause one of them may overlap tree(*pp) */
                    631:        replace(pp, table[symfound].r_node);
                    632:        down(pp) || Abort();
                    633:        replace(pp, n1);
                    634:        rite(pp) || Abort();
                    635:        replace(pp, n2);
                    636:        up(pp) || Abort();
                    637:        return Yes;
                    638: }
                    639: 
                    640: 
                    641: /*
                    642:  * Try to join a node (implicit as tree(*pp)) with some text.
                    643:  * That is, try to replace the node by one with it as first child,
                    644:  * (some of) the text as second child, and nothing or a space in between.
                    645:  *
                    646:  * 'Spflag' indicates whether a space is desirable between the nodes
                    647:  * (but if No it is only used as advice).
                    648:  *
                    649:  * Returns the number of characters consumed from str.
                    650:  */
                    651: 
                    652: Visible int
                    653: joinstring(pp, str, spflag, alt_c, mayindent)
                    654:        path *pp;
                    655:        register string str;
                    656:        register bool spflag;
                    657:        int alt_c;
                    658:        bool mayindent;
                    659: {
                    660:        register struct table *tp;
                    661:        path pa = parent(*pp);
                    662:        node n1;
                    663:        struct classinfo *ci;
                    664:        register classptr cp;
                    665:        int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
                    666:        register int sym1;
                    667:        register int symcp;
                    668:        int symfound;
                    669:        int len;
                    670:        char buf[2];
                    671:        bool interactive = alt_c != 0;
                    672: 
                    673:        if (alt_c < 0)
                    674:                alt_c = 0;
                    675:        ci = table[sympa].r_class[ichild(*pp) - 1];
                    676:        Assert(ci);
                    677:        cp = ci->c_join;
                    678:        if (!cp)
                    679:                return 0;
                    680: 
                    681:        n1 = tree(*pp);
                    682:        sym1 = symbol(n1);
                    683:        symfound = -1;
                    684:        for (; *cp; cp += 2) {
                    685:                if (cp[0] < spflag + 1)
                    686:                        continue;
                    687:                symcp = cp[1];
                    688:                tp = &table[symcp];
                    689:                if (!mayindent && tp->r_repr[1] && index(tp->r_repr[1], '\t'))
                    690:                        continue;
                    691:                if (isinclass(sym1, tp->r_class[0])
                    692:                        && ((canfitchar(str[0], tp->r_class[1]))
                    693:                                || str[0] == '?' && !interactive)) {
                    694:                        if (cp[0] == spflag + 1) {
                    695:                                symfound = symcp;
                    696:                                break;
                    697:                        }
                    698:                        if (symfound < 0)
                    699:                                symfound = symcp;
                    700:                }
                    701:        }
                    702: 
                    703:        if (symfound < 0) { /* 1-level recursion */
                    704:                if (!alt_c)
                    705:                        return 0;
                    706:                buf[0] = alt_c;
                    707:                buf[1] = 0;
                    708:                return joinstring(pp, buf, spflag, 0, mayindent);
                    709:        }
                    710:        n1 = nodecopy(n1); /* 'Cause it overlaps tree(*pp) */
                    711:        replace(pp, table[symfound].r_node);
                    712:        down(pp) || Abort();
                    713:        replace(pp, n1);
                    714:        rite(pp) || Abort();
                    715:        len = fitstring(pp, str, 0);
                    716:        if (len == 0 && str[0] == '?')
                    717:                len = 1;
                    718:        Assert(len > 0); /* Disagreement between canfitchar and fitstring */
                    719:        up(pp) || Abort();
                    720:        return len;
                    721: }
                    722: 
                    723: 
                    724: /*
                    725:  * Similar to joinstring, but now the string must match the delimiter
                    726:  * rather than being acceptable as second child.
                    727:  * (Interface has changed to resemble resuggest/soften.)
                    728:  */
                    729: 
                    730: Hidden bool
                    731: add_string(ep, pstr, alt_c)
                    732:        environ *ep;
                    733:        string *pstr;
                    734:        int alt_c; /* Yet unused */
                    735: {
                    736:        register struct table *tp;
                    737:        path pa = parent(ep->focus);
                    738:        node n1;
                    739:        struct classinfo *ci;
                    740:        register classptr cp;
                    741:        int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
                    742:        register int sym1;
                    743:        register int symcp;
                    744:        register int c;
                    745: 
                    746:        ci = table[sympa].r_class[ichild(ep->focus) - 1];
                    747:        Assert(ci);
                    748:        cp = ci->c_append;
                    749:        if (!cp)
                    750:                return No;
                    751:        n1 = tree(ep->focus);
                    752:        sym1 = symbol(n1);
                    753:        c = **pstr;
                    754:        for (; *cp; cp += 2) {
                    755:                if ((*cp&0177) != c)
                    756:                        continue;
                    757:                symcp = cp[1];
                    758:                tp = &table[symcp];
                    759:                if (isinclass(sym1, tp->r_class[0]))
                    760:                        break;
                    761:        }
                    762:        if (!*cp)
                    763:                return No;
                    764:        ++*pstr;
                    765:        if (c == ' ') {
                    766:                ep->spflag = Yes;
                    767:                return Yes;
                    768:        }
                    769:        n1 = nodecopy(n1); /* 'Cause it overlaps tree(ep->focus) */
                    770:        replace(&ep->focus, table[symcp].r_node);
                    771:        s_down(ep);
                    772:        replace(&ep->focus, n1);
                    773:        s_up(ep);
                    774:        ep->mode = FHOLE;
                    775:        ep->s1 = 3;
                    776:        ep->s2 = (*cp&0200) ? 2 : 1;
                    777:        ep->spflag = No;
                    778:        return Yes;
                    779: }
                    780: 
                    781: 
                    782: /*
                    783:  * See whether a character may start a new node in a hole with given class.
                    784:  */
                    785: 
                    786: Visible bool
                    787: canfitchar(c, ci)
                    788:        int c;
                    789:        struct classinfo *ci;
                    790: {
                    791:        register classptr cp;
                    792:        register int code = Code(c);
                    793: 
                    794:        Assert(ci);
                    795:        cp = ci->c_insert;
                    796:        Assert(cp);
                    797:        for (; *cp; cp += 2) {
                    798:                if (cp[0] == code)
                    799:                        return Yes;
                    800:        }
                    801:        return No;
                    802: }
                    803: 
                    804: 
                    805: /*
                    806:  * Debug routine to print a queue.
                    807:  */
                    808: 
                    809: Visible Procedure
                    810: qshow(q, where)
                    811:        queue q;
                    812:        string where;
                    813: {
                    814: #ifndef NDEBUG
                    815:        node n;
                    816:        char buf[256];
                    817:        string cp;
                    818:        string sp;
                    819: 
                    820:        sprintf(buf, "%s:", where);
                    821:        cp = buf + strlen(buf);
                    822:        for (;q; q = q->q_link) {
                    823:                n = q->q_data;
                    824:                *cp++ = ' ';
                    825:                if (Type(n) == Tex) {
                    826:                        *cp++ = '"';
                    827:                        for (sp = Str((value) n); *sp; ++sp) {
                    828:                                if (isprint(*sp) || *sp == ' ') {
                    829:                                        *cp++ = *sp;
                    830:                                        if (*sp == '"')
                    831:                                                *cp++ = *sp;
                    832:                                }
                    833:                                else {
                    834:                                        sprintf(cp, "\\%03o", *sp&0377);
                    835:                                        cp += 4;
                    836:                                }
                    837:                        }
                    838:                        *cp++ = '"';
                    839:                }
                    840:                else {
                    841:                        strncpy(cp, table[symbol(n)].r_name, 80);
                    842:                        cp += strlen(cp);
                    843:                }
                    844:                if (cp >= buf+80) {
                    845:                        strcpy(buf+76, "...");
                    846:                        break;
                    847:                }
                    848:        }
                    849:        *cp = 0;
                    850:        debug(buf);
                    851: #endif NDEBUG
                    852: }

unix.superglobalmegacorp.com

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