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: }

Defined functions

clearmarks defined in line 320; used 2 times
connect defined in line 194; used 1 times
firstleaf defined in line 482; used 1 times
lastleaf defined in line 515; used 1 times
left defined in line 419; used 4 times
newpath defined in line 158; used 3 times
nextleaf defined in line 492; used 1 times
nextmarked defined in line 536; used 1 times
nextnode defined in line 470; used 3 times
nodecopy defined in line 36; never used
noderelease defined in line 43; never used
nodeuniql defined in line 49; never used
pathcopy defined in line 131; never used
pathlength defined in line 605; used 2 times
pathrelease defined in line 138; never used
pathuniql defined in line 145; never used
prevleaf defined in line 525; used 1 times
prevmarked defined in line 579; used 1 times
prevnode defined in line 504; used 3 times
putintrim defined in line 623; used 3 times
repwidth defined in line 253; used 2 times
setchild defined in line 93; used 4 times
touchpath defined in line 648; used 1 times

Defined variables

rcsid defined in line 2; never used

Defined macros

Addmarks defined in line 187; used 3 times
Child defined in line 25; used 5 times
Delmarks defined in line 190; used 2 times
Ichild defined in line 119; used 1 times
Isnode defined in line 21; used 4 times
Level defined in line 122; used 2 times
Locchild defined in line 81; used 3 times
Locparent defined in line 183; used 1 times
Loctree defined in line 185; used 5 times
Marks defined in line 26; used 6 times
NPATHFIELDS defined in line 115; never used
Nchildren defined in line 23; used 5 times
Parent defined in line 117; used 6 times
Register defined in line 13; used 7 times
Setcoord defined in line 180; used 1 times
Setmarks defined in line 83; used 5 times
Setwidth defined in line 85; used 2 times
Symbol defined in line 24; used 1 times
  • in line 69
Tree defined in line 118; used 12 times
Uniqp defined in line 178; used 5 times
Width defined in line 27; used 3 times
Xcoord defined in line 121; used 2 times
Ycoord defined in line 120; used 2 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2498
Valid CSS Valid XHTML 1.0 Strict