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