1 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
2 /*	  All Rights Reserved  	*/
3 
4 
5 /*
6  * Copyright (c) 1980 Regents of the University of California.
7  * All rights reserved. The Berkeley software License Agreement
8  * specifies the terms and conditions for redistribution.
9  */
10 
11 /*
12  * Copyright (c) 1983-1988, 2001 by Sun Microsystems, Inc.
13  * All rights reserved.
14  */
15 
16 /*	from OpenSolaris "io.c	1.10	05/06/02 SMI"	 SVr4.0 1.1		*/
17 
18 /*
19  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
20  *
21  * Sccsid @(#)io.c	1.13 (gritter) 1/13/08
22  */
23 
24 # include "e.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <libgen.h>
28 
29 char	*in;	/* input buffer */
30 size_t	insize;	/* input buffer size */
31 int noeqn;
32 
33 int
main(int argc,char ** argv)34 main(int argc,char **argv) {
35 
36 	progname = basename(argv[0]);
37 	eqnexit(eqn(argc, argv));
38 	/*NOTREACHED*/
39 	return 0;
40 }
41 
42 void
eqnexit(int n)43 eqnexit(int n) {
44 #ifdef gcos
45 	if (n)
46 		fprintf(stderr, "run terminated due to eqn error\n");
47 	exit(0);
48 #endif
49 	exit(n);
50 }
51 
52 int
eqn(int argc,char ** argv)53 eqn(int argc,char **argv) {
54 	int i, type;
55 
56 	setfile(argc,argv);
57 	init_tbl();	/* install keywords in tables */
58 	while ((type=getline(&in, &insize)) != EOF) {
59 		eqline = linect;
60 		if (type == lefteq)
61 			do_inline();
62 		else if (*in == '.') {
63 			char *p;
64 			printf("%s",in);
65 			for (p = in + 1; *p == ' ' || *p == '\t'; p++);
66 			if (!*p || *p != 'E' || p[1] != 'Q') continue;
67 			for (i=11; i<100; used[i++]=0);
68 			printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
69 			printf(".if \\n(.X .nrf 99 \\n(.s\n");
70 			markline = 0;
71 			init();
72 			yyparse();
73 			if (eqnreg>0) {
74 				printf(".nr %d \\w'\\*(%d'\n", eqnreg, eqnreg);
75 				/* printf(".if \\n(%d>\\n(.l .tm too-long eqn, file %s, between lines %d-%d\n",	*/
76 				/*	eqnreg, svargv[ifile], eqline, linect);	*/
77 				printf(".nr MK %d\n", markline);	/* for -ms macros */
78 				printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht);
79 				printf(".rn %d 10\n", eqnreg);
80 				if(!noeqn)printf("\\*(10\n");
81 			}
82 			printf(".ps \\n(99\n.ft \\n(98\n");
83 			printf(".EN");
84 			if (lastchar == EOF) {
85 				putchar('\n');
86 				break;
87 			}
88 			if (putchar(lastchar) != '\n')
89 				while (putchar(gtc()) != '\n');
90 		} else
91 			printf("%s",in);
92 	}
93 	return(0);
94 }
95 
96 int
getline(char ** sp,size_t * np)97 getline(char **sp, size_t *np) {
98 	register int c, n = 0, esc = 0, par = 0, brack = 0;
99 	char *xp;
100 	for (;;) {
101 		c = gtc();
102 		if (n+1 >= *np) {
103 			xp = realloc(*sp, *np += 128);
104 			if (xp == NULL) {
105 				error( !FATAL, "input line too long: %.20s\n",
106 						in);
107 				xp[--n] = '\0';
108 				break;
109 			}
110 			*sp = xp;
111 		}
112 		(*sp)[n++] = c;
113 		if (c=='\\')
114 			esc++;
115 		else {
116 			if (c=='\n' || c==EOF ||
117 					(c==lefteq && !esc && !par && !brack))
118 				break;
119 			if (par)
120 				par--;
121 			if (brack && c == ']')
122 				brack = 0;
123 			if (esc) {
124 				switch (c) {
125 				case '*':
126 				case 'f':
127 				case 'g':
128 				case 'k':
129 				case 'n':
130 				case 'P':
131 				case 'V':
132 				case 'Y':
133 					break;
134 				case '(':
135 					par += 2;
136 					break;
137 				case '[':
138 					brack++;
139 					break;
140 				default:
141 					esc = 0;
142 				}
143 			}
144 		}
145 	}
146 	if (c==lefteq && !esc)
147 		n--;
148 	(*sp)[n++] = '\0';
149 	return(c);
150 }
151 
152 void
do_inline(void)153 do_inline(void) {
154 	int ds;
155 
156 	printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
157 	printf(".if \\n(.X .nrf 99 \\n(.s\n");
158 	ds = oalloc();
159 	printf(".rm %d \n", ds);
160 	do{
161 		if (*in)
162 			printf(".as %d \"%s\n", ds, in);
163 		init();
164 		yyparse();
165 		if (eqnreg > 0) {
166 			printf(".as %d \\*(%d\n", ds, eqnreg);
167 			ofree(eqnreg);
168 		}
169 		printf(".ps \\n(99\n.ft \\n(98\n");
170 	} while (getline(&in, &insize) == lefteq);
171 	if (*in)
172 		printf(".as %d \"%s", ds, in);
173 	printf(".ps \\n(99\n.ft \\n(98\n");
174 	printf("\\*(%d\n", ds);
175 	ofree(ds);
176 }
177 
178 void
putout(int p1)179 putout(int p1) {
180 #ifndef	NEQN
181 	float before, after;
182 	if(dbg)printf(".\tanswer <- S%d, h=%g,b=%g\n",p1, eht[p1], ebase[p1]);
183 #else	/* NEQN */
184 	int before, after;
185 	if(dbg)printf(".\tanswer <- S%d, h=%d,b=%d\n",p1, eht[p1], ebase[p1]);
186 #endif	/* NEQN */
187 	eqnht = eht[p1];
188 	printf(".ds %d ", p1);
189 	/* suppposed to leave room for a subscript or superscript */
190 #ifndef NEQN
191 	before = eht[p1] - ebase[p1] - VERT(EM(1.2, ps));
192 #else /* NEQN */
193 	before = eht[p1] - ebase[p1] - VERT(3);	/* 3 = 1.5 lines */
194 #endif /* NEQN */
195 	if (spaceval != NULL)
196 		printf("\\x'0-%s'", spaceval);
197 	else if (before > 0)
198 #ifndef	NEQN
199 		printf("\\x'0-%gp'", before);
200 #else	/* NEQN */
201 		printf("\\x'0-%du'", before);
202 #endif	/* NEQN */
203 	printf("\\f%c\\s%s\\*(%d%s\n",
204 		gfont, tsize(gsize), p1, ital(rfont[p1]) ? "\\|" : "");
205 	printf(".ie \\n(.X=0 .as %d \\s\\n(99\n", p1);
206 	printf(".el .as %d \\s[\\n(99]\n", p1);
207 	printf(".as %d \\f\\n(98", p1);
208 #ifndef NEQN
209 	after = ebase[p1] - VERT(EM(0.2, ps));
210 #else /* NEQN */
211 	after = ebase[p1] - VERT(1);
212 #endif /* NEQN */
213 	if (spaceval == NULL && after > 0)
214 #ifndef	NEQN
215 		printf("\\x'%gp'", after);
216 #else	/* NEQN */
217 		printf("\\x'%du'", after);
218 #endif	/* NEQN */
219 	putchar('\n');
220 	eqnreg = p1;
221 	if (spaceval != NULL) {
222 		free(spaceval);
223 		spaceval = NULL;
224 	}
225 
226 }
227 
228 float
max(float i,float j)229 max(float i,float j) {
230 	return (i>j ? i : j);
231 }
232 
233 int
oalloc(void)234 oalloc(void) {
235 	int i;
236 	for (i=11; i<100; i++)
237 		if (used[i]++ == 0) return(i);
238 	error( FATAL, "no eqn strings left", i);
239 	return(0);
240 }
241 
242 void
ofree(int n)243 ofree(int n) {
244 	used[n] = 0;
245 }
246 
247 void
setps(float p)248 setps(float p) {
249 	printf(".ps %g\n", EFFPS(p));
250 }
251 
252 void
nrwid(int n1,float p,int n2)253 nrwid(int n1, float p, int n2) {
254 	printf(".nr %d \\w'\\s%s\\*(%d'\n", n1, tsize(EFFPS(p)), n2);
255 }
256 
257 void
setfile(int argc,char ** argv)258 setfile(int argc, char **argv) {
259 	static char *nullstr = "-";
260 
261 	svargc = --argc;
262 	svargv = argv;
263 	while (svargc > 0 && svargv[1][0] == '-') {
264 		switch (svargv[1][1]) {
265 
266 		case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break;
267 		case 's': gsize = atof(&svargv[1][2]); break;
268 		case 'p': deltaps = atof(&svargv[1][2]); break;
269 		case 'f': gfont = svargv[1][2]; break;
270 		case 'e': noeqn++; break;
271 		case 'r': /*resolution = atoi(&svargv[1][2]);*/ break;
272 		case 0:	goto endargs;
273 		default: dbg = 1;
274 		}
275 		svargc--;
276 		svargv++;
277 	}
278   endargs:
279 	ifile = 1;
280 	linect = 1;
281 	if (svargc <= 0) {
282 		curfile = stdin;
283 		svargv[1] = nullstr;
284 	}
285 	else
286 		openinfile();	/* opens up the first input file */
287 }
288 
289 void
yyerror(char * unused)290 yyerror(char *unused) {;}
291 
292 void
init(void)293 init(void) {
294 	ct = 0;
295 	ps = gsize;
296 	ft = gfont;
297 	setps(ps);
298 	printf(".ft %c\n", ft);
299 }
300 
301 void
error(int fatal,const char * s1,...)302 error(int fatal, const char *s1, ...) {
303 	va_list ap;
304 
305 	if (fatal>0)
306 		printf("%s fatal error: ", progname);
307 	va_start(ap, s1);
308 	vfprintf(stdout, s1, ap);
309 	va_end(ap);
310 	printf("\nfile %s, between lines %d and %d\n",
311 		 svargv[ifile], eqline, linect);
312 	fprintf(stderr, "%s: ", progname);
313 	if (fatal>0)
314 		fprintf(stderr, "fatal error: ");
315 	va_start(ap, s1);
316 	vfprintf(stderr, s1, ap);
317 	va_end(ap);
318 	fprintf(stderr, "\nfile %s, between lines %d and %d\n",
319 		 svargv[ifile], eqline, linect);
320 	if (fatal > 0)
321 		eqnexit(1);
322 }
323