|
|
1.1 root 1: /*********************************************************************
2: * COPYRIGHT NOTICE *
3: **********************************************************************
4: * This software is copyright (C) 1982 by Pavel Curtis *
5: * *
6: * Permission is granted to reproduce and distribute *
7: * this file by any means so long as no fee is charged *
8: * above a nominal handling fee and so long as this *
9: * notice is always included in the copies. *
10: * *
11: * Other rights are reserved except as explicitly granted *
12: * by written permission of the author. *
13: * Pavel Curtis *
14: * Computer Science Dept. *
15: * 405 Upson Hall *
16: * Cornell University *
17: * Ithaca, NY 14853 *
18: * *
19: * Ph- (607) 256-4934 *
20: * *
21: * Pavel.Cornell@Udel-Relay (ARPAnet) *
22: * decvax!cornell!pavel (UUCPnet) *
23: *********************************************************************/
24:
25: /*
26: * comp_scan.c --- Lexical scanner for terminfo compiler.
27: *
28: * $Log: comp_scan.c,v $
29: * Revision 1.1 92/03/13 10:45:48 bin
30: * Initial revision
31: *
32: * Revision 2.1 82/10/25 14:45:55 pavel
33: * Added Copyright Notice
34: *
35: * Revision 2.0 82/10/24 15:17:12 pavel
36: * Beta-one Test Release
37: *
38: * Revision 1.3 82/08/23 22:30:03 pavel
39: * The REAL Alpha-one Release Version
40: *
41: * Revision 1.2 82/08/19 19:10:06 pavel
42: * Alpha Test Release One
43: *
44: * Revision 1.1 82/08/12 18:37:46 pavel
45: * Initial revision
46: *
47: *
48: */
49:
50: #ifndef COHERENT
51: static char RCSid[] =
52: "$Header: /src386/usr/bin/tic/RCS/comp_scan.c,v 1.1 92/03/13 10:45:48 bin Exp $";
53: #endif
54:
55: #include <stdio.h>
56: #include <ctype.h>
57: #include "compiler.h"
58:
59: #define iswhite(ch) (ch == ' ' || ch == '\t')
60:
61:
62: static int first_column; /* See 'next_char()' below */
63:
64:
65:
66: /*
67: * int
68: * get_token()
69: *
70: * Scans the input for the next token, storing the specifics in the
71: * global structure 'curr_token' and returning one of the following:
72: *
73: * NAMES A line beginning in column 1. 'name'
74: * will be set to point to everything up to
75: * but not including the first comma on the line.
76: * BOOLEAN An entry consisting of a name followed by
77: * a comma. 'name' will be set to point to the
78: * name of the capability.
79: * NUMBER An entry of the form
80: * name#digits,
81: * 'name' will be set to point to the capability
82: * name and 'valnumber' to the number given.
83: * STRING An entry of the form
84: * name=characters,
85: * 'name' is set to the capability name and
86: * 'valstring' to the string of characters, with
87: * input translations done.
88: * CANCEL An entry of the form
89: * name@,
90: * 'name' is set to the capability name and
91: * 'valnumber' to -1.
92: * EOF The end of the file has been reached.
93: *
94: */
95:
96: int
97: get_token()
98: {
99: long number;
100: int type;
101: register char ch;
102: static char buffer[1024];
103: register char *ptr;
104: int dot_flag = FALSE;
105:
106: while ((ch = next_char()) == '\n' || iswhite(ch))
107: ;
108:
109: if (ch == EOF)
110: type = EOF;
111: else
112: {
113: if (ch == '.')
114: {
115: dot_flag = TRUE;
116:
117: while ((ch = next_char()) == ' ' || ch == '\t')
118: ;
119: }
120:
121: if (! isalnum(ch))
122: {
123: warning("Illegal character - '%c'", ch);
124: panic_mode(',');
125: }
126:
127: ptr = buffer;
128: *(ptr++) = ch;
129:
130: if (first_column)
131: {
132: while ((ch = next_char()) != ',' && ch != '\n' && ch != EOF)
133: *(ptr++) = ch;
134:
135: if (ch == EOF)
136: err_abort("Premature EOF");
137: else if (ch == '\n') {
138: warning("Newline in middle of terminal name");
139: panic_mode(',');
140: }
141:
142: *ptr = '\0';
143: curr_token.tk_name = buffer;
144: type = NAMES;
145: }
146: else
147: {
148: ch = next_char();
149: while (isalnum(ch))
150: {
151: *(ptr++) = ch;
152: ch = next_char();
153: }
154:
155: *ptr++ = '\0';
156: switch (ch)
157: {
158: case ',':
159: curr_token.tk_name = buffer;
160: type = BOOLEAN;
161: break;
162:
163: case '@':
164: if (next_char() != ',')
165: warning("Missing comma");
166: curr_token.tk_name = buffer;
167: type = CANCEL;
168: break;
169:
170: case '#':
171: number = 0;
172: while (isdigit(ch = next_char()))
173: number = number * 10 + ch - '0';
174: if (ch != ',')
175: warning("Missing comma");
176: curr_token.tk_name = buffer;
177: curr_token.tk_valnumber = number;
178: type = NUMBER;
179: break;
180:
181: case '=':
182: ch = trans_string(ptr);
183: if (ch != ',')
184: warning("Missing comma");
185: curr_token.tk_name = buffer;
186: curr_token.tk_valstring = ptr;
187: type = STRING;
188: break;
189:
190: default:
191: warning("Illegal character - '%c'", ch);
192: }
193: } /* end else (first_column == FALSE) */
194: } /* end else (ch != EOF) */
195:
196: if (dot_flag == TRUE)
197: DEBUG(8, "Commented out ", "");
198:
199: if (debug_level >= 8)
200: {
201: fprintf(stderr, "Token: ");
202: switch (type)
203: {
204: case BOOLEAN:
205: fprintf(stderr, "Boolean; name='%s'\n",
206: curr_token.tk_name);
207: break;
208:
209: case NUMBER:
210: fprintf(stderr, "Number; name='%s', value=%d\n",
211: curr_token.tk_name, curr_token.tk_valnumber);
212: break;
213:
214: case STRING:
215: fprintf(stderr, "String; name='%s', value='%s'\n",
216: curr_token.tk_name, curr_token.tk_valstring);
217: break;
218:
219: case CANCEL:
220: fprintf(stderr, "Cancel; name='%s'\n",
221: curr_token.tk_name);
222: break;
223:
224: case NAMES:
225:
226: fprintf(stderr, "Names; value='%s'\n",
227: curr_token.tk_name);
228: break;
229:
230: case EOF:
231: fprintf(stderr, "End of file\n");
232: break;
233:
234: default:
235: warning("Bad token type");
236: }
237: }
238:
239: if (dot_flag == TRUE) /* if commented out, use the next one */
240: type = get_token();
241:
242: return(type);
243: }
244:
245:
246:
247: /*
248: * char
249: * next_char()
250: *
251: * Returns the next character in the input stream. Comments and leading
252: * white space are stripped. The global state variable 'firstcolumn' is
253: * set TRUE if the character returned is from the first column of the input
254: * line. The global variable curr_line is incremented for each new line.
255: * The global variable curr_file_pos is set to the file offset of the
256: * beginning of each line.
257: *
258: */
259:
260: int curr_column = -1;
261: char line[1024];
262:
263: char
264: next_char()
265: {
266: char *rtn_value;
267: long ftell();
268:
269: if (curr_column < 0 || curr_column > 1023 ||
270: line[curr_column] == '\0')
271: {
272: do
273: {
274: curr_file_pos = ftell(stdin);
275:
276: if ((rtn_value = fgets(line, 1024, stdin)) != NULL)
277: curr_line++;
278: } while (rtn_value != NULL && line[0] == '#');
279:
280: if (rtn_value == NULL)
281: return (EOF);
282:
283: curr_column = 0;
284: while (iswhite(line[curr_column]))
285: curr_column++;
286: }
287:
288: if (curr_column == 0 && line[0] != '\n')
289: first_column = TRUE;
290: else
291: first_column = FALSE;
292:
293: return (line[curr_column++]);
294: }
295:
296:
297: backspace()
298: {
299: curr_column--;
300:
301: if (curr_column < 0)
302: syserr_abort("Backspaced off beginning of line");
303: }
304:
305:
306:
307: /*
308: * reset_input()
309: *
310: * Resets the input-reading routines. Used after a seek has been done.
311: *
312: */
313:
314: reset_input()
315: {
316: curr_column = -1;
317: }
318:
319:
320:
321: /*
322: * char
323: * trans_string(ptr)
324: *
325: * Reads characters using next_char() until encountering a comma, newline
326: * or end-of-file. The returned value is the character which caused
327: * reading to stop. The following translations are done on the input:
328: *
329: * ^X goes to ctrl-X (i.e. X & 037)
330: * {\E,\n,\r,\b,\t,\f} go to
331: * {ESCAPE,newline,carriage-return,backspace,tab,formfeed}
332: * {\^,\\} go to {carat,backslash}
333: * \ddd (for ddd = up to three octal digits) goes to
334: * the character ddd
335: *
336: * \e == \E
337: * \0 == \200
338: *
339: */
340:
341: char
342: trans_string(ptr)
343: char *ptr;
344: {
345: register int count = 0;
346: int number;
347: int i;
348: char ch;
349:
350: while ((ch = next_char()) != ',' && ch != EOF)
351: {
352: if (ch == '^')
353: {
354: ch = next_char();
355: if (ch == EOF)
356: err_abort("Premature EOF");
357:
358: if (! isprint(ch))
359: {
360: warning("Illegal ^ character - '%c'", ch);
361: }
362:
363: *(ptr++) = ch & 037;
364: }
365: else if (ch == '\\')
366: {
367: ch = next_char();
368: if (ch == EOF)
369: err_abort("Premature EOF");
370:
371: if (ch >= '0' && ch <= '7')
372: {
373: number = ch - '0';
374: for (i=0; i < 2; i++)
375: {
376: ch = next_char();
377: if (ch == EOF)
378: err_abort("Premature EOF");
379:
380: if (ch < '0' || ch > '7')
381: {
382: backspace();
383: break;
384: }
385:
386: number = number * 8 + ch - '0';
387: }
388:
389: if (number == 0)
390: number = 0200;
391: *(ptr++) = (char) number;
392: }
393: else
394: {
395: switch (ch)
396: {
397: case 'E':
398: case 'e': *(ptr++) = '\033'; break;
399:
400: case 'l':
401: case 'n': *(ptr++) = '\n'; break;
402:
403: case 'r': *(ptr++) = '\r'; break;
404:
405: case 'b': *(ptr++) = '\b'; break;
406:
407: case 's': *(ptr++) = ' '; break;
408:
409: case 'f': *(ptr++) = '\014'; break;
410:
411: case 't': *(ptr++) = '\t'; break;
412:
413: case '\\': *(ptr++) = '\\'; break;
414:
415: case '^': *(ptr++) = '^'; break;
416:
417: case ',': *(ptr++) = ','; break;
418:
419: case ':': *(ptr++) = ':'; break;
420:
421: default:
422: warning("Illegal character in \\ sequence");
423: *(ptr++) = ch;
424: } /* endswitch (ch) */
425: } /* endelse (ch < '0' || ch > '7') */
426: } /* end else if (ch == '\\') */
427: else
428: {
429: *(ptr++) = ch;
430: }
431:
432: count ++;
433:
434: if (count > 500)
435: warning("Very long string found. Missing comma?");
436: } /* end while */
437:
438: *ptr = '\0';
439:
440: return(ch);
441: }
442:
443: /*
444: * Panic mode error recovery - skip everything until a "ch" is found.
445: */
446: panic_mode(ch)
447: char ch;
448: {
449: int c;
450:
451: for (;;) {
452: c = next_char();
453: if (c == ch)
454: return;
455: if (c == EOF);
456: return;
457: }
458: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.