xref: /csrg-svn/usr.bin/pascal/src/tree.c (revision 14745)
1778Speter /* Copyright (c) 1979 Regents of the University of California */
2778Speter 
3*14745Sthien #ifndef lint
4*14745Sthien static	char sccsid[] = "@(#)tree.c 1.3 08/19/83";
5*14745Sthien #endif
6778Speter 
7778Speter #include "whoami.h"
8778Speter #include "0.h"
9778Speter 
10778Speter /*
11778Speter  * TREE SPACE DECLARATIONS
12778Speter  */
13778Speter struct tr {
14778Speter 	int	*tr_low;
15778Speter 	int	*tr_high;
16778Speter } ttab[MAXTREE], *tract;
17778Speter 
18778Speter /*
19778Speter  * The variable space is the
20778Speter  * absolute base of the tree segments.
21778Speter  * (exactly the same as ttab[0].tr_low)
22778Speter  * Spacep is maintained to point at the
23778Speter  * beginning of the next tree slot to
24778Speter  * be allocated for use by the grammar.
25778Speter  * Spacep is used "extern" by the semantic
26778Speter  * actions in pas.y.
27778Speter  * The variable tract is maintained to point
28778Speter  * at the tree segment out of which we are
29778Speter  * allocating (the active segment).
30778Speter  */
31778Speter int	*space, *spacep;
32778Speter 
33778Speter /*
34778Speter  * TREENMAX is the maximum width
35778Speter  * in words that any tree node
36778Speter  * due to the way in which the parser uses
37778Speter  * the pointer spacep.
38778Speter  */
39778Speter #define	TREENMAX	6
40778Speter 
41778Speter int	trspace[ITREE];
42778Speter int	*space	= trspace;
43778Speter int	*spacep	= trspace;
44778Speter struct	tr *tract	= ttab;
45778Speter 
46778Speter /*
47778Speter  * Inittree allocates the first tree slot
48778Speter  * and sets up the first segment descriptor.
49778Speter  * A lot of this work is actually done statically
50778Speter  * above.
51778Speter  */
52778Speter inittree()
53778Speter {
54778Speter 
55778Speter 	ttab[0].tr_low = space;
56778Speter 	ttab[0].tr_high = &space[ITREE];
57778Speter }
58778Speter 
59778Speter /*
60778Speter  * Tree builds the nodes in the
61778Speter  * parse tree. It is rarely called
62778Speter  * directly, rather calls are made
63778Speter  * to tree[12345] which supplies the
64778Speter  * first argument to save space in
65778Speter  * the code. Tree also guarantees
66778Speter  * that spacep points to the beginning
67778Speter  * of the next slot it will return,
68778Speter  * a property required by the parser
69778Speter  * which was always true before we
70778Speter  * segmented the tree space.
71778Speter  */
72*14745Sthien /*VARARGS*/
73*14745Sthien struct tnode *
74*14745Sthien tree(cnt, a)
75778Speter 	int cnt;
76778Speter {
77778Speter 	register int *p, *q;
78778Speter 	register int i;
79778Speter 
80778Speter 	i = cnt;
81778Speter 	p = spacep;
82778Speter 	q = &a;
83778Speter 	do
84778Speter 		*p++ = *q++;
85778Speter 	while (--i);
86778Speter 	q = spacep;
87778Speter 	spacep = p;
88778Speter 	if (p+TREENMAX >= tract->tr_high)
89778Speter 		/*
90778Speter 		 * this peek-ahead should
91778Speter 		 * save a great number of calls
92778Speter 		 * to tralloc.
93778Speter 		 */
94778Speter 		tralloc(TREENMAX);
95*14745Sthien 	return ((struct tnode *) q);
96778Speter }
97778Speter 
98778Speter /*
99778Speter  * Tralloc preallocates enough
100778Speter  * space in the tree to allow
101778Speter  * the grammar to use the variable
102778Speter  * spacep, as it did before the
103778Speter  * tree was segmented.
104778Speter  */
105778Speter tralloc(howmuch)
106778Speter {
107778Speter 	register char *cp;
108778Speter 	register i;
109778Speter 
110778Speter 	if (spacep + howmuch >= tract->tr_high) {
111778Speter 		i = TRINC;
112*14745Sthien 		cp = malloc((unsigned) (i * sizeof ( int )));
1131837Speter 		if (cp == 0) {
114778Speter 			yerror("Ran out of memory (tralloc)");
115778Speter 			pexit(DIED);
116778Speter 		}
117*14745Sthien 		spacep = (int *) cp;
118778Speter 		tract++;
119778Speter 		if (tract >= &ttab[MAXTREE]) {
120778Speter 			yerror("Ran out of tree tables");
121778Speter 			pexit(DIED);
122778Speter 		}
123*14745Sthien 		tract->tr_low = (int *) cp;
124778Speter 		tract->tr_high = tract->tr_low+i;
125778Speter 	}
126778Speter }
127778Speter 
128778Speter extern	int yylacnt;
129*14745Sthien extern	struct B *bottled;
130778Speter #ifdef PXP
131778Speter #endif
132778Speter /*
133778Speter  * Free up the tree segments
134778Speter  * at the end of a block.
135778Speter  * If there is scanner lookahead,
136778Speter  * i.e. if yylacnt != 0 or there is bottled output, then we
137778Speter  * cannot free the tree space.
138778Speter  * This happens only when errors
139778Speter  * occur and the forward move extends
140778Speter  * across "units".
141778Speter  */
142778Speter trfree()
143778Speter {
144778Speter 
145778Speter 	if (yylacnt != 0 || bottled != NIL)
146778Speter 		return;
147778Speter #ifdef PXP
148778Speter 	if (needtree())
149778Speter 		return;
150778Speter #endif
151778Speter 	spacep = space;
152778Speter 	while (tract->tr_low > spacep || tract->tr_high <= spacep) {
153*14745Sthien 		free((char *) tract->tr_low);
154778Speter 		tract->tr_low = NIL;
155778Speter 		tract->tr_high = NIL;
156778Speter 		tract--;
157778Speter 		if (tract < ttab)
158778Speter 			panic("ttab");
159778Speter 	}
160778Speter #ifdef PXP
161778Speter 	packtree();
162778Speter #endif
163778Speter }
164778Speter 
165778Speter /*
166778Speter  * Copystr copies a token from
167778Speter  * the "token" buffer into the
168778Speter  * tree space.
169778Speter  */
170778Speter copystr(token)
171778Speter 	register char *token;
172778Speter {
173778Speter 	register char *cp;
174778Speter 	register int i;
175778Speter 
176778Speter 	i = (strlen(token) + sizeof ( int )) & ~( ( sizeof ( int ) ) - 1 );
177778Speter 	tralloc(i / sizeof ( int ));
178*14745Sthien 	(void) pstrcpy((char *) spacep, token);
179*14745Sthien 	cp = (char *) spacep;
180*14745Sthien 	spacep = ((int *) cp + i);
181778Speter 	tralloc(TREENMAX);
182*14745Sthien 	return ((int) cp);
183778Speter }
184