]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/eqn/main.c
ndb/dns: remove single-ip-address assuptions
[plan9front.git] / sys / src / cmd / eqn / main.c
1 #include "e.h"
2 #include <errno.h>
3
4 #define MAXLINE 3600    /* maximum input line */
5
6 char *version = "version Oct 24, 1991";
7
8 char    in[MAXLINE+1];  /* input buffer */
9 int     noeqn;
10 char    *cmdname;
11
12 int     yyparse(void);
13 void    settype(char *);
14 int     getdata(void);
15 int     getline(char *);
16 void    inlineeq(void);
17 void    init(void);
18 void    init_tbl(void);
19
20 void
21 main(int argc, char *argv[])
22 {
23         char *p, buf[20];
24
25         cmdname = argv[0];
26         if (p = getenv("TYPESETTER"))
27                 typesetter = p;
28         while (argc > 1 && argv[1][0] == '-') {
29                 switch (argv[1][1]) {
30
31                 case 'd':
32                         if (argv[1][2] == '\0') {
33                                 dbg++;
34                                 printf("...\teqn %s\n", version);
35                         } else {
36                                 lefteq = argv[1][2];
37                                 righteq = argv[1][3];
38                         }
39                         break;
40                 case 's': szstack[0] = gsize = atoi(&argv[1][2]); break;
41                 case 'p': deltaps = atoi(&argv[1][2]); dps_set = 1; break;
42                 case 'm': minsize = atoi(&argv[1][2]); break;
43                 case 'f': strcpy(ftstack[0].name,&argv[1][2]); break;
44                 case 'e': noeqn++; break;
45                 case 'T': typesetter = &argv[1][2]; break;
46                 default:
47                         fprintf(stderr, "%s: unknown option %s\n", cmdname, argv[1]);
48                         break;
49                 }
50                 argc--;
51                 argv++;
52         }
53         settype(typesetter);
54         sprintf(buf, "\"%s\"", typesetter);
55         install(deftbl, strsave(typesetter), strsave(buf), 0);
56         init_tbl();     /* install other keywords in tables */
57         curfile = infile;
58         pushsrc(File, curfile->fname);
59         if (argc <= 1) {
60                 curfile->fin = stdin;
61                 curfile->fname = strsave("-");
62                 getdata();
63         } else
64                 while (argc-- > 1) {
65                         if (strcmp(*++argv, "-") == 0)
66                                 curfile->fin = stdin;
67                         else if ((curfile->fin = fopen(*argv, "r")) == NULL)
68                                 ERROR "can't open file %s", *argv FATAL;
69                         curfile->fname = strsave(*argv);
70                         getdata();
71                         if (curfile->fin != stdin)
72                                 fclose(curfile->fin);
73                 }
74         exit(0);
75 }
76
77 void settype(char *s)   /* initialize data for particular typesetter */
78                         /* the minsize could profitably come from the */
79 {                       /* troff description file /usr/lib/font/dev.../DESC.out */
80         if (strcmp(s, "202") == 0)
81                 { minsize = 5; ttype = DEV202; }
82         else if (strcmp(s, "aps") == 0)
83                 { minsize = 5; ttype = DEVAPS; }
84         else if (strcmp(s, "cat") == 0)
85                 { minsize = 6; ttype = DEVCAT; }
86         else if (strcmp(s, "post") == 0)
87                 { minsize = 4; ttype = DEVPOST; }
88         else
89                 { minsize = 5; ttype = DEV202; }
90 }
91
92 getdata(void)
93 {
94         int i, type, ln;
95         char fname[100];
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
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
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
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
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
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
245 void sfree(int n)
246 {
247         used[n] = 0;
248 }
249
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
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
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
308 EFFPS(int n)    /* effective value of n */
309 {
310         if (n >= minsize)
311                 return n;
312         else
313                 return minsize;
314 }
315
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
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 }