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: }
Defined functions
Defined variables