1: # 2: /* 3: ** CVAR -- routines to manipulate the c variable trees 4: ** 5: ** C variable trees are binary trees of cvar structs, 6: ** with the c_left < c_right with respect to c_id. 7: ** 8: ** Defines: 9: ** decl_cvar() -- declare a C variable 10: ** decl_field() -- declare a structure field 11: ** getcvar() -- get cvar node of a C variable 12: ** getfield() -- get field's node 13: ** freecvar() -- frees cvar tree 14: ** 15: ** Required By: 16: ** semantic productions, and initialization routines 17: ** 18: ** Files: 19: ** constants.h -- for globals.h 20: ** globals.h -- for globals 21: ** 22: ** History: 23: ** 6/1/78 -- (marc) written 24: ** 8/28/78 -- (marc) modified for structure vars 25: */ 26: 27: # include <stdio.h> 28: 29: # include "constants.h" 30: # include "globals.h" 31: 32: struct cvar *dec_var(), *get_var(); 33: char *nalloc(), *salloc(); 34: 35: /* 36: ** DECL_CVAR -- Declare a C variable 37: ** 38: ** Parameters: 39: ** name -- identifier string (makes its own copy for the tree) 40: ** type 41: ** indir_level -- level of indirection of declaration 42: ** (- 1 if string) 43: ** block_level -- 0 - global, else local var 44: ** 45: ** Returns: 46: ** none 47: ** 48: ** Side Effects: 49: ** allocates a cvar node, and a copy of name, may put a node 50: ** in a cvar tree (if not previously declared). 51: ** 52: ** Requires: 53: ** C_locals -- local var tree 54: ** C_globals -- global var tree 55: ** 56: ** Called By: 57: ** the c_variable productions of the parser [grammar.y] 58: ** 59: ** Diagnostics: 60: ** out of space diagnostics 61: ** already declared diagnostic (node's storage is freed) 62: ** 63: ** History: 64: ** 6/1/78 -- (marc) written 65: ** 6/24/78 -- (marc) modified to take advantage of 66: ** dec_var() 67: */ 68: 69: 70: decl_cvar(name, type, indir_level, block_level) 71: char *name; 72: int type; 73: int indir_level; 74: int block_level; 75: { 76: register struct cvar *bad_node; 77: 78: if (bad_node = dec_var(name, type, indir_level, block_level, 79: &C_locals, &C_globals)) 80: { 81: yysemerr("re-declared identifier", bad_node->c_id); 82: xfree(bad_node->c_id); 83: xfree(bad_node); 84: } 85: } 86: 87: /* 88: ** DECL_FIELD -- Declare a structures field 89: ** 90: ** Same as decl_cvar() for fields within C records (structs). 91: ** NOTE : if a !0 is returned from dec_var() (i.e. the field 92: ** was already declared) the storage for that node is freed 93: ** but no error has been comitted, as fields may be re-declared. 94: ** 95: ** History: 96: ** 8/24/78 -- (marc) written 97: */ 98: 99: decl_field(name, type, indir_level, block_level) 100: char *name; 101: int type; 102: int indir_level; 103: int block_level; 104: { 105: register struct cvar *bad_node; 106: 107: if (bad_node = dec_var(name, type, indir_level, block_level, 108: &F_locals, &F_globals)) 109: { 110: xfree(bad_node->c_id); 111: xfree(bad_node); 112: } 113: } 114: /* 115: ** DEC_VAR -- declare a C var or field. 116: ** 117: ** Parameters: 118: ** same as decl_cvar() & decl_field plus 119: ** the local and global tree variables. 120: ** 121: ** Returns: 122: ** 0 -- successful 123: ** other -- cvar node pointer that couldn't be entered 124: ** to tree 125: ** 126: ** History: 127: ** 8/24/78 -- (marc) written 128: */ 129: 130: struct cvar *dec_var(name, type, indir_level, block_level, local_tree, global_tree) 131: char *name; 132: int type, indir_level, block_level; 133: struct cvar **local_tree, **global_tree; 134: { 135: register struct cvar *cvarp; 136: register i; 137: 138: cvarp = (struct cvar *) nalloc(sizeof *cvarp); 139: if (!cvarp) 140: { 141: yysemerr("unable to allocate space for a variable", name); 142: return (0); 143: } 144: if (!(cvarp->c_id = salloc(name))) 145: { 146: yysemerr("no space for variable name", name); 147: xfree(cvarp); 148: return (0); 149: } 150: cvarp->c_type = type; 151: cvarp->c_indir = indir_level; 152: cvarp->c_left = cvarp->c_right = 0; 153: i = c_enter(cvarp, block_level > 0 ? local_tree : global_tree); 154: return (i ? 0 : cvarp); 155: } 156: /* 157: ** C_ENTER -- Enter a cvar node in a cvar tree 158: ** 159: ** Parameters: 160: ** node -- the cvar node to insert 161: ** root -- a pointer to the root pointer 162: ** 163: ** Returns: 164: ** 1 -- if successful 165: ** 0 -- otherwise (node of same name existed 166: ** 167: ** Side Effects: 168: ** If a node of that name didn't exist one is inserted 169: ** 170: ** Called By: 171: ** dec_var() 172: ** 173: ** 174: ** History: 175: ** 6/1/78 -- (marc) written 176: ** 8/24/78 -- (marc) modified for inclusion of structures 177: ** 178: */ 179: 180: c_enter(node, root) 181: struct cvar *node; 182: struct cvar **root; 183: { 184: register char *name; 185: register struct cvar *n, *r; 186: 187: r = *root; 188: n = node; 189: name = n->c_id; 190: if (!r) 191: { 192: *root = n; 193: return (1); 194: } 195: for ( ; ; ) 196: { 197: switch (scompare(name, 0, r->c_id, 0)) 198: { 199: 200: case -1 : 201: if (!r->c_left) 202: { 203: r->c_left = n; 204: return (1); 205: } 206: r = r->c_left; 207: break; 208: 209: case 0 : 210: yysemerr("identifier re-declared", name); 211: xfree(name); 212: xfree(n); 213: return (0); 214: 215: case 1 : 216: if (!r->c_right) 217: { 218: r->c_right = n; 219: return (1); 220: } 221: r = r->c_right; 222: break; 223: } 224: } 225: } 226: 227: 228: /* 229: ** GET_VAR -- get a cvar node from a local_tree, global_tree pair 230: ** searching first through the local then the global. 231: ** 232: ** Parameters: 233: ** id -- c_id key 234: ** local_tree -- first tree 235: ** global_tree -- secomd tree to search 236: ** 237: ** Returns: 238: ** 0 -- if no node by that name 239: ** otherwise -- pointer to the node 240: ** 241: ** History: 242: ** 8/24/78 -- (marc) written 243: */ 244: 245: 246: struct cvar *get_var(id, local_tree, global_tree) 247: char *id; 248: struct cvar *local_tree, *global_tree; 249: { 250: register char *name; 251: register struct cvar *tree, *node; 252: char flag; 253: 254: flag = 0; 255: name = id; 256: tree = local_tree; 257: for ( ; ; ) 258: { 259: for (node = tree; node; ) 260: { 261: switch (scompare(name, 0, node->c_id, 0)) 262: { 263: 264: case -1 : 265: if (!node->c_left) 266: break; 267: else 268: node = node->c_left; 269: continue; 270: 271: case 0 : 272: return (node); 273: 274: case 1 : 275: if (!node->c_right) 276: break; 277: else 278: node = node->c_right; 279: continue; 280: } 281: break; 282: } 283: if (!flag) 284: { 285: flag += 1; 286: tree = global_tree; 287: } 288: else 289: return (0); 290: } 291: } 292: /* 293: ** GETCVAR -- get the cvar node for a given identifier 294: ** Looks first in C_locals, then in C_globals. 295: ** 296: ** Parameters: 297: ** id -- name of cvar to look for 298: ** 299: ** Returns: 300: ** adress of cvar node if found 301: ** 0 -- otherwise 302: ** 303: ** Requires: 304: ** C_locals & C_globals -- to search them 305: ** 306: ** Called BY: 307: ** semantic productions 308: ** 309: ** History: 310: ** 6/1/78 -- (marc) written 311: ** 312: */ 313: struct cvar *getcvar(id) 314: char *id; 315: { 316: return (get_var(id, C_locals, C_globals)); 317: } 318: 319: /* 320: ** GETFIELD -- Same as getcvar() for structure fields 321: ** 322: ** Requires: 323: ** F_locals & F_globals 324: ** 325: ** History: 326: ** 8/24/78 -- (marc) written 327: */ 328: 329: 330: struct cvar *getfield(id) 331: char *id; 332: { 333: return (get_var(id, F_locals, F_globals)); 334: } 335: 336: 337: /* 338: ** FREECVAR & F_CVAR -- Free up storage in a cvar tree 339: ** Freecvar calls f_cvar to free storage for a tree, then 340: ** 0's out the root pointer passed it. 341: ** 342: ** Usage: 343: ** Freecvar(rootp) -- should be called to free 344: ** a tree *rootp 345: ** 346: ** History: 347: ** 6/1/78 -- (marc) written 348: ** 349: */ 350: 351: freecvar(rootp) 352: struct cvar **rootp; 353: { 354: f_cvar(*rootp); 355: *rootp = 0; 356: } 357: 358: f_cvar(root) 359: struct cvar *root; 360: { 361: if (root) 362: { 363: f_cvar(root->c_left); 364: f_cvar(root->c_right); 365: xfree(root->c_id); 366: xfree(root); 367: } 368: }