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