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