148116Sbostic /*-
2*62219Sbostic * Copyright (c) 1980, 1993
3*62219Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622198Sdist */
7778Speter
814745Sthien #ifndef lint
9*62219Sbostic static char sccsid[] = "@(#)tree.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11778Speter
12778Speter #include "whoami.h"
13778Speter #include "0.h"
14778Speter
15778Speter /*
16778Speter * TREE SPACE DECLARATIONS
17778Speter */
18778Speter struct tr {
19778Speter int *tr_low;
20778Speter int *tr_high;
21778Speter } ttab[MAXTREE], *tract;
22778Speter
23778Speter /*
24778Speter * The variable space is the
25778Speter * absolute base of the tree segments.
26778Speter * (exactly the same as ttab[0].tr_low)
27778Speter * Spacep is maintained to point at the
28778Speter * beginning of the next tree slot to
29778Speter * be allocated for use by the grammar.
30778Speter * Spacep is used "extern" by the semantic
31778Speter * actions in pas.y.
32778Speter * The variable tract is maintained to point
33778Speter * at the tree segment out of which we are
34778Speter * allocating (the active segment).
35778Speter */
36778Speter int *space, *spacep;
37778Speter
38778Speter /*
39778Speter * TREENMAX is the maximum width
40778Speter * in words that any tree node
41778Speter * due to the way in which the parser uses
42778Speter * the pointer spacep.
43778Speter */
44778Speter #define TREENMAX 6
45778Speter
46778Speter int trspace[ITREE];
47778Speter int *space = trspace;
48778Speter int *spacep = trspace;
49778Speter struct tr *tract = ttab;
50778Speter
51778Speter /*
52778Speter * Inittree allocates the first tree slot
53778Speter * and sets up the first segment descriptor.
54778Speter * A lot of this work is actually done statically
55778Speter * above.
56778Speter */
inittree()57778Speter inittree()
58778Speter {
59778Speter
60778Speter ttab[0].tr_low = space;
61778Speter ttab[0].tr_high = &space[ITREE];
62778Speter }
63778Speter
64778Speter /*
65778Speter * Tree builds the nodes in the
66778Speter * parse tree. It is rarely called
67778Speter * directly, rather calls are made
68778Speter * to tree[12345] which supplies the
69778Speter * first argument to save space in
70778Speter * the code. Tree also guarantees
71778Speter * that spacep points to the beginning
72778Speter * of the next slot it will return,
73778Speter * a property required by the parser
74778Speter * which was always true before we
75778Speter * segmented the tree space.
76778Speter */
7715925Sthien /*VARARGS1*/
7814745Sthien struct tnode *
tree(cnt,a)7914745Sthien tree(cnt, a)
80778Speter int cnt;
81778Speter {
82778Speter register int *p, *q;
83778Speter register int i;
84778Speter
85778Speter i = cnt;
86778Speter p = spacep;
87778Speter q = &a;
88778Speter do
89778Speter *p++ = *q++;
90778Speter while (--i);
91778Speter q = spacep;
92778Speter spacep = p;
93778Speter if (p+TREENMAX >= tract->tr_high)
94778Speter /*
95778Speter * this peek-ahead should
96778Speter * save a great number of calls
97778Speter * to tralloc.
98778Speter */
99778Speter tralloc(TREENMAX);
10014745Sthien return ((struct tnode *) q);
101778Speter }
102778Speter
103778Speter /*
104778Speter * Tralloc preallocates enough
105778Speter * space in the tree to allow
106778Speter * the grammar to use the variable
107778Speter * spacep, as it did before the
108778Speter * tree was segmented.
109778Speter */
tralloc(howmuch)110778Speter tralloc(howmuch)
111778Speter {
112778Speter register char *cp;
113778Speter register i;
114778Speter
115778Speter if (spacep + howmuch >= tract->tr_high) {
116778Speter i = TRINC;
11714745Sthien cp = malloc((unsigned) (i * sizeof ( int )));
1181837Speter if (cp == 0) {
119778Speter yerror("Ran out of memory (tralloc)");
120778Speter pexit(DIED);
121778Speter }
12214745Sthien spacep = (int *) cp;
123778Speter tract++;
124778Speter if (tract >= &ttab[MAXTREE]) {
125778Speter yerror("Ran out of tree tables");
126778Speter pexit(DIED);
127778Speter }
12814745Sthien tract->tr_low = (int *) cp;
129778Speter tract->tr_high = tract->tr_low+i;
130778Speter }
131778Speter }
132778Speter
133778Speter extern int yylacnt;
13414745Sthien extern struct B *bottled;
135778Speter #ifdef PXP
136778Speter #endif
137778Speter /*
138778Speter * Free up the tree segments
139778Speter * at the end of a block.
140778Speter * If there is scanner lookahead,
141778Speter * i.e. if yylacnt != 0 or there is bottled output, then we
142778Speter * cannot free the tree space.
143778Speter * This happens only when errors
144778Speter * occur and the forward move extends
145778Speter * across "units".
146778Speter */
trfree()147778Speter trfree()
148778Speter {
149778Speter
150778Speter if (yylacnt != 0 || bottled != NIL)
151778Speter return;
152778Speter #ifdef PXP
153778Speter if (needtree())
154778Speter return;
155778Speter #endif
156778Speter spacep = space;
157778Speter while (tract->tr_low > spacep || tract->tr_high <= spacep) {
15814745Sthien free((char *) tract->tr_low);
159778Speter tract->tr_low = NIL;
160778Speter tract->tr_high = NIL;
161778Speter tract--;
162778Speter if (tract < ttab)
163778Speter panic("ttab");
164778Speter }
165778Speter #ifdef PXP
166778Speter packtree();
167778Speter #endif
168778Speter }
169778Speter
170778Speter /*
171778Speter * Copystr copies a token from
172778Speter * the "token" buffer into the
173778Speter * tree space.
174778Speter */
copystr(token)175778Speter copystr(token)
176778Speter register char *token;
177778Speter {
178778Speter register char *cp;
179778Speter register int i;
180778Speter
181778Speter i = (strlen(token) + sizeof ( int )) & ~( ( sizeof ( int ) ) - 1 );
182778Speter tralloc(i / sizeof ( int ));
18314745Sthien (void) pstrcpy((char *) spacep, token);
18414745Sthien cp = (char *) spacep;
18514745Sthien spacep = ((int *) cp + i);
186778Speter tralloc(TREENMAX);
18714745Sthien return ((int) cp);
188778Speter }
189