0b55f123 |
1 | /***** spin: spinlex.c *****/ |
2 | |
3 | /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ |
4 | /* All Rights Reserved. This software is for educational purposes only. */ |
5 | /* No guarantee whatsoever is expressed or implied by the distribution of */ |
6 | /* this code. Permission is given to distribute this code provided that */ |
7 | /* this introductory message is not removed and no monies are exchanged. */ |
8 | /* Software written by Gerard J. Holzmann. For tool documentation see: */ |
9 | /* http://spinroot.com/ */ |
10 | /* Send all bug-reports and/or questions to: bugs@spinroot.com */ |
11 | |
12 | #include <stdlib.h> |
13 | #include "spin.h" |
14 | #include "y.tab.h" |
15 | |
16 | #define MAXINL 16 /* max recursion depth inline fcts */ |
17 | #define MAXPAR 32 /* max params to an inline call */ |
18 | #define MAXLEN 512 /* max len of an actual parameter text */ |
19 | |
20 | typedef struct IType { |
21 | Symbol *nm; /* name of the type */ |
22 | Lextok *cn; /* contents */ |
23 | Lextok *params; /* formal pars if any */ |
24 | char **anms; /* literal text for actual pars */ |
25 | char *prec; /* precondition for c_code or c_expr */ |
26 | int dln, cln; /* def and call linenr */ |
27 | Symbol *dfn, *cfn; /* def and call filename */ |
28 | struct IType *nxt; /* linked list */ |
29 | } IType; |
30 | |
31 | typedef struct C_Added { |
32 | Symbol *s; |
33 | Symbol *t; |
34 | Symbol *ival; |
35 | struct C_Added *nxt; |
36 | } C_Added; |
37 | |
38 | extern RunList *X; |
39 | extern ProcList *rdy; |
40 | extern Symbol *Fname; |
41 | extern Symbol *context, *owner; |
42 | extern YYSTYPE yylval; |
43 | extern short has_last, has_code; |
44 | extern int verbose, IArgs, hastrack, separate; |
45 | |
46 | short has_stack = 0; |
47 | int lineno = 1; |
48 | char yytext[2048]; |
49 | FILE *yyin, *yyout; |
50 | |
51 | static C_Added *c_added, *c_tracked; |
52 | static IType *Inline_stub[MAXINL]; |
53 | static char *ReDiRect; |
54 | static char *Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN]; |
55 | static unsigned char in_comment=0; |
56 | static int IArgno = 0, Inlining = -1; |
57 | static int check_name(char *); |
58 | |
59 | #if 1 |
60 | #define Token(y) { if (in_comment) goto again; \ |
61 | yylval = nn(ZN,0,ZN,ZN); return y; } |
62 | |
63 | #define ValToken(x, y) { if (in_comment) goto again; \ |
64 | yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; } |
65 | |
66 | #define SymToken(x, y) { if (in_comment) goto again; \ |
67 | yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; } |
68 | #else |
69 | #define Token(y) { yylval = nn(ZN,0,ZN,ZN); \ |
70 | if (!in_comment) return y; else goto again; } |
71 | |
72 | #define ValToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \ |
73 | if (!in_comment) return y; else goto again; } |
74 | |
75 | #define SymToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \ |
76 | if (!in_comment) return y; else goto again; } |
77 | #endif |
78 | |
79 | static int getinline(void); |
80 | static void uninline(void); |
81 | |
82 | #if 1 |
83 | #define Getchar() ((Inlining<0)?getc(yyin):getinline()) |
84 | #define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline(); } |
85 | |
86 | #else |
87 | |
88 | static int |
89 | Getchar(void) |
90 | { int c; |
91 | if (Inlining<0) |
92 | c = getc(yyin); |
93 | else |
94 | c = getinline(); |
95 | if (0) |
96 | { printf("<%c:%d>[%d] ", c, c, Inlining); |
97 | } |
98 | return c; |
99 | } |
100 | |
101 | static void |
102 | Ungetch(int c) |
103 | { |
104 | if (Inlining<0) |
105 | ungetc(c,yyin); |
106 | else |
107 | uninline(); |
108 | #if 1 |
109 | printf("<bs>"); |
110 | #endif |
111 | } |
112 | #endif |
113 | |
114 | static int |
115 | notquote(int c) |
116 | { return (c != '\"' && c != '\n'); |
117 | } |
118 | |
119 | int |
120 | isalnum_(int c) |
121 | { return (isalnum(c) || c == '_'); |
122 | } |
123 | |
124 | static int |
125 | isalpha_(int c) |
126 | { return isalpha(c); /* could be macro */ |
127 | } |
128 | |
129 | static int |
130 | isdigit_(int c) |
131 | { return isdigit(c); /* could be macro */ |
132 | } |
133 | |
134 | static void |
135 | getword(int first, int (*tst)(int)) |
136 | { int i=0, c; |
137 | |
138 | yytext[i++]= (char) first; |
139 | while (tst(c = Getchar())) |
140 | { yytext[i++] = (char) c; |
141 | if (c == '\\') |
142 | { c = Getchar(); |
143 | yytext[i++] = (char) c; /* no tst */ |
144 | } } |
145 | yytext[i] = '\0'; |
146 | Ungetch(c); |
147 | } |
148 | |
149 | static int |
150 | follow(int tok, int ifyes, int ifno) |
151 | { int c; |
152 | |
153 | if ((c = Getchar()) == tok) |
154 | return ifyes; |
155 | Ungetch(c); |
156 | |
157 | return ifno; |
158 | } |
159 | |
160 | static IType *seqnames; |
161 | |
162 | static void |
163 | def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms) |
164 | { IType *tmp; |
165 | char *nw = (char *) emalloc(strlen(ptr)+1); |
166 | strcpy(nw, ptr); |
167 | |
168 | for (tmp = seqnames; tmp; tmp = tmp->nxt) |
169 | if (!strcmp(s->name, tmp->nm->name)) |
170 | { non_fatal("procedure name %s redefined", |
171 | tmp->nm->name); |
172 | tmp->cn = (Lextok *) nw; |
173 | tmp->params = nms; |
174 | tmp->dln = ln; |
175 | tmp->dfn = Fname; |
176 | return; |
177 | } |
178 | tmp = (IType *) emalloc(sizeof(IType)); |
179 | tmp->nm = s; |
180 | tmp->cn = (Lextok *) nw; |
181 | tmp->params = nms; |
182 | if (strlen(prc) > 0) |
183 | { tmp->prec = (char *) emalloc(strlen(prc)+1); |
184 | strcpy(tmp->prec, prc); |
185 | } |
186 | tmp->dln = ln; |
187 | tmp->dfn = Fname; |
188 | tmp->nxt = seqnames; |
189 | seqnames = tmp; |
190 | } |
191 | |
192 | void |
193 | gencodetable(FILE *fd) |
194 | { IType *tmp; |
195 | char *q; |
196 | int cnt; |
197 | |
198 | if (separate == 2) return; |
199 | |
200 | fprintf(fd, "struct {\n"); |
201 | fprintf(fd, " char *c; char *t;\n"); |
202 | fprintf(fd, "} code_lookup[] = {\n"); |
203 | |
204 | if (has_code) |
205 | for (tmp = seqnames; tmp; tmp = tmp->nxt) |
206 | if (tmp->nm->type == CODE_FRAG |
207 | || tmp->nm->type == CODE_DECL) |
208 | { fprintf(fd, "\t{ \"%s\", ", |
209 | tmp->nm->name); |
210 | q = (char *) tmp->cn; |
211 | |
212 | while (*q == '\n' || *q == '\r' || *q == '\\') |
213 | q++; |
214 | |
215 | fprintf(fd, "\""); |
216 | cnt = 0; |
217 | while (*q && cnt < 1024) /* pangen1.h allows 2048 */ |
218 | { switch (*q) { |
219 | case '"': |
220 | fprintf(fd, "\\\""); |
221 | break; |
222 | case '%': |
223 | fprintf(fd, "%%"); |
224 | break; |
225 | case '\n': |
226 | fprintf(fd, "\\n"); |
227 | break; |
228 | default: |
229 | putc(*q, fd); |
230 | break; |
231 | } |
232 | q++; cnt++; |
233 | } |
234 | if (*q) fprintf(fd, "..."); |
235 | fprintf(fd, "\""); |
236 | fprintf(fd, " },\n"); |
237 | } |
238 | |
239 | fprintf(fd, " { (char *) 0, \"\" }\n"); |
240 | fprintf(fd, "};\n"); |
241 | } |
242 | |
243 | static int |
244 | iseqname(char *t) |
245 | { IType *tmp; |
246 | |
247 | for (tmp = seqnames; tmp; tmp = tmp->nxt) |
248 | { if (!strcmp(t, tmp->nm->name)) |
249 | return 1; |
250 | } |
251 | return 0; |
252 | } |
253 | |
254 | static int |
255 | getinline(void) |
256 | { int c; |
257 | |
258 | if (ReDiRect) |
259 | { c = *ReDiRect++; |
260 | if (c == '\0') |
261 | { ReDiRect = (char *) 0; |
262 | c = *Inliner[Inlining]++; |
263 | } |
264 | } else |
265 | c = *Inliner[Inlining]++; |
266 | |
267 | if (c == '\0') |
268 | { lineno = Inline_stub[Inlining]->cln; |
269 | Fname = Inline_stub[Inlining]->cfn; |
270 | Inlining--; |
271 | #if 0 |
272 | if (verbose&32) |
273 | printf("spin: line %d, done inlining %s\n", |
274 | lineno, Inline_stub[Inlining+1]->nm->name); |
275 | #endif |
276 | return Getchar(); |
277 | } |
278 | return c; |
279 | } |
280 | |
281 | static void |
282 | uninline(void) |
283 | { |
284 | if (ReDiRect) |
285 | ReDiRect--; |
286 | else |
287 | Inliner[Inlining]--; |
288 | } |
289 | |
290 | IType * |
291 | find_inline(char *s) |
292 | { IType *tmp; |
293 | |
294 | for (tmp = seqnames; tmp; tmp = tmp->nxt) |
295 | if (!strcmp(s, tmp->nm->name)) |
296 | break; |
297 | if (!tmp) |
298 | fatal("cannot happen, missing inline def %s", s); |
299 | |
300 | return tmp; |
301 | } |
302 | |
303 | void |
304 | c_state(Symbol *s, Symbol *t, Symbol *ival) /* name, scope, ival */ |
305 | { C_Added *r; |
306 | |
307 | r = (C_Added *) emalloc(sizeof(C_Added)); |
308 | r->s = s; /* pointer to a data object */ |
309 | r->t = t; /* size of object, or "global", or "local proctype_name" */ |
310 | r->ival = ival; |
311 | r->nxt = c_added; |
312 | c_added = r; |
313 | } |
314 | |
315 | void |
316 | c_track(Symbol *s, Symbol *t, Symbol *stackonly) /* name, size */ |
317 | { C_Added *r; |
318 | |
319 | r = (C_Added *) emalloc(sizeof(C_Added)); |
320 | r->s = s; |
321 | r->t = t; |
322 | r->ival = stackonly; /* abuse of name */ |
323 | r->nxt = c_tracked; |
324 | c_tracked = r; |
325 | |
326 | if (stackonly != ZS) |
327 | { if (strcmp(stackonly->name, "\"Matched\"") == 0) |
328 | r->ival = ZS; /* the default */ |
329 | else if (strcmp(stackonly->name, "\"UnMatched\"") != 0 |
330 | && strcmp(stackonly->name, "\"unMatched\"") != 0 |
331 | && strcmp(stackonly->name, "\"StackOnly\"") != 0) |
332 | non_fatal("expecting '[Un]Matched', saw %s", stackonly->name); |
333 | else |
334 | has_stack = 1; /* unmatched stack */ |
335 | } |
336 | } |
337 | |
338 | char * |
339 | jump_etc(char *op) |
340 | { char *p = op; |
341 | |
342 | /* kludgy - try to get the type separated from the name */ |
343 | |
344 | while (*p == ' ' || *p == '\t') |
345 | p++; /* initial white space */ |
346 | while (*p != ' ' && *p != '\t') |
347 | p++; /* type name */ |
348 | while (*p == ' ' || *p == '\t') |
349 | p++; /* white space */ |
350 | while (*p == '*') |
351 | p++; /* decorations */ |
352 | while (*p == ' ' || *p == '\t') |
353 | p++; /* white space */ |
354 | |
355 | if (*p == '\0') |
356 | fatal("c_state format (%s)", op); |
357 | |
358 | if (strchr(p, '[') |
359 | && !strchr(p, '{')) |
360 | { non_fatal("array initialization error, c_state (%s)", p); |
361 | return (char *) 0; |
362 | } |
363 | |
364 | return p; |
365 | } |
366 | |
367 | void |
368 | c_add_globinit(FILE *fd) |
369 | { C_Added *r; |
370 | char *p, *q; |
371 | |
372 | fprintf(fd, "void\nglobinit(void)\n{\n"); |
373 | for (r = c_added; r; r = r->nxt) |
374 | { if (r->ival == ZS) |
375 | continue; |
376 | |
377 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0) |
378 | { for (q = r->ival->name; *q; q++) |
379 | { if (*q == '\"') |
380 | *q = ' '; |
381 | if (*q == '\\') |
382 | *q++ = ' '; /* skip over the next */ |
383 | } |
384 | p = jump_etc(r->s->name); /* e.g., "int **q" */ |
385 | if (p) |
386 | fprintf(fd, " now.%s = %s;\n", p, r->ival->name); |
387 | |
388 | } else |
389 | if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0) |
390 | { for (q = r->ival->name; *q; q++) |
391 | { if (*q == '\"') |
392 | *q = ' '; |
393 | if (*q == '\\') |
394 | *q++ = ' '; /* skip over the next */ |
395 | } |
396 | p = jump_etc(r->s->name); /* e.g., "int **q" */ |
397 | if (p) |
398 | fprintf(fd, " %s = %s;\n", p, r->ival->name); /* no now. prefix */ |
399 | |
400 | } } |
401 | fprintf(fd, "}\n"); |
402 | } |
403 | |
404 | void |
405 | c_add_locinit(FILE *fd, int tpnr, char *pnm) |
406 | { C_Added *r; |
407 | char *p, *q, *s; |
408 | int frst = 1; |
409 | |
410 | fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr); |
411 | for (r = c_added; r; r = r->nxt) |
412 | if (r->ival != ZS |
413 | && strncmp(r->t->name, " Local", strlen(" Local")) == 0) |
414 | { for (q = r->ival->name; *q; q++) |
415 | if (*q == '\"') |
416 | *q = ' '; |
417 | |
418 | p = jump_etc(r->s->name); /* e.g., "int **q" */ |
419 | |
420 | q = r->t->name + strlen(" Local"); |
421 | while (*q == ' ' || *q == '\t') |
422 | q++; /* process name */ |
423 | |
424 | s = (char *) emalloc(strlen(q)+1); |
425 | strcpy(s, q); |
426 | |
427 | q = &s[strlen(s)-1]; |
428 | while (*q == ' ' || *q == '\t') |
429 | *q-- = '\0'; |
430 | |
431 | if (strcmp(pnm, s) != 0) |
432 | continue; |
433 | |
434 | if (frst) |
435 | { fprintf(fd, "\tuchar *this = pptr(h);\n"); |
436 | frst = 0; |
437 | } |
438 | |
439 | if (p) |
440 | fprintf(fd, " ((P%d *)this)->%s = %s;\n", |
441 | tpnr, p, r->ival->name); |
442 | |
443 | } |
444 | fprintf(fd, "}\n"); |
445 | } |
446 | |
447 | /* tracking: |
448 | 1. for non-global and non-local c_state decls: add up all the sizes in c_added |
449 | 2. add a global char array of that size into now |
450 | 3. generate a routine that memcpy's the required values into that array |
451 | 4. generate a call to that routine |
452 | */ |
453 | |
454 | void |
455 | c_preview(void) |
456 | { C_Added *r; |
457 | |
458 | hastrack = 0; |
459 | if (c_tracked) |
460 | hastrack = 1; |
461 | else |
462 | for (r = c_added; r; r = r->nxt) |
463 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0 |
464 | && strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0 |
465 | && strncmp(r->t->name, " Local", strlen(" Local")) != 0) |
466 | { hastrack = 1; /* c_state variant now obsolete */ |
467 | break; |
468 | } |
469 | } |
470 | |
471 | int |
472 | c_add_sv(FILE *fd) /* 1+2 -- called in pangen1.c */ |
473 | { C_Added *r; |
474 | int cnt = 0; |
475 | |
476 | if (!c_added && !c_tracked) return 0; |
477 | |
478 | for (r = c_added; r; r = r->nxt) /* pickup global decls */ |
479 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0) |
480 | fprintf(fd, " %s;\n", r->s->name); |
481 | |
482 | for (r = c_added; r; r = r->nxt) |
483 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0 |
484 | && strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0 |
485 | && strncmp(r->t->name, " Local", strlen(" Local")) != 0) |
486 | { cnt++; /* obsolete use */ |
487 | } |
488 | |
489 | for (r = c_tracked; r; r = r->nxt) |
490 | cnt++; /* preferred use */ |
491 | |
492 | if (cnt == 0) return 0; |
493 | |
494 | cnt = 0; |
495 | fprintf(fd, " uchar c_state["); |
496 | for (r = c_added; r; r = r->nxt) |
497 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0 |
498 | && strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0 |
499 | && strncmp(r->t->name, " Local", strlen(" Local")) != 0) |
500 | { fprintf(fd, "%ssizeof(%s)", |
501 | (cnt==0)?"":"+", r->t->name); |
502 | cnt++; |
503 | } |
504 | |
505 | for (r = c_tracked; r; r = r->nxt) |
506 | { if (r->ival != ZS) continue; |
507 | |
508 | fprintf(fd, "%s%s", |
509 | (cnt==0)?"":"+", r->t->name); |
510 | cnt++; |
511 | } |
512 | |
513 | if (cnt == 0) fprintf(fd, "4"); /* now redundant */ |
514 | fprintf(fd, "];\n"); |
515 | return 1; |
516 | } |
517 | |
518 | void |
519 | c_stack_size(FILE *fd) |
520 | { C_Added *r; |
521 | int cnt = 0; |
522 | |
523 | for (r = c_tracked; r; r = r->nxt) |
524 | if (r->ival != ZS) |
525 | { fprintf(fd, "%s%s", |
526 | (cnt==0)?"":"+", r->t->name); |
527 | cnt++; |
528 | } |
529 | if (cnt == 0) |
530 | { fprintf(fd, "WS"); |
531 | } |
532 | } |
533 | |
534 | void |
535 | c_add_stack(FILE *fd) |
536 | { C_Added *r; |
537 | int cnt = 0; |
538 | |
539 | if ((!c_added && !c_tracked) || !has_stack) |
540 | { return; |
541 | } |
542 | |
543 | for (r = c_tracked; r; r = r->nxt) |
544 | if (r->ival != ZS) |
545 | { cnt++; |
546 | } |
547 | |
548 | if (cnt > 0) |
549 | { fprintf(fd, " uchar c_stack[StackSize];\n"); |
550 | } |
551 | } |
552 | |
553 | void |
554 | c_add_hidden(FILE *fd) |
555 | { C_Added *r; |
556 | |
557 | for (r = c_added; r; r = r->nxt) /* pickup hidden decls */ |
558 | if (strncmp(r->t->name, "\"Hidden\"", strlen("\"Hidden\"")) == 0) |
559 | { r->s->name[strlen(r->s->name)-1] = ' '; |
560 | fprintf(fd, "%s; /* Hidden */\n", &r->s->name[1]); |
561 | r->s->name[strlen(r->s->name)-1] = '"'; |
562 | } |
563 | /* called before c_add_def - quotes are still there */ |
564 | } |
565 | |
566 | void |
567 | c_add_loc(FILE *fd, char *s) /* state vector entries for proctype s */ |
568 | { C_Added *r; |
569 | static char buf[1024]; |
570 | char *p; |
571 | |
572 | if (!c_added) return; |
573 | |
574 | strcpy(buf, s); |
575 | strcat(buf, " "); |
576 | for (r = c_added; r; r = r->nxt) /* pickup local decls */ |
577 | if (strncmp(r->t->name, " Local", strlen(" Local")) == 0) |
578 | { p = r->t->name + strlen(" Local"); |
579 | while (*p == ' ' || *p == '\t') |
580 | p++; |
581 | if (strcmp(p, buf) == 0) |
582 | fprintf(fd, " %s;\n", r->s->name); |
583 | } |
584 | } |
585 | void |
586 | c_add_def(FILE *fd) /* 3 - called in plunk_c_fcts() */ |
587 | { C_Added *r; |
588 | |
589 | fprintf(fd, "#if defined(C_States) && defined(HAS_TRACK)\n"); |
590 | for (r = c_added; r; r = r->nxt) |
591 | { r->s->name[strlen(r->s->name)-1] = ' '; |
592 | r->s->name[0] = ' '; /* remove the "s */ |
593 | |
594 | r->t->name[strlen(r->t->name)-1] = ' '; |
595 | r->t->name[0] = ' '; |
596 | |
597 | if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0 |
598 | || strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0 |
599 | || strncmp(r->t->name, " Local", strlen(" Local")) == 0) |
600 | continue; |
601 | |
602 | if (strchr(r->s->name, '&')) |
603 | fatal("dereferencing state object: %s", r->s->name); |
604 | |
605 | fprintf(fd, "extern %s %s;\n", r->t->name, r->s->name); |
606 | } |
607 | for (r = c_tracked; r; r = r->nxt) |
608 | { r->s->name[strlen(r->s->name)-1] = ' '; |
609 | r->s->name[0] = ' '; /* remove " */ |
610 | |
611 | r->t->name[strlen(r->t->name)-1] = ' '; |
612 | r->t->name[0] = ' '; |
613 | } |
614 | |
615 | if (separate == 2) |
616 | { fprintf(fd, "#endif\n"); |
617 | return; |
618 | } |
619 | |
620 | if (has_stack) |
621 | { fprintf(fd, "int cpu_printf(const char *, ...);\n"); |
622 | fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n"); |
623 | fprintf(fd, "#ifdef VERBOSE\n"); |
624 | fprintf(fd, " cpu_printf(\"c_stack %%u\\n\", p_t_r);\n"); |
625 | fprintf(fd, "#endif\n"); |
626 | for (r = c_tracked; r; r = r->nxt) |
627 | { if (r->ival == ZS) continue; |
628 | |
629 | fprintf(fd, "\tif(%s)\n", r->s->name); |
630 | fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n", |
631 | r->s->name, r->t->name); |
632 | fprintf(fd, "\telse\n"); |
633 | fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n", |
634 | r->t->name); |
635 | fprintf(fd, "\tp_t_r += %s;\n", r->t->name); |
636 | } |
637 | fprintf(fd, "}\n\n"); |
638 | } |
639 | |
640 | fprintf(fd, "void\nc_update(uchar *p_t_r)\n{\n"); |
641 | fprintf(fd, "#ifdef VERBOSE\n"); |
642 | fprintf(fd, " printf(\"c_update %%u\\n\", p_t_r);\n"); |
643 | fprintf(fd, "#endif\n"); |
644 | for (r = c_added; r; r = r->nxt) |
645 | { if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0 |
646 | || strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0 |
647 | || strncmp(r->t->name, " Local", strlen(" Local")) == 0) |
648 | continue; |
649 | |
650 | fprintf(fd, "\tmemcpy(p_t_r, &%s, sizeof(%s));\n", |
651 | r->s->name, r->t->name); |
652 | fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name); |
653 | } |
654 | |
655 | for (r = c_tracked; r; r = r->nxt) |
656 | { if (r->ival) continue; |
657 | |
658 | fprintf(fd, "\tif(%s)\n", r->s->name); |
659 | fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n", |
660 | r->s->name, r->t->name); |
661 | fprintf(fd, "\telse\n"); |
662 | fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n", |
663 | r->t->name); |
664 | fprintf(fd, "\tp_t_r += %s;\n", r->t->name); |
665 | } |
666 | |
667 | fprintf(fd, "}\n"); |
668 | |
669 | if (has_stack) |
670 | { fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n"); |
671 | fprintf(fd, "#ifdef VERBOSE\n"); |
672 | fprintf(fd, " cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n"); |
673 | fprintf(fd, "#endif\n"); |
674 | for (r = c_tracked; r; r = r->nxt) |
675 | { if (r->ival == ZS) continue; |
676 | |
677 | fprintf(fd, "\tif(%s)\n", r->s->name); |
678 | fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n", |
679 | r->s->name, r->t->name); |
680 | fprintf(fd, "\tp_t_r += %s;\n", r->t->name); |
681 | } |
682 | fprintf(fd, "}\n"); |
683 | } |
684 | |
685 | fprintf(fd, "void\nc_revert(uchar *p_t_r)\n{\n"); |
686 | fprintf(fd, "#ifdef VERBOSE\n"); |
687 | fprintf(fd, " printf(\"c_revert %%u\\n\", p_t_r);\n"); |
688 | fprintf(fd, "#endif\n"); |
689 | for (r = c_added; r; r = r->nxt) |
690 | { if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0 |
691 | || strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0 |
692 | || strncmp(r->t->name, " Local", strlen(" Local")) == 0) |
693 | continue; |
694 | |
695 | fprintf(fd, "\tmemcpy(&%s, p_t_r, sizeof(%s));\n", |
696 | r->s->name, r->t->name); |
697 | fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name); |
698 | } |
699 | for (r = c_tracked; r; r = r->nxt) |
700 | { if (r->ival != ZS) continue; |
701 | |
702 | fprintf(fd, "\tif(%s)\n", r->s->name); |
703 | fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n", |
704 | r->s->name, r->t->name); |
705 | fprintf(fd, "\tp_t_r += %s;\n", r->t->name); |
706 | } |
707 | |
708 | fprintf(fd, "}\n"); |
709 | fprintf(fd, "#endif\n"); |
710 | } |
711 | |
712 | void |
713 | plunk_reverse(FILE *fd, IType *p, int matchthis) |
714 | { char *y, *z; |
715 | |
716 | if (!p) return; |
717 | plunk_reverse(fd, p->nxt, matchthis); |
718 | |
719 | if (!p->nm->context |
720 | && p->nm->type == matchthis) |
721 | { fprintf(fd, "\n/* start of %s */\n", p->nm->name); |
722 | z = (char *) p->cn; |
723 | while (*z == '\n' || *z == '\r' || *z == '\\') |
724 | z++; |
725 | /* e.g.: \#include "..." */ |
726 | |
727 | y = z; |
728 | while ((y = strstr(y, "\\#")) != NULL) |
729 | { *y = '\n'; y++; |
730 | } |
731 | |
732 | fprintf(fd, "%s\n", z); |
733 | fprintf(fd, "\n/* end of %s */\n", p->nm->name); |
734 | } |
735 | } |
736 | |
737 | void |
738 | plunk_c_decls(FILE *fd) |
739 | { |
740 | plunk_reverse(fd, seqnames, CODE_DECL); |
741 | } |
742 | |
743 | void |
744 | plunk_c_fcts(FILE *fd) |
745 | { |
746 | if (separate == 2 && hastrack) |
747 | { c_add_def(fd); |
748 | return; |
749 | } |
750 | |
751 | c_add_hidden(fd); |
752 | plunk_reverse(fd, seqnames, CODE_FRAG); |
753 | |
754 | if (c_added || c_tracked) /* enables calls to c_revert and c_update */ |
755 | fprintf(fd, "#define C_States 1\n"); |
756 | else |
757 | fprintf(fd, "#undef C_States\n"); |
758 | |
759 | if (hastrack) |
760 | c_add_def(fd); |
761 | |
762 | c_add_globinit(fd); |
763 | do_locinits(fd); |
764 | } |
765 | |
766 | static void |
767 | check_inline(IType *tmp) |
768 | { char buf[128]; |
769 | ProcList *p; |
770 | |
771 | if (!X) return; |
772 | |
773 | for (p = rdy; p; p = p->nxt) |
774 | { if (strcmp(p->n->name, X->n->name) == 0) |
775 | continue; |
776 | sprintf(buf, "P%s->", p->n->name); |
777 | if (strstr((char *)tmp->cn, buf)) |
778 | { printf("spin: in proctype %s, ref to object in proctype %s\n", |
779 | X->n->name, p->n->name); |
780 | fatal("invalid variable ref in '%s'", tmp->nm->name); |
781 | } } |
782 | } |
783 | |
784 | void |
785 | plunk_expr(FILE *fd, char *s) |
786 | { IType *tmp; |
787 | |
788 | tmp = find_inline(s); |
789 | check_inline(tmp); |
790 | |
791 | fprintf(fd, "%s", (char *) tmp->cn); |
792 | } |
793 | |
794 | void |
795 | preruse(FILE *fd, Lextok *n) /* check a condition for c_expr with preconditions */ |
796 | { IType *tmp; |
797 | |
798 | if (!n) return; |
799 | if (n->ntyp == C_EXPR) |
800 | { tmp = find_inline(n->sym->name); |
801 | if (tmp->prec) |
802 | { fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec); |
803 | fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;"); |
804 | fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec); |
805 | fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec); |
806 | fprintf(fd, "_m = 3; goto P999; } } \n\t\t"); |
807 | } |
808 | } else |
809 | { preruse(fd, n->rgt); |
810 | preruse(fd, n->lft); |
811 | } |
812 | } |
813 | |
814 | int |
815 | glob_inline(char *s) |
816 | { IType *tmp; |
817 | char *bdy; |
818 | |
819 | tmp = find_inline(s); |
820 | bdy = (char *) tmp->cn; |
821 | return (strstr(bdy, "now.") /* global ref or */ |
822 | || strchr(bdy, '(') > bdy); /* possible C-function call */ |
823 | } |
824 | |
825 | void |
826 | plunk_inline(FILE *fd, char *s, int how) /* c_code with precondition */ |
827 | { IType *tmp; |
828 | |
829 | tmp = find_inline(s); |
830 | check_inline(tmp); |
831 | |
832 | fprintf(fd, "{ "); |
833 | if (how && tmp->prec) |
834 | { fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec); |
835 | fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;"); |
836 | fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec); |
837 | fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec); |
838 | fprintf(fd, "_m = 3; goto P999; } } "); |
839 | } |
840 | fprintf(fd, "%s", (char *) tmp->cn); |
841 | fprintf(fd, " }\n"); |
842 | } |
843 | |
844 | void |
845 | no_side_effects(char *s) |
846 | { IType *tmp; |
847 | char *t; |
848 | |
849 | /* could still defeat this check via hidden |
850 | * side effects in function calls, |
851 | * but this will catch at least some cases |
852 | */ |
853 | |
854 | tmp = find_inline(s); |
855 | t = (char *) tmp->cn; |
856 | |
857 | if (strchr(t, ';') |
858 | || strstr(t, "++") |
859 | || strstr(t, "--")) |
860 | { |
861 | bad: lineno = tmp->dln; |
862 | Fname = tmp->dfn; |
863 | non_fatal("c_expr %s has side-effects", s); |
864 | return; |
865 | } |
866 | while ((t = strchr(t, '=')) != NULL) |
867 | { if (*(t-1) == '!' |
868 | || *(t-1) == '>' |
869 | || *(t-1) == '<') |
870 | { t++; |
871 | continue; |
872 | } |
873 | t++; |
874 | if (*t != '=') |
875 | goto bad; |
876 | t++; |
877 | } |
878 | } |
879 | |
880 | void |
881 | pickup_inline(Symbol *t, Lextok *apars) |
882 | { IType *tmp; Lextok *p, *q; int j; |
883 | |
884 | tmp = find_inline(t->name); |
885 | |
886 | if (++Inlining >= MAXINL) |
887 | fatal("inline fcts too deeply nested", 0); |
888 | tmp->cln = lineno; /* remember calling point */ |
889 | tmp->cfn = Fname; /* and filename */ |
890 | |
891 | for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt) |
892 | j++; /* count them */ |
893 | if (p || q) |
894 | fatal("wrong nr of params on call of '%s'", t->name); |
895 | |
896 | tmp->anms = (char **) emalloc(j * sizeof(char *)); |
897 | for (p = apars, j = 0; p; p = p->rgt, j++) |
898 | { tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1); |
899 | strcpy(tmp->anms[j], IArg_cont[j]); |
900 | } |
901 | |
902 | lineno = tmp->dln; /* linenr of def */ |
903 | Fname = tmp->dfn; /* filename of same */ |
904 | Inliner[Inlining] = (char *)tmp->cn; |
905 | Inline_stub[Inlining] = tmp; |
906 | #if 0 |
907 | if (verbose&32) |
908 | printf("spin: line %d, file %s, inlining '%s' (from line %d, file %s)\n", |
909 | tmp->cln, tmp->cfn->name, t->name, tmp->dln, tmp->dfn->name); |
910 | #endif |
911 | for (j = 0; j < Inlining; j++) |
912 | if (Inline_stub[j] == Inline_stub[Inlining]) |
913 | fatal("cyclic inline attempt on: %s", t->name); |
914 | } |
915 | |
916 | static void |
917 | do_directive(int first) |
918 | { int c = first; /* handles lines starting with pound */ |
919 | |
920 | getword(c, isalpha_); |
921 | |
922 | if (strcmp(yytext, "#ident") == 0) |
923 | goto done; |
924 | |
925 | if ((c = Getchar()) != ' ') |
926 | fatal("malformed preprocessor directive - # .", 0); |
927 | |
928 | if (!isdigit_(c = Getchar())) |
929 | fatal("malformed preprocessor directive - # .lineno", 0); |
930 | |
931 | getword(c, isdigit_); |
932 | lineno = atoi(yytext); /* pickup the line number */ |
933 | |
934 | if ((c = Getchar()) == '\n') |
935 | return; /* no filename */ |
936 | |
937 | if (c != ' ') |
938 | fatal("malformed preprocessor directive - .fname", 0); |
939 | |
940 | if ((c = Getchar()) != '\"') |
941 | fatal("malformed preprocessor directive - .fname", 0); |
942 | |
943 | getword(c, notquote); |
944 | if (Getchar() != '\"') |
945 | fatal("malformed preprocessor directive - fname.", 0); |
946 | |
947 | strcat(yytext, "\""); |
948 | Fname = lookup(yytext); |
949 | done: |
950 | while (Getchar() != '\n') |
951 | ; |
952 | } |
953 | |
954 | void |
955 | precondition(char *q) |
956 | { int c, nest = 1; |
957 | |
958 | for (;;) |
959 | { c = Getchar(); |
960 | *q++ = c; |
961 | switch (c) { |
962 | case '\n': |
963 | lineno++; |
964 | break; |
965 | case '[': |
966 | nest++; |
967 | break; |
968 | case ']': |
969 | if (--nest <= 0) |
970 | { *--q = '\0'; |
971 | return; |
972 | } |
973 | break; |
974 | } |
975 | } |
976 | fatal("cannot happen", (char *) 0); /* unreachable */ |
977 | } |
978 | |
979 | |
980 | Symbol * |
981 | prep_inline(Symbol *s, Lextok *nms) |
982 | { int c, nest = 1, dln, firstchar, cnr; |
983 | char *p; |
984 | Lextok *t; |
985 | static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL]; |
986 | static int c_code = 1; |
987 | |
988 | for (t = nms; t; t = t->rgt) |
989 | if (t->lft) |
990 | { if (t->lft->ntyp != NAME) |
991 | fatal("bad param to inline %s", s?s->name:"--"); |
992 | t->lft->sym->hidden |= 32; |
993 | } |
994 | |
995 | if (!s) /* C_Code fragment */ |
996 | { s = (Symbol *) emalloc(sizeof(Symbol)); |
997 | s->name = (char *) emalloc(strlen("c_code")+26); |
998 | sprintf(s->name, "c_code%d", c_code++); |
999 | s->context = context; |
1000 | s->type = CODE_FRAG; |
1001 | } else |
1002 | s->type = PREDEF; |
1003 | |
1004 | p = &Buf1[0]; |
1005 | Buf2[0] = '\0'; |
1006 | for (;;) |
1007 | { c = Getchar(); |
1008 | switch (c) { |
1009 | case '[': |
1010 | if (s->type != CODE_FRAG) |
1011 | goto bad; |
1012 | precondition(&Buf2[0]); /* e.g., c_code [p] { r = p-r; } */ |
1013 | continue; |
1014 | case '{': |
1015 | break; |
1016 | case '\n': |
1017 | lineno++; |
1018 | /* fall through */ |
1019 | case ' ': case '\t': case '\f': case '\r': |
1020 | continue; |
1021 | default : |
1022 | printf("spin: saw char '%c'\n", c); |
1023 | bad: fatal("bad inline: %s", s->name); |
1024 | } |
1025 | break; |
1026 | } |
1027 | dln = lineno; |
1028 | if (s->type == CODE_FRAG) |
1029 | { if (verbose&32) |
1030 | sprintf(Buf1, "\t/* line %d %s */\n\t\t", |
1031 | lineno, Fname->name); |
1032 | else |
1033 | strcpy(Buf1, ""); |
1034 | } else |
1035 | sprintf(Buf1, "\n#line %d %s\n{", lineno, Fname->name); |
1036 | p += strlen(Buf1); |
1037 | firstchar = 1; |
1038 | |
1039 | cnr = 1; /* not zero */ |
1040 | more: |
1041 | *p++ = c = Getchar(); |
1042 | if (p - Buf1 >= SOMETHINGBIG) |
1043 | fatal("inline text too long", 0); |
1044 | switch (c) { |
1045 | case '\n': |
1046 | lineno++; |
1047 | cnr = 0; |
1048 | break; |
1049 | case '{': |
1050 | cnr++; |
1051 | nest++; |
1052 | break; |
1053 | case '}': |
1054 | cnr++; |
1055 | if (--nest <= 0) |
1056 | { *p = '\0'; |
1057 | if (s->type == CODE_FRAG) |
1058 | *--p = '\0'; /* remove trailing '}' */ |
1059 | def_inline(s, dln, &Buf1[0], &Buf2[0], nms); |
1060 | if (firstchar) |
1061 | printf("%3d: %s, warning: empty inline definition (%s)\n", |
1062 | dln, Fname->name, s->name); |
1063 | return s; /* normal return */ |
1064 | } |
1065 | break; |
1066 | case '#': |
1067 | if (cnr == 0) |
1068 | { p--; |
1069 | do_directive(c); /* reads to newline */ |
1070 | break; |
1071 | } /* else fall through */ |
1072 | default: |
1073 | firstchar = 0; |
1074 | case '\t': |
1075 | case ' ': |
1076 | case '\f': |
1077 | cnr++; |
1078 | break; |
1079 | } |
1080 | goto more; |
1081 | } |
1082 | |
1083 | static int |
1084 | lex(void) |
1085 | { int c; |
1086 | |
1087 | again: |
1088 | c = Getchar(); |
1089 | yytext[0] = (char) c; |
1090 | yytext[1] = '\0'; |
1091 | switch (c) { |
1092 | case '\n': /* newline */ |
1093 | lineno++; |
1094 | case '\r': /* carriage return */ |
1095 | goto again; |
1096 | |
1097 | case ' ': case '\t': case '\f': /* white space */ |
1098 | goto again; |
1099 | |
1100 | case '#': /* preprocessor directive */ |
1101 | if (in_comment) goto again; |
1102 | do_directive(c); |
1103 | goto again; |
1104 | |
1105 | case '\"': |
1106 | getword(c, notquote); |
1107 | if (Getchar() != '\"') |
1108 | fatal("string not terminated", yytext); |
1109 | strcat(yytext, "\""); |
1110 | SymToken(lookup(yytext), STRING) |
1111 | |
1112 | case '\'': /* new 3.0.9 */ |
1113 | c = Getchar(); |
1114 | if (c == '\\') |
1115 | { c = Getchar(); |
1116 | if (c == 'n') c = '\n'; |
1117 | else if (c == 'r') c = '\r'; |
1118 | else if (c == 't') c = '\t'; |
1119 | else if (c == 'f') c = '\f'; |
1120 | } |
1121 | if (Getchar() != '\'' && !in_comment) |
1122 | fatal("character quote missing: %s", yytext); |
1123 | ValToken(c, CONST) |
1124 | |
1125 | default: |
1126 | break; |
1127 | } |
1128 | |
1129 | if (isdigit_(c)) |
1130 | { getword(c, isdigit_); |
1131 | ValToken(atoi(yytext), CONST) |
1132 | } |
1133 | |
1134 | if (isalpha_(c) || c == '_') |
1135 | { getword(c, isalnum_); |
1136 | if (!in_comment) |
1137 | { c = check_name(yytext); |
1138 | if (c) return c; |
1139 | /* else fall through */ |
1140 | } |
1141 | goto again; |
1142 | } |
1143 | |
1144 | switch (c) { |
1145 | case '/': c = follow('*', 0, '/'); |
1146 | if (!c) { in_comment = 1; goto again; } |
1147 | break; |
1148 | case '*': c = follow('/', 0, '*'); |
1149 | if (!c) { in_comment = 0; goto again; } |
1150 | break; |
1151 | case ':': c = follow(':', SEP, ':'); break; |
1152 | case '-': c = follow('>', SEMI, follow('-', DECR, '-')); break; |
1153 | case '+': c = follow('+', INCR, '+'); break; |
1154 | case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break; |
1155 | case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break; |
1156 | case '=': c = follow('=', EQ, ASGN); break; |
1157 | case '!': c = follow('=', NE, follow('!', O_SND, SND)); break; |
1158 | case '?': c = follow('?', R_RCV, RCV); break; |
1159 | case '&': c = follow('&', AND, '&'); break; |
1160 | case '|': c = follow('|', OR, '|'); break; |
1161 | case ';': c = SEMI; break; |
1162 | default : break; |
1163 | } |
1164 | Token(c) |
1165 | } |
1166 | |
1167 | static struct { |
1168 | char *s; int tok; int val; char *sym; |
1169 | } Names[] = { |
1170 | {"active", ACTIVE, 0, 0}, |
1171 | {"assert", ASSERT, 0, 0}, |
1172 | {"atomic", ATOMIC, 0, 0}, |
1173 | {"bit", TYPE, BIT, 0}, |
1174 | {"bool", TYPE, BIT, 0}, |
1175 | {"break", BREAK, 0, 0}, |
1176 | {"byte", TYPE, BYTE, 0}, |
1177 | {"c_code", C_CODE, 0, 0}, |
1178 | {"c_decl", C_DECL, 0, 0}, |
1179 | {"c_expr", C_EXPR, 0, 0}, |
1180 | {"c_state", C_STATE, 0, 0}, |
1181 | {"c_track", C_TRACK, 0, 0}, |
1182 | {"D_proctype", D_PROCTYPE, 0, 0}, |
1183 | {"do", DO, 0, 0}, |
1184 | {"chan", TYPE, CHAN, 0}, |
1185 | {"else", ELSE, 0, 0}, |
1186 | {"empty", EMPTY, 0, 0}, |
1187 | {"enabled", ENABLED, 0, 0}, |
1188 | {"eval", EVAL, 0, 0}, |
1189 | {"false", CONST, 0, 0}, |
1190 | {"fi", FI, 0, 0}, |
1191 | {"full", FULL, 0, 0}, |
1192 | {"goto", GOTO, 0, 0}, |
1193 | {"hidden", HIDDEN, 0, ":hide:"}, |
1194 | {"if", IF, 0, 0}, |
1195 | {"init", INIT, 0, ":init:"}, |
1196 | {"int", TYPE, INT, 0}, |
1197 | {"len", LEN, 0, 0}, |
1198 | {"local", ISLOCAL, 0, ":local:"}, |
1199 | {"mtype", TYPE, MTYPE, 0}, |
1200 | {"nempty", NEMPTY, 0, 0}, |
1201 | {"never", CLAIM, 0, ":never:"}, |
1202 | {"nfull", NFULL, 0, 0}, |
1203 | {"notrace", TRACE, 0, ":notrace:"}, |
1204 | {"np_", NONPROGRESS, 0, 0}, |
1205 | {"od", OD, 0, 0}, |
1206 | {"of", OF, 0, 0}, |
1207 | {"pc_value", PC_VAL, 0, 0}, |
1208 | {"pid", TYPE, BYTE, 0}, |
1209 | {"printf", PRINT, 0, 0}, |
1210 | {"printm", PRINTM, 0, 0}, |
1211 | {"priority", PRIORITY, 0, 0}, |
1212 | {"proctype", PROCTYPE, 0, 0}, |
1213 | {"provided", PROVIDED, 0, 0}, |
1214 | {"run", RUN, 0, 0}, |
1215 | {"d_step", D_STEP, 0, 0}, |
1216 | {"inline", INLINE, 0, 0}, |
1217 | {"short", TYPE, SHORT, 0}, |
1218 | {"skip", CONST, 1, 0}, |
1219 | {"timeout", TIMEOUT, 0, 0}, |
1220 | {"trace", TRACE, 0, ":trace:"}, |
1221 | {"true", CONST, 1, 0}, |
1222 | {"show", SHOW, 0, ":show:"}, |
1223 | {"typedef", TYPEDEF, 0, 0}, |
1224 | {"unless", UNLESS, 0, 0}, |
1225 | {"unsigned", TYPE, UNSIGNED, 0}, |
1226 | {"xr", XU, XR, 0}, |
1227 | {"xs", XU, XS, 0}, |
1228 | {0, 0, 0, 0}, |
1229 | }; |
1230 | |
1231 | static int |
1232 | check_name(char *s) |
1233 | { int i; |
1234 | |
1235 | yylval = nn(ZN, 0, ZN, ZN); |
1236 | for (i = 0; Names[i].s; i++) |
1237 | if (strcmp(s, Names[i].s) == 0) |
1238 | { yylval->val = Names[i].val; |
1239 | if (Names[i].sym) |
1240 | yylval->sym = lookup(Names[i].sym); |
1241 | return Names[i].tok; |
1242 | } |
1243 | |
1244 | if ((yylval->val = ismtype(s)) != 0) |
1245 | { yylval->ismtyp = 1; |
1246 | return CONST; |
1247 | } |
1248 | |
1249 | if (strcmp(s, "_last") == 0) |
1250 | has_last++; |
1251 | |
1252 | if (Inlining >= 0 && !ReDiRect) |
1253 | { Lextok *tt, *t = Inline_stub[Inlining]->params; |
1254 | |
1255 | for (i = 0; t; t = t->rgt, i++) /* formal pars */ |
1256 | if (!strcmp(s, t->lft->sym->name) /* varname matches formal */ |
1257 | && strcmp(s, Inline_stub[Inlining]->anms[i]) != 0) /* actual pars */ |
1258 | { |
1259 | #if 0 |
1260 | if (verbose&32) |
1261 | printf("\tline %d, replace %s in call of '%s' with %s\n", |
1262 | lineno, s, |
1263 | Inline_stub[Inlining]->nm->name, |
1264 | Inline_stub[Inlining]->anms[i]); |
1265 | #endif |
1266 | for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt) |
1267 | if (!strcmp(Inline_stub[Inlining]->anms[i], |
1268 | tt->lft->sym->name)) |
1269 | { /* would be cyclic if not caught */ |
1270 | printf("spin: line %d replacement value: %s\n", |
1271 | lineno, tt->lft->sym->name); |
1272 | wrong: fatal("formal par of %s contains replacement value", |
1273 | Inline_stub[Inlining]->nm->name); |
1274 | yylval->ntyp = tt->lft->ntyp; |
1275 | yylval->sym = lookup(tt->lft->sym->name); |
1276 | return NAME; |
1277 | } |
1278 | |
1279 | /* check for occurrence of param as field of struct */ |
1280 | { char *ptr = Inline_stub[Inlining]->anms[i]; |
1281 | while ((ptr = strstr(ptr, s)) != NULL) |
1282 | { if (*(ptr-1) == '.' |
1283 | || *(ptr+strlen(s)) == '.') |
1284 | { goto wrong; |
1285 | } |
1286 | ptr++; |
1287 | } } |
1288 | ReDiRect = Inline_stub[Inlining]->anms[i]; |
1289 | return 0; |
1290 | } } |
1291 | |
1292 | yylval->sym = lookup(s); /* symbol table */ |
1293 | if (isutype(s)) |
1294 | return UNAME; |
1295 | if (isproctype(s)) |
1296 | return PNAME; |
1297 | if (iseqname(s)) |
1298 | return INAME; |
1299 | |
1300 | return NAME; |
1301 | } |
1302 | |
1303 | int |
1304 | yylex(void) |
1305 | { static int last = 0; |
1306 | static int hold = 0; |
1307 | int c; |
1308 | /* |
1309 | * repair two common syntax mistakes with |
1310 | * semi-colons before or after a '}' |
1311 | */ |
1312 | if (hold) |
1313 | { c = hold; |
1314 | hold = 0; |
1315 | } else |
1316 | { c = lex(); |
1317 | if (last == ELSE |
1318 | && c != SEMI |
1319 | && c != FI) |
1320 | { hold = c; |
1321 | last = 0; |
1322 | return SEMI; |
1323 | } |
1324 | if (last == '}' |
1325 | && c != PROCTYPE |
1326 | && c != INIT |
1327 | && c != CLAIM |
1328 | && c != SEP |
1329 | && c != FI |
1330 | && c != OD |
1331 | && c != '}' |
1332 | && c != UNLESS |
1333 | && c != SEMI |
1334 | && c != EOF) |
1335 | { hold = c; |
1336 | last = 0; |
1337 | return SEMI; /* insert ';' */ |
1338 | } |
1339 | if (c == SEMI) |
1340 | { /* if context, we're not in a typedef |
1341 | * because they're global. |
1342 | * if owner, we're at the end of a ref |
1343 | * to a struct field -- prevent that the |
1344 | * lookahead is interpreted as a field of |
1345 | * the same struct... |
1346 | */ |
1347 | if (context) owner = ZS; |
1348 | hold = lex(); /* look ahead */ |
1349 | if (hold == '}' |
1350 | || hold == SEMI) |
1351 | { c = hold; /* omit ';' */ |
1352 | hold = 0; |
1353 | } |
1354 | } |
1355 | } |
1356 | last = c; |
1357 | |
1358 | if (IArgs) |
1359 | { static int IArg_nst = 0; |
1360 | |
1361 | if (strcmp(yytext, ",") == 0) |
1362 | { IArg_cont[++IArgno][0] = '\0'; |
1363 | } else if (strcmp(yytext, "(") == 0) |
1364 | { if (IArg_nst++ == 0) |
1365 | { IArgno = 0; |
1366 | IArg_cont[0][0] = '\0'; |
1367 | } else |
1368 | strcat(IArg_cont[IArgno], yytext); |
1369 | } else if (strcmp(yytext, ")") == 0) |
1370 | { if (--IArg_nst > 0) |
1371 | strcat(IArg_cont[IArgno], yytext); |
1372 | } else if (c == CONST && yytext[0] == '\'') |
1373 | { sprintf(yytext, "'%c'", yylval->val); |
1374 | strcat(IArg_cont[IArgno], yytext); |
1375 | } else if (c == CONST) |
1376 | { sprintf(yytext, "%d", yylval->val); |
1377 | strcat(IArg_cont[IArgno], yytext); |
1378 | } else |
1379 | { |
1380 | switch (c) { |
1381 | case SEP: strcpy(yytext, "::"); break; |
1382 | case SEMI: strcpy(yytext, ";"); break; |
1383 | case DECR: strcpy(yytext, "--"); break; |
1384 | case INCR: strcpy(yytext, "++"); break; |
1385 | case LSHIFT: strcpy(yytext, "<<"); break; |
1386 | case RSHIFT: strcpy(yytext, ">>"); break; |
1387 | case LE: strcpy(yytext, "<="); break; |
1388 | case LT: strcpy(yytext, "<"); break; |
1389 | case GE: strcpy(yytext, ">="); break; |
1390 | case GT: strcpy(yytext, ">"); break; |
1391 | case EQ: strcpy(yytext, "=="); break; |
1392 | case ASGN: strcpy(yytext, "="); break; |
1393 | case NE: strcpy(yytext, "!="); break; |
1394 | case R_RCV: strcpy(yytext, "??"); break; |
1395 | case RCV: strcpy(yytext, "?"); break; |
1396 | case O_SND: strcpy(yytext, "!!"); break; |
1397 | case SND: strcpy(yytext, "!"); break; |
1398 | case AND: strcpy(yytext, "&&"); break; |
1399 | case OR: strcpy(yytext, "||"); break; |
1400 | } |
1401 | strcat(IArg_cont[IArgno], yytext); |
1402 | } |
1403 | } |
1404 | return c; |
1405 | } |