1 /* $NetBSD: llscan.c,v 1.9 2005/02/26 22:39:49 perry Exp $ */
2
3 /*
4 * ************************* NOTICE *******************************
5 * This code is in the public domain. It cannot be copyrighted.
6 * This scanner was originally written by Keith Thompson for the
7 * University of Wisconsin Crystal project.
8 * It was subsequently modified significantly by Nancy Hall at the
9 * University of Wisconsin for the ARGO project.
10 * ****************************************************************
11 */
12
13 #include <sys/cdefs.h>
14 __KERNEL_RCSID(0, "$NetBSD: llscan.c,v 1.9 2005/02/26 22:39:49 perry Exp $");
15
16 #include "xebec.h"
17 #include "llparse.h"
18
19 #include "main.h"
20 #include <stdio.h>
21 #include "procs.h"
22 #include "debug.h"
23 #include <string.h>
24
25 #define EOFILE 0x01
26 #define UNUSED 0x02
27 #define IGNORE 0x04
28 #define OPCHAR 0x8
29 #define DIGITS 0x10
30 #define LETTER 0x20
31
32 int chtype[128] = {
33 /* null, soh ^a, stx ^b etx ^c eot ^d enq ^e ack ^f bel ^g */
34 EOFILE, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED,
35 /* bs ^h ht ^i lf ^j vt ^k ff ^l cr ^m so ^n si ^o */
36 UNUSED, IGNORE, IGNORE, UNUSED, IGNORE, IGNORE, UNUSED, UNUSED,
37 /* dle ^p dc1 ^q dc2 ^r dc3 ^s dc4 ^t nak ^u syn ^v etb ^w */
38 UNUSED, UNUSED, UNUSED, UNUSED, EOFILE, UNUSED, UNUSED, UNUSED,
39 /* can ^x em ^y sub ^z esc ^] fs ^\ gs ^} rs ^` us ^/ */
40 UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED,
41
42 /* ! " # $ % & ' */
43 IGNORE, UNUSED, OPCHAR, UNUSED, OPCHAR, UNUSED, OPCHAR, OPCHAR,
44 /* ( ) * + , - . / */
45 OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR,
46 /* 0 1 2 3 4 5 6 7 */
47 DIGITS, DIGITS, DIGITS, DIGITS, DIGITS, DIGITS, DIGITS, DIGITS,
48 /* 8 9 : ; < = > ? */
49 DIGITS, DIGITS, OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR, OPCHAR,
50
51 /* @ A B C D E F G */
52 UNUSED, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
53 /* H I J K L M N O */
54 LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
55 /* P Q R S T U V W */
56 LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
57 /* X Y Z [ \ ] ^ _ */
58 LETTER, LETTER, LETTER, OPCHAR, UNUSED, OPCHAR, OPCHAR, LETTER,
59
60 /* ` a b c d e f g */
61 UNUSED, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
62 /* h i j k l m n o */
63 LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
64 /* p q r s t u v w */
65 LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
66 /* x y z { | } ~ del */
67 LETTER, LETTER, LETTER, OPCHAR, UNUSED, OPCHAR, UNUSED, UNUSED
68 };
69
70
71 extern FILE *astringfile;
72 static char *buffptr;
73 static char buffer[2][LINELEN];
74 static int currentbuf = 1;
75
76 #define addbuf(x) *buffptr++ = x
77
78 static int ch = ' ';
79
80 int getch();
81 extern void AddCurrentEventName();
82
83 void
84 skip()
85 {
86 while((chtype[ch] == IGNORE) ) {
87 ch = getch();
88 }
89 }
90
91 void
92 llaccept(t)
93 LLtoken *t;
94 {
95 switch(t->llstate) {
96 case NORMAL:
97 break;
98 case INSERT:
99 fprintf(stderr,"Insert %s\n", llstrings[t->llterm]);
100 break;
101 case DELETE:
102 fprintf(stderr,"Delete %s\n", llstrings[t->llterm]);
103 break;
104 }
105 }
106
107 #define TVAL (t->llattrib)
108
109 void
110 dump_buffer()
111 {
112 register int i;
113 for(i=0; i<20; i++)
114 (void) fputc(buffer[currentbuf][i], stderr);
115 (void) fputc('\n', stderr);
116 (void) fflush(stderr);
117 }
118
119 int iskey(c, buf)
120 char *c;
121 char **buf;
122 {
123 register int i;
124 static struct { char *key_word; int term_type; } keys[] = {
125 { "SAME", T_SAME },
126 { "DEFAULT", T_DEFAULT },
127 { "NULLACTION", T_NULLACTION },
128 { "STRUCT", T_STRUCT },
129 { "SYNONYM", T_SYNONYM },
130 { "TRANSITIONS", T_TRANSITIONS },
131 { "STATES", T_STATES },
132 { "EVENTS", T_EVENTS },
133 { "PCB", T_PCB },
134 { "INCLUDE", T_INCLUDE },
135 { "PROTOCOL", T_PROTOCOL },
136 { 0, 0},
137 };
138
139 for (i = 0; keys[i].key_word ; i++) {
140 if( !strcmp(c, (*buf = keys[i].key_word) ) ) {
141 return ( keys[i].term_type );
142 }
143 }
144 *buf = (char *)0;
145 return(0);
146 }
147
148 void
149 getstr(o,c)
150 /* c is the string delimiter
151 * allow the delimiter to be escaped
152 * the messy part: translate $ID to
153 * e->ev_union.ID
154 * where ID is an event with a non-zero obj_struc
155 * need we check for the field???
156 */
157 char o,c;
158 {
159 register int nested = 1;
160 register int allow_nesting = (o==c)?-1:1;
161
162 IFDEBUG(S)
163 fprintf(stdout,"getstr: ch=%c, delimiters %c %c\n",
164 ch,o, c);
165 fprintf(stdout,"getstr: buffptr 0x%p, currentbuf 0x%x\n",
166 buffptr, currentbuf);
167 ENDDEBUG
168
169 if( ch == c ) nested--;
170 while(nested) {
171 if(ch == '\0') {
172 fprintf(stderr,
173 "Eof inside of a string, delims= %c,%c, nesting %d",c,o, nested);
174 Exit(-1);
175 /* notreached */
176 } else if(ch == '$') {
177 /* might be an attribute */
178 IFDEBUG(S)
179 fprintf(stdout,"getstr: atttribute?\n");
180 ENDDEBUG
181
182 /* assume it's an event */
183 /* addbuf is a macro so this isn't as bad as
184 * it looks
185 * add "e->ev_union."
186 */
187 if( (ch = getch()) == '$' ) {
188 addbuf('e'); addbuf('-'); addbuf('>');
189 addbuf('e'); addbuf('v'); addbuf('_');
190 addbuf('u'); addbuf('n'); addbuf('i');
191 addbuf('o'); addbuf('n');
192 addbuf('.');
193 AddCurrentEventName(& buffptr);
194 } else {
195 char *obufp = buffptr;
196
197 do {
198 addbuf(ch);
199 ch = getch();
200 } while(chtype[ch] & LETTER);
201 addbuf('\0');
202 if( !strncmp(obufp, synonyms[PCB_SYN],
203 strlen(synonyms[PCB_SYN]) )) {
204 buffptr = obufp;
205 addbuf('p');
206 } else if( !strncmp(obufp, synonyms[EVENT_SYN],
207 strlen(synonyms[EVENT_SYN]))) {
208 buffptr = obufp;
209 addbuf('e');
210 } else {
211 fprintf(stderr, "Unknown synonym %s\n", obufp);
212 Exit(-1);
213 }
214 if(ch == '.') {
215 addbuf('-'); addbuf('>');
216 } else {
217 /* needs to be checked for nesting */
218 goto check;
219 }
220 }
221 /* end of attribute handling */
222 goto skip;
223 } else if(ch == '\\') {
224 /* possible escape - this is kludgy beyond belief:
225 * \ is used to escape open and closing delimiters
226 * and '$'
227 * otherwise it's passed through to be compiled by C
228 */
229 ch = getch();
230 if( (ch != o ) && (ch != c) && (ch != '$') ) {
231 /* may need to handle case where \ is last char in file... */
232 /* don't treat is as escape; not open or close so
233 * don't have to worry about nesting either
234 */
235 addbuf('\\');
236 }
237 }
238 addbuf(ch);
239 skip:
240 ch = getch();
241 check:
242 if( ch == o ) nested += allow_nesting;
243 else if( ch == c ) nested--;
244 if ( (buffptr - buffer[currentbuf]) > LINELEN) {
245 fprintf(stderr,
246 "%s too long.\n", (o=='{')?"Action":"Predicate"); /*}*/
247 fprintf(stderr,
248 "buffptr, currentbuf 0x%p, 0x%x\n",buffptr,currentbuf );
249 Exit(-1);
250 }
251 IFDEBUG(S)
252 fprintf(stdout,"loop in getstr: ch 0x%x,%c o=%c,c=%c nested=%d\n",
253 ch,ch,o,c,nested);
254 ENDDEBUG
255 }
256 addbuf(ch);
257 addbuf('\0');
258
259 IFDEBUG(S)
260 fprintf(stdout,"exit getstr: got %s\n", buffer[currentbuf]);
261 fprintf(stdout,"exit getstr: buffptr 0x%p, currentbuf 0x%x\n",
262 buffptr, currentbuf);
263 ENDDEBUG
264 }
265
266 int
267 getch()
268 {
269 char c;
270 extern FILE *infile;
271 extern int lineno;
272
273 c = fgetc(infile) ;
274 if (c == '\n') lineno++;
275 if ((int)c == EOF) c = (char)0;
276 if (feof(infile)) c = (char) 0;
277 IFDEBUG(e)
278 fprintf(stdout, "getch: 0x%x\n", c);
279 (void) fputc( c, stdout);
280 fflush(stdout);
281 ENDDEBUG
282
283 return c;
284 }
285
286 void
287 llscan(t)
288 LLtoken *t;
289 {
290 char c;
291
292 t->llstate = NORMAL;
293
294 ++currentbuf;
295 currentbuf&=1;
296 again:
297 buffptr = &buffer[currentbuf][0];
298
299 skip();
300
301 switch(chtype[ch]) {
302
303 case EOFILE:
304 t->llterm = T_ENDMARKER;
305 break;
306
307 case UNUSED:
308 fprintf(stderr, "Illegal character in input - 0x%x ignored.", ch);
309 ch = getch();
310 goto again;
311
312 case OPCHAR:
313
314 switch(ch) {
315
316 case '/':
317 /* possible comment : elide ; kludge */
318 IFDEBUG(S)
319 fprintf(stdout, "Comment ch=%c\n", ch);
320 ENDDEBUG
321 c = getch();
322 if (c != '*') {
323 fprintf(stderr,"Syntax error : character(0x%x) ignored", ch);
324 ch = c;
325 goto again;
326 } else {
327 register int state = 2, whatchar=0;
328 static int dfa[3][3] = {
329 /* done seen-star middle */
330 /* star */ { 0, 1, 1 },
331 /* / */ { 0, 0, 2 },
332 /* other */ { 0, 2, 2 }
333 };
334
335 while( state ) {
336 if( (c = getch()) == (char)0)
337 break;
338 whatchar = (c=='*')?0:(c=='/'?1:2);
339 IFDEBUG(S)
340 fprintf(stdout,
341 "comment: whatchar = %d, c = 0x%x,%c, oldstate=%d",
342 whatchar, c,c, state);
343 ENDDEBUG
344 state = dfa[whatchar][state];
345 IFDEBUG(S)
346 fprintf(stdout, ", newstate=%d\n", state);
347 ENDDEBUG
348 }
349 if(state) {
350 fprintf(stderr,
351 "Syntax error: end of file inside a comment");
352 Exit(-1);
353 } else ch = getch();
354 }
355 IFDEBUG(S)
356 fprintf(stdout, "end of comment at 0x%x,%c\n",ch,ch);
357 ENDDEBUG
358 goto again;
359
360
361 case '*':
362 t->llterm = T_STAR;
363 break;
364
365 case ',':
366 t->llterm = T_COMMA;
367 break;
368
369 case ';':
370 t->llterm = T_SEMI;
371 break;
372
373 case '<':
374 t->llterm = T_LANGLE;
375 break;
376
377 case '=':
378 t->llterm = T_EQUAL;
379 break;
380
381 case '[':
382 t->llterm = T_LBRACK;
383 break;
384
385 case ']':
386 t->llterm = T_RBRACK;
387 break;
388
389 #ifdef T_FSTRING
390 case '"':
391 t->llterm = T_FSTRING;
392 addbuf(ch);
393 ch = getch();
394 getstr('"', '"');
395 TVAL.FSTRING.address = stash(buffer[currentbuf]);
396 break;
397 #endif /* T_FSTRING */
398
399 case '(':
400 t->llterm = T_PREDICATE;
401 getstr(ch, ')' );
402 TVAL.PREDICATE.address = buffer[currentbuf];
403 break;
404
405 case '{':
406 t->llterm = T_ACTION;
407 getstr(ch, '}');
408 TVAL.ACTION.address = buffer[currentbuf];
409 break;
410
411 default:
412 fprintf(stderr,"Syntax error : character(0x%x) ignored", ch);
413 ch = getch();
414 goto again;
415
416 }
417 ch = getch();
418 break;
419
420 case LETTER:
421 do {
422 addbuf(ch);
423 ch = getch();
424 } while(chtype[ch] & (LETTER | DIGITS));
425
426 addbuf('\0');
427
428 t->llterm = iskey(buffer[currentbuf], &TVAL.ID.address);
429 if(!t->llterm) {
430 t->llterm = T_ID;
431 TVAL.ID.address = buffer[currentbuf];
432 }
433 IFDEBUG(S)
434 fprintf(stdout, "llscan: id or keyword 0x%p, %s\n",
435 TVAL.ID.address, TVAL.ID.address);
436 ENDDEBUG
437 break;
438
439 default:
440 fprintf(stderr, "Snark in llscan: chtype=0x%x, ch=0x%x\n",
441 chtype[ch], ch);
442 }
443 }
Cache object: b0cff8fab69d9105246166c5c8fd0485
|