|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.