Annotation of 43BSD/contrib/B/src/bed/node.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: node.c,v 2.4 85/08/22 16:05:27 timo Exp $";
        !             3: 
        !             4: /*
        !             5:  * B editor -- Parse tree and Focus stack.
        !             6:  */
        !             7: 
        !             8: #include "b.h"
        !             9: #include "bobj.h"
        !            10: 
        !            11: #include "node.h"
        !            12: 
        !            13: #define Register register
        !            14:        /* Used for registers 4-6.  Define as empty macro on PDP */
        !            15: 
        !            16: 
        !            17: /*
        !            18:  * Lowest level routines for 'node' data type.
        !            19:  */
        !            20: 
        !            21: #define Isnode(n) ((n) && (n)->type == Nod)
        !            22: 
        !            23: #define Nchildren(n) ((n)->len)
        !            24: #define Symbol(n) ((n)->n_symbol)
        !            25: #define Child(n, i) ((n)->n_child[(i)-1])
        !            26: #define Marks(n) ((n)->n_marks)
        !            27: #define Width(n) ((n)->n_width)
        !            28: 
        !            29: 
        !            30: /*
        !            31:  * Routines which are macros for the compiler but real functions for lint,
        !            32:  * so it will check the argument types more strictly.
        !            33:  */
        !            34: 
        !            35: #ifdef lint
        !            36: node
        !            37: nodecopy(n)
        !            38:        node n;
        !            39: {
        !            40:        return (node) copy((value) n);
        !            41: }
        !            42: 
        !            43: noderelease(n)
        !            44:        node n;
        !            45: {
        !            46:        release((value)n);
        !            47: }
        !            48: 
        !            49: nodeuniql(pn)
        !            50:        node *pn;
        !            51: {
        !            52:        uniql((value*)pn);
        !            53: }
        !            54: #endif lint
        !            55: 
        !            56: 
        !            57: /*
        !            58:  * Allocate a new node.
        !            59:  */
        !            60: 
        !            61: Visible node
        !            62: newnode(nch, sym, children)
        !            63:        register int nch;
        !            64:        Register int sym;
        !            65:        register node children[];
        !            66: {
        !            67:        register node n = (node) grab_node(nch); /* Must preset with zeros! */
        !            68: 
        !            69:        Symbol(n) = sym;
        !            70:        for (; nch > 0; --nch)
        !            71:                Child(n, nch) = children[nch-1];
        !            72:        Width(n) = evalwidth(n);
        !            73:        return n;
        !            74: }
        !            75: 
        !            76: 
        !            77: /*
        !            78:  * Macros to change the fields of a node.
        !            79:  */
        !            80: 
        !            81: #define Locchild(pn, i) \
        !            82:        (Refcnt(*(pn)) == 1 || nodeuniql(pn), &Child(*(pn), i))
        !            83: #define Setmarks(pn, x) \
        !            84:        (Refcnt(*(pn)) == 1 || nodeuniql(pn), Marks(*(pn))=(x))
        !            85: #define Setwidth(pn, w) (Refcnt(*(pn)) == 1 || nodeuniql(pn), Width(*(pn))=w)
        !            86: 
        !            87: 
        !            88: /*
        !            89:  * Change a child of a node.
        !            90:  * Like replace(), it does not increase the reference count of n.
        !            91:  */
        !            92: 
        !            93: Visible Procedure
        !            94: setchild(pn, i, n)
        !            95:        register node *pn;
        !            96:        register int i;
        !            97:        Register node n;
        !            98: {
        !            99:        register node *pch;
        !           100:        register node oldchild;
        !           101: 
        !           102:        Assert(Isnode(*pn));
        !           103:        pch = Locchild(pn, i);
        !           104:        oldchild = *pch;
        !           105:        *pch = n;
        !           106:        repwidth(pn, oldchild, n);
        !           107:        noderelease(oldchild);
        !           108: }
        !           109: 
        !           110: 
        !           111: /*
        !           112:  * Lowest level routines for 'path' data type.
        !           113:  */
        !           114: 
        !           115: #define NPATHFIELDS 6
        !           116: 
        !           117: #define Parent(p) ((p)->p_parent)
        !           118: #define Tree(p) ((p)->p_tree)
        !           119: #define Ichild(p) ((p)->p_ichild)
        !           120: #define Ycoord(p) ((p)->p_ycoord)
        !           121: #define Xcoord(p) ((p)->p_xcoord)
        !           122: #define Level(p) ((p)->p_level)
        !           123: 
        !           124: 
        !           125: /*
        !           126:  * Routines which are macros for the compiler but real functions for lint,
        !           127:  * so it will check the argument types more strictly.
        !           128:  */
        !           129: 
        !           130: #ifdef lint
        !           131: Visible path
        !           132: pathcopy(p)
        !           133:        path p;
        !           134: {
        !           135:        return (path) copy((value) p);
        !           136: }
        !           137: 
        !           138: Visible Procedure
        !           139: pathrelease(p)
        !           140:        path p;
        !           141: {
        !           142:        release((value)p);
        !           143: }
        !           144: 
        !           145: Visible Procedure
        !           146: pathuniql(pp)
        !           147:        path *pp;
        !           148: {
        !           149:        uniql((value*)pp);
        !           150: }
        !           151: #endif lint
        !           152: 
        !           153: 
        !           154: /*
        !           155:  * Allocate a new path entry.
        !           156:  */
        !           157: 
        !           158: Visible path
        !           159: newpath(pa, n, i)
        !           160:        register path pa;
        !           161:        register node n;
        !           162:        Register int i;
        !           163: {
        !           164:        register path p = (path) grab_path();
        !           165: 
        !           166:        Parent(p) = pa;
        !           167:        Tree(p) = n;
        !           168:        Ichild(p) = i;
        !           169:        Ycoord(p) = Xcoord(p) = Level(p) = 0;
        !           170:        return p;
        !           171: }
        !           172: 
        !           173: 
        !           174: /*
        !           175:  * Macros to change the fields of a path entry.
        !           176:  */
        !           177: 
        !           178: #define Uniqp(pp) (Refcnt(*(pp)) == 1 || pathuniql(pp))
        !           179: 
        !           180: #define Setcoord(pp, y, x, level) (Uniqp(pp), \
        !           181:        (*(pp))->p_ycoord = y, (*(pp))->p_xcoord = x, (*(pp))->p_level = level)
        !           182: 
        !           183: #define Locparent(pp) (Uniqp(pp), &Parent(*(pp)))
        !           184: 
        !           185: #define Loctree(pp) (Uniqp(pp), &Tree(*(pp)))
        !           186: 
        !           187: #define Addmarks(pp, x) (Uniqp(pp), \
        !           188:        (*(pp))->p_addmarks |= (x), (*(pp))->p_delmarks &= ~(x))
        !           189: 
        !           190: #define Delmarks(pp, x) (Uniqp(pp), \
        !           191:        (*(pp))->p_delmarks |= (x), (*(pp))->p_addmarks &= ~(x))
        !           192: 
        !           193: 
        !           194: Hidden Procedure
        !           195: connect(pp)
        !           196:        path *pp;
        !           197: {
        !           198:        register path p = *pp;
        !           199:        register path pa = Parent(p);
        !           200:        register path *ppa;
        !           201:        register node n;
        !           202:        register node npa;
        !           203:        register node *pn;
        !           204:        node oldchild;
        !           205:        node *pnpa;
        !           206:        int i;
        !           207:        markbits add;
        !           208:        markbits del;
        !           209: 
        !           210:        if (!pa)
        !           211:                return;
        !           212:        i = ichild(p);
        !           213:        n = Tree(p);
        !           214:        if (Child(Tree(pa), i) == n)
        !           215:                return; /* Still connected */
        !           216: 
        !           217:        n = nodecopy(n);
        !           218:        ppa = Locparent(pp);
        !           219:        pnpa = Loctree(ppa);
        !           220:        pn = Locchild(pnpa, i);
        !           221:        oldchild = *pn;
        !           222:        *pn = n;
        !           223:        repwidth(pnpa, oldchild, n);
        !           224:        noderelease(oldchild);
        !           225: 
        !           226:        add = p->p_addmarks;
        !           227:        del = p->p_delmarks;
        !           228:        if (add|del) {
        !           229:                p = *pp;
        !           230:                p->p_addmarks = 0;
        !           231:                p->p_delmarks = 0;
        !           232:                if (add)
        !           233:                        Addmarks(ppa, add);
        !           234:                npa = *pnpa;
        !           235:                if (del) {
        !           236:                        for (i = Nchildren(npa); i > 0; --i)
        !           237:                                if (i != ichild(p))
        !           238:                                        del &= ~marks(Child(npa, i));
        !           239:                        Delmarks(ppa, del);
        !           240:                }
        !           241:                Setmarks(pnpa, Marks(npa)&~del|add);
        !           242:        }
        !           243: }
        !           244: 
        !           245: 
        !           246: /*
        !           247:  * The following procedure sets the new width of node *pn when child
        !           248:  * oldchild is replaced by child newchild.
        !           249:  * This was added because the original call to evalwidth seemed to
        !           250:  * be the major caller of noderepr() and fwidth().
        !           251:  */
        !           252: 
        !           253: Hidden Procedure
        !           254: repwidth(pn, old, new)
        !           255:        register node *pn;
        !           256:        Register node old;
        !           257:        Register node new;
        !           258: {
        !           259:        register int w = Width(*pn);
        !           260:        register int oldwidth = width(old);
        !           261:        register int newwidth = width(new);
        !           262: 
        !           263:        if (w < 0) {
        !           264:                if (oldwidth > 0)
        !           265:                        oldwidth = 0;
        !           266:                if (newwidth > 0)
        !           267:                        newwidth = 0;
        !           268:        }
        !           269:        else {
        !           270:                Assert(oldwidth >= 0);
        !           271:                if (newwidth < 0) {
        !           272:                        Setwidth(pn, newwidth);
        !           273:                        return;
        !           274:                }
        !           275:        }
        !           276:        newwidth -= oldwidth;
        !           277:        if (newwidth)
        !           278:                Setwidth(pn, w + newwidth);
        !           279: }
        !           280: 
        !           281: 
        !           282: Visible Procedure
        !           283: markpath(pp, new)
        !           284:        register path *pp;
        !           285:        register markbits new;
        !           286: {
        !           287:        register node *pn;
        !           288:        register markbits old;
        !           289: 
        !           290:        Assert(Type(Tree(*pp)) == Nod);
        !           291:        old = Marks(Tree(*pp));
        !           292:        if ((old|new) == old)
        !           293:                return; /* Bits already set */
        !           294: 
        !           295:        pn = Loctree(pp);
        !           296:        Setmarks(pn, old|new);
        !           297:        Addmarks(pp, new&~old);
        !           298: }
        !           299: 
        !           300: 
        !           301: Visible Procedure
        !           302: unmkpath(pp, del)
        !           303:        register path *pp;
        !           304:        register int del;
        !           305: {
        !           306:        register node *pn;
        !           307:        register markbits old;
        !           308: 
        !           309:        Assert(Type(Tree(*pp)) == Nod);
        !           310:        old = Marks(Tree(*pp));
        !           311:        if ((old&~del) == del)
        !           312:                return;
        !           313: 
        !           314:        pn = Loctree(pp);
        !           315:        Setmarks(pn, old&~del);
        !           316:        Delmarks(pp, del&old);
        !           317: }
        !           318: 
        !           319: 
        !           320: Hidden Procedure
        !           321: clearmarks(pn)
        !           322:        register node *pn;
        !           323: {
        !           324:        register int i;
        !           325: 
        !           326:        if (!Marks(*pn))
        !           327:                return;
        !           328:        if (Isnode(*pn)) {
        !           329:                Setmarks(pn, 0);
        !           330:                for (i = Nchildren(*pn); i > 0; --i)
        !           331:                        clearmarks(Locchild(pn, i));
        !           332:        }
        !           333: }
        !           334: 
        !           335: 
        !           336: /*
        !           337:  * Replace the focus' tree by a new node.
        !           338:  * WARNING: n's reference count is not increased!
        !           339:  * You can also think of this as: replace(pp, n) implies noderelease(n).
        !           340:  * Mark bits are copied from the node being replaced.
        !           341:  */
        !           342: 
        !           343: Visible Procedure
        !           344: replace(pp, n)
        !           345:        register path *pp;
        !           346:        register node n;
        !           347: {
        !           348:        register node *pn;
        !           349:        register markbits old;
        !           350: 
        !           351:        pn = Loctree(pp);
        !           352:        if (Type(*pn) == Nod)
        !           353:                old = Marks(*pn);
        !           354:        else
        !           355:                old = 0;
        !           356:        noderelease(*pn);
        !           357:        *pn = n;
        !           358:        if (Type(n) == Nod) {
        !           359:                clearmarks(pn);
        !           360:                if (old)
        !           361:                        Setmarks(pn, old);
        !           362:        }
        !           363:        else if (old)
        !           364:                Addmarks(pp, old);
        !           365: }
        !           366: 
        !           367: 
        !           368: Visible bool
        !           369: up(pp)
        !           370:        register path *pp;
        !           371: {
        !           372:        register path p = *pp;
        !           373: 
        !           374:        if (!Parent(p))
        !           375:                return No;
        !           376: 
        !           377:        connect(pp);
        !           378:        p = pathcopy(Parent(*pp));
        !           379:        pathrelease(*pp);
        !           380:        *pp = p;
        !           381:        return Yes;
        !           382: }
        !           383: 
        !           384: 
        !           385: Visible bool
        !           386: downi(pp, i)
        !           387:        register path *pp;
        !           388:        register int i;
        !           389: {
        !           390:        register node n;
        !           391:        auto int y;
        !           392:        auto int x;
        !           393:        auto int level;
        !           394: 
        !           395:        n = Tree(*pp);
        !           396:        if (!Isnode(n) || i < 1 || i > Nchildren(n))
        !           397:                return No;
        !           398: 
        !           399:        y = Ycoord(*pp);
        !           400:        x = Xcoord(*pp);
        !           401:        level = Level(*pp);
        !           402:        *pp = newpath(*pp, nodecopy(Child(n, i)), i);
        !           403:        evalcoord(n, i, &y, &x, &level);
        !           404:        Setcoord(pp, y, x, level);
        !           405:        return Yes;
        !           406: }
        !           407: 
        !           408: 
        !           409: Visible bool
        !           410: downrite(pp)
        !           411:        register path *pp;
        !           412: {
        !           413:        if (!Isnode(Tree(*pp)))
        !           414:                return No;
        !           415:        return downi(pp, Nchildren(Tree(*pp)));
        !           416: }
        !           417: 
        !           418: 
        !           419: Visible bool
        !           420: left(pp)
        !           421:        register path *pp;
        !           422: {
        !           423:        register int i;
        !           424: 
        !           425:        i = ichild(*pp) - 1;
        !           426:        if (i <= 0)
        !           427:                return No;
        !           428:        if (!up(pp))
        !           429:                return No;
        !           430:        return downi(pp, i);
        !           431: }
        !           432: 
        !           433: 
        !           434: Visible bool
        !           435: rite(pp)
        !           436:        register path *pp;
        !           437: {
        !           438:        register int i;
        !           439:        register path pa = Parent(*pp);
        !           440: 
        !           441:        i = ichild(*pp) + 1;
        !           442:        if (!pa || i > Nchildren(Tree(pa)))
        !           443:                return No;
        !           444:        if (!up(pp))
        !           445:                return No;
        !           446:        return downi(pp, i);
        !           447: }
        !           448: 
        !           449: 
        !           450: /*
        !           451:  * Highest level: small utilities.
        !           452:  *
        !           453:  * WARNING: Several of the following routines may change their argument
        !           454:  * even if they return No.
        !           455:  * HINT: Some of these routines are not used; they are included for
        !           456:  * completeness of the provided set of operators only.  If you have
        !           457:  * space problems (as, e.g., on a PDP-11), you can delete the superfluous
        !           458:  * ones (lint will tell you which they are).
        !           459:  */
        !           460: 
        !           461: Visible Procedure
        !           462: top(pp)
        !           463:        register path *pp;
        !           464: {
        !           465:        while (up(pp))
        !           466:                ;
        !           467: }
        !           468: 
        !           469: 
        !           470: Visible bool
        !           471: nextnode(pp)
        !           472:        register path *pp;
        !           473: {
        !           474:        while (!rite(pp)) {
        !           475:                if (!up(pp))
        !           476:                        return No;
        !           477:        }
        !           478:        return Yes;
        !           479: }
        !           480: 
        !           481: 
        !           482: Visible Procedure
        !           483: firstleaf(pp)
        !           484:        register path *pp;
        !           485: {
        !           486:        while (down(pp))
        !           487:                ;
        !           488: }
        !           489: 
        !           490: #if NOT_USED
        !           491: 
        !           492: Visible bool
        !           493: nextleaf(pp)
        !           494:        register path *pp;
        !           495: {
        !           496:        if (!nextnode(pp))
        !           497:                return No;
        !           498:        firstleaf(pp);
        !           499:        return Yes;
        !           500: }
        !           501: 
        !           502: #endif NOT_USED
        !           503: 
        !           504: Visible bool
        !           505: prevnode(pp)
        !           506:        register path *pp;
        !           507: {
        !           508:        while (!left(pp)) {
        !           509:                if (!up(pp))
        !           510:                        return No;
        !           511:        }
        !           512:        return Yes;
        !           513: }
        !           514: 
        !           515: Visible Procedure
        !           516: lastleaf(pp)
        !           517:        register path *pp;
        !           518: {
        !           519:        while (downrite(pp))
        !           520:                        ;
        !           521: }
        !           522: 
        !           523: #ifdef NOT_USED
        !           524: 
        !           525: Visible bool
        !           526: prevleaf(pp)
        !           527:        register path *pp;
        !           528: {
        !           529:        if (!prevnode(pp))
        !           530:                return No;
        !           531:        lastleaf(pp);
        !           532:        return Yes;
        !           533: }
        !           534: 
        !           535: 
        !           536: Visible bool
        !           537: nextmarked(pp, x)
        !           538:        register path *pp;
        !           539:        register markbits x;
        !           540: {
        !           541:        do {
        !           542:                if (!nextnode(pp))
        !           543:                        return No;
        !           544:        } while (!marked(*pp, x));
        !           545:        while (down(pp)) {
        !           546:                while (!marked(*pp, x)) {
        !           547:                        if (!rite(pp)) {
        !           548:                                up(pp) || Abort();
        !           549:                                return Yes;
        !           550:                        }
        !           551:                }
        !           552:        }
        !           553:        return Yes;
        !           554: }
        !           555: 
        !           556: #endif NOT_UED
        !           557: 
        !           558: Visible bool
        !           559: firstmarked(pp, x)
        !           560:        register path *pp;
        !           561:        register markbits x;
        !           562: {
        !           563:        while (!marked(*pp, x)) {
        !           564:                if (!up(pp))
        !           565:                        return No;
        !           566:        }
        !           567:        while (down(pp)) {
        !           568:                while (Type(tree(*pp)) == Tex || !marked(*pp, x)) {
        !           569:                        if (!rite(pp)) {
        !           570:                                up(pp) || Abort();
        !           571:                                return Yes;
        !           572:                        }
        !           573:                }
        !           574:        }
        !           575:        return Yes;
        !           576: }
        !           577: 
        !           578: 
        !           579: Visible bool
        !           580: prevmarked(pp, x)
        !           581:        register path *pp;
        !           582:        register markbits x;
        !           583: {
        !           584:        do {
        !           585:                if (!prevnode(pp))
        !           586:                        return No;
        !           587:        } while (!marked(*pp, x));
        !           588:        while (downrite(pp)) {
        !           589:                while (!marked(*pp, x)) {
        !           590:                        if (!left(pp)) {
        !           591:                                up(pp) || Abort();
        !           592:                                return Yes;
        !           593:                        }
        !           594:                }
        !           595:        }
        !           596:        return Yes;
        !           597: }
        !           598: 
        !           599: 
        !           600: /*
        !           601:  * Deliver the path length to the root.
        !           602:  */
        !           603: 
        !           604: 
        !           605: Visible Procedure
        !           606: pathlength(p)
        !           607:        register path p;
        !           608: {
        !           609:        register int n;
        !           610: 
        !           611:        for (n = 0; p; ++n)
        !           612:                p = parent(p);
        !           613:        return n;
        !           614: }
        !           615: 
        !           616: 
        !           617: /*
        !           618:  * Put a C string in a trimmed location (this name should change,
        !           619:  * the 'official' routine of this name has quite different parameters).
        !           620:  */
        !           621: 
        !           622: 
        !           623: Visible Procedure
        !           624: putintrim(pn, head, tail, str)
        !           625:        register value *pn;
        !           626:        register int head;
        !           627:        Register int tail;
        !           628:        Register string str;
        !           629: {
        !           630:        register value v = *pn; 
        !           631:        value w = head == 0 ? mk_text("") :
        !           632:                head == Length(v) ? copy(v) : trim(v, 0, Length(v) - head);
        !           633: 
        !           634:        Assert(head >= 0 && tail >= 0 && head + tail <= Length(v));
        !           635:        if (*str)
        !           636:                concato(&w, str);
        !           637:        if (tail > 0)
        !           638:                concato(&w, Str(v)+(Length(v) - tail));
        !           639:        release(v);
        !           640:        *pn = w;
        !           641: }
        !           642: 
        !           643: 
        !           644: /*
        !           645:  * Touch the node in focus.
        !           646:  */
        !           647: 
        !           648: Visible Procedure
        !           649: touchpath(pp)
        !           650:        register path *pp;
        !           651: {
        !           652:        nodeuniql(Loctree(pp));
        !           653: }

unix.superglobalmegacorp.com

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