xref: /plan9/sys/src/cmd/eqn/main.c (revision 9f2726c34299ea5a81cda1b22133dd5a4b421e04)
13e12c5d1SDavid du Colombier #include "e.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier #define	MAXLINE	3600	/* maximum input line */
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier char *version = "version Oct 24, 1991";
63e12c5d1SDavid du Colombier 
7*9f2726c3SDavid du Colombier char	in[MAXLINE+1];	/* input buffer */
83e12c5d1SDavid du Colombier int	noeqn;
93e12c5d1SDavid du Colombier char	*cmdname;
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier int	yyparse(void);
123e12c5d1SDavid du Colombier void	settype(char *);
133e12c5d1SDavid du Colombier int	getdata(void);
143e12c5d1SDavid du Colombier int	getline(char *);
15824682f6SDavid du Colombier void	inlineeq(void);
163e12c5d1SDavid du Colombier void	init(void);
173e12c5d1SDavid du Colombier void	init_tbl(void);
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier void
main(int argc,char * argv[])203e12c5d1SDavid du Colombier main(int argc, char *argv[])
213e12c5d1SDavid du Colombier {
223e12c5d1SDavid du Colombier 	char *p, buf[20];
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier 	cmdname = argv[0];
253e12c5d1SDavid du Colombier 	if (p = getenv("TYPESETTER"))
263e12c5d1SDavid du Colombier 		typesetter = p;
273e12c5d1SDavid du Colombier 	while (argc > 1 && argv[1][0] == '-') {
283e12c5d1SDavid du Colombier 		switch (argv[1][1]) {
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier 		case 'd':
313e12c5d1SDavid du Colombier 			if (argv[1][2] == '\0') {
323e12c5d1SDavid du Colombier 				dbg++;
333e12c5d1SDavid du Colombier 				printf("...\teqn %s\n", version);
343e12c5d1SDavid du Colombier 			} else {
353e12c5d1SDavid du Colombier 				lefteq = argv[1][2];
363e12c5d1SDavid du Colombier 				righteq = argv[1][3];
373e12c5d1SDavid du Colombier 			}
383e12c5d1SDavid du Colombier 			break;
393e12c5d1SDavid du Colombier 		case 's': szstack[0] = gsize = atoi(&argv[1][2]); break;
403e12c5d1SDavid du Colombier 		case 'p': deltaps = atoi(&argv[1][2]); dps_set = 1; break;
413e12c5d1SDavid du Colombier 		case 'm': minsize = atoi(&argv[1][2]); break;
423e12c5d1SDavid du Colombier 		case 'f': strcpy(ftstack[0].name,&argv[1][2]); break;
433e12c5d1SDavid du Colombier 		case 'e': noeqn++; break;
443e12c5d1SDavid du Colombier 		case 'T': typesetter = &argv[1][2]; break;
453e12c5d1SDavid du Colombier 		default:
463e12c5d1SDavid du Colombier 			fprintf(stderr, "%s: unknown option %s\n", cmdname, argv[1]);
473e12c5d1SDavid du Colombier 			break;
483e12c5d1SDavid du Colombier 		}
493e12c5d1SDavid du Colombier 		argc--;
503e12c5d1SDavid du Colombier 		argv++;
513e12c5d1SDavid du Colombier 	}
523e12c5d1SDavid du Colombier 	settype(typesetter);
533e12c5d1SDavid du Colombier 	sprintf(buf, "\"%s\"", typesetter);
543e12c5d1SDavid du Colombier 	install(deftbl, strsave(typesetter), strsave(buf), 0);
553e12c5d1SDavid du Colombier 	init_tbl();	/* install other keywords in tables */
563e12c5d1SDavid du Colombier 	curfile = infile;
573e12c5d1SDavid du Colombier 	pushsrc(File, curfile->fname);
583e12c5d1SDavid du Colombier 	if (argc <= 1) {
593e12c5d1SDavid du Colombier 		curfile->fin = stdin;
603e12c5d1SDavid du Colombier 		curfile->fname = strsave("-");
613e12c5d1SDavid du Colombier 		getdata();
623e12c5d1SDavid du Colombier 	} else
633e12c5d1SDavid du Colombier 		while (argc-- > 1) {
643e12c5d1SDavid du Colombier 			if (strcmp(*++argv, "-") == 0)
653e12c5d1SDavid du Colombier 				curfile->fin = stdin;
663e12c5d1SDavid du Colombier 			else if ((curfile->fin = fopen(*argv, "r")) == NULL)
673e12c5d1SDavid du Colombier 				ERROR "can't open file %s", *argv FATAL;
683e12c5d1SDavid du Colombier 			curfile->fname = strsave(*argv);
693e12c5d1SDavid du Colombier 			getdata();
703e12c5d1SDavid du Colombier 			if (curfile->fin != stdin)
713e12c5d1SDavid du Colombier 				fclose(curfile->fin);
723e12c5d1SDavid du Colombier 		}
733e12c5d1SDavid du Colombier 	exit(0);
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier 
settype(char * s)763e12c5d1SDavid du Colombier void settype(char *s)	/* initialize data for particular typesetter */
773e12c5d1SDavid du Colombier 			/* the minsize could profitably come from the */
783e12c5d1SDavid du Colombier {			/* troff description file /usr/lib/font/dev.../DESC.out */
793e12c5d1SDavid du Colombier 	if (strcmp(s, "202") == 0)
803e12c5d1SDavid du Colombier 		{ minsize = 5; ttype = DEV202; }
813e12c5d1SDavid du Colombier 	else if (strcmp(s, "aps") == 0)
823e12c5d1SDavid du Colombier 		{ minsize = 5; ttype = DEVAPS; }
833e12c5d1SDavid du Colombier 	else if (strcmp(s, "cat") == 0)
843e12c5d1SDavid du Colombier 		{ minsize = 6; ttype = DEVCAT; }
853e12c5d1SDavid du Colombier 	else if (strcmp(s, "post") == 0)
863e12c5d1SDavid du Colombier 		{ minsize = 4; ttype = DEVPOST; }
873e12c5d1SDavid du Colombier 	else
883e12c5d1SDavid du Colombier 		{ minsize = 5; ttype = DEV202; }
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier 
getdata(void)913e12c5d1SDavid du Colombier getdata(void)
923e12c5d1SDavid du Colombier {
933e12c5d1SDavid du Colombier 	int i, type, ln;
943e12c5d1SDavid du Colombier 	char fname[100];
953e12c5d1SDavid du Colombier 	extern int errno;
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier 	errno = 0;
983e12c5d1SDavid du Colombier 	curfile->lineno = 0;
993e12c5d1SDavid du Colombier 	printf(".lf 1 %s\n", curfile->fname);
1003e12c5d1SDavid du Colombier 	while ((type = getline(in)) != EOF) {
1013e12c5d1SDavid du Colombier 		if (in[0] == '.' && in[1] == 'E' && in[2] == 'Q') {
1023e12c5d1SDavid du Colombier 			for (i = 11; i < 100; i++)
1033e12c5d1SDavid du Colombier 				used[i] = 0;
1043e12c5d1SDavid du Colombier 			printf("%s", in);
1053e12c5d1SDavid du Colombier 			if (markline) {	/* turn off from last time */
1063e12c5d1SDavid du Colombier 				printf(".nr MK 0\n");
1073e12c5d1SDavid du Colombier 				markline = 0;
1083e12c5d1SDavid du Colombier 			}
1093e12c5d1SDavid du Colombier 			display = 1;
1103e12c5d1SDavid du Colombier 			init();
1113e12c5d1SDavid du Colombier 			yyparse();
1123e12c5d1SDavid du Colombier 			if (eqnreg > 0) {
1133e12c5d1SDavid du Colombier 				if (markline)
1143e12c5d1SDavid du Colombier 					printf(".nr MK %d\n", markline); /* for -ms macros */
1153e12c5d1SDavid du Colombier 				printf(".if %gm>\\n(.v .ne %gm\n", eqnht, eqnht);
1163e12c5d1SDavid du Colombier 				printf(".rn %d 10\n", eqnreg);
1173e12c5d1SDavid du Colombier 				if (!noeqn)
1183e12c5d1SDavid du Colombier 					printf("\\&\\*(10\n");
1193e12c5d1SDavid du Colombier 			}
1203e12c5d1SDavid du Colombier 			printf(".EN");
1213e12c5d1SDavid du Colombier 			while (putchar(input()) != '\n')
1223e12c5d1SDavid du Colombier 				;
1233e12c5d1SDavid du Colombier 			printf(".lf %d\n", curfile->lineno+1);
1243e12c5d1SDavid du Colombier 		}
1253e12c5d1SDavid du Colombier 		else if (type == lefteq)
126824682f6SDavid du Colombier 			inlineeq();
1273e12c5d1SDavid du Colombier 		else if (in[0] == '.' && in[1] == 'l' && in[2] == 'f') {
1283e12c5d1SDavid du Colombier 			if (sscanf(in+3, "%d %s", &ln, fname) == 2) {
1293e12c5d1SDavid du Colombier 				free(curfile->fname);
1303e12c5d1SDavid du Colombier 				printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = strsave(fname));
1313e12c5d1SDavid du Colombier 			} else
1323e12c5d1SDavid du Colombier 				printf(".lf %d\n", curfile->lineno = ln);
1333e12c5d1SDavid du Colombier 		} else
1343e12c5d1SDavid du Colombier 			printf("%s", in);
1353e12c5d1SDavid du Colombier 	}
1363e12c5d1SDavid du Colombier 	return(0);
1373e12c5d1SDavid du Colombier }
1383e12c5d1SDavid du Colombier 
getline(char * s)1393e12c5d1SDavid du Colombier getline(char *s)
1403e12c5d1SDavid du Colombier {
1413e12c5d1SDavid du Colombier 	register c;
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	while ((c=input()) != '\n' && c != EOF && c != lefteq) {
1443e12c5d1SDavid du Colombier 		if (s >= in+MAXLINE) {
1453e12c5d1SDavid du Colombier 			ERROR "input line too long: %.20s\n", in WARNING;
1463e12c5d1SDavid du Colombier 			in[MAXLINE] = '\0';
1473e12c5d1SDavid du Colombier 			break;
1483e12c5d1SDavid du Colombier 		}
1493e12c5d1SDavid du Colombier 		*s++ = c;
1503e12c5d1SDavid du Colombier 	}
1513e12c5d1SDavid du Colombier 	if (c != lefteq)
1523e12c5d1SDavid du Colombier 		*s++ = c;
1533e12c5d1SDavid du Colombier 	*s = '\0';
1543e12c5d1SDavid du Colombier 	return(c);
1553e12c5d1SDavid du Colombier }
1563e12c5d1SDavid du Colombier 
inlineeq(void)157824682f6SDavid du Colombier void inlineeq(void)
1583e12c5d1SDavid du Colombier {
1593e12c5d1SDavid du Colombier 	int ds, n, sz1 = 0;
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier 	n = curfile->lineno;
1623e12c5d1SDavid du Colombier 	if (szstack[0] != 0)
1633e12c5d1SDavid du Colombier 		printf(".nr %d \\n(.s\n", sz1 = salloc());
1643e12c5d1SDavid du Colombier 	ds = salloc();
1653e12c5d1SDavid du Colombier 	printf(".rm %d \n", ds);
1663e12c5d1SDavid du Colombier 	display = 0;
1673e12c5d1SDavid du Colombier 	do {
1683e12c5d1SDavid du Colombier 		if (*in)
1693e12c5d1SDavid du Colombier 			printf(".as %d \"%s\n", ds, in);
1703e12c5d1SDavid du Colombier 		init();
1713e12c5d1SDavid du Colombier 		yyparse();
1723e12c5d1SDavid du Colombier 		if (eqnreg > 0) {
1733e12c5d1SDavid du Colombier 			printf(".as %d \\*(%d\n", ds, eqnreg);
1743e12c5d1SDavid du Colombier 			sfree(eqnreg);
1753e12c5d1SDavid du Colombier 			printf(".lf %d\n", curfile->lineno+1);
1763e12c5d1SDavid du Colombier 		}
1773e12c5d1SDavid du Colombier 	} while (getline(in) == lefteq);
1783e12c5d1SDavid du Colombier 	if (*in)
1793e12c5d1SDavid du Colombier 		printf(".as %d \"%s", ds, in);
1803e12c5d1SDavid du Colombier 	if (sz1)
1813e12c5d1SDavid du Colombier 		printf("\\s\\n(%d", sz1);
1823e12c5d1SDavid du Colombier 	printf("\\*(%d\n", ds);
1833e12c5d1SDavid du Colombier 	printf(".lf %d\n", curfile->lineno+1);
1843e12c5d1SDavid du Colombier 	if (curfile->lineno > n+3)
1857dd7cddfSDavid du Colombier 		fprintf(stderr, "eqn warning: multi-line %c...%c, file %s:%d,%d\n",
1867dd7cddfSDavid du Colombier 			lefteq, righteq, curfile->fname, n, curfile->lineno);
1873e12c5d1SDavid du Colombier 	sfree(ds);
1883e12c5d1SDavid du Colombier 	if (sz1) sfree(sz1);
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier 
putout(int p1)1913e12c5d1SDavid du Colombier void putout(int p1)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier 	double before, after;
1943e12c5d1SDavid du Colombier 	extern double BeforeSub, AfterSub;
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier 	dprintf(".\tanswer <- S%d, h=%g,b=%g\n",p1, eht[p1], ebase[p1]);
1973e12c5d1SDavid du Colombier 	eqnht = eht[p1];
1983e12c5d1SDavid du Colombier 	before = eht[p1] - ebase[p1] - BeforeSub;	/* leave room for sub or superscript */
1993e12c5d1SDavid du Colombier 	after = ebase[p1] - AfterSub;
2003e12c5d1SDavid du Colombier 	if (spaceval || before > 0.01 || after > 0.01) {
2013e12c5d1SDavid du Colombier 		printf(".ds %d ", p1);	/* used to be \\x'0' here:  why? */
2023e12c5d1SDavid du Colombier 		if (spaceval != NULL)
2033e12c5d1SDavid du Colombier 			printf("\\x'0-%s'", spaceval);
2043e12c5d1SDavid du Colombier 		else if (before > 0.01)
2053e12c5d1SDavid du Colombier 			printf("\\x'0-%gm'", before);
2063e12c5d1SDavid du Colombier 		printf("\\*(%d", p1);
2073e12c5d1SDavid du Colombier 		if (spaceval == NULL && after > 0.01)
2083e12c5d1SDavid du Colombier 			printf("\\x'%gm'", after);
2093e12c5d1SDavid du Colombier 		putchar('\n');
2103e12c5d1SDavid du Colombier 	}
2113e12c5d1SDavid du Colombier 	if (szstack[0] != 0)
2123e12c5d1SDavid du Colombier 		printf(".ds %d %s\\*(%d\\s\\n(99\n", p1, DPS(gsize,gsize), p1);
2133e12c5d1SDavid du Colombier 	eqnreg = p1;
2143e12c5d1SDavid du Colombier 	if (spaceval != NULL) {
2153e12c5d1SDavid du Colombier 		free(spaceval);
2163e12c5d1SDavid du Colombier 		spaceval = NULL;
2173e12c5d1SDavid du Colombier 	}
2183e12c5d1SDavid du Colombier }
2193e12c5d1SDavid du Colombier 
init(void)2203e12c5d1SDavid du Colombier void init(void)
2213e12c5d1SDavid du Colombier {
2223e12c5d1SDavid du Colombier 	synerr = 0;
2233e12c5d1SDavid du Colombier 	ct = 0;
2243e12c5d1SDavid du Colombier 	ps = gsize;
2253e12c5d1SDavid du Colombier 	ftp = ftstack;
2263e12c5d1SDavid du Colombier 	ft = ftp->ft;
2273e12c5d1SDavid du Colombier 	nszstack = 0;
2283e12c5d1SDavid du Colombier 	if (szstack[0] != 0)	/* absolute gsize in effect */
2293e12c5d1SDavid du Colombier 		printf(".nr 99 \\n(.s\n");
2303e12c5d1SDavid du Colombier }
2313e12c5d1SDavid du Colombier 
salloc(void)2323e12c5d1SDavid du Colombier salloc(void)
2333e12c5d1SDavid du Colombier {
2343e12c5d1SDavid du Colombier 	int i;
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier 	for (i = 11; i < 100; i++)
2373e12c5d1SDavid du Colombier 		if (used[i] == 0) {
2383e12c5d1SDavid du Colombier 			used[i]++;
2393e12c5d1SDavid du Colombier 			return(i);
2403e12c5d1SDavid du Colombier 		}
2413e12c5d1SDavid du Colombier 	ERROR "no eqn strings left (%d)", i FATAL;
2423e12c5d1SDavid du Colombier 	return(0);
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier 
sfree(int n)2453e12c5d1SDavid du Colombier void sfree(int n)
2463e12c5d1SDavid du Colombier {
2473e12c5d1SDavid du Colombier 	used[n] = 0;
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier 
nrwid(int n1,int p,int n2)2503e12c5d1SDavid du Colombier void nrwid(int n1, int p, int n2)
2513e12c5d1SDavid du Colombier {
2523e12c5d1SDavid du Colombier 	printf(".nr %d 0\\w'%s\\*(%d'\n", n1, DPS(gsize,p), n2);	/* 0 defends against - width */
2533e12c5d1SDavid du Colombier }
2543e12c5d1SDavid du Colombier 
ABSPS(int dn)2553e12c5d1SDavid du Colombier char *ABSPS(int dn)	/* absolute size dn in printable form \sd or \s(dd (dd >= 40) */
2563e12c5d1SDavid du Colombier {
2573e12c5d1SDavid du Colombier 	static char buf[100], *lb = buf;
2583e12c5d1SDavid du Colombier 	char *p;
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier 	if (lb > buf + sizeof(buf) - 10)
2613e12c5d1SDavid du Colombier 		lb = buf;
2623e12c5d1SDavid du Colombier 	p = lb;
2633e12c5d1SDavid du Colombier 	*lb++ = '\\';
2643e12c5d1SDavid du Colombier 	*lb++ = 's';
2653e12c5d1SDavid du Colombier 	if (dn >= 10) {		/* \s(dd only works in new troff */
2663e12c5d1SDavid du Colombier 		if (dn >= 40)
2673e12c5d1SDavid du Colombier 			*lb++ = '(';
2683e12c5d1SDavid du Colombier 		*lb++ = dn/10 + '0';
2693e12c5d1SDavid du Colombier 		*lb++ = dn%10 + '0';
2703e12c5d1SDavid du Colombier 	} else {
2713e12c5d1SDavid du Colombier 		*lb++ = dn + '0';
2723e12c5d1SDavid du Colombier 	}
2733e12c5d1SDavid du Colombier 	*lb++ = '\0';
2743e12c5d1SDavid du Colombier 	return p;
2753e12c5d1SDavid du Colombier }
2763e12c5d1SDavid du Colombier 
DPS(int f,int t)2773e12c5d1SDavid du Colombier char *DPS(int f, int t)	/* delta ps (t-f) in printable form \s+d or \s-d or \s+-(dd */
2783e12c5d1SDavid du Colombier {
2793e12c5d1SDavid du Colombier 	static char buf[100], *lb = buf;
2803e12c5d1SDavid du Colombier 	char *p;
2813e12c5d1SDavid du Colombier 	int dn;
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier 	if (lb > buf + sizeof(buf) - 10)
2843e12c5d1SDavid du Colombier 		lb = buf;
2853e12c5d1SDavid du Colombier 	p = lb;
2863e12c5d1SDavid du Colombier 	*lb++ = '\\';
2873e12c5d1SDavid du Colombier 	*lb++ = 's';
2883e12c5d1SDavid du Colombier 	dn = EFFPS(t) - EFFPS(f);
2893e12c5d1SDavid du Colombier 	if (szstack[nszstack] != 0)	/* absolute */
2903e12c5d1SDavid du Colombier 		dn = EFFPS(t);		/* should do proper \s(dd */
2913e12c5d1SDavid du Colombier 	else if (dn >= 0)
2923e12c5d1SDavid du Colombier 		*lb++ = '+';
2933e12c5d1SDavid du Colombier 	else {
2943e12c5d1SDavid du Colombier 		*lb++ = '-';
2953e12c5d1SDavid du Colombier 		dn = -dn;
2963e12c5d1SDavid du Colombier 	}
2973e12c5d1SDavid du Colombier 	if (dn >= 10) {		/* \s+(dd only works in new troff */
2983e12c5d1SDavid du Colombier 		*lb++ = '(';
2993e12c5d1SDavid du Colombier 		*lb++ = dn/10 + '0';
3003e12c5d1SDavid du Colombier 		*lb++ = dn%10 + '0';
3013e12c5d1SDavid du Colombier 	} else {
3023e12c5d1SDavid du Colombier 		*lb++ = dn + '0';
3033e12c5d1SDavid du Colombier 	}
3043e12c5d1SDavid du Colombier 	*lb++ = '\0';
3053e12c5d1SDavid du Colombier 	return p;
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier 
EFFPS(int n)3083e12c5d1SDavid du Colombier EFFPS(int n)	/* effective value of n */
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier 	if (n >= minsize)
3113e12c5d1SDavid du Colombier 		return n;
3123e12c5d1SDavid du Colombier 	else
3133e12c5d1SDavid du Colombier 		return minsize;
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
EM(double m,int ps)3163e12c5d1SDavid du Colombier double EM(double m, int ps)	/* convert m to ems in gsize */
3173e12c5d1SDavid du Colombier {
3183e12c5d1SDavid du Colombier 	m *= (double) EFFPS(ps) / gsize;
3193e12c5d1SDavid du Colombier 	if (m <= 0.001 && m >= -0.001)
3203e12c5d1SDavid du Colombier 		return 0;
3213e12c5d1SDavid du Colombier 	else
3223e12c5d1SDavid du Colombier 		return m;
3233e12c5d1SDavid du Colombier }
3243e12c5d1SDavid du Colombier 
REL(double m,int ps)3253e12c5d1SDavid du Colombier double REL(double m, int ps)	/* convert m to ems in ps */
3263e12c5d1SDavid du Colombier {
3273e12c5d1SDavid du Colombier 	m *= (double) gsize / EFFPS(ps);
3283e12c5d1SDavid du Colombier 	if (m <= 0.001 && m >= -0.001)
3293e12c5d1SDavid du Colombier 		return 0;
3303e12c5d1SDavid du Colombier 	else
3313e12c5d1SDavid du Colombier 		return m;
3323e12c5d1SDavid du Colombier }
333