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