xref: /plan9/sys/src/cmd/eqn/main.c (revision 9f2726c34299ea5a81cda1b22133dd5a4b421e04)
1 #include "e.h"
2 
3 #define	MAXLINE	3600	/* maximum input line */
4 
5 char *version = "version Oct 24, 1991";
6 
7 char	in[MAXLINE+1];	/* input buffer */
8 int	noeqn;
9 char	*cmdname;
10 
11 int	yyparse(void);
12 void	settype(char *);
13 int	getdata(void);
14 int	getline(char *);
15 void	inlineeq(void);
16 void	init(void);
17 void	init_tbl(void);
18 
19 void
main(int argc,char * argv[])20 main(int argc, char *argv[])
21 {
22 	char *p, buf[20];
23 
24 	cmdname = argv[0];
25 	if (p = getenv("TYPESETTER"))
26 		typesetter = p;
27 	while (argc > 1 && argv[1][0] == '-') {
28 		switch (argv[1][1]) {
29 
30 		case 'd':
31 			if (argv[1][2] == '\0') {
32 				dbg++;
33 				printf("...\teqn %s\n", version);
34 			} else {
35 				lefteq = argv[1][2];
36 				righteq = argv[1][3];
37 			}
38 			break;
39 		case 's': szstack[0] = gsize = atoi(&argv[1][2]); break;
40 		case 'p': deltaps = atoi(&argv[1][2]); dps_set = 1; break;
41 		case 'm': minsize = atoi(&argv[1][2]); break;
42 		case 'f': strcpy(ftstack[0].name,&argv[1][2]); break;
43 		case 'e': noeqn++; break;
44 		case 'T': typesetter = &argv[1][2]; break;
45 		default:
46 			fprintf(stderr, "%s: unknown option %s\n", cmdname, argv[1]);
47 			break;
48 		}
49 		argc--;
50 		argv++;
51 	}
52 	settype(typesetter);
53 	sprintf(buf, "\"%s\"", typesetter);
54 	install(deftbl, strsave(typesetter), strsave(buf), 0);
55 	init_tbl();	/* install other keywords in tables */
56 	curfile = infile;
57 	pushsrc(File, curfile->fname);
58 	if (argc <= 1) {
59 		curfile->fin = stdin;
60 		curfile->fname = strsave("-");
61 		getdata();
62 	} else
63 		while (argc-- > 1) {
64 			if (strcmp(*++argv, "-") == 0)
65 				curfile->fin = stdin;
66 			else if ((curfile->fin = fopen(*argv, "r")) == NULL)
67 				ERROR "can't open file %s", *argv FATAL;
68 			curfile->fname = strsave(*argv);
69 			getdata();
70 			if (curfile->fin != stdin)
71 				fclose(curfile->fin);
72 		}
73 	exit(0);
74 }
75 
settype(char * s)76 void settype(char *s)	/* initialize data for particular typesetter */
77 			/* the minsize could profitably come from the */
78 {			/* troff description file /usr/lib/font/dev.../DESC.out */
79 	if (strcmp(s, "202") == 0)
80 		{ minsize = 5; ttype = DEV202; }
81 	else if (strcmp(s, "aps") == 0)
82 		{ minsize = 5; ttype = DEVAPS; }
83 	else if (strcmp(s, "cat") == 0)
84 		{ minsize = 6; ttype = DEVCAT; }
85 	else if (strcmp(s, "post") == 0)
86 		{ minsize = 4; ttype = DEVPOST; }
87 	else
88 		{ minsize = 5; ttype = DEV202; }
89 }
90 
getdata(void)91 getdata(void)
92 {
93 	int i, type, ln;
94 	char fname[100];
95 	extern int errno;
96 
97 	errno = 0;
98 	curfile->lineno = 0;
99 	printf(".lf 1 %s\n", curfile->fname);
100 	while ((type = getline(in)) != EOF) {
101 		if (in[0] == '.' && in[1] == 'E' && in[2] == 'Q') {
102 			for (i = 11; i < 100; i++)
103 				used[i] = 0;
104 			printf("%s", in);
105 			if (markline) {	/* turn off from last time */
106 				printf(".nr MK 0\n");
107 				markline = 0;
108 			}
109 			display = 1;
110 			init();
111 			yyparse();
112 			if (eqnreg > 0) {
113 				if (markline)
114 					printf(".nr MK %d\n", markline); /* for -ms macros */
115 				printf(".if %gm>\\n(.v .ne %gm\n", eqnht, eqnht);
116 				printf(".rn %d 10\n", eqnreg);
117 				if (!noeqn)
118 					printf("\\&\\*(10\n");
119 			}
120 			printf(".EN");
121 			while (putchar(input()) != '\n')
122 				;
123 			printf(".lf %d\n", curfile->lineno+1);
124 		}
125 		else if (type == lefteq)
126 			inlineeq();
127 		else if (in[0] == '.' && in[1] == 'l' && in[2] == 'f') {
128 			if (sscanf(in+3, "%d %s", &ln, fname) == 2) {
129 				free(curfile->fname);
130 				printf(".lf %d %s\n", curfile->lineno = ln, curfile->fname = strsave(fname));
131 			} else
132 				printf(".lf %d\n", curfile->lineno = ln);
133 		} else
134 			printf("%s", in);
135 	}
136 	return(0);
137 }
138 
getline(char * s)139 getline(char *s)
140 {
141 	register c;
142 
143 	while ((c=input()) != '\n' && c != EOF && c != lefteq) {
144 		if (s >= in+MAXLINE) {
145 			ERROR "input line too long: %.20s\n", in WARNING;
146 			in[MAXLINE] = '\0';
147 			break;
148 		}
149 		*s++ = c;
150 	}
151 	if (c != lefteq)
152 		*s++ = c;
153 	*s = '\0';
154 	return(c);
155 }
156 
inlineeq(void)157 void inlineeq(void)
158 {
159 	int ds, n, sz1 = 0;
160 
161 	n = curfile->lineno;
162 	if (szstack[0] != 0)
163 		printf(".nr %d \\n(.s\n", sz1 = salloc());
164 	ds = salloc();
165 	printf(".rm %d \n", ds);
166 	display = 0;
167 	do {
168 		if (*in)
169 			printf(".as %d \"%s\n", ds, in);
170 		init();
171 		yyparse();
172 		if (eqnreg > 0) {
173 			printf(".as %d \\*(%d\n", ds, eqnreg);
174 			sfree(eqnreg);
175 			printf(".lf %d\n", curfile->lineno+1);
176 		}
177 	} while (getline(in) == lefteq);
178 	if (*in)
179 		printf(".as %d \"%s", ds, in);
180 	if (sz1)
181 		printf("\\s\\n(%d", sz1);
182 	printf("\\*(%d\n", ds);
183 	printf(".lf %d\n", curfile->lineno+1);
184 	if (curfile->lineno > n+3)
185 		fprintf(stderr, "eqn warning: multi-line %c...%c, file %s:%d,%d\n",
186 			lefteq, righteq, curfile->fname, n, curfile->lineno);
187 	sfree(ds);
188 	if (sz1) sfree(sz1);
189 }
190 
putout(int p1)191 void putout(int p1)
192 {
193 	double before, after;
194 	extern double BeforeSub, AfterSub;
195 
196 	dprintf(".\tanswer <- S%d, h=%g,b=%g\n",p1, eht[p1], ebase[p1]);
197 	eqnht = eht[p1];
198 	before = eht[p1] - ebase[p1] - BeforeSub;	/* leave room for sub or superscript */
199 	after = ebase[p1] - AfterSub;
200 	if (spaceval || before > 0.01 || after > 0.01) {
201 		printf(".ds %d ", p1);	/* used to be \\x'0' here:  why? */
202 		if (spaceval != NULL)
203 			printf("\\x'0-%s'", spaceval);
204 		else if (before > 0.01)
205 			printf("\\x'0-%gm'", before);
206 		printf("\\*(%d", p1);
207 		if (spaceval == NULL && after > 0.01)
208 			printf("\\x'%gm'", after);
209 		putchar('\n');
210 	}
211 	if (szstack[0] != 0)
212 		printf(".ds %d %s\\*(%d\\s\\n(99\n", p1, DPS(gsize,gsize), p1);
213 	eqnreg = p1;
214 	if (spaceval != NULL) {
215 		free(spaceval);
216 		spaceval = NULL;
217 	}
218 }
219 
init(void)220 void init(void)
221 {
222 	synerr = 0;
223 	ct = 0;
224 	ps = gsize;
225 	ftp = ftstack;
226 	ft = ftp->ft;
227 	nszstack = 0;
228 	if (szstack[0] != 0)	/* absolute gsize in effect */
229 		printf(".nr 99 \\n(.s\n");
230 }
231 
salloc(void)232 salloc(void)
233 {
234 	int i;
235 
236 	for (i = 11; i < 100; i++)
237 		if (used[i] == 0) {
238 			used[i]++;
239 			return(i);
240 		}
241 	ERROR "no eqn strings left (%d)", i FATAL;
242 	return(0);
243 }
244 
sfree(int n)245 void sfree(int n)
246 {
247 	used[n] = 0;
248 }
249 
nrwid(int n1,int p,int n2)250 void nrwid(int n1, int p, int n2)
251 {
252 	printf(".nr %d 0\\w'%s\\*(%d'\n", n1, DPS(gsize,p), n2);	/* 0 defends against - width */
253 }
254 
ABSPS(int dn)255 char *ABSPS(int dn)	/* absolute size dn in printable form \sd or \s(dd (dd >= 40) */
256 {
257 	static char buf[100], *lb = buf;
258 	char *p;
259 
260 	if (lb > buf + sizeof(buf) - 10)
261 		lb = buf;
262 	p = lb;
263 	*lb++ = '\\';
264 	*lb++ = 's';
265 	if (dn >= 10) {		/* \s(dd only works in new troff */
266 		if (dn >= 40)
267 			*lb++ = '(';
268 		*lb++ = dn/10 + '0';
269 		*lb++ = dn%10 + '0';
270 	} else {
271 		*lb++ = dn + '0';
272 	}
273 	*lb++ = '\0';
274 	return p;
275 }
276 
DPS(int f,int t)277 char *DPS(int f, int t)	/* delta ps (t-f) in printable form \s+d or \s-d or \s+-(dd */
278 {
279 	static char buf[100], *lb = buf;
280 	char *p;
281 	int dn;
282 
283 	if (lb > buf + sizeof(buf) - 10)
284 		lb = buf;
285 	p = lb;
286 	*lb++ = '\\';
287 	*lb++ = 's';
288 	dn = EFFPS(t) - EFFPS(f);
289 	if (szstack[nszstack] != 0)	/* absolute */
290 		dn = EFFPS(t);		/* should do proper \s(dd */
291 	else if (dn >= 0)
292 		*lb++ = '+';
293 	else {
294 		*lb++ = '-';
295 		dn = -dn;
296 	}
297 	if (dn >= 10) {		/* \s+(dd only works in new troff */
298 		*lb++ = '(';
299 		*lb++ = dn/10 + '0';
300 		*lb++ = dn%10 + '0';
301 	} else {
302 		*lb++ = dn + '0';
303 	}
304 	*lb++ = '\0';
305 	return p;
306 }
307 
EFFPS(int n)308 EFFPS(int n)	/* effective value of n */
309 {
310 	if (n >= minsize)
311 		return n;
312 	else
313 		return minsize;
314 }
315 
EM(double m,int ps)316 double EM(double m, int ps)	/* convert m to ems in gsize */
317 {
318 	m *= (double) EFFPS(ps) / gsize;
319 	if (m <= 0.001 && m >= -0.001)
320 		return 0;
321 	else
322 		return m;
323 }
324 
REL(double m,int ps)325 double REL(double m, int ps)	/* convert m to ems in ps */
326 {
327 	m *= (double) gsize / EFFPS(ps);
328 	if (m <= 0.001 && m >= -0.001)
329 		return 0;
330 	else
331 		return m;
332 }
333