1: # 2: # include "../unix.h" 3: 4: extern jmp_buf Env; 5: 6: /* 7: ** DISPLAY.C -- display manipulation routines 8: ** 9: ** a display is a list of strings, the symbol 10: ** space Symsp is impemented by means of displays. 11: ** 12: ** Defines: 13: ** enter_display() 14: ** addsym() 15: ** free_display() 16: ** symspfree() 17: ** w_display() 18: ** eat_display() 19: ** 20: ** Required By: 21: ** Lexical analysis routines to add to the symbol space 22: ** semantic productions to manipulate input 23: ** 24: ** Files: 25: ** constants.h 26: ** globals.h 27: ** 28: ** History: 29: ** 6/1/78 -- (marc) written 30: ** 31: */ 32: 33: 34: # include <stdio.h> 35: 36: # include "constants.h" 37: # include "globals.h" 38: 39: 40: /* this avoids having to specify &Cv_display in the semantic 41: * routines, by making Cv_display a pointer to the pertinent 42: * display structure. 43: */ 44: extern struct display *Cv_display = &Displays [0]; 45: 46: /* 47: ** ENTER_DISPLAY -- enter a new string into a display 48: ** 49: ** Parameters: 50: ** disp -- display to be added to 51: ** string -- string to add 52: ** 53: ** Returns: 54: ** pointer to new disp_node structure. 55: ** 56: ** Side Effects: 57: ** allocates a new disp_node structure. 58: ** Expects a dynamic "string", i.e. one that it can 59: ** dispose of as it wishes, so it is the users responsability 60: ** to allocate space for this string. 61: ** If the string passed is 0, the string 62: ** "ERROR_TOKEN" is substituted, and a message is printed, 63: ** so a caller may call enter_display with the return of an 64: ** salloc() directly. 65: ** If no space is available for the allocation of the 66: ** new node, an error message is given, and a longjump(3) 67: ** is performed (this should goto equel()[main.c]) 68: ** 69: ** Called By: 70: ** add_sym() -- to add a token to the Symsp 71: ** the semantic productions -- for manipulating usages 72: ** of C variables. 73: ** 74: ** Diagnostics: 75: ** "symbol space overflow" -- total reset to after 76: ** current top level file (not #included) 77: ** "alloc error in display" -- someone called enter_display 78: ** with a string == 0 79: ** 80: ** History: 81: ** 6/1/78 -- (marc) written 82: ** 83: */ 84: 85: 86: struct disp_node *enter_display(disp, string) 87: struct display *disp; 88: char *string; 89: { 90: register struct display *d; 91: register struct disp_node *node; 92: extern char *nalloc(); 93: 94: node = (struct disp_node *) nalloc(sizeof *node); 95: if (node == 0) 96: { 97: yysemerr("symbol space overflow", string); 98: reset(Env, 1); 99: } 100: d = disp; 101: if (!d->disp_first) 102: d->disp_first = d->disp_last = node; 103: else 104: { 105: d->disp_last->d_next = node; 106: d->disp_last = node; 107: } 108: node->d_next = 0; 109: if (!(node->d_elm = string)) 110: { 111: printf("alloc error in display\n"); 112: node->d_elm = "ERROR_TOKEN"; 113: } 114: return (node); 115: } 116: 117: /* 118: ** ADDSYM -- add a token to the symbol space 119: ** 120: ** The node's .d_line field is set to the value of yyline, 121: ** which, if this routine is called from a lexical routine 122: ** taking lexemes that can't include newlines (and back them up), 123: ** is the line the lexeme was read from. This fact is used 124: ** be yyserror() [yyerror.c] to report accurate line numbers 125: ** for errors. 126: ** 127: ** Parameters: 128: ** s -- string to add 129: ** 130: ** Returns: 131: ** pointer to node added 132: ** 133: ** Requires: 134: ** enter_display() -- to enter the string 135: 136: ** Symsp -- display in which to enter it 137: ** 138: ** Called By: 139: ** All lexical routines 140: ** 141: ** History: 142: ** 6/1/78 -- (marc) written 143: ** 144: */ 145: 146: 147: 148: struct disp_node *addsym(s) 149: char *s; 150: { 151: register struct disp_node *d; 152: 153: d = enter_display(&Symsp, s); 154: d->d_line = yyline; 155: return (d); 156: } 157: 158: /* 159: ** FREE_DISPLAY -- frees all elements of a display 160: ** 161: ** Parameters: 162: ** disp -- the display to free 163: ** 164: ** Called By: 165: ** The semantic produtions dealing with 166: ** usage of C variables. 167: ** 168: ** History: 169: ** 6/1/78 -- (marc) written 170: ** 171: */ 172: 173: 174: 175: 176: 177: free_display(disp) 178: struct display *disp; 179: { 180: register struct display *d; 181: register struct disp_node *f, *n; 182: 183: d = disp; 184: for (f = d->disp_first; f; f = n) 185: { 186: n = f->d_next; 187: xfree(f->d_elm); 188: xfree(f); 189: } 190: d->disp_first = d->disp_last = 0; 191: } 192: 193: /* 194: ** SYSMSPFREE -- Frees symbol space 195: ** Symspfree frees all the symbol table, EXCEPT 196: ** for the last element in it, as this is the lookahead 197: ** element. That is to say, the element which forced reduction 198: ** to the non-terminal program, which called on symspfree() 199: ** 200: ** Requires: 201: ** Symsp -- to free it 202: ** 203: ** Called By: 204: ** argproc() 205: ** semantic routines (nonterminal "program") 206: ** 207: ** History: 208: ** 6/1/78 -- (marc) written 209: ** 210: */ 211: 212: 213: 214: symspfree() 215: { 216: register struct display *d; 217: register struct disp_node *f, *n; 218: 219: d = &Symsp; 220: for (f = d->disp_first; f && f->d_next; f = n) 221: { 222: n = f->d_next; 223: xfree(f->d_elm); 224: xfree(f); 225: } 226: d->disp_first = d->disp_last; 227: } 228: 229: /* 230: ** W_DISPLAY -- write out the contents of a display 231: ** 232: ** Parameters: 233: ** disp -- display to take write out 234: ** 235: ** Side Effects: 236: ** Writes onto Out_file 237: ** the contents of the display, 238: ** each string is comsidered a separate 239: ** word to be written out(so w_raw may 240: ** break a line between words). 241: ** Calls are made to w_op() and w_key() so as 242: ** to have the minimum number of spaces in the text. 243: ** 244: ** Requires: 245: ** w_op() -- to write out operator terminated 246: ** strings 247: ** w_key() -- to write out KEYCHAR terminated 248: ** strings 249: ** 250: ** Called By: 251: ** semantic productions dealing with usage of 252: ** C variables. 253: ** 254: ** History: 255: ** 6/1/78 -- (marc) written 256: ** 257: */ 258: 259: 260: 261: w_display(disp) 262: struct display *disp; 263: { 264: register struct disp_node *n; 265: 266: for (n = disp->disp_first; n; n = n->d_next) 267: { 268: switch (Cmap [n->d_elm [length(n->d_elm) - 1]]) 269: { 270: 271: case OPATR : 272: case PUNCT : 273: w_op(n->d_elm); 274: break; 275: 276: default : 277: w_key(n->d_elm); 278: break; 279: } 280: } 281: } 282: /* 283: ** EAT_DISPLAY -- enter text from In_file into a display 284: ** Enters all text gotten through getch() [getch.c] 285: ** lying between one character delimiters, which may 286: ** be nested, into a display or w_op()'s it. 287: ** eat_display() assumes that when it is called a 288: ** "left_ch" has just been seen. It will "eat" up to 289: ** MAXSTRING characters. 290: ** Newline is played with because : 291: ** a) a newline may have been read by eat_display 292: ** instead of yylex(), therefore if eat_display 293: ** stops there, yylex() must know that a newline 294: ** has just been seen and it must test for C_CODE. 295: ** b) Newline may have to be set to 0 if an include() 296: ** was done which sets it to 1, and no yylex() was 297: ** done afterwards to reset it. 298: ** 299: ** NOTE : This playing with Newline is needed because 300: ** yylex() and not getch() maintains Newline. If getch() 301: ** maintained Newline then it would be automatically right. 302: ** 303: ** Parameters: 304: ** disp -- display to add elements to if != 0 else 305: ** characters are written out. 306: ** left_ch -- left delimiter character 307: ** right_ch -- right delimiter character 308: ** 309: ** Side Effects: 310: ** advances input to after the close of the 311: ** left_ch, right_ch pair. 312: ** may back up 2 characters. 313: ** 314: ** Called By: 315: ** semantic routines dealing with array subscription 316: ** 317: ** Diagnostics: 318: ** "missing closing character" -- if end-of-file 319: ** encountered in the stream. 320: ** "display too long" -- if more than MAXSTRING 321: ** chars between delimiters. 322: ** 323: ** History: 324: ** 6/1/78 -- (marc) written 325: ** 326: ** Bugs: 327: ** #include's encountered, are treated wrongly 328: ** because the "#include ...c.h" is put out immediately, 329: ** while the display is put out only later. 330: ** 331: ** 332: */ 333: 334: 335: eat_display(disp, left_ch, right_ch) 336: struct display *disp; 337: char left_ch; 338: char right_ch; 339: { 340: char buf [MAXSTRING + 1]; 341: register char *cp; 342: register level; 343: register i; 344: char pk; 345: char r_c [2]; 346: 347: cp = buf; 348: level = i = 1; 349: *cp = left_ch; 350: do 351: { 352: i++; 353: if (i >= sizeof buf) 354: { 355: yysemerr("display too long", 0); 356: break; 357: } 358: if ((*++cp = getch()) == left_ch) 359: level++; 360: else if (*cp == right_ch) 361: level -= 1; 362: else if (*cp == EOF_TOK) 363: { 364: backup(*cp); 365: missing : 366: r_c [1] = '\0'; 367: r_c [0] = right_ch; 368: yysemerr("missing closing character", r_c); 369: *cp = right_ch; 370: /* make next line be read as possible 371: * C_CODE by yylex() [yylex.c] 372: */ 373: Newline = 1; 374: break; 375: } 376: else if (*cp == '\n') 377: { 378: /* test that next line is valid equel line, 379: * and strip "##" 380: */ 381: if ((pk = getch()) != '#') 382: { 383: backup(pk); 384: goto missing; 385: } 386: if ((pk = getch()) != '#') 387: { 388: backup(pk); 389: backup('#'); 390: goto missing; 391: } 392: } 393: } while (*cp != right_ch || level > 0); 394: if (level == 0) 395: Newline = 0; 396: *++cp = '\0'; 397: if (disp) 398: enter_display(disp, salloc(buf)); 399: else 400: w_op(buf); 401: }