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