xref: /plan9/sys/src/cmd/spin/tl_main.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** tl_spin: tl_main.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11312a1df1SDavid du Colombier 
127dd7cddfSDavid du Colombier /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
137dd7cddfSDavid du Colombier /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier #include "tl.h"
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier extern FILE	*tl_out;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier int	newstates  = 0;	/* debugging only */
207dd7cddfSDavid du Colombier int	tl_errs    = 0;
217dd7cddfSDavid du Colombier int	tl_verbose = 0;
227dd7cddfSDavid du Colombier int	tl_terse   = 0;
237dd7cddfSDavid du Colombier int	tl_clutter = 0;
24*00d97012SDavid du Colombier int	state_cnt = 0;
25*00d97012SDavid du Colombier 
267dd7cddfSDavid du Colombier unsigned long	All_Mem = 0;
27*00d97012SDavid du Colombier char	*claim_name;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier static char	uform[4096];
307dd7cddfSDavid du Colombier static int	hasuform=0, cnt=0;
317dd7cddfSDavid du Colombier 
32312a1df1SDavid du Colombier extern void cache_stats(void);
33312a1df1SDavid du Colombier extern void a_stats(void);
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier int
tl_Getchar(void)367dd7cddfSDavid du Colombier tl_Getchar(void)
377dd7cddfSDavid du Colombier {
387dd7cddfSDavid du Colombier 	if (cnt < hasuform)
397dd7cddfSDavid du Colombier 		return uform[cnt++];
407dd7cddfSDavid du Colombier 	cnt++;
417dd7cddfSDavid du Colombier 	return -1;
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier 
44*00d97012SDavid du Colombier int
tl_peek(int n)45*00d97012SDavid du Colombier tl_peek(int n)
46*00d97012SDavid du Colombier {
47*00d97012SDavid du Colombier 	if (cnt+n < hasuform)
48*00d97012SDavid du Colombier 	{	return uform[cnt+n];
49*00d97012SDavid du Colombier 	}
50*00d97012SDavid du Colombier 	return -1;
51*00d97012SDavid du Colombier }
52*00d97012SDavid du Colombier 
537dd7cddfSDavid du Colombier void
tl_balanced(void)54f3793cddSDavid du Colombier tl_balanced(void)
55f3793cddSDavid du Colombier {	int i;
56f3793cddSDavid du Colombier 	int k = 0;
57f3793cddSDavid du Colombier 
58f3793cddSDavid du Colombier 	for (i = 0; i < hasuform; i++)
59f3793cddSDavid du Colombier 	{	if (uform[i] == '(')
60f3793cddSDavid du Colombier 		{	k++;
61f3793cddSDavid du Colombier 		} else if (uform[i] == ')')
62f3793cddSDavid du Colombier 		{	k--;
63f3793cddSDavid du Colombier 	}	}
64f3793cddSDavid du Colombier 	if (k != 0)
65f3793cddSDavid du Colombier 	{	tl_errs++;
66f3793cddSDavid du Colombier 		tl_yyerror("parentheses not balanced");
67f3793cddSDavid du Colombier 	}
68f3793cddSDavid du Colombier }
69f3793cddSDavid du Colombier 
70f3793cddSDavid du Colombier void
put_uform(void)717dd7cddfSDavid du Colombier put_uform(void)
727dd7cddfSDavid du Colombier {
737dd7cddfSDavid du Colombier 	fprintf(tl_out, "%s", uform);
747dd7cddfSDavid du Colombier }
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier void
tl_UnGetchar(void)777dd7cddfSDavid du Colombier tl_UnGetchar(void)
787dd7cddfSDavid du Colombier {
797dd7cddfSDavid du Colombier 	if (cnt > 0) cnt--;
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier 
82312a1df1SDavid du Colombier static void
tl_stats(void)83312a1df1SDavid du Colombier tl_stats(void)
84312a1df1SDavid du Colombier {	extern int Stack_mx;
85312a1df1SDavid du Colombier 	printf("total memory used: %9ld\n", All_Mem);
86312a1df1SDavid du Colombier 	printf("largest stack sze: %9d\n", Stack_mx);
87312a1df1SDavid du Colombier 	cache_stats();
88312a1df1SDavid du Colombier 	a_stats();
89312a1df1SDavid du Colombier }
90312a1df1SDavid du Colombier 
917dd7cddfSDavid du Colombier int
tl_main(int argc,char * argv[])927dd7cddfSDavid du Colombier tl_main(int argc, char *argv[])
937dd7cddfSDavid du Colombier {	int i;
94*00d97012SDavid du Colombier 	extern int /* verbose, */ xspin;
95*00d97012SDavid du Colombier 
96*00d97012SDavid du Colombier 	tl_verbose = 0; /* was: tl_verbose = verbose; */
977dd7cddfSDavid du Colombier 	tl_clutter = 1-xspin;	/* use -X -f to turn off uncluttering */
987dd7cddfSDavid du Colombier 
99*00d97012SDavid du Colombier 	newstates  = 0;
100*00d97012SDavid du Colombier 	state_cnt  = 0;
101*00d97012SDavid du Colombier 	tl_errs    = 0;
102*00d97012SDavid du Colombier 	tl_terse   = 0;
103*00d97012SDavid du Colombier 	All_Mem = 0;
104*00d97012SDavid du Colombier 	memset(uform, 0, sizeof(uform));
105*00d97012SDavid du Colombier 	hasuform=0;
106*00d97012SDavid du Colombier 	cnt=0;
107*00d97012SDavid du Colombier 	claim_name = (char *) 0;
108*00d97012SDavid du Colombier 
109*00d97012SDavid du Colombier 	ini_buchi();
110*00d97012SDavid du Colombier 	ini_cache();
111*00d97012SDavid du Colombier 	ini_rewrt();
112*00d97012SDavid du Colombier 	ini_trans();
113*00d97012SDavid du Colombier 
1147dd7cddfSDavid du Colombier 	while (argc > 1 && argv[1][0] == '-')
115*00d97012SDavid du Colombier 	{
116*00d97012SDavid du Colombier 		switch (argv[1][1]) {
1177dd7cddfSDavid du Colombier 		case 'd':	newstates = 1;	/* debugging mode */
1187dd7cddfSDavid du Colombier 				break;
1197dd7cddfSDavid du Colombier 		case 'f':	argc--; argv++;
120*00d97012SDavid du Colombier 				for (i = 0; argv[1][i]; i++)
1217dd7cddfSDavid du Colombier 				{	if (argv[1][i] == '\t'
1227dd7cddfSDavid du Colombier 					||  argv[1][i] == '\"'
1237dd7cddfSDavid du Colombier 					||  argv[1][i] == '\n')
1247dd7cddfSDavid du Colombier 						argv[1][i] = ' ';
1257dd7cddfSDavid du Colombier 				}
1267dd7cddfSDavid du Colombier 				strcpy(uform, argv[1]);
127312a1df1SDavid du Colombier 				hasuform = (int) strlen(uform);
1287dd7cddfSDavid du Colombier 				break;
1297dd7cddfSDavid du Colombier 		case 'v':	tl_verbose++;
1307dd7cddfSDavid du Colombier 				break;
1317dd7cddfSDavid du Colombier 		case 'n':	tl_terse = 1;
1327dd7cddfSDavid du Colombier 				break;
133*00d97012SDavid du Colombier 		case 'c':	argc--; argv++;
134*00d97012SDavid du Colombier 				claim_name = (char *) emalloc(strlen(argv[1])+1);
135*00d97012SDavid du Colombier 				strcpy(claim_name, argv[1]);
136*00d97012SDavid du Colombier 				break;
1377dd7cddfSDavid du Colombier 		default :	printf("spin -f: saw '-%c'\n", argv[1][1]);
1387dd7cddfSDavid du Colombier 				goto nogood;
1397dd7cddfSDavid du Colombier 		}
1407dd7cddfSDavid du Colombier 		argc--; argv++;
1417dd7cddfSDavid du Colombier 	}
1427dd7cddfSDavid du Colombier 	if (hasuform == 0)
1437dd7cddfSDavid du Colombier 	{
1447dd7cddfSDavid du Colombier nogood:		printf("usage:\tspin [-v] [-n] -f formula\n");
1457dd7cddfSDavid du Colombier 		printf("	-v verbose translation\n");
1467dd7cddfSDavid du Colombier 		printf("	-n normalize tl formula and exit\n");
1477dd7cddfSDavid du Colombier 		exit(1);
1487dd7cddfSDavid du Colombier 	}
149f3793cddSDavid du Colombier 	tl_balanced();
150f3793cddSDavid du Colombier 
151f3793cddSDavid du Colombier 	if (tl_errs == 0)
1527dd7cddfSDavid du Colombier 		tl_parse();
153f3793cddSDavid du Colombier 
1547dd7cddfSDavid du Colombier 	if (tl_verbose) tl_stats();
1557dd7cddfSDavid du Colombier 	return tl_errs;
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier #define Binop(a)		\
1597dd7cddfSDavid du Colombier 		fprintf(tl_out, "(");	\
1607dd7cddfSDavid du Colombier 		dump(n->lft);		\
1617dd7cddfSDavid du Colombier 		fprintf(tl_out, a);	\
1627dd7cddfSDavid du Colombier 		dump(n->rgt);		\
1637dd7cddfSDavid du Colombier 		fprintf(tl_out, ")")
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier void
dump(Node * n)1667dd7cddfSDavid du Colombier dump(Node *n)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier 	if (!n) return;
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier 	switch(n->ntyp) {
1717dd7cddfSDavid du Colombier 	case OR:	Binop(" || "); break;
1727dd7cddfSDavid du Colombier 	case AND:	Binop(" && "); break;
1737dd7cddfSDavid du Colombier 	case U_OPER:	Binop(" U ");  break;
1747dd7cddfSDavid du Colombier 	case V_OPER:	Binop(" V ");  break;
1757dd7cddfSDavid du Colombier #ifdef NXT
1767dd7cddfSDavid du Colombier 	case NEXT:
1777dd7cddfSDavid du Colombier 		fprintf(tl_out, "X");
1787dd7cddfSDavid du Colombier 		fprintf(tl_out, " (");
1797dd7cddfSDavid du Colombier 		dump(n->lft);
1807dd7cddfSDavid du Colombier 		fprintf(tl_out, ")");
1817dd7cddfSDavid du Colombier 		break;
1827dd7cddfSDavid du Colombier #endif
1837dd7cddfSDavid du Colombier 	case NOT:
1847dd7cddfSDavid du Colombier 		fprintf(tl_out, "!");
1857dd7cddfSDavid du Colombier 		fprintf(tl_out, " (");
1867dd7cddfSDavid du Colombier 		dump(n->lft);
1877dd7cddfSDavid du Colombier 		fprintf(tl_out, ")");
1887dd7cddfSDavid du Colombier 		break;
1897dd7cddfSDavid du Colombier 	case FALSE:
1907dd7cddfSDavid du Colombier 		fprintf(tl_out, "false");
1917dd7cddfSDavid du Colombier 		break;
1927dd7cddfSDavid du Colombier 	case TRUE:
1937dd7cddfSDavid du Colombier 		fprintf(tl_out, "true");
1947dd7cddfSDavid du Colombier 		break;
1957dd7cddfSDavid du Colombier 	case PREDICATE:
1967dd7cddfSDavid du Colombier 		fprintf(tl_out, "(%s)", n->sym->name);
1977dd7cddfSDavid du Colombier 		break;
1987dd7cddfSDavid du Colombier 	case -1:
1997dd7cddfSDavid du Colombier 		fprintf(tl_out, " D ");
2007dd7cddfSDavid du Colombier 		break;
2017dd7cddfSDavid du Colombier 	default:
2027dd7cddfSDavid du Colombier 		printf("Unknown token: ");
2037dd7cddfSDavid du Colombier 		tl_explain(n->ntyp);
2047dd7cddfSDavid du Colombier 		break;
2057dd7cddfSDavid du Colombier 	}
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier 
2087dd7cddfSDavid du Colombier void
tl_explain(int n)2097dd7cddfSDavid du Colombier tl_explain(int n)
2107dd7cddfSDavid du Colombier {
2117dd7cddfSDavid du Colombier 	switch (n) {
2127dd7cddfSDavid du Colombier 	case ALWAYS:	printf("[]"); break;
2137dd7cddfSDavid du Colombier 	case EVENTUALLY: printf("<>"); break;
2147dd7cddfSDavid du Colombier 	case IMPLIES:	printf("->"); break;
2157dd7cddfSDavid du Colombier 	case EQUIV:	printf("<->"); break;
2167dd7cddfSDavid du Colombier 	case PREDICATE:	printf("predicate"); break;
2177dd7cddfSDavid du Colombier 	case OR:	printf("||"); break;
2187dd7cddfSDavid du Colombier 	case AND:	printf("&&"); break;
2197dd7cddfSDavid du Colombier 	case NOT:	printf("!"); break;
2207dd7cddfSDavid du Colombier 	case U_OPER:	printf("U"); break;
2217dd7cddfSDavid du Colombier 	case V_OPER:	printf("V"); break;
2227dd7cddfSDavid du Colombier #ifdef NXT
2237dd7cddfSDavid du Colombier 	case NEXT:	printf("X"); break;
2247dd7cddfSDavid du Colombier #endif
2257dd7cddfSDavid du Colombier 	case TRUE:	printf("true"); break;
2267dd7cddfSDavid du Colombier 	case FALSE:	printf("false"); break;
2277dd7cddfSDavid du Colombier 	case ';':	printf("end of formula"); break;
2287dd7cddfSDavid du Colombier 	default:	printf("%c", n); break;
2297dd7cddfSDavid du Colombier 	}
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier static void
tl_non_fatal(char * s1,char * s2)233312a1df1SDavid du Colombier tl_non_fatal(char *s1, char *s2)
2347dd7cddfSDavid du Colombier {	extern int tl_yychar;
2357dd7cddfSDavid du Colombier 	int i;
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier 	printf("tl_spin: ");
2387dd7cddfSDavid du Colombier 	if (s2)
2397dd7cddfSDavid du Colombier 		printf(s1, s2);
2407dd7cddfSDavid du Colombier 	else
2417dd7cddfSDavid du Colombier 		printf(s1);
2427dd7cddfSDavid du Colombier 	if (tl_yychar != -1 && tl_yychar != 0)
2437dd7cddfSDavid du Colombier 	{	printf(", saw '");
2447dd7cddfSDavid du Colombier 		tl_explain(tl_yychar);
2457dd7cddfSDavid du Colombier 		printf("'");
2467dd7cddfSDavid du Colombier 	}
2477dd7cddfSDavid du Colombier 	printf("\ntl_spin: %s\n---------", uform);
2487dd7cddfSDavid du Colombier 	for (i = 0; i < cnt; i++)
2497dd7cddfSDavid du Colombier 		printf("-");
2507dd7cddfSDavid du Colombier 	printf("^\n");
2517dd7cddfSDavid du Colombier 	fflush(stdout);
2527dd7cddfSDavid du Colombier 	tl_errs++;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier void
tl_yyerror(char * s1)2567dd7cddfSDavid du Colombier tl_yyerror(char *s1)
2577dd7cddfSDavid du Colombier {
2587dd7cddfSDavid du Colombier 	Fatal(s1, (char *) 0);
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier 
2617dd7cddfSDavid du Colombier void
Fatal(char * s1,char * s2)2627dd7cddfSDavid du Colombier Fatal(char *s1, char *s2)
2637dd7cddfSDavid du Colombier {
264312a1df1SDavid du Colombier 	tl_non_fatal(s1, s2);
2657dd7cddfSDavid du Colombier 	/* tl_stats(); */
2667dd7cddfSDavid du Colombier 	exit(1);
2677dd7cddfSDavid du Colombier }
268