main.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /***** spin: main.c *****/
  2. /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* No guarantee whatsoever is expressed or implied by the distribution of */
  5. /* this code. Permission is given to distribute this code provided that */
  6. /* this introductory message is not removed and no monies are exchanged. */
  7. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  8. /* http://spinroot.com/ */
  9. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  10. #include <stdlib.h>
  11. #include "spin.h"
  12. #include "version.h"
  13. #include <signal.h>
  14. /* #include <malloc.h> */
  15. #include <time.h>
  16. #ifdef PC
  17. #include <io.h>
  18. #include "y_tab.h"
  19. extern int unlink(const char *);
  20. #else
  21. #include <unistd.h>
  22. #include "y.tab.h"
  23. #endif
  24. extern int DstepStart, lineno, tl_terse;
  25. extern FILE *yyin, *yyout, *tl_out;
  26. extern Symbol *context;
  27. extern char *claimproc;
  28. extern void repro_src(void);
  29. extern void qhide(int);
  30. Symbol *Fname, *oFname;
  31. int Etimeouts; /* nr timeouts in program */
  32. int Ntimeouts; /* nr timeouts in never claim */
  33. int analyze, columns, dumptab, has_remote, has_remvar;
  34. int interactive, jumpsteps, m_loss, nr_errs, cutoff;
  35. int s_trail, ntrail, verbose, xspin, notabs, rvopt;
  36. int no_print, no_wrapup, Caccess, limited_vis, like_java;
  37. int separate; /* separate compilation */
  38. int export_ast; /* pangen5.c */
  39. int inlineonly; /* show inlined code */
  40. int seedy; /* be verbose about chosen seed */
  41. int dataflow = 1, merger = 1, deadvar = 1, ccache = 1;
  42. static int preprocessonly, SeedUsed;
  43. #if 0
  44. meaning of flags on verbose:
  45. 1 -g global variable values
  46. 2 -l local variable values
  47. 4 -p all process actions
  48. 8 -r receives
  49. 16 -s sends
  50. 32 -v verbose
  51. 64 -w very verbose
  52. #endif
  53. static char Operator[] = "operator: ";
  54. static char Keyword[] = "keyword: ";
  55. static char Function[] = "function-name: ";
  56. static char **add_ltl = (char **)0;
  57. static char **ltl_file = (char **)0;
  58. static char **nvr_file = (char **)0;
  59. static char *PreArg[64];
  60. static int PreCnt = 0;
  61. static char out1[64];
  62. static void explain(int);
  63. #ifndef CPP
  64. /* OS2: "spin -Picc -E/Pd+ -E/Q+" */
  65. /* Visual C++: "spin -PCL -E/E */
  66. #ifdef PC
  67. #define CPP "gcc -E -x c" /* most systems have gcc anyway */
  68. /* else use "cpp" */
  69. #else
  70. #ifdef SOLARIS
  71. #define CPP "/usr/ccs/lib/cpp"
  72. #else
  73. #if defined(__FreeBSD__) || defined(__OpenBSD__)
  74. #define CPP "cpp"
  75. #else
  76. #define CPP "/bin/cpp" /* classic Unix systems */
  77. #endif
  78. #endif
  79. #endif
  80. #endif
  81. static char *PreProc = CPP;
  82. extern int depth; /* at least some steps were made */
  83. void
  84. alldone(int estatus)
  85. {
  86. if (preprocessonly == 0
  87. && strlen(out1) > 0)
  88. (void) unlink((const char *)out1);
  89. if (seedy && !analyze && !export_ast
  90. && !s_trail && !preprocessonly && depth > 0)
  91. printf("seed used: %d\n", SeedUsed);
  92. if (xspin && (analyze || s_trail))
  93. { if (estatus)
  94. printf("spin: %d error(s) - aborting\n",
  95. estatus);
  96. else
  97. printf("Exit-Status 0\n");
  98. }
  99. exit(estatus);
  100. }
  101. void
  102. preprocess(char *a, char *b, int a_tmp)
  103. { char precmd[512], cmd[1024]; int i;
  104. #ifdef PC
  105. extern int try_zpp(char *, char *);
  106. if (PreCnt == 0 && try_zpp(a, b)) goto out;
  107. #endif
  108. strcpy(precmd, PreProc);
  109. for (i = 1; i <= PreCnt; i++)
  110. { strcat(precmd, " ");
  111. strcat(precmd, PreArg[i]);
  112. }
  113. sprintf(cmd, "%s %s > %s", precmd, a, b);
  114. if (system((const char *)cmd))
  115. { (void) unlink((const char *) b);
  116. if (a_tmp) (void) unlink((const char *) a);
  117. fprintf(stdout, "spin: preprocessing failed\n"); /* 4.1.2 was stderr */
  118. alldone(1); /* no return, error exit */
  119. }
  120. #ifdef PC
  121. out:
  122. #endif
  123. if (a_tmp) (void) unlink((const char *) a);
  124. }
  125. FILE *
  126. cpyfile(char *src, char *tgt)
  127. { FILE *inp, *out;
  128. char buf[1024];
  129. inp = fopen(src, "r");
  130. out = fopen(tgt, "w");
  131. if (!inp || !out)
  132. { printf("spin: cannot cp %s to %s\n", src, tgt);
  133. alldone(1);
  134. }
  135. while (fgets(buf, 1024, inp))
  136. fprintf(out, "%s", buf);
  137. fclose(inp);
  138. return out;
  139. }
  140. void
  141. usage(void)
  142. {
  143. printf("use: spin [-option] ... [-option] file\n");
  144. printf("\tNote: file must always be the last argument\n");
  145. printf("\t-A apply slicing algorithm\n");
  146. printf("\t-a generate a verifier in pan.c\n");
  147. printf("\t-B no final state details in simulations\n");
  148. printf("\t-b don't execute printfs in simulation\n");
  149. printf("\t-C print channel access info (combine with -g etc.)\n");
  150. printf("\t-c columnated -s -r simulation output\n");
  151. printf("\t-d produce symbol-table information\n");
  152. printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
  153. printf("\t-Eyyy pass yyy to the preprocessor\n");
  154. printf("\t-f \"..formula..\" translate LTL ");
  155. printf("into never claim\n");
  156. printf("\t-F file like -f, but with the LTL ");
  157. printf("formula stored in a 1-line file\n");
  158. printf("\t-g print all global variables\n");
  159. printf("\t-h at end of run, print value of seed for random nr generator used\n");
  160. printf("\t-i interactive (random simulation)\n");
  161. printf("\t-I show result of inlining and preprocessing\n");
  162. printf("\t-J reverse eval order of nested unlesses\n");
  163. printf("\t-jN skip the first N steps ");
  164. printf("in simulation trail\n");
  165. printf("\t-l print all local variables\n");
  166. printf("\t-M print msc-flow in Postscript\n");
  167. printf("\t-m lose msgs sent to full queues\n");
  168. printf("\t-N file use never claim stored in file\n");
  169. printf("\t-nN seed for random nr generator\n");
  170. printf("\t-o1 turn off dataflow-optimizations in verifier\n");
  171. printf("\t-o2 don't hide write-only variables in verifier\n");
  172. printf("\t-o3 turn off statement merging in verifier\n");
  173. printf("\t-Pxxx use xxx for preprocessing\n");
  174. printf("\t-p print all statements\n");
  175. printf("\t-qN suppress io for queue N in printouts\n");
  176. printf("\t-r print receive events\n");
  177. printf("\t-S1 and -S2 separate pan source for claim and model\n");
  178. printf("\t-s print send events\n");
  179. printf("\t-T do not indent printf output\n");
  180. printf("\t-t[N] follow [Nth] simulation trail\n");
  181. printf("\t-Uyyy pass -Uyyy to the preprocessor\n");
  182. printf("\t-uN stop a simulation run after N steps\n");
  183. printf("\t-v verbose, more warnings\n");
  184. printf("\t-w very verbose (when combined with -l or -g)\n");
  185. printf("\t-[XYZ] reserved for use by xspin interface\n");
  186. printf("\t-V print version number and exit\n");
  187. alldone(1);
  188. }
  189. void
  190. optimizations(char nr)
  191. {
  192. switch (nr) {
  193. case '1':
  194. dataflow = 1 - dataflow; /* dataflow */
  195. if (verbose&32)
  196. printf("spin: dataflow optimizations turned %s\n",
  197. dataflow?"on":"off");
  198. break;
  199. case '2':
  200. /* dead variable elimination */
  201. deadvar = 1 - deadvar;
  202. if (verbose&32)
  203. printf("spin: dead variable elimination turned %s\n",
  204. deadvar?"on":"off");
  205. break;
  206. case '3':
  207. /* statement merging */
  208. merger = 1 - merger;
  209. if (verbose&32)
  210. printf("spin: statement merging turned %s\n",
  211. merger?"on":"off");
  212. break;
  213. case '4':
  214. /* rv optimization */
  215. rvopt = 1 - rvopt;
  216. if (verbose&32)
  217. printf("spin: rendezvous optimization turned %s\n",
  218. rvopt?"on":"off");
  219. break;
  220. case '5':
  221. /* case caching */
  222. ccache = 1 - ccache;
  223. if (verbose&32)
  224. printf("spin: case caching turned %s\n",
  225. ccache?"on":"off");
  226. break;
  227. default:
  228. printf("spin: bad or missing parameter on -o\n");
  229. usage();
  230. break;
  231. }
  232. }
  233. #if 0
  234. static int
  235. Rename(const char *old, char *new)
  236. { FILE *fo, *fn;
  237. char buf[1024];
  238. if ((fo = fopen(old, "r")) == NULL)
  239. { printf("spin: cannot open %s\n", old);
  240. return 1;
  241. }
  242. if ((fn = fopen(new, "w")) == NULL)
  243. { printf("spin: cannot create %s\n", new);
  244. fclose(fo);
  245. return 2;
  246. }
  247. while (fgets(buf, 1024, fo))
  248. fputs(buf, fn);
  249. fclose(fo);
  250. fclose(fn);
  251. return 0; /* success */
  252. }
  253. #endif
  254. int
  255. main(int argc, char *argv[])
  256. { Symbol *s;
  257. int T = (int) time((time_t *)0);
  258. int usedopts = 0;
  259. extern void ana_src(int, int);
  260. yyin = stdin;
  261. yyout = stdout;
  262. tl_out = stdout;
  263. /* unused flags: e, w, x, y, z, A, G, I, L, O, Q, R, S, T, W */
  264. while (argc > 1 && argv[1][0] == '-')
  265. { switch (argv[1][1]) {
  266. /* generate code for separate compilation: S1 or S2 */
  267. case 'S': separate = atoi(&argv[1][2]);
  268. /* fall through */
  269. case 'a': analyze = 1; break;
  270. case 'A': export_ast = 1; break;
  271. case 'B': no_wrapup = 1; break;
  272. case 'b': no_print = 1; break;
  273. case 'C': Caccess = 1; break;
  274. case 'c': columns = 1; break;
  275. case 'D': PreArg[++PreCnt] = (char *) &argv[1][0];
  276. break; /* define */
  277. case 'd': dumptab = 1; break;
  278. case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
  279. break;
  280. case 'F': ltl_file = (char **) (argv+2);
  281. argc--; argv++; break;
  282. case 'f': add_ltl = (char **) argv;
  283. argc--; argv++; break;
  284. case 'g': verbose += 1; break;
  285. case 'h': seedy = 1; break;
  286. case 'i': interactive = 1; break;
  287. case 'I': inlineonly = 1; break;
  288. case 'J': like_java = 1; break;
  289. case 'j': jumpsteps = atoi(&argv[1][2]); break;
  290. case 'l': verbose += 2; break;
  291. case 'M': columns = 2; break;
  292. case 'm': m_loss = 1; break;
  293. case 'N': nvr_file = (char **) (argv+2);
  294. argc--; argv++; break;
  295. case 'n': T = atoi(&argv[1][2]); tl_terse = 1; break;
  296. case 'o': optimizations(argv[1][2]);
  297. usedopts = 1; break;
  298. case 'P': PreProc = (char *) &argv[1][2]; break;
  299. case 'p': verbose += 4; break;
  300. case 'q': if (isdigit(argv[1][2]))
  301. qhide(atoi(&argv[1][2]));
  302. break;
  303. case 'r': verbose += 8; break;
  304. case 's': verbose += 16; break;
  305. case 'T': notabs = 1; break;
  306. case 't': s_trail = 1;
  307. if (isdigit(argv[1][2]))
  308. ntrail = atoi(&argv[1][2]);
  309. break;
  310. case 'U': PreArg[++PreCnt] = (char *) &argv[1][0];
  311. break; /* undefine */
  312. case 'u': cutoff = atoi(&argv[1][2]); break; /* new 3.4.14 */
  313. case 'v': verbose += 32; break;
  314. case 'V': printf("%s\n", Version);
  315. alldone(0);
  316. break;
  317. case 'w': verbose += 64; break;
  318. case 'X': xspin = notabs = 1;
  319. #ifndef PC
  320. signal(SIGPIPE, alldone); /* not posix... */
  321. #endif
  322. break;
  323. case 'Y': limited_vis = 1; break; /* used by xspin */
  324. case 'Z': preprocessonly = 1; break; /* used by xspin */
  325. default : usage(); break;
  326. }
  327. argc--, argv++;
  328. }
  329. if (usedopts && !analyze)
  330. printf("spin: warning -o[123] option ignored in simulations\n");
  331. if (ltl_file)
  332. { char formula[4096];
  333. add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
  334. if (!(tl_out = fopen(*ltl_file, "r")))
  335. { printf("spin: cannot open %s\n", *ltl_file);
  336. alldone(1);
  337. }
  338. fgets(formula, 4096, tl_out);
  339. fclose(tl_out);
  340. tl_out = stdout;
  341. *ltl_file = (char *) formula;
  342. }
  343. if (argc > 1)
  344. { char cmd[128], out2[64];
  345. /* must remain in current dir */
  346. strcpy(out1, "pan.pre");
  347. if (add_ltl || nvr_file)
  348. strcpy(out2, "pan.___");
  349. if (add_ltl)
  350. { tl_out = cpyfile(argv[1], out2);
  351. nr_errs = tl_main(2, add_ltl); /* in tl_main.c */
  352. fclose(tl_out);
  353. preprocess(out2, out1, 1);
  354. } else if (nvr_file)
  355. { FILE *fd; char buf[1024];
  356. if ((fd = fopen(*nvr_file, "r")) == NULL)
  357. { printf("spin: cannot open %s\n",
  358. *nvr_file);
  359. alldone(1);
  360. }
  361. tl_out = cpyfile(argv[1], out2);
  362. while (fgets(buf, 1024, fd))
  363. fprintf(tl_out, "%s", buf);
  364. fclose(tl_out);
  365. fclose(fd);
  366. preprocess(out2, out1, 1);
  367. } else
  368. preprocess(argv[1], out1, 0);
  369. if (preprocessonly)
  370. alldone(0);
  371. if (!(yyin = fopen(out1, "r")))
  372. { printf("spin: cannot open %s\n", out1);
  373. alldone(1);
  374. }
  375. if (strncmp(argv[1], "progress", 8) == 0
  376. || strncmp(argv[1], "accept", 6) == 0)
  377. sprintf(cmd, "_%s", argv[1]);
  378. else
  379. strcpy(cmd, argv[1]);
  380. oFname = Fname = lookup(cmd);
  381. if (oFname->name[0] == '\"')
  382. { int i = (int) strlen(oFname->name);
  383. oFname->name[i-1] = '\0';
  384. oFname = lookup(&oFname->name[1]);
  385. }
  386. } else
  387. { oFname = Fname = lookup("<stdin>");
  388. if (add_ltl)
  389. { if (argc > 0)
  390. exit(tl_main(2, add_ltl));
  391. printf("spin: missing argument to -f\n");
  392. alldone(1);
  393. }
  394. printf("%s\n", Version);
  395. printf("reading input from stdin:\n");
  396. fflush(stdout);
  397. }
  398. if (columns == 2)
  399. { extern void putprelude(void);
  400. if (xspin || verbose&(1|4|8|16|32))
  401. { printf("spin: -c precludes all flags except -t\n");
  402. alldone(1);
  403. }
  404. putprelude();
  405. }
  406. if (columns && !(verbose&8) && !(verbose&16))
  407. verbose += (8+16);
  408. if (columns == 2 && limited_vis)
  409. verbose += (1+4);
  410. Srand(T); /* defined in run.c */
  411. SeedUsed = T;
  412. s = lookup("_"); s->type = PREDEF; /* write-only global var */
  413. s = lookup("_p"); s->type = PREDEF;
  414. s = lookup("_pid"); s->type = PREDEF;
  415. s = lookup("_last"); s->type = PREDEF;
  416. s = lookup("_nr_pr"); s->type = PREDEF; /* new 3.3.10 */
  417. yyparse();
  418. fclose(yyin);
  419. loose_ends();
  420. if (inlineonly)
  421. { repro_src();
  422. return 0;
  423. }
  424. chanaccess();
  425. if (!Caccess)
  426. { if (!s_trail && (dataflow || merger))
  427. ana_src(dataflow, merger);
  428. sched();
  429. alldone(nr_errs);
  430. }
  431. return 0;
  432. }
  433. int
  434. yywrap(void) /* dummy routine */
  435. {
  436. return 1;
  437. }
  438. void
  439. non_fatal(char *s1, char *s2)
  440. { extern char yytext[];
  441. printf("spin: line %3d %s, Error: ",
  442. lineno, Fname?Fname->name:"nofilename");
  443. if (s2)
  444. printf(s1, s2);
  445. else
  446. printf(s1);
  447. #if 0
  448. if (yychar != -1 && yychar != 0)
  449. { printf(" saw '");
  450. explain(yychar);
  451. printf("'");
  452. }
  453. #endif
  454. if (yytext && strlen(yytext)>1)
  455. printf(" near '%s'", yytext);
  456. printf("\n");
  457. nr_errs++;
  458. }
  459. void
  460. fatal(char *s1, char *s2)
  461. {
  462. non_fatal(s1, s2);
  463. alldone(1);
  464. }
  465. char *
  466. emalloc(int n)
  467. { char *tmp;
  468. if (!(tmp = (char *) malloc(n)))
  469. fatal("not enough memory", (char *)0);
  470. memset(tmp, 0, n);
  471. return tmp;
  472. }
  473. void
  474. trapwonly(Lextok *n, char *unused)
  475. { extern int realread;
  476. short i = (n->sym)?n->sym->type:0;
  477. if (i != MTYPE
  478. && i != BIT
  479. && i != BYTE
  480. && i != SHORT
  481. && i != INT
  482. && i != UNSIGNED)
  483. return;
  484. if (realread)
  485. n->sym->hidden |= 32; /* var is read at least once */
  486. }
  487. void
  488. setaccess(Symbol *sp, Symbol *what, int cnt, int t)
  489. { Access *a;
  490. for (a = sp->access; a; a = a->lnk)
  491. if (a->who == context
  492. && a->what == what
  493. && a->cnt == cnt
  494. && a->typ == t)
  495. return;
  496. a = (Access *) emalloc(sizeof(Access));
  497. a->who = context;
  498. a->what = what;
  499. a->cnt = cnt;
  500. a->typ = t;
  501. a->lnk = sp->access;
  502. sp->access = a;
  503. }
  504. Lextok *
  505. nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
  506. { Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
  507. static int warn_nn = 0;
  508. n->ntyp = (short) t;
  509. if (s && s->fn)
  510. { n->ln = s->ln;
  511. n->fn = s->fn;
  512. } else if (rl && rl->fn)
  513. { n->ln = rl->ln;
  514. n->fn = rl->fn;
  515. } else if (ll && ll->fn)
  516. { n->ln = ll->ln;
  517. n->fn = ll->fn;
  518. } else
  519. { n->ln = lineno;
  520. n->fn = Fname;
  521. }
  522. if (s) n->sym = s->sym;
  523. n->lft = ll;
  524. n->rgt = rl;
  525. n->indstep = DstepStart;
  526. if (t == TIMEOUT) Etimeouts++;
  527. if (!context) return n;
  528. if (t == 'r' || t == 's')
  529. setaccess(n->sym, ZS, 0, t);
  530. if (t == 'R')
  531. setaccess(n->sym, ZS, 0, 'P');
  532. if (context->name == claimproc)
  533. { int forbidden = separate;
  534. switch (t) {
  535. case ASGN:
  536. printf("spin: Warning, never claim has side-effect\n");
  537. break;
  538. case 'r': case 's':
  539. non_fatal("never claim contains i/o stmnts",(char *)0);
  540. break;
  541. case TIMEOUT:
  542. /* never claim polls timeout */
  543. if (Ntimeouts && Etimeouts)
  544. forbidden = 0;
  545. Ntimeouts++; Etimeouts--;
  546. break;
  547. case LEN: case EMPTY: case FULL:
  548. case 'R': case NFULL: case NEMPTY:
  549. /* status becomes non-exclusive */
  550. if (n->sym && !(n->sym->xu&XX))
  551. { n->sym->xu |= XX;
  552. if (separate == 2) {
  553. printf("spin: warning, make sure that the S1 model\n");
  554. printf(" also polls channel '%s' in its claim\n",
  555. n->sym->name);
  556. } }
  557. forbidden = 0;
  558. break;
  559. case 'c':
  560. AST_track(n, 0); /* register as a slice criterion */
  561. /* fall thru */
  562. default:
  563. forbidden = 0;
  564. break;
  565. }
  566. if (forbidden)
  567. { printf("spin: never, saw "); explain(t); printf("\n");
  568. fatal("incompatible with separate compilation",(char *)0);
  569. }
  570. } else if ((t == ENABLED || t == PC_VAL) && !(warn_nn&t))
  571. { printf("spin: Warning, using %s outside never claim\n",
  572. (t == ENABLED)?"enabled()":"pc_value()");
  573. warn_nn |= t;
  574. } else if (t == NONPROGRESS)
  575. { fatal("spin: Error, using np_ outside never claim\n", (char *)0);
  576. }
  577. return n;
  578. }
  579. Lextok *
  580. rem_lab(Symbol *a, Lextok *b, Symbol *c) /* proctype name, pid, label name */
  581. { Lextok *tmp1, *tmp2, *tmp3;
  582. has_remote++;
  583. c->type = LABEL; /* refered to in global context here */
  584. fix_dest(c, a); /* in case target of rem_lab is jump */
  585. tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a;
  586. tmp1 = nn(ZN, 'p', tmp1, ZN);
  587. tmp1->sym = lookup("_p");
  588. tmp2 = nn(ZN, NAME, ZN, ZN); tmp2->sym = a;
  589. tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c;
  590. return nn(ZN, EQ, tmp1, tmp3);
  591. #if 0
  592. .---------------EQ-------.
  593. / \
  594. 'p' -sym-> _p 'q' -sym-> c (label name)
  595. / /
  596. '?' -sym-> a (proctype) NAME -sym-> a (proctype name)
  597. /
  598. b (pid expr)
  599. #endif
  600. }
  601. Lextok *
  602. rem_var(Symbol *a, Lextok *b, Symbol *c, Lextok *ndx)
  603. { Lextok *tmp1;
  604. has_remote++;
  605. has_remvar++;
  606. dataflow = 0; /* turn off dead variable resets 4.2.5 */
  607. tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a;
  608. tmp1 = nn(ZN, 'p', tmp1, ndx);
  609. tmp1->sym = c;
  610. return tmp1;
  611. #if 0
  612. cannot refer to struct elements
  613. only to scalars and arrays
  614. 'p' -sym-> c (variable name)
  615. / \______ possible arrayindex on c
  616. /
  617. '?' -sym-> a (proctype)
  618. /
  619. b (pid expr)
  620. #endif
  621. }
  622. static void
  623. explain(int n)
  624. { FILE *fd = stdout;
  625. switch (n) {
  626. default: if (n > 0 && n < 256)
  627. fprintf(fd, "'%c' = '", n);
  628. fprintf(fd, "%d'", n);
  629. break;
  630. case '\b': fprintf(fd, "\\b"); break;
  631. case '\t': fprintf(fd, "\\t"); break;
  632. case '\f': fprintf(fd, "\\f"); break;
  633. case '\n': fprintf(fd, "\\n"); break;
  634. case '\r': fprintf(fd, "\\r"); break;
  635. case 'c': fprintf(fd, "condition"); break;
  636. case 's': fprintf(fd, "send"); break;
  637. case 'r': fprintf(fd, "recv"); break;
  638. case 'R': fprintf(fd, "recv poll %s", Operator); break;
  639. case '@': fprintf(fd, "@"); break;
  640. case '?': fprintf(fd, "(x->y:z)"); break;
  641. case ACTIVE: fprintf(fd, "%sactive", Keyword); break;
  642. case AND: fprintf(fd, "%s&&", Operator); break;
  643. case ASGN: fprintf(fd, "%s=", Operator); break;
  644. case ASSERT: fprintf(fd, "%sassert", Function); break;
  645. case ATOMIC: fprintf(fd, "%satomic", Keyword); break;
  646. case BREAK: fprintf(fd, "%sbreak", Keyword); break;
  647. case C_CODE: fprintf(fd, "%sc_code", Keyword); break;
  648. case C_DECL: fprintf(fd, "%sc_decl", Keyword); break;
  649. case C_EXPR: fprintf(fd, "%sc_expr", Keyword); break;
  650. case C_STATE: fprintf(fd, "%sc_state",Keyword); break;
  651. case C_TRACK: fprintf(fd, "%sc_track",Keyword); break;
  652. case CLAIM: fprintf(fd, "%snever", Keyword); break;
  653. case CONST: fprintf(fd, "a constant"); break;
  654. case DECR: fprintf(fd, "%s--", Operator); break;
  655. case D_STEP: fprintf(fd, "%sd_step", Keyword); break;
  656. case D_PROCTYPE: fprintf(fd, "%sd_proctype", Keyword); break;
  657. case DO: fprintf(fd, "%sdo", Keyword); break;
  658. case DOT: fprintf(fd, "."); break;
  659. case ELSE: fprintf(fd, "%selse", Keyword); break;
  660. case EMPTY: fprintf(fd, "%sempty", Function); break;
  661. case ENABLED: fprintf(fd, "%senabled",Function); break;
  662. case EQ: fprintf(fd, "%s==", Operator); break;
  663. case EVAL: fprintf(fd, "%seval", Function); break;
  664. case FI: fprintf(fd, "%sfi", Keyword); break;
  665. case FULL: fprintf(fd, "%sfull", Function); break;
  666. case GE: fprintf(fd, "%s>=", Operator); break;
  667. case GOTO: fprintf(fd, "%sgoto", Keyword); break;
  668. case GT: fprintf(fd, "%s>", Operator); break;
  669. case HIDDEN: fprintf(fd, "%shidden", Keyword); break;
  670. case IF: fprintf(fd, "%sif", Keyword); break;
  671. case INCR: fprintf(fd, "%s++", Operator); break;
  672. case INAME: fprintf(fd, "inline name"); break;
  673. case INLINE: fprintf(fd, "%sinline", Keyword); break;
  674. case INIT: fprintf(fd, "%sinit", Keyword); break;
  675. case ISLOCAL: fprintf(fd, "%slocal", Keyword); break;
  676. case LABEL: fprintf(fd, "a label-name"); break;
  677. case LE: fprintf(fd, "%s<=", Operator); break;
  678. case LEN: fprintf(fd, "%slen", Function); break;
  679. case LSHIFT: fprintf(fd, "%s<<", Operator); break;
  680. case LT: fprintf(fd, "%s<", Operator); break;
  681. case MTYPE: fprintf(fd, "%smtype", Keyword); break;
  682. case NAME: fprintf(fd, "an identifier"); break;
  683. case NE: fprintf(fd, "%s!=", Operator); break;
  684. case NEG: fprintf(fd, "%s! (not)",Operator); break;
  685. case NEMPTY: fprintf(fd, "%snempty", Function); break;
  686. case NFULL: fprintf(fd, "%snfull", Function); break;
  687. case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
  688. case NONPROGRESS: fprintf(fd, "%snp_", Function); break;
  689. case OD: fprintf(fd, "%sod", Keyword); break;
  690. case OF: fprintf(fd, "%sof", Keyword); break;
  691. case OR: fprintf(fd, "%s||", Operator); break;
  692. case O_SND: fprintf(fd, "%s!!", Operator); break;
  693. case PC_VAL: fprintf(fd, "%spc_value",Function); break;
  694. case PNAME: fprintf(fd, "process name"); break;
  695. case PRINT: fprintf(fd, "%sprintf", Function); break;
  696. case PRINTM: fprintf(fd, "%sprintm", Function); break;
  697. case PRIORITY: fprintf(fd, "%spriority", Keyword); break;
  698. case PROCTYPE: fprintf(fd, "%sproctype",Keyword); break;
  699. case PROVIDED: fprintf(fd, "%sprovided",Keyword); break;
  700. case RCV: fprintf(fd, "%s?", Operator); break;
  701. case R_RCV: fprintf(fd, "%s??", Operator); break;
  702. case RSHIFT: fprintf(fd, "%s>>", Operator); break;
  703. case RUN: fprintf(fd, "%srun", Operator); break;
  704. case SEP: fprintf(fd, "token: ::"); break;
  705. case SEMI: fprintf(fd, ";"); break;
  706. case SHOW: fprintf(fd, "%sshow", Keyword); break;
  707. case SND: fprintf(fd, "%s!", Operator); break;
  708. case STRING: fprintf(fd, "a string"); break;
  709. case TRACE: fprintf(fd, "%strace", Keyword); break;
  710. case TIMEOUT: fprintf(fd, "%stimeout",Keyword); break;
  711. case TYPE: fprintf(fd, "data typename"); break;
  712. case TYPEDEF: fprintf(fd, "%stypedef",Keyword); break;
  713. case XU: fprintf(fd, "%sx[rs]", Keyword); break;
  714. case UMIN: fprintf(fd, "%s- (unary minus)", Operator); break;
  715. case UNAME: fprintf(fd, "a typename"); break;
  716. case UNLESS: fprintf(fd, "%sunless", Keyword); break;
  717. }
  718. }