1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622198Sdist */ 7778Speter 814745Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)tree.c 5.2 (Berkeley) 04/16/91"; 10*48116Sbostic #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 */ 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 * 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 */ 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 */ 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 */ 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