1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 #ifndef lint 4 static char sccsid[] = "@(#)tree.c 1.4 09/19/83"; 5 #endif 6 7 #include "whoami.h" 8 #include "0.h" 9 10 /* 11 * TREE SPACE DECLARATIONS 12 */ 13 struct tr { 14 int *tr_low; 15 int *tr_high; 16 } ttab[MAXTREE], *tract; 17 18 /* 19 * The variable space is the 20 * absolute base of the tree segments. 21 * (exactly the same as ttab[0].tr_low) 22 * Spacep is maintained to point at the 23 * beginning of the next tree slot to 24 * be allocated for use by the grammar. 25 * Spacep is used "extern" by the semantic 26 * actions in pas.y. 27 * The variable tract is maintained to point 28 * at the tree segment out of which we are 29 * allocating (the active segment). 30 */ 31 int *space, *spacep; 32 33 /* 34 * TREENMAX is the maximum width 35 * in words that any tree node 36 * due to the way in which the parser uses 37 * the pointer spacep. 38 */ 39 #define TREENMAX 6 40 41 int trspace[ITREE]; 42 int *space = trspace; 43 int *spacep = trspace; 44 struct tr *tract = ttab; 45 46 /* 47 * Inittree allocates the first tree slot 48 * and sets up the first segment descriptor. 49 * A lot of this work is actually done statically 50 * above. 51 */ 52 inittree() 53 { 54 55 ttab[0].tr_low = space; 56 ttab[0].tr_high = &space[ITREE]; 57 } 58 59 /* 60 * Tree builds the nodes in the 61 * parse tree. It is rarely called 62 * directly, rather calls are made 63 * to tree[12345] which supplies the 64 * first argument to save space in 65 * the code. Tree also guarantees 66 * that spacep points to the beginning 67 * of the next slot it will return, 68 * a property required by the parser 69 * which was always true before we 70 * segmented the tree space. 71 */ 72 /*VARARGS*/ 73 struct tnode * 74 tree(cnt, a) 75 int cnt; 76 { 77 register int *p, *q; 78 register int i; 79 80 i = cnt; 81 p = spacep; 82 q = &a; 83 do 84 *p++ = *q++; 85 while (--i); 86 q = spacep; 87 spacep = p; 88 if (p+TREENMAX >= tract->tr_high) 89 /* 90 * this peek-ahead should 91 * save a great number of calls 92 * to tralloc. 93 */ 94 tralloc(TREENMAX); 95 return ((struct tnode *) q); 96 } 97 98 /* 99 * Tralloc preallocates enough 100 * space in the tree to allow 101 * the grammar to use the variable 102 * spacep, as it did before the 103 * tree was segmented. 104 */ 105 tralloc(howmuch) 106 { 107 register char *cp; 108 register i; 109 110 if (spacep + howmuch >= tract->tr_high) { 111 i = TRINC; 112 cp = malloc((unsigned) (i * sizeof ( int ))); 113 if (cp == 0) { 114 yerror("Ran out of memory (tralloc)"); 115 pexit(DIED); 116 } 117 spacep = (int *) cp; 118 tract++; 119 if (tract >= &ttab[MAXTREE]) { 120 yerror("Ran out of tree tables"); 121 pexit(DIED); 122 } 123 tract->tr_low = (int *) cp; 124 tract->tr_high = tract->tr_low+i; 125 } 126 } 127 128 extern int yylacnt; 129 extern struct B *bottled; 130 #ifdef PXP 131 #endif 132 /* 133 * Free up the tree segments 134 * at the end of a block. 135 * If there is scanner lookahead, 136 * i.e. if yylacnt != 0 or there is bottled output, then we 137 * cannot free the tree space. 138 * This happens only when errors 139 * occur and the forward move extends 140 * across "units". 141 */ 142 trfree() 143 { 144 145 if (yylacnt != 0 || bottled != NIL) 146 return; 147 #ifdef PXP 148 if (needtree()) 149 return; 150 #endif 151 spacep = space; 152 while (tract->tr_low > spacep || tract->tr_high <= spacep) { 153 free((char *) tract->tr_low); 154 tract->tr_low = NIL; 155 tract->tr_high = NIL; 156 tract--; 157 if (tract < ttab) 158 panic("ttab"); 159 } 160 #ifdef PXP 161 packtree(); 162 #endif 163 } 164 165 /* 166 * Copystr copies a token from 167 * the "token" buffer into the 168 * tree space. 169 */ 170 copystr(token) 171 register char *token; 172 { 173 register char *cp; 174 register int i; 175 176 i = (strlen(token) + sizeof ( int )) & ~( ( sizeof ( int ) ) - 1 ); 177 tralloc(i / sizeof ( int )); 178 (void) pstrcpy((char *) spacep, token); 179 cp = (char *) spacep; 180 spacep = ((int *) cp + i); 181 tralloc(TREENMAX); 182 return ((int) cp); 183 } 184