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