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