xref: /plan9-contrib/sys/src/cmd/spin/tl_main.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
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