main.c 18 KB

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