spinlex.c 34 KB

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