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