|
|
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.