pangen3.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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: pangen3.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 "spin.h"
  19. #include "y.tab.h"
  20. extern FILE *th;
  21. extern int eventmapnr;
  22. typedef struct SRC {
  23. int ln, st; /* linenr, statenr */
  24. Symbol *fn; /* filename */
  25. struct SRC *nxt;
  26. } SRC;
  27. static int col;
  28. static Symbol *lastfnm;
  29. static Symbol lastdef;
  30. static int lastfrom;
  31. static SRC *frst = (SRC *) 0;
  32. static SRC *skip = (SRC *) 0;
  33. extern int ltl_mode;
  34. extern void sr_mesg(FILE *, int, int);
  35. static void
  36. putnr(int n)
  37. {
  38. if (col++ == 8)
  39. { fprintf(th, "\n\t");
  40. col = 1;
  41. }
  42. fprintf(th, "%3d, ", n);
  43. }
  44. static void
  45. putfnm(int j, Symbol *s)
  46. {
  47. if (lastfnm && lastfnm == s && j != -1)
  48. return;
  49. if (lastfnm)
  50. fprintf(th, "{ \"%s\", %d, %d },\n\t",
  51. lastfnm->name,
  52. lastfrom,
  53. j-1);
  54. lastfnm = s;
  55. lastfrom = j;
  56. }
  57. static void
  58. putfnm_flush(int j)
  59. {
  60. if (lastfnm)
  61. fprintf(th, "{ \"%s\", %d, %d }\n",
  62. lastfnm->name,
  63. lastfrom, j);
  64. }
  65. void
  66. putskip(int m) /* states that need not be reached */
  67. { SRC *tmp;
  68. for (tmp = skip; tmp; tmp = tmp->nxt)
  69. if (tmp->st == m)
  70. return;
  71. tmp = (SRC *) emalloc(sizeof(SRC));
  72. tmp->st = m;
  73. tmp->nxt = skip;
  74. skip = tmp;
  75. }
  76. void
  77. unskip(int m) /* a state that needs to be reached after all */
  78. { SRC *tmp, *lst=(SRC *)0;
  79. for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
  80. if (tmp->st == m)
  81. { if (tmp == skip)
  82. skip = skip->nxt;
  83. else if (lst) /* always true, but helps coverity */
  84. lst->nxt = tmp->nxt;
  85. break;
  86. }
  87. }
  88. void
  89. putsrc(Element *e) /* match states to source lines */
  90. { SRC *tmp;
  91. int n, m;
  92. if (!e || !e->n) return;
  93. n = e->n->ln;
  94. m = e->seqno;
  95. for (tmp = frst; tmp; tmp = tmp->nxt)
  96. if (tmp->st == m)
  97. { if (tmp->ln != n || tmp->fn != e->n->fn)
  98. printf("putsrc mismatch seqno %d, line %d - %d, file %s\n", m, n,
  99. tmp->ln, tmp->fn->name);
  100. return;
  101. }
  102. tmp = (SRC *) emalloc(sizeof(SRC));
  103. tmp->ln = n;
  104. tmp->st = m;
  105. tmp->fn = e->n->fn;
  106. tmp->nxt = frst;
  107. frst = tmp;
  108. }
  109. static void
  110. dumpskip(int n, int m)
  111. { SRC *tmp, *lst;
  112. int j;
  113. fprintf(th, "uchar reached%d [] = {\n\t", m);
  114. for (j = 0, col = 0; j <= n; j++)
  115. { lst = (SRC *) 0;
  116. for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
  117. if (tmp->st == j)
  118. { putnr(1);
  119. if (lst)
  120. lst->nxt = tmp->nxt;
  121. else
  122. skip = tmp->nxt;
  123. break;
  124. }
  125. if (!tmp)
  126. putnr(0);
  127. }
  128. fprintf(th, "};\n");
  129. fprintf(th, "uchar *loopstate%d;\n", m);
  130. if (m == eventmapnr)
  131. fprintf(th, "#define reached_event reached%d\n", m);
  132. skip = (SRC *) 0;
  133. }
  134. void
  135. dumpsrc(int n, int m)
  136. { SRC *tmp, *lst;
  137. int j;
  138. static int did_claim = 0;
  139. fprintf(th, "short src_ln%d [] = {\n\t", m);
  140. for (j = 0, col = 0; j <= n; j++)
  141. { lst = (SRC *) 0;
  142. for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
  143. if (tmp->st == j)
  144. { putnr(tmp->ln);
  145. break;
  146. }
  147. if (!tmp)
  148. putnr(0);
  149. }
  150. fprintf(th, "};\n");
  151. lastfnm = (Symbol *) 0;
  152. lastdef.name = "-";
  153. fprintf(th, "S_F_MAP src_file%d [] = {\n\t", m);
  154. for (j = 0, col = 0; j <= n; j++)
  155. { lst = (SRC *) 0;
  156. for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
  157. if (tmp->st == j)
  158. { putfnm(j, tmp->fn);
  159. if (lst)
  160. lst->nxt = tmp->nxt;
  161. else
  162. frst = tmp->nxt;
  163. break;
  164. }
  165. if (!tmp)
  166. putfnm(j, &lastdef);
  167. }
  168. putfnm_flush(j);
  169. fprintf(th, "};\n");
  170. if (pid_is_claim(m) && !did_claim)
  171. { fprintf(th, "short *src_claim;\n");
  172. did_claim++;
  173. }
  174. if (m == eventmapnr)
  175. fprintf(th, "#define src_event src_ln%d\n", m);
  176. frst = (SRC *) 0;
  177. dumpskip(n, m);
  178. }
  179. #define Cat0(x) comwork(fd,now->lft,m); fprintf(fd, x); \
  180. comwork(fd,now->rgt,m)
  181. #define Cat1(x) fprintf(fd,"("); Cat0(x); fprintf(fd,")")
  182. #define Cat2(x,y) fprintf(fd,x); comwork(fd,y,m)
  183. #define Cat3(x,y,z) fprintf(fd,x); comwork(fd,y,m); fprintf(fd,z)
  184. static int
  185. symbolic(FILE *fd, Lextok *tv)
  186. { Lextok *n; extern Lextok *Mtype;
  187. int cnt = 1;
  188. if (tv->ismtyp)
  189. for (n = Mtype; n; n = n->rgt, cnt++)
  190. if (cnt == tv->val)
  191. { fprintf(fd, "%s", n->lft->sym->name);
  192. return 1;
  193. }
  194. return 0;
  195. }
  196. static void
  197. comwork(FILE *fd, Lextok *now, int m)
  198. { Lextok *v;
  199. int i, j;
  200. if (!now) { fprintf(fd, "0"); return; }
  201. switch (now->ntyp) {
  202. case CONST: sr_mesg(fd, now->val, now->ismtyp); break;
  203. case '!': Cat3("!(", now->lft, ")"); break;
  204. case UMIN: Cat3("-(", now->lft, ")"); break;
  205. case '~': Cat3("~(", now->lft, ")"); break;
  206. case '/': Cat1("/"); break;
  207. case '*': Cat1("*"); break;
  208. case '-': Cat1("-"); break;
  209. case '+': Cat1("+"); break;
  210. case '%': Cat1("%%"); break;
  211. case '&': Cat1("&"); break;
  212. case '^': Cat1("^"); break;
  213. case '|': Cat1("|"); break;
  214. case LE: Cat1("<="); break;
  215. case GE: Cat1(">="); break;
  216. case GT: Cat1(">"); break;
  217. case LT: Cat1("<"); break;
  218. case NE: Cat1("!="); break;
  219. case EQ:
  220. if (ltl_mode
  221. && now->lft->ntyp == 'p'
  222. && now->rgt->ntyp == 'q') /* remote ref */
  223. { Lextok *p = now->lft->lft;
  224. fprintf(fd, "(");
  225. fprintf(fd, "%s", p->sym->name);
  226. if (p->lft)
  227. { fprintf(fd, "[");
  228. putstmnt(fd, p->lft, 0); /* pid */
  229. fprintf(fd, "]");
  230. }
  231. fprintf(fd, "@");
  232. fprintf(fd, "%s", now->rgt->sym->name);
  233. fprintf(fd, ")");
  234. break;
  235. }
  236. Cat1("==");
  237. break;
  238. case OR: Cat1("||"); break;
  239. case AND: Cat1("&&"); break;
  240. case LSHIFT: Cat1("<<"); break;
  241. case RSHIFT: Cat1(">>"); break;
  242. case RUN: fprintf(fd, "run %s(", now->sym->name);
  243. for (v = now->lft; v; v = v->rgt)
  244. if (v == now->lft)
  245. { comwork(fd, v->lft, m);
  246. } else
  247. { Cat2(",", v->lft);
  248. }
  249. fprintf(fd, ")");
  250. break;
  251. case LEN: putname(fd, "len(", now->lft, m, ")");
  252. break;
  253. case FULL: putname(fd, "full(", now->lft, m, ")");
  254. break;
  255. case EMPTY: putname(fd, "empty(", now->lft, m, ")");
  256. break;
  257. case NFULL: putname(fd, "nfull(", now->lft, m, ")");
  258. break;
  259. case NEMPTY: putname(fd, "nempty(", now->lft, m, ")");
  260. break;
  261. case 's': putname(fd, "", now->lft, m, now->val?"!!":"!");
  262. for (v = now->rgt, i=0; v; v = v->rgt, i++)
  263. { if (v != now->rgt) fprintf(fd,",");
  264. if (!symbolic(fd, v->lft))
  265. comwork(fd,v->lft,m);
  266. }
  267. break;
  268. case 'r': putname(fd, "", now->lft, m, "?");
  269. switch (now->val) {
  270. case 0: break;
  271. case 1: fprintf(fd, "?"); break;
  272. case 2: fprintf(fd, "<"); break;
  273. case 3: fprintf(fd, "?<"); break;
  274. }
  275. for (v = now->rgt, i=0; v; v = v->rgt, i++)
  276. { if (v != now->rgt) fprintf(fd,",");
  277. if (!symbolic(fd, v->lft))
  278. comwork(fd,v->lft,m);
  279. }
  280. if (now->val >= 2)
  281. fprintf(fd, ">");
  282. break;
  283. case 'R': putname(fd, "", now->lft, m, now->val?"??[":"?[");
  284. for (v = now->rgt, i=0; v; v = v->rgt, i++)
  285. { if (v != now->rgt) fprintf(fd,",");
  286. if (!symbolic(fd, v->lft))
  287. comwork(fd,v->lft,m);
  288. }
  289. fprintf(fd, "]");
  290. break;
  291. case ENABLED: Cat3("enabled(", now->lft, ")");
  292. break;
  293. case EVAL: Cat3("eval(", now->lft, ")");
  294. break;
  295. case NONPROGRESS:
  296. fprintf(fd, "np_");
  297. break;
  298. case PC_VAL: Cat3("pc_value(", now->lft, ")");
  299. break;
  300. case 'c': Cat3("(", now->lft, ")");
  301. break;
  302. case '?': if (now->lft)
  303. { Cat3("( (", now->lft, ") -> ");
  304. }
  305. if (now->rgt)
  306. { Cat3("(", now->rgt->lft, ") : ");
  307. Cat3("(", now->rgt->rgt, ") )");
  308. }
  309. break;
  310. case ASGN: comwork(fd,now->lft,m);
  311. fprintf(fd," = ");
  312. comwork(fd,now->rgt,m);
  313. break;
  314. case PRINT: { char c, buf[512];
  315. strncpy(buf, now->sym->name, 510);
  316. for (i = j = 0; i < 510; i++, j++)
  317. { c = now->sym->name[i];
  318. buf[j] = c;
  319. if (c == '\\') buf[++j] = c;
  320. if (c == '\"') buf[j] = '\'';
  321. if (c == '\0') break;
  322. }
  323. if (now->ntyp == PRINT)
  324. fprintf(fd, "printf");
  325. else
  326. fprintf(fd, "annotate");
  327. fprintf(fd, "(%s", buf);
  328. }
  329. for (v = now->lft; v; v = v->rgt)
  330. { Cat2(",", v->lft);
  331. }
  332. fprintf(fd, ")");
  333. break;
  334. case PRINTM: fprintf(fd, "printm(");
  335. comwork(fd, now->lft, m);
  336. fprintf(fd, ")");
  337. break;
  338. case NAME:
  339. putname(fd, "", now, m, "");
  340. break;
  341. case 'p': if (ltl_mode)
  342. { fprintf(fd, "%s", now->lft->sym->name); /* proctype */
  343. if (now->lft->lft)
  344. { fprintf(fd, "[");
  345. putstmnt(fd, now->lft->lft, 0); /* pid */
  346. fprintf(fd, "]");
  347. }
  348. fprintf(fd, ":"); /* remote varref */
  349. fprintf(fd, "%s", now->sym->name); /* varname */
  350. break;
  351. }
  352. putremote(fd, now, m);
  353. break;
  354. case 'q': fprintf(fd, "%s", now->sym->name);
  355. break;
  356. case C_EXPR:
  357. case C_CODE: fprintf(fd, "{%s}", now->sym->name);
  358. break;
  359. case ASSERT: Cat3("assert(", now->lft, ")");
  360. break;
  361. case '.': fprintf(fd, ".(goto)"); break;
  362. case GOTO: fprintf(fd, "goto %s", now->sym->name); break;
  363. case BREAK: fprintf(fd, "break"); break;
  364. case ELSE: fprintf(fd, "else"); break;
  365. case '@': fprintf(fd, "-end-"); break;
  366. case D_STEP: fprintf(fd, "D_STEP"); break;
  367. case ATOMIC: fprintf(fd, "ATOMIC"); break;
  368. case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
  369. case IF: fprintf(fd, "IF"); break;
  370. case DO: fprintf(fd, "DO"); break;
  371. case UNLESS: fprintf(fd, "unless"); break;
  372. case TIMEOUT: fprintf(fd, "timeout"); break;
  373. default: if (isprint(now->ntyp))
  374. fprintf(fd, "'%c'", now->ntyp);
  375. else
  376. fprintf(fd, "%d", now->ntyp);
  377. break;
  378. }
  379. }
  380. void
  381. comment(FILE *fd, Lextok *now, int m)
  382. { extern int16_t terse, nocast;
  383. terse=nocast=1;
  384. comwork(fd, now, m);
  385. terse=nocast=0;
  386. }