17dd7cddfSDavid du Colombier /***** tl_spin: tl_main.c *****/
27dd7cddfSDavid du Colombier
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier *
8*de2caf28SDavid du Colombier * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
9*de2caf28SDavid du Colombier * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
10*de2caf28SDavid du Colombier */
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier #include "tl.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier extern FILE *tl_out;
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier int newstates = 0; /* debugging only */
177dd7cddfSDavid du Colombier int tl_errs = 0;
187dd7cddfSDavid du Colombier int tl_verbose = 0;
197dd7cddfSDavid du Colombier int tl_terse = 0;
207dd7cddfSDavid du Colombier int tl_clutter = 0;
2100d97012SDavid du Colombier int state_cnt = 0;
2200d97012SDavid du Colombier
237dd7cddfSDavid du Colombier unsigned long All_Mem = 0;
2400d97012SDavid du Colombier char *claim_name;
257dd7cddfSDavid du Colombier
26*de2caf28SDavid du Colombier static char *uform;
277dd7cddfSDavid du Colombier static int hasuform=0, cnt=0;
287dd7cddfSDavid du Colombier
29312a1df1SDavid du Colombier extern void cache_stats(void);
30312a1df1SDavid du Colombier extern void a_stats(void);
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier int
tl_Getchar(void)337dd7cddfSDavid du Colombier tl_Getchar(void)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier if (cnt < hasuform)
367dd7cddfSDavid du Colombier return uform[cnt++];
377dd7cddfSDavid du Colombier cnt++;
387dd7cddfSDavid du Colombier return -1;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier
4100d97012SDavid du Colombier int
tl_peek(int n)4200d97012SDavid du Colombier tl_peek(int n)
4300d97012SDavid du Colombier {
4400d97012SDavid du Colombier if (cnt+n < hasuform)
4500d97012SDavid du Colombier { return uform[cnt+n];
4600d97012SDavid du Colombier }
4700d97012SDavid du Colombier return -1;
4800d97012SDavid du Colombier }
4900d97012SDavid du Colombier
507dd7cddfSDavid du Colombier void
tl_balanced(void)51f3793cddSDavid du Colombier tl_balanced(void)
52f3793cddSDavid du Colombier { int i;
53f3793cddSDavid du Colombier int k = 0;
54f3793cddSDavid du Colombier
55f3793cddSDavid du Colombier for (i = 0; i < hasuform; i++)
56f3793cddSDavid du Colombier { if (uform[i] == '(')
57*de2caf28SDavid du Colombier { if (i > 0
58*de2caf28SDavid du Colombier && ((uform[i-1] == '"' && uform[i+1] == '"')
59*de2caf28SDavid du Colombier || (uform[i-1] == '\'' && uform[i+1] == '\'')))
60*de2caf28SDavid du Colombier { continue;
61*de2caf28SDavid du Colombier }
62*de2caf28SDavid du Colombier k++;
63f3793cddSDavid du Colombier } else if (uform[i] == ')')
64*de2caf28SDavid du Colombier { if (i > 0
65*de2caf28SDavid du Colombier && ((uform[i-1] == '"' && uform[i+1] == '"')
66*de2caf28SDavid du Colombier || (uform[i-1] == '\'' && uform[i+1] == '\'')))
67*de2caf28SDavid du Colombier { continue;
68*de2caf28SDavid du Colombier }
69*de2caf28SDavid du Colombier k--;
70f3793cddSDavid du Colombier } }
71*de2caf28SDavid du Colombier
72f3793cddSDavid du Colombier if (k != 0)
73f3793cddSDavid du Colombier { tl_errs++;
74f3793cddSDavid du Colombier tl_yyerror("parentheses not balanced");
75f3793cddSDavid du Colombier }
76f3793cddSDavid du Colombier }
77f3793cddSDavid du Colombier
78f3793cddSDavid du Colombier void
put_uform(void)797dd7cddfSDavid du Colombier put_uform(void)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier fprintf(tl_out, "%s", uform);
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier void
tl_UnGetchar(void)857dd7cddfSDavid du Colombier tl_UnGetchar(void)
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier if (cnt > 0) cnt--;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier
90312a1df1SDavid du Colombier static void
tl_stats(void)91312a1df1SDavid du Colombier tl_stats(void)
92312a1df1SDavid du Colombier { extern int Stack_mx;
93312a1df1SDavid du Colombier printf("total memory used: %9ld\n", All_Mem);
94312a1df1SDavid du Colombier printf("largest stack sze: %9d\n", Stack_mx);
95312a1df1SDavid du Colombier cache_stats();
96312a1df1SDavid du Colombier a_stats();
97312a1df1SDavid du Colombier }
98312a1df1SDavid du Colombier
997dd7cddfSDavid du Colombier int
tl_main(int argc,char * argv[])1007dd7cddfSDavid du Colombier tl_main(int argc, char *argv[])
1017dd7cddfSDavid du Colombier { int i;
102*de2caf28SDavid du Colombier extern int xspin, s_trail;
10300d97012SDavid du Colombier
10400d97012SDavid du Colombier tl_verbose = 0; /* was: tl_verbose = verbose; */
105*de2caf28SDavid du Colombier if (xspin && s_trail)
106*de2caf28SDavid du Colombier { tl_clutter = 1;
107*de2caf28SDavid du Colombier /* generating claims for a replay should
108*de2caf28SDavid du Colombier be done the same as when generating the
109*de2caf28SDavid du Colombier pan.c that produced the error-trail */
110*de2caf28SDavid du Colombier } else
111*de2caf28SDavid du Colombier { tl_clutter = 1-xspin; /* use -X -f to turn off uncluttering */
112*de2caf28SDavid du Colombier }
11300d97012SDavid du Colombier newstates = 0;
11400d97012SDavid du Colombier state_cnt = 0;
11500d97012SDavid du Colombier tl_errs = 0;
11600d97012SDavid du Colombier tl_terse = 0;
11700d97012SDavid du Colombier All_Mem = 0;
11800d97012SDavid du Colombier hasuform=0;
11900d97012SDavid du Colombier cnt=0;
12000d97012SDavid du Colombier claim_name = (char *) 0;
12100d97012SDavid du Colombier
12200d97012SDavid du Colombier ini_buchi();
12300d97012SDavid du Colombier ini_cache();
12400d97012SDavid du Colombier ini_rewrt();
12500d97012SDavid du Colombier ini_trans();
12600d97012SDavid du Colombier
1277dd7cddfSDavid du Colombier while (argc > 1 && argv[1][0] == '-')
12800d97012SDavid du Colombier {
12900d97012SDavid du Colombier switch (argv[1][1]) {
1307dd7cddfSDavid du Colombier case 'd': newstates = 1; /* debugging mode */
1317dd7cddfSDavid du Colombier break;
1327dd7cddfSDavid du Colombier case 'f': argc--; argv++;
13300d97012SDavid du Colombier for (i = 0; argv[1][i]; i++)
1347dd7cddfSDavid du Colombier { if (argv[1][i] == '\t'
1357dd7cddfSDavid du Colombier || argv[1][i] == '\n')
1367dd7cddfSDavid du Colombier argv[1][i] = ' ';
1377dd7cddfSDavid du Colombier }
138*de2caf28SDavid du Colombier size_t len = strlen(argv[1]);
139*de2caf28SDavid du Colombier uform = tl_emalloc(len + 1);
1407dd7cddfSDavid du Colombier strcpy(uform, argv[1]);
141*de2caf28SDavid du Colombier hasuform = (int) len;
1427dd7cddfSDavid du Colombier break;
1437dd7cddfSDavid du Colombier case 'v': tl_verbose++;
1447dd7cddfSDavid du Colombier break;
1457dd7cddfSDavid du Colombier case 'n': tl_terse = 1;
1467dd7cddfSDavid du Colombier break;
14700d97012SDavid du Colombier case 'c': argc--; argv++;
14800d97012SDavid du Colombier claim_name = (char *) emalloc(strlen(argv[1])+1);
14900d97012SDavid du Colombier strcpy(claim_name, argv[1]);
15000d97012SDavid du Colombier break;
1517dd7cddfSDavid du Colombier default : printf("spin -f: saw '-%c'\n", argv[1][1]);
1527dd7cddfSDavid du Colombier goto nogood;
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier argc--; argv++;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier if (hasuform == 0)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier nogood: printf("usage:\tspin [-v] [-n] -f formula\n");
1597dd7cddfSDavid du Colombier printf(" -v verbose translation\n");
1607dd7cddfSDavid du Colombier printf(" -n normalize tl formula and exit\n");
1617dd7cddfSDavid du Colombier exit(1);
1627dd7cddfSDavid du Colombier }
163f3793cddSDavid du Colombier tl_balanced();
164f3793cddSDavid du Colombier
165f3793cddSDavid du Colombier if (tl_errs == 0)
1667dd7cddfSDavid du Colombier tl_parse();
167f3793cddSDavid du Colombier
1687dd7cddfSDavid du Colombier if (tl_verbose) tl_stats();
1697dd7cddfSDavid du Colombier return tl_errs;
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier #define Binop(a) \
1737dd7cddfSDavid du Colombier fprintf(tl_out, "("); \
1747dd7cddfSDavid du Colombier dump(n->lft); \
1757dd7cddfSDavid du Colombier fprintf(tl_out, a); \
1767dd7cddfSDavid du Colombier dump(n->rgt); \
1777dd7cddfSDavid du Colombier fprintf(tl_out, ")")
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier void
dump(Node * n)1807dd7cddfSDavid du Colombier dump(Node *n)
1817dd7cddfSDavid du Colombier {
1827dd7cddfSDavid du Colombier if (!n) return;
1837dd7cddfSDavid du Colombier
1847dd7cddfSDavid du Colombier switch(n->ntyp) {
1857dd7cddfSDavid du Colombier case OR: Binop(" || "); break;
1867dd7cddfSDavid du Colombier case AND: Binop(" && "); break;
1877dd7cddfSDavid du Colombier case U_OPER: Binop(" U "); break;
1887dd7cddfSDavid du Colombier case V_OPER: Binop(" V "); break;
1897dd7cddfSDavid du Colombier #ifdef NXT
1907dd7cddfSDavid du Colombier case NEXT:
1917dd7cddfSDavid du Colombier fprintf(tl_out, "X");
1927dd7cddfSDavid du Colombier fprintf(tl_out, " (");
1937dd7cddfSDavid du Colombier dump(n->lft);
1947dd7cddfSDavid du Colombier fprintf(tl_out, ")");
1957dd7cddfSDavid du Colombier break;
1967dd7cddfSDavid du Colombier #endif
1977dd7cddfSDavid du Colombier case NOT:
1987dd7cddfSDavid du Colombier fprintf(tl_out, "!");
1997dd7cddfSDavid du Colombier fprintf(tl_out, " (");
2007dd7cddfSDavid du Colombier dump(n->lft);
2017dd7cddfSDavid du Colombier fprintf(tl_out, ")");
2027dd7cddfSDavid du Colombier break;
2037dd7cddfSDavid du Colombier case FALSE:
2047dd7cddfSDavid du Colombier fprintf(tl_out, "false");
2057dd7cddfSDavid du Colombier break;
2067dd7cddfSDavid du Colombier case TRUE:
2077dd7cddfSDavid du Colombier fprintf(tl_out, "true");
2087dd7cddfSDavid du Colombier break;
2097dd7cddfSDavid du Colombier case PREDICATE:
2107dd7cddfSDavid du Colombier fprintf(tl_out, "(%s)", n->sym->name);
2117dd7cddfSDavid du Colombier break;
212*de2caf28SDavid du Colombier case CEXPR:
213*de2caf28SDavid du Colombier fprintf(tl_out, "c_expr");
214*de2caf28SDavid du Colombier fprintf(tl_out, " {");
215*de2caf28SDavid du Colombier dump(n->lft);
216*de2caf28SDavid du Colombier fprintf(tl_out, "}");
217*de2caf28SDavid du Colombier break;
2187dd7cddfSDavid du Colombier case -1:
2197dd7cddfSDavid du Colombier fprintf(tl_out, " D ");
2207dd7cddfSDavid du Colombier break;
2217dd7cddfSDavid du Colombier default:
2227dd7cddfSDavid du Colombier printf("Unknown token: ");
2237dd7cddfSDavid du Colombier tl_explain(n->ntyp);
2247dd7cddfSDavid du Colombier break;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier void
tl_explain(int n)2297dd7cddfSDavid du Colombier tl_explain(int n)
2307dd7cddfSDavid du Colombier {
2317dd7cddfSDavid du Colombier switch (n) {
2327dd7cddfSDavid du Colombier case ALWAYS: printf("[]"); break;
2337dd7cddfSDavid du Colombier case EVENTUALLY: printf("<>"); break;
2347dd7cddfSDavid du Colombier case IMPLIES: printf("->"); break;
2357dd7cddfSDavid du Colombier case EQUIV: printf("<->"); break;
2367dd7cddfSDavid du Colombier case PREDICATE: printf("predicate"); break;
2377dd7cddfSDavid du Colombier case OR: printf("||"); break;
2387dd7cddfSDavid du Colombier case AND: printf("&&"); break;
2397dd7cddfSDavid du Colombier case NOT: printf("!"); break;
2407dd7cddfSDavid du Colombier case U_OPER: printf("U"); break;
2417dd7cddfSDavid du Colombier case V_OPER: printf("V"); break;
2427dd7cddfSDavid du Colombier #ifdef NXT
2437dd7cddfSDavid du Colombier case NEXT: printf("X"); break;
2447dd7cddfSDavid du Colombier #endif
245*de2caf28SDavid du Colombier case CEXPR: printf("c_expr"); break;
2467dd7cddfSDavid du Colombier case TRUE: printf("true"); break;
2477dd7cddfSDavid du Colombier case FALSE: printf("false"); break;
2487dd7cddfSDavid du Colombier case ';': printf("end of formula"); break;
2497dd7cddfSDavid du Colombier default: printf("%c", n); break;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier static void
tl_non_fatal(char * s1,char * s2)254312a1df1SDavid du Colombier tl_non_fatal(char *s1, char *s2)
2557dd7cddfSDavid du Colombier { extern int tl_yychar;
2567dd7cddfSDavid du Colombier int i;
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier printf("tl_spin: ");
259*de2caf28SDavid du Colombier #if 1
260*de2caf28SDavid du Colombier printf(s1, s2); /* prevent a compiler warning */
261*de2caf28SDavid du Colombier #else
2627dd7cddfSDavid du Colombier if (s2)
2637dd7cddfSDavid du Colombier printf(s1, s2);
2647dd7cddfSDavid du Colombier else
2657dd7cddfSDavid du Colombier printf(s1);
266*de2caf28SDavid du Colombier #endif
2677dd7cddfSDavid du Colombier if (tl_yychar != -1 && tl_yychar != 0)
2687dd7cddfSDavid du Colombier { printf(", saw '");
2697dd7cddfSDavid du Colombier tl_explain(tl_yychar);
2707dd7cddfSDavid du Colombier printf("'");
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier printf("\ntl_spin: %s\n---------", uform);
2737dd7cddfSDavid du Colombier for (i = 0; i < cnt; i++)
2747dd7cddfSDavid du Colombier printf("-");
2757dd7cddfSDavid du Colombier printf("^\n");
2767dd7cddfSDavid du Colombier fflush(stdout);
2777dd7cddfSDavid du Colombier tl_errs++;
2787dd7cddfSDavid du Colombier }
2797dd7cddfSDavid du Colombier
2807dd7cddfSDavid du Colombier void
tl_yyerror(char * s1)2817dd7cddfSDavid du Colombier tl_yyerror(char *s1)
2827dd7cddfSDavid du Colombier {
2837dd7cddfSDavid du Colombier Fatal(s1, (char *) 0);
2847dd7cddfSDavid du Colombier }
2857dd7cddfSDavid du Colombier
2867dd7cddfSDavid du Colombier void
Fatal(char * s1,char * s2)2877dd7cddfSDavid du Colombier Fatal(char *s1, char *s2)
2887dd7cddfSDavid du Colombier {
289312a1df1SDavid du Colombier tl_non_fatal(s1, s2);
2907dd7cddfSDavid du Colombier /* tl_stats(); */
2917dd7cddfSDavid du Colombier exit(1);
2927dd7cddfSDavid du Colombier }
293