convert from svn repository: remove tags directory
[lttv.git] / trunk / verif / Spin / Src5.1.6 / spinlex.c
CommitLineData
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
20typedef 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
31typedef struct C_Added {
32 Symbol *s;
33 Symbol *t;
34 Symbol *ival;
35 struct C_Added *nxt;
36} C_Added;
37
38extern RunList *X;
39extern ProcList *rdy;
40extern Symbol *Fname;
41extern Symbol *context, *owner;
42extern YYSTYPE yylval;
43extern short has_last, has_code;
44extern int verbose, IArgs, hastrack, separate;
45
46short has_stack = 0;
47int lineno = 1;
48char yytext[2048];
49FILE *yyin, *yyout;
50
51static C_Added *c_added, *c_tracked;
52static IType *Inline_stub[MAXINL];
53static char *ReDiRect;
54static char *Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN];
55static unsigned char in_comment=0;
56static int IArgno = 0, Inlining = -1;
57static 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
79static int getinline(void);
80static 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
88static int
89Getchar(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
101static void
102Ungetch(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
114static int
115notquote(int c)
116{ return (c != '\"' && c != '\n');
117}
118
119int
120isalnum_(int c)
121{ return (isalnum(c) || c == '_');
122}
123
124static int
125isalpha_(int c)
126{ return isalpha(c); /* could be macro */
127}
128
129static int
130isdigit_(int c)
131{ return isdigit(c); /* could be macro */
132}
133
134static void
135getword(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
149static int
150follow(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
160static IType *seqnames;
161
162static void
163def_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
192void
193gencodetable(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
243static int
244iseqname(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
254static int
255getinline(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
281static void
282uninline(void)
283{
284 if (ReDiRect)
285 ReDiRect--;
286 else
287 Inliner[Inlining]--;
288}
289
290IType *
291find_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
303void
304c_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
315void
316c_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
338char *
339jump_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
367void
368c_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
404void
405c_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
454void
455c_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
471int
472c_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
518void
519c_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
534void
535c_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
553void
554c_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
566void
567c_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}
585void
586c_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
712void
713plunk_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
737void
738plunk_c_decls(FILE *fd)
739{
740 plunk_reverse(fd, seqnames, CODE_DECL);
741}
742
743void
744plunk_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
766static void
767check_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
784void
785plunk_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
794void
795preruse(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
814int
815glob_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
825void
826plunk_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
844void
845no_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 {
861bad: 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
880void
881pickup_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
916static void
917do_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);
949done:
950 while (Getchar() != '\n')
951 ;
952}
953
954void
955precondition(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
980Symbol *
981prep_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);
1023bad: 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 */
1040more:
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
1083static int
1084lex(void)
1085{ int c;
1086
1087again:
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
1167static 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
1231static int
1232check_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);
1272wrong: 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
1303int
1304yylex(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}
This page took 0.071809 seconds and 4 git commands to generate.