Annotation of 43BSD/contrib/B/src/bed/que2.c, revision 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.