1*426d2b71SDavid du Colombier #include "a.h"
2*426d2b71SDavid du Colombier
3*426d2b71SDavid du Colombier enum
4*426d2b71SDavid du Colombier {
5*426d2b71SDavid du Colombier MAXREQ = 100,
6*426d2b71SDavid du Colombier MAXRAW = 40,
7*426d2b71SDavid du Colombier MAXESC = 60,
8*426d2b71SDavid du Colombier MAXLINE = 1024,
9*426d2b71SDavid du Colombier MAXIF = 20,
10*426d2b71SDavid du Colombier MAXARG = 10,
11*426d2b71SDavid du Colombier };
12*426d2b71SDavid du Colombier
13*426d2b71SDavid du Colombier typedef struct Esc Esc;
14*426d2b71SDavid du Colombier typedef struct Req Req;
15*426d2b71SDavid du Colombier typedef struct Raw Raw;
16*426d2b71SDavid du Colombier
17*426d2b71SDavid du Colombier /* escape sequence handler, like for \c */
18*426d2b71SDavid du Colombier struct Esc
19*426d2b71SDavid du Colombier {
20*426d2b71SDavid du Colombier Rune r;
21*426d2b71SDavid du Colombier int (*f)(void);
22*426d2b71SDavid du Colombier int mode;
23*426d2b71SDavid du Colombier };
24*426d2b71SDavid du Colombier
25*426d2b71SDavid du Colombier /* raw request handler, like for .ie */
26*426d2b71SDavid du Colombier struct Raw
27*426d2b71SDavid du Colombier {
28*426d2b71SDavid du Colombier Rune *name;
29*426d2b71SDavid du Colombier void (*f)(Rune*);
30*426d2b71SDavid du Colombier };
31*426d2b71SDavid du Colombier
32*426d2b71SDavid du Colombier /* regular request handler, like for .ft */
33*426d2b71SDavid du Colombier struct Req
34*426d2b71SDavid du Colombier {
35*426d2b71SDavid du Colombier int argc;
36*426d2b71SDavid du Colombier Rune *name;
37*426d2b71SDavid du Colombier void (*f)(int, Rune**);
38*426d2b71SDavid du Colombier };
39*426d2b71SDavid du Colombier
40*426d2b71SDavid du Colombier int dot = '.';
41*426d2b71SDavid du Colombier int tick = '\'';
42*426d2b71SDavid du Colombier int backslash = '\\';
43*426d2b71SDavid du Colombier
44*426d2b71SDavid du Colombier int inputmode;
45*426d2b71SDavid du Colombier Req req[MAXREQ];
46*426d2b71SDavid du Colombier int nreq;
47*426d2b71SDavid du Colombier Raw raw[MAXRAW];
48*426d2b71SDavid du Colombier int nraw;
49*426d2b71SDavid du Colombier Esc esc[MAXESC];
50*426d2b71SDavid du Colombier int nesc;
51*426d2b71SDavid du Colombier int iftrue[MAXIF];
52*426d2b71SDavid du Colombier int niftrue;
53*426d2b71SDavid du Colombier
54*426d2b71SDavid du Colombier int isoutput;
55*426d2b71SDavid du Colombier int linepos;
56*426d2b71SDavid du Colombier
57*426d2b71SDavid du Colombier
58*426d2b71SDavid du Colombier void
addraw(Rune * name,void (* f)(Rune *))59*426d2b71SDavid du Colombier addraw(Rune *name, void (*f)(Rune*))
60*426d2b71SDavid du Colombier {
61*426d2b71SDavid du Colombier Raw *r;
62*426d2b71SDavid du Colombier
63*426d2b71SDavid du Colombier if(nraw >= nelem(raw)){
64*426d2b71SDavid du Colombier fprint(2, "too many raw requets\n");
65*426d2b71SDavid du Colombier return;
66*426d2b71SDavid du Colombier }
67*426d2b71SDavid du Colombier r = &raw[nraw++];
68*426d2b71SDavid du Colombier r->name = erunestrdup(name);
69*426d2b71SDavid du Colombier r->f = f;
70*426d2b71SDavid du Colombier }
71*426d2b71SDavid du Colombier
72*426d2b71SDavid du Colombier void
delraw(Rune * name)73*426d2b71SDavid du Colombier delraw(Rune *name)
74*426d2b71SDavid du Colombier {
75*426d2b71SDavid du Colombier int i;
76*426d2b71SDavid du Colombier
77*426d2b71SDavid du Colombier for(i=0; i<nraw; i++){
78*426d2b71SDavid du Colombier if(runestrcmp(raw[i].name, name) == 0){
79*426d2b71SDavid du Colombier if(i != --nraw){
80*426d2b71SDavid du Colombier free(raw[i].name);
81*426d2b71SDavid du Colombier raw[i] = raw[nraw];
82*426d2b71SDavid du Colombier }
83*426d2b71SDavid du Colombier return;
84*426d2b71SDavid du Colombier }
85*426d2b71SDavid du Colombier }
86*426d2b71SDavid du Colombier }
87*426d2b71SDavid du Colombier
88*426d2b71SDavid du Colombier void
renraw(Rune * from,Rune * to)89*426d2b71SDavid du Colombier renraw(Rune *from, Rune *to)
90*426d2b71SDavid du Colombier {
91*426d2b71SDavid du Colombier int i;
92*426d2b71SDavid du Colombier
93*426d2b71SDavid du Colombier delraw(to);
94*426d2b71SDavid du Colombier for(i=0; i<nraw; i++)
95*426d2b71SDavid du Colombier if(runestrcmp(raw[i].name, from) == 0){
96*426d2b71SDavid du Colombier free(raw[i].name);
97*426d2b71SDavid du Colombier raw[i].name = erunestrdup(to);
98*426d2b71SDavid du Colombier return;
99*426d2b71SDavid du Colombier }
100*426d2b71SDavid du Colombier }
101*426d2b71SDavid du Colombier
102*426d2b71SDavid du Colombier
103*426d2b71SDavid du Colombier void
addreq(Rune * s,void (* f)(int,Rune **),int argc)104*426d2b71SDavid du Colombier addreq(Rune *s, void (*f)(int, Rune**), int argc)
105*426d2b71SDavid du Colombier {
106*426d2b71SDavid du Colombier Req *r;
107*426d2b71SDavid du Colombier
108*426d2b71SDavid du Colombier if(nreq >= nelem(req)){
109*426d2b71SDavid du Colombier fprint(2, "too many requests\n");
110*426d2b71SDavid du Colombier return;
111*426d2b71SDavid du Colombier }
112*426d2b71SDavid du Colombier r = &req[nreq++];
113*426d2b71SDavid du Colombier r->name = erunestrdup(s);
114*426d2b71SDavid du Colombier r->f = f;
115*426d2b71SDavid du Colombier r->argc = argc;
116*426d2b71SDavid du Colombier }
117*426d2b71SDavid du Colombier
118*426d2b71SDavid du Colombier void
delreq(Rune * name)119*426d2b71SDavid du Colombier delreq(Rune *name)
120*426d2b71SDavid du Colombier {
121*426d2b71SDavid du Colombier int i;
122*426d2b71SDavid du Colombier
123*426d2b71SDavid du Colombier for(i=0; i<nreq; i++){
124*426d2b71SDavid du Colombier if(runestrcmp(req[i].name, name) == 0){
125*426d2b71SDavid du Colombier if(i != --nreq){
126*426d2b71SDavid du Colombier free(req[i].name);
127*426d2b71SDavid du Colombier req[i] = req[nreq];
128*426d2b71SDavid du Colombier }
129*426d2b71SDavid du Colombier return;
130*426d2b71SDavid du Colombier }
131*426d2b71SDavid du Colombier }
132*426d2b71SDavid du Colombier }
133*426d2b71SDavid du Colombier
134*426d2b71SDavid du Colombier void
renreq(Rune * from,Rune * to)135*426d2b71SDavid du Colombier renreq(Rune *from, Rune *to)
136*426d2b71SDavid du Colombier {
137*426d2b71SDavid du Colombier int i;
138*426d2b71SDavid du Colombier
139*426d2b71SDavid du Colombier delreq(to);
140*426d2b71SDavid du Colombier for(i=0; i<nreq; i++)
141*426d2b71SDavid du Colombier if(runestrcmp(req[i].name, from) == 0){
142*426d2b71SDavid du Colombier free(req[i].name);
143*426d2b71SDavid du Colombier req[i].name = erunestrdup(to);
144*426d2b71SDavid du Colombier return;
145*426d2b71SDavid du Colombier }
146*426d2b71SDavid du Colombier }
147*426d2b71SDavid du Colombier
148*426d2b71SDavid du Colombier void
addesc(Rune r,int (* f)(void),int mode)149*426d2b71SDavid du Colombier addesc(Rune r, int (*f)(void), int mode)
150*426d2b71SDavid du Colombier {
151*426d2b71SDavid du Colombier Esc *e;
152*426d2b71SDavid du Colombier
153*426d2b71SDavid du Colombier if(nesc >= nelem(esc)){
154*426d2b71SDavid du Colombier fprint(2, "too many escapes\n");
155*426d2b71SDavid du Colombier return;
156*426d2b71SDavid du Colombier }
157*426d2b71SDavid du Colombier e = &esc[nesc++];
158*426d2b71SDavid du Colombier e->r = r;
159*426d2b71SDavid du Colombier e->f = f;
160*426d2b71SDavid du Colombier e->mode = mode;
161*426d2b71SDavid du Colombier }
162*426d2b71SDavid du Colombier
163*426d2b71SDavid du Colombier /*
164*426d2b71SDavid du Colombier * Get the next logical character in the input stream.
165*426d2b71SDavid du Colombier */
166*426d2b71SDavid du Colombier int
getnext(void)167*426d2b71SDavid du Colombier getnext(void)
168*426d2b71SDavid du Colombier {
169*426d2b71SDavid du Colombier int i, r;
170*426d2b71SDavid du Colombier
171*426d2b71SDavid du Colombier next:
172*426d2b71SDavid du Colombier r = getrune();
173*426d2b71SDavid du Colombier if(r < 0)
174*426d2b71SDavid du Colombier return -1;
175*426d2b71SDavid du Colombier if(r == Uformatted){
176*426d2b71SDavid du Colombier br();
177*426d2b71SDavid du Colombier assert(!isoutput);
178*426d2b71SDavid du Colombier while((r = getrune()) >= 0 && r != Uunformatted){
179*426d2b71SDavid du Colombier if(r == Uformatted)
180*426d2b71SDavid du Colombier continue;
181*426d2b71SDavid du Colombier outrune(r);
182*426d2b71SDavid du Colombier }
183*426d2b71SDavid du Colombier goto next;
184*426d2b71SDavid du Colombier }
185*426d2b71SDavid du Colombier if(r == Uunformatted)
186*426d2b71SDavid du Colombier goto next;
187*426d2b71SDavid du Colombier if(r == backslash){
188*426d2b71SDavid du Colombier r = getrune();
189*426d2b71SDavid du Colombier if(r < 0)
190*426d2b71SDavid du Colombier return -1;
191*426d2b71SDavid du Colombier for(i=0; i<nesc; i++){
192*426d2b71SDavid du Colombier if(r == esc[i].r && (inputmode&esc[i].mode)==inputmode){
193*426d2b71SDavid du Colombier if(esc[i].f == e_warn)
194*426d2b71SDavid du Colombier warn("ignoring %C%C", backslash, r);
195*426d2b71SDavid du Colombier r = esc[i].f();
196*426d2b71SDavid du Colombier if(r <= 0)
197*426d2b71SDavid du Colombier goto next;
198*426d2b71SDavid du Colombier return r;
199*426d2b71SDavid du Colombier }
200*426d2b71SDavid du Colombier }
201*426d2b71SDavid du Colombier if(inputmode&(ArgMode|CopyMode)){
202*426d2b71SDavid du Colombier ungetrune(r);
203*426d2b71SDavid du Colombier r = backslash;
204*426d2b71SDavid du Colombier }
205*426d2b71SDavid du Colombier }
206*426d2b71SDavid du Colombier return r;
207*426d2b71SDavid du Colombier }
208*426d2b71SDavid du Colombier
209*426d2b71SDavid du Colombier void
ungetnext(Rune r)210*426d2b71SDavid du Colombier ungetnext(Rune r)
211*426d2b71SDavid du Colombier {
212*426d2b71SDavid du Colombier /*
213*426d2b71SDavid du Colombier * really we want to undo the getrunes that led us here,
214*426d2b71SDavid du Colombier * since the call after ungetnext might be getrune!
215*426d2b71SDavid du Colombier */
216*426d2b71SDavid du Colombier ungetrune(r);
217*426d2b71SDavid du Colombier }
218*426d2b71SDavid du Colombier
219*426d2b71SDavid du Colombier int
_readx(Rune * p,int n,int nmode,int line)220*426d2b71SDavid du Colombier _readx(Rune *p, int n, int nmode, int line)
221*426d2b71SDavid du Colombier {
222*426d2b71SDavid du Colombier int c, omode;
223*426d2b71SDavid du Colombier Rune *e;
224*426d2b71SDavid du Colombier
225*426d2b71SDavid du Colombier while((c = getrune()) == ' ' || c == '\t')
226*426d2b71SDavid du Colombier ;
227*426d2b71SDavid du Colombier ungetrune(c);
228*426d2b71SDavid du Colombier omode = inputmode;
229*426d2b71SDavid du Colombier inputmode = nmode;
230*426d2b71SDavid du Colombier e = p+n-1;
231*426d2b71SDavid du Colombier for(c=getnext(); p<e; c=getnext()){
232*426d2b71SDavid du Colombier if(c < 0)
233*426d2b71SDavid du Colombier break;
234*426d2b71SDavid du Colombier if(!line && (c == ' ' || c == '\t'))
235*426d2b71SDavid du Colombier break;
236*426d2b71SDavid du Colombier if(c == '\n'){
237*426d2b71SDavid du Colombier if(!line)
238*426d2b71SDavid du Colombier ungetnext(c);
239*426d2b71SDavid du Colombier break;
240*426d2b71SDavid du Colombier }
241*426d2b71SDavid du Colombier *p++ = c;
242*426d2b71SDavid du Colombier }
243*426d2b71SDavid du Colombier inputmode = omode;
244*426d2b71SDavid du Colombier *p = 0;
245*426d2b71SDavid du Colombier if(c < 0)
246*426d2b71SDavid du Colombier return -1;
247*426d2b71SDavid du Colombier return 0;
248*426d2b71SDavid du Colombier }
249*426d2b71SDavid du Colombier
250*426d2b71SDavid du Colombier /*
251*426d2b71SDavid du Colombier * Get the next argument from the current line.
252*426d2b71SDavid du Colombier */
253*426d2b71SDavid du Colombier Rune*
copyarg(void)254*426d2b71SDavid du Colombier copyarg(void)
255*426d2b71SDavid du Colombier {
256*426d2b71SDavid du Colombier static Rune buf[MaxLine];
257*426d2b71SDavid du Colombier int c;
258*426d2b71SDavid du Colombier Rune *r;
259*426d2b71SDavid du Colombier
260*426d2b71SDavid du Colombier if(_readx(buf, sizeof buf, ArgMode, 0) < 0)
261*426d2b71SDavid du Colombier return nil;
262*426d2b71SDavid du Colombier r = runestrstr(buf, L("\\\""));
263*426d2b71SDavid du Colombier if(r){
264*426d2b71SDavid du Colombier *r = 0;
265*426d2b71SDavid du Colombier while((c = getrune()) >= 0 && c != '\n')
266*426d2b71SDavid du Colombier ;
267*426d2b71SDavid du Colombier ungetrune('\n');
268*426d2b71SDavid du Colombier }
269*426d2b71SDavid du Colombier r = erunestrdup(buf);
270*426d2b71SDavid du Colombier return r;
271*426d2b71SDavid du Colombier }
272*426d2b71SDavid du Colombier
273*426d2b71SDavid du Colombier /*
274*426d2b71SDavid du Colombier * Read the current line in given mode. Newline not kept.
275*426d2b71SDavid du Colombier * Uses different buffer from copyarg!
276*426d2b71SDavid du Colombier */
277*426d2b71SDavid du Colombier Rune*
readline(int m)278*426d2b71SDavid du Colombier readline(int m)
279*426d2b71SDavid du Colombier {
280*426d2b71SDavid du Colombier static Rune buf[MaxLine];
281*426d2b71SDavid du Colombier Rune *r;
282*426d2b71SDavid du Colombier
283*426d2b71SDavid du Colombier if(_readx(buf, sizeof buf, m, 1) < 0)
284*426d2b71SDavid du Colombier return nil;
285*426d2b71SDavid du Colombier r = erunestrdup(buf);
286*426d2b71SDavid du Colombier return r;
287*426d2b71SDavid du Colombier }
288*426d2b71SDavid du Colombier
289*426d2b71SDavid du Colombier /*
290*426d2b71SDavid du Colombier * Given the argument line (already read in copy+arg mode),
291*426d2b71SDavid du Colombier * parse into arguments. Note that \" has been left in place
292*426d2b71SDavid du Colombier * during copy+arg mode parsing, so comments still need to be stripped.
293*426d2b71SDavid du Colombier */
294*426d2b71SDavid du Colombier int
parseargs(Rune * p,Rune ** argv)295*426d2b71SDavid du Colombier parseargs(Rune *p, Rune **argv)
296*426d2b71SDavid du Colombier {
297*426d2b71SDavid du Colombier int argc;
298*426d2b71SDavid du Colombier Rune *w;
299*426d2b71SDavid du Colombier
300*426d2b71SDavid du Colombier for(argc=0; argc<MAXARG; argc++){
301*426d2b71SDavid du Colombier while(*p == ' ' || *p == '\t')
302*426d2b71SDavid du Colombier p++;
303*426d2b71SDavid du Colombier if(*p == 0)
304*426d2b71SDavid du Colombier break;
305*426d2b71SDavid du Colombier argv[argc] = p;
306*426d2b71SDavid du Colombier if(*p == '"'){
307*426d2b71SDavid du Colombier /* quoted argument */
308*426d2b71SDavid du Colombier if(*(p+1) == '"'){
309*426d2b71SDavid du Colombier /* empty argument */
310*426d2b71SDavid du Colombier *p = 0;
311*426d2b71SDavid du Colombier p += 2;
312*426d2b71SDavid du Colombier }else{
313*426d2b71SDavid du Colombier /* parse quoted string */
314*426d2b71SDavid du Colombier w = p++;
315*426d2b71SDavid du Colombier for(; *p; p++){
316*426d2b71SDavid du Colombier if(*p == '"' && *(p+1) == '"')
317*426d2b71SDavid du Colombier *w++ = '"';
318*426d2b71SDavid du Colombier else if(*p == '"'){
319*426d2b71SDavid du Colombier p++;
320*426d2b71SDavid du Colombier break;
321*426d2b71SDavid du Colombier }else
322*426d2b71SDavid du Colombier *w++ = *p;
323*426d2b71SDavid du Colombier }
324*426d2b71SDavid du Colombier *w = 0;
325*426d2b71SDavid du Colombier }
326*426d2b71SDavid du Colombier }else{
327*426d2b71SDavid du Colombier /* unquoted argument - need to watch out for \" comment */
328*426d2b71SDavid du Colombier for(; *p; p++){
329*426d2b71SDavid du Colombier if(*p == ' ' || *p == '\t'){
330*426d2b71SDavid du Colombier *p++ = 0;
331*426d2b71SDavid du Colombier break;
332*426d2b71SDavid du Colombier }
333*426d2b71SDavid du Colombier if(*p == '\\' && *(p+1) == '"'){
334*426d2b71SDavid du Colombier *p = 0;
335*426d2b71SDavid du Colombier if(p != argv[argc])
336*426d2b71SDavid du Colombier argc++;
337*426d2b71SDavid du Colombier return argc;
338*426d2b71SDavid du Colombier }
339*426d2b71SDavid du Colombier }
340*426d2b71SDavid du Colombier }
341*426d2b71SDavid du Colombier }
342*426d2b71SDavid du Colombier return argc;
343*426d2b71SDavid du Colombier }
344*426d2b71SDavid du Colombier
345*426d2b71SDavid du Colombier /*
346*426d2b71SDavid du Colombier * Process a dot line. The dot has been read.
347*426d2b71SDavid du Colombier */
348*426d2b71SDavid du Colombier void
dotline(int dot)349*426d2b71SDavid du Colombier dotline(int dot)
350*426d2b71SDavid du Colombier {
351*426d2b71SDavid du Colombier int argc, i;
352*426d2b71SDavid du Colombier Rune *a, *argv[1+MAXARG];
353*426d2b71SDavid du Colombier
354*426d2b71SDavid du Colombier /*
355*426d2b71SDavid du Colombier * Read request/macro name
356*426d2b71SDavid du Colombier */
357*426d2b71SDavid du Colombier a = copyarg();
358*426d2b71SDavid du Colombier if(a == nil || a[0] == 0){
359*426d2b71SDavid du Colombier free(a);
360*426d2b71SDavid du Colombier getrune(); /* \n */
361*426d2b71SDavid du Colombier return;
362*426d2b71SDavid du Colombier }
363*426d2b71SDavid du Colombier argv[0] = a;
364*426d2b71SDavid du Colombier /*
365*426d2b71SDavid du Colombier * Check for .if, .ie, and others with special parsing.
366*426d2b71SDavid du Colombier */
367*426d2b71SDavid du Colombier for(i=0; i<nraw; i++){
368*426d2b71SDavid du Colombier if(runestrcmp(raw[i].name, a) == 0){
369*426d2b71SDavid du Colombier raw[i].f(raw[i].name);
370*426d2b71SDavid du Colombier free(a);
371*426d2b71SDavid du Colombier return;
372*426d2b71SDavid du Colombier }
373*426d2b71SDavid du Colombier }
374*426d2b71SDavid du Colombier
375*426d2b71SDavid du Colombier /*
376*426d2b71SDavid du Colombier * Read rest of line in copy mode, invoke regular request.
377*426d2b71SDavid du Colombier */
378*426d2b71SDavid du Colombier a = readline(ArgMode);
379*426d2b71SDavid du Colombier if(a == nil){
380*426d2b71SDavid du Colombier free(argv[0]);
381*426d2b71SDavid du Colombier return;
382*426d2b71SDavid du Colombier }
383*426d2b71SDavid du Colombier argc = 1+parseargs(a, argv+1);
384*426d2b71SDavid du Colombier for(i=0; i<nreq; i++){
385*426d2b71SDavid du Colombier if(runestrcmp(req[i].name, argv[0]) == 0){
386*426d2b71SDavid du Colombier if(req[i].argc != -1){
387*426d2b71SDavid du Colombier if(argc < 1+req[i].argc){
388*426d2b71SDavid du Colombier warn("not enough arguments for %C%S", dot, req[i].name);
389*426d2b71SDavid du Colombier free(argv[0]);
390*426d2b71SDavid du Colombier free(a);
391*426d2b71SDavid du Colombier return;
392*426d2b71SDavid du Colombier }
393*426d2b71SDavid du Colombier if(argc > 1+req[i].argc)
394*426d2b71SDavid du Colombier warn("too many arguments for %C%S", dot, req[i].name);
395*426d2b71SDavid du Colombier }
396*426d2b71SDavid du Colombier req[i].f(argc, argv);
397*426d2b71SDavid du Colombier free(argv[0]);
398*426d2b71SDavid du Colombier free(a);
399*426d2b71SDavid du Colombier return;
400*426d2b71SDavid du Colombier }
401*426d2b71SDavid du Colombier }
402*426d2b71SDavid du Colombier
403*426d2b71SDavid du Colombier /*
404*426d2b71SDavid du Colombier * Invoke user-defined macros.
405*426d2b71SDavid du Colombier */
406*426d2b71SDavid du Colombier runmacro(dot, argc, argv);
407*426d2b71SDavid du Colombier free(argv[0]);
408*426d2b71SDavid du Colombier free(a);
409*426d2b71SDavid du Colombier }
410*426d2b71SDavid du Colombier
411*426d2b71SDavid du Colombier /*
412*426d2b71SDavid du Colombier * newlines are magical in various ways.
413*426d2b71SDavid du Colombier */
414*426d2b71SDavid du Colombier int bol;
415*426d2b71SDavid du Colombier void
newline(void)416*426d2b71SDavid du Colombier newline(void)
417*426d2b71SDavid du Colombier {
418*426d2b71SDavid du Colombier int n;
419*426d2b71SDavid du Colombier
420*426d2b71SDavid du Colombier if(bol)
421*426d2b71SDavid du Colombier sp(eval(L("1v")));
422*426d2b71SDavid du Colombier bol = 1;
423*426d2b71SDavid du Colombier if((n=getnr(L(".ce"))) > 0){
424*426d2b71SDavid du Colombier nr(L(".ce"), n-1);
425*426d2b71SDavid du Colombier br();
426*426d2b71SDavid du Colombier }
427*426d2b71SDavid du Colombier if(getnr(L(".fi")) == 0)
428*426d2b71SDavid du Colombier br();
429*426d2b71SDavid du Colombier outrune('\n');
430*426d2b71SDavid du Colombier }
431*426d2b71SDavid du Colombier
432*426d2b71SDavid du Colombier void
startoutput(void)433*426d2b71SDavid du Colombier startoutput(void)
434*426d2b71SDavid du Colombier {
435*426d2b71SDavid du Colombier char *align;
436*426d2b71SDavid du Colombier double ps, vs, lm, rm, ti;
437*426d2b71SDavid du Colombier Rune buf[200];
438*426d2b71SDavid du Colombier
439*426d2b71SDavid du Colombier if(isoutput)
440*426d2b71SDavid du Colombier return;
441*426d2b71SDavid du Colombier isoutput = 1;
442*426d2b71SDavid du Colombier
443*426d2b71SDavid du Colombier if(getnr(L(".paragraph")) == 0)
444*426d2b71SDavid du Colombier return;
445*426d2b71SDavid du Colombier
446*426d2b71SDavid du Colombier nr(L(".ns"), 0);
447*426d2b71SDavid du Colombier isoutput = 1;
448*426d2b71SDavid du Colombier ps = getnr(L(".s"));
449*426d2b71SDavid du Colombier if(ps <= 1)
450*426d2b71SDavid du Colombier ps = 10;
451*426d2b71SDavid du Colombier ps /= 72.0;
452*426d2b71SDavid du Colombier USED(ps);
453*426d2b71SDavid du Colombier
454*426d2b71SDavid du Colombier vs = getnr(L(".v"))*getnr(L(".ls")) * 1.0/UPI;
455*426d2b71SDavid du Colombier vs /= (10.0/72.0); /* ps */
456*426d2b71SDavid du Colombier if(vs == 0)
457*426d2b71SDavid du Colombier vs = 1.2;
458*426d2b71SDavid du Colombier
459*426d2b71SDavid du Colombier lm = (getnr(L(".o"))+getnr(L(".i"))) * 1.0/UPI;
460*426d2b71SDavid du Colombier ti = getnr(L(".ti")) * 1.0/UPI;
461*426d2b71SDavid du Colombier nr(L(".ti"), 0);
462*426d2b71SDavid du Colombier
463*426d2b71SDavid du Colombier rm = 8.0 - getnr(L(".l"))*1.0/UPI - getnr(L(".o"))*1.0/UPI;
464*426d2b71SDavid du Colombier if(rm < 0)
465*426d2b71SDavid du Colombier rm = 0;
466*426d2b71SDavid du Colombier switch(getnr(L(".j"))){
467*426d2b71SDavid du Colombier default:
468*426d2b71SDavid du Colombier case 0:
469*426d2b71SDavid du Colombier align = "left";
470*426d2b71SDavid du Colombier break;
471*426d2b71SDavid du Colombier case 1:
472*426d2b71SDavid du Colombier align = "justify";
473*426d2b71SDavid du Colombier break;
474*426d2b71SDavid du Colombier case 3:
475*426d2b71SDavid du Colombier align = "center";
476*426d2b71SDavid du Colombier break;
477*426d2b71SDavid du Colombier case 5:
478*426d2b71SDavid du Colombier align = "right";
479*426d2b71SDavid du Colombier break;
480*426d2b71SDavid du Colombier }
481*426d2b71SDavid du Colombier if(getnr(L(".ce")))
482*426d2b71SDavid du Colombier align = "center";
483*426d2b71SDavid du Colombier if(!getnr(L(".margin")))
484*426d2b71SDavid du Colombier runesnprint(buf, nelem(buf), "<p style=\"line-height: %.1fem; text-indent: %.2fin; margin-top: 0; margin-bottom: 0; text-align: %s;\">\n",
485*426d2b71SDavid du Colombier vs, ti, align);
486*426d2b71SDavid du Colombier else
487*426d2b71SDavid du Colombier runesnprint(buf, nelem(buf), "<p style=\"line-height: %.1fem; margin-left: %.2fin; text-indent: %.2fin; margin-right: %.2fin; margin-top: 0; margin-bottom: 0; text-align: %s;\">\n",
488*426d2b71SDavid du Colombier vs, lm, ti, rm, align);
489*426d2b71SDavid du Colombier outhtml(buf);
490*426d2b71SDavid du Colombier }
491*426d2b71SDavid du Colombier void
br(void)492*426d2b71SDavid du Colombier br(void)
493*426d2b71SDavid du Colombier {
494*426d2b71SDavid du Colombier if(!isoutput)
495*426d2b71SDavid du Colombier return;
496*426d2b71SDavid du Colombier isoutput = 0;
497*426d2b71SDavid du Colombier
498*426d2b71SDavid du Colombier nr(L(".dv"), 0);
499*426d2b71SDavid du Colombier dv(0);
500*426d2b71SDavid du Colombier hideihtml();
501*426d2b71SDavid du Colombier if(getnr(L(".paragraph")))
502*426d2b71SDavid du Colombier outhtml(L("</p>"));
503*426d2b71SDavid du Colombier }
504*426d2b71SDavid du Colombier
505*426d2b71SDavid du Colombier void
r_margin(int argc,Rune ** argv)506*426d2b71SDavid du Colombier r_margin(int argc, Rune **argv)
507*426d2b71SDavid du Colombier {
508*426d2b71SDavid du Colombier USED(argc);
509*426d2b71SDavid du Colombier
510*426d2b71SDavid du Colombier nr(L(".margin"), eval(argv[1]));
511*426d2b71SDavid du Colombier }
512*426d2b71SDavid du Colombier
513*426d2b71SDavid du Colombier int inrequest;
514*426d2b71SDavid du Colombier void
runinput(void)515*426d2b71SDavid du Colombier runinput(void)
516*426d2b71SDavid du Colombier {
517*426d2b71SDavid du Colombier int c;
518*426d2b71SDavid du Colombier
519*426d2b71SDavid du Colombier bol = 1;
520*426d2b71SDavid du Colombier for(;;){
521*426d2b71SDavid du Colombier c = getnext();
522*426d2b71SDavid du Colombier if(c < 0)
523*426d2b71SDavid du Colombier break;
524*426d2b71SDavid du Colombier if((c == dot || c == tick) && bol){
525*426d2b71SDavid du Colombier inrequest = 1;
526*426d2b71SDavid du Colombier dotline(c);
527*426d2b71SDavid du Colombier bol = 1;
528*426d2b71SDavid du Colombier inrequest = 0;
529*426d2b71SDavid du Colombier }else if(c == '\n'){
530*426d2b71SDavid du Colombier newline();
531*426d2b71SDavid du Colombier itrap();
532*426d2b71SDavid du Colombier linepos = 0;
533*426d2b71SDavid du Colombier }else{
534*426d2b71SDavid du Colombier outtrap();
535*426d2b71SDavid du Colombier startoutput();
536*426d2b71SDavid du Colombier showihtml();
537*426d2b71SDavid du Colombier if(c == '\t'){
538*426d2b71SDavid du Colombier /* XXX do better */
539*426d2b71SDavid du Colombier outrune(' ');
540*426d2b71SDavid du Colombier while(++linepos%4)
541*426d2b71SDavid du Colombier outrune(' ');
542*426d2b71SDavid du Colombier }else{
543*426d2b71SDavid du Colombier outrune(c);
544*426d2b71SDavid du Colombier linepos++;
545*426d2b71SDavid du Colombier }
546*426d2b71SDavid du Colombier bol = 0;
547*426d2b71SDavid du Colombier }
548*426d2b71SDavid du Colombier }
549*426d2b71SDavid du Colombier }
550*426d2b71SDavid du Colombier
551*426d2b71SDavid du Colombier void
run(void)552*426d2b71SDavid du Colombier run(void)
553*426d2b71SDavid du Colombier {
554*426d2b71SDavid du Colombier t1init();
555*426d2b71SDavid du Colombier t2init();
556*426d2b71SDavid du Colombier t3init();
557*426d2b71SDavid du Colombier t4init();
558*426d2b71SDavid du Colombier t5init();
559*426d2b71SDavid du Colombier t6init();
560*426d2b71SDavid du Colombier t7init();
561*426d2b71SDavid du Colombier t8init();
562*426d2b71SDavid du Colombier /* t9init(); t9.c */
563*426d2b71SDavid du Colombier t10init();
564*426d2b71SDavid du Colombier t11init();
565*426d2b71SDavid du Colombier /* t12init(); t12.c */
566*426d2b71SDavid du Colombier t13init();
567*426d2b71SDavid du Colombier t14init();
568*426d2b71SDavid du Colombier t15init();
569*426d2b71SDavid du Colombier t16init();
570*426d2b71SDavid du Colombier t17init();
571*426d2b71SDavid du Colombier t18init();
572*426d2b71SDavid du Colombier t19init();
573*426d2b71SDavid du Colombier t20init();
574*426d2b71SDavid du Colombier htmlinit();
575*426d2b71SDavid du Colombier hideihtml();
576*426d2b71SDavid du Colombier
577*426d2b71SDavid du Colombier addreq(L("margin"), r_margin, 1);
578*426d2b71SDavid du Colombier nr(L(".margin"), 1);
579*426d2b71SDavid du Colombier nr(L(".paragraph"), 1);
580*426d2b71SDavid du Colombier
581*426d2b71SDavid du Colombier runinput();
582*426d2b71SDavid du Colombier while(popinput())
583*426d2b71SDavid du Colombier ;
584*426d2b71SDavid du Colombier dot = '.';
585*426d2b71SDavid du Colombier if(verbose)
586*426d2b71SDavid du Colombier fprint(2, "eof\n");
587*426d2b71SDavid du Colombier runmacro1(L("eof"));
588*426d2b71SDavid du Colombier closehtml();
589*426d2b71SDavid du Colombier }
590*426d2b71SDavid du Colombier
591*426d2b71SDavid du Colombier void
out(Rune * s)592*426d2b71SDavid du Colombier out(Rune *s)
593*426d2b71SDavid du Colombier {
594*426d2b71SDavid du Colombier if(s == nil)
595*426d2b71SDavid du Colombier return;
596*426d2b71SDavid du Colombier for(; *s; s++)
597*426d2b71SDavid du Colombier outrune(*s);
598*426d2b71SDavid du Colombier }
599*426d2b71SDavid du Colombier
600*426d2b71SDavid du Colombier void (*outcb)(Rune);
601*426d2b71SDavid du Colombier
602*426d2b71SDavid du Colombier void
inroman(Rune r)603*426d2b71SDavid du Colombier inroman(Rune r)
604*426d2b71SDavid du Colombier {
605*426d2b71SDavid du Colombier int f;
606*426d2b71SDavid du Colombier
607*426d2b71SDavid du Colombier f = getnr(L(".f"));
608*426d2b71SDavid du Colombier nr(L(".f"), 1);
609*426d2b71SDavid du Colombier runmacro1(L("font"));
610*426d2b71SDavid du Colombier outrune(r);
611*426d2b71SDavid du Colombier nr(L(".f"), f);
612*426d2b71SDavid du Colombier runmacro1(L("font"));
613*426d2b71SDavid du Colombier }
614*426d2b71SDavid du Colombier
615*426d2b71SDavid du Colombier void
Brune(Rune r)616*426d2b71SDavid du Colombier Brune(Rune r)
617*426d2b71SDavid du Colombier {
618*426d2b71SDavid du Colombier if(r == '&')
619*426d2b71SDavid du Colombier Bprint(&bout, "&");
620*426d2b71SDavid du Colombier else if(r == '<')
621*426d2b71SDavid du Colombier Bprint(&bout, "<");
622*426d2b71SDavid du Colombier else if(r == '>')
623*426d2b71SDavid du Colombier Bprint(&bout, ">");
624*426d2b71SDavid du Colombier else if(r < Runeself || utf8)
625*426d2b71SDavid du Colombier Bprint(&bout, "%C", r);
626*426d2b71SDavid du Colombier else
627*426d2b71SDavid du Colombier Bprint(&bout, "%S", rune2html(r));
628*426d2b71SDavid du Colombier }
629*426d2b71SDavid du Colombier
630*426d2b71SDavid du Colombier void
outhtml(Rune * s)631*426d2b71SDavid du Colombier outhtml(Rune *s)
632*426d2b71SDavid du Colombier {
633*426d2b71SDavid du Colombier Rune r;
634*426d2b71SDavid du Colombier
635*426d2b71SDavid du Colombier for(; *s; s++){
636*426d2b71SDavid du Colombier switch(r = *s){
637*426d2b71SDavid du Colombier case '<':
638*426d2b71SDavid du Colombier r = Ult;
639*426d2b71SDavid du Colombier break;
640*426d2b71SDavid du Colombier case '>':
641*426d2b71SDavid du Colombier r = Ugt;
642*426d2b71SDavid du Colombier break;
643*426d2b71SDavid du Colombier case '&':
644*426d2b71SDavid du Colombier r = Uamp;
645*426d2b71SDavid du Colombier break;
646*426d2b71SDavid du Colombier case ' ':
647*426d2b71SDavid du Colombier r = Uspace;
648*426d2b71SDavid du Colombier break;
649*426d2b71SDavid du Colombier }
650*426d2b71SDavid du Colombier outrune(r);
651*426d2b71SDavid du Colombier }
652*426d2b71SDavid du Colombier }
653*426d2b71SDavid du Colombier
654*426d2b71SDavid du Colombier void
outrune(Rune r)655*426d2b71SDavid du Colombier outrune(Rune r)
656*426d2b71SDavid du Colombier {
657*426d2b71SDavid du Colombier switch(r){
658*426d2b71SDavid du Colombier case ' ':
659*426d2b71SDavid du Colombier if(getnr(L(".fi")) == 0)
660*426d2b71SDavid du Colombier r = Unbsp;
661*426d2b71SDavid du Colombier break;
662*426d2b71SDavid du Colombier case Uformatted:
663*426d2b71SDavid du Colombier case Uunformatted:
664*426d2b71SDavid du Colombier abort();
665*426d2b71SDavid du Colombier }
666*426d2b71SDavid du Colombier if(outcb){
667*426d2b71SDavid du Colombier if(r == ' ')
668*426d2b71SDavid du Colombier r = Uspace;
669*426d2b71SDavid du Colombier outcb(r);
670*426d2b71SDavid du Colombier return;
671*426d2b71SDavid du Colombier }
672*426d2b71SDavid du Colombier /* writing to bout */
673*426d2b71SDavid du Colombier switch(r){
674*426d2b71SDavid du Colombier case Uempty:
675*426d2b71SDavid du Colombier return;
676*426d2b71SDavid du Colombier case Upl:
677*426d2b71SDavid du Colombier inroman('+');
678*426d2b71SDavid du Colombier return;
679*426d2b71SDavid du Colombier case Ueq:
680*426d2b71SDavid du Colombier inroman('=');
681*426d2b71SDavid du Colombier return;
682*426d2b71SDavid du Colombier case Umi:
683*426d2b71SDavid du Colombier inroman(0x2212);
684*426d2b71SDavid du Colombier return;
685*426d2b71SDavid du Colombier case Utick:
686*426d2b71SDavid du Colombier r = '\'';
687*426d2b71SDavid du Colombier break;
688*426d2b71SDavid du Colombier case Ubtick:
689*426d2b71SDavid du Colombier r = '`';
690*426d2b71SDavid du Colombier break;
691*426d2b71SDavid du Colombier case Uminus:
692*426d2b71SDavid du Colombier r = '-';
693*426d2b71SDavid du Colombier break;
694*426d2b71SDavid du Colombier case '\'':
695*426d2b71SDavid du Colombier Bprint(&bout, "’");
696*426d2b71SDavid du Colombier return;
697*426d2b71SDavid du Colombier case '`':
698*426d2b71SDavid du Colombier Bprint(&bout, "‘");
699*426d2b71SDavid du Colombier return;
700*426d2b71SDavid du Colombier case Uamp:
701*426d2b71SDavid du Colombier Bputrune(&bout, '&');
702*426d2b71SDavid du Colombier return;
703*426d2b71SDavid du Colombier case Ult:
704*426d2b71SDavid du Colombier Bputrune(&bout, '<');
705*426d2b71SDavid du Colombier return;
706*426d2b71SDavid du Colombier case Ugt:
707*426d2b71SDavid du Colombier Bputrune(&bout, '>');
708*426d2b71SDavid du Colombier return;
709*426d2b71SDavid du Colombier case Uspace:
710*426d2b71SDavid du Colombier Bputrune(&bout, ' ');
711*426d2b71SDavid du Colombier return;
712*426d2b71SDavid du Colombier case 0x2032:
713*426d2b71SDavid du Colombier /*
714*426d2b71SDavid du Colombier * In Firefox, at least, the prime is not
715*426d2b71SDavid du Colombier * a superscript by default.
716*426d2b71SDavid du Colombier */
717*426d2b71SDavid du Colombier Bprint(&bout, "<sup>");
718*426d2b71SDavid du Colombier Brune(r);
719*426d2b71SDavid du Colombier Bprint(&bout, "</sup>");
720*426d2b71SDavid du Colombier return;
721*426d2b71SDavid du Colombier }
722*426d2b71SDavid du Colombier Brune(r);
723*426d2b71SDavid du Colombier }
724*426d2b71SDavid du Colombier
725*426d2b71SDavid du Colombier void
r_nop(int argc,Rune ** argv)726*426d2b71SDavid du Colombier r_nop(int argc, Rune **argv)
727*426d2b71SDavid du Colombier {
728*426d2b71SDavid du Colombier USED(argc);
729*426d2b71SDavid du Colombier USED(argv);
730*426d2b71SDavid du Colombier }
731*426d2b71SDavid du Colombier
732*426d2b71SDavid du Colombier void
r_warn(int argc,Rune ** argv)733*426d2b71SDavid du Colombier r_warn(int argc, Rune **argv)
734*426d2b71SDavid du Colombier {
735*426d2b71SDavid du Colombier USED(argc);
736*426d2b71SDavid du Colombier warn("ignoring %C%S", dot, argv[0]);
737*426d2b71SDavid du Colombier }
738*426d2b71SDavid du Colombier
739*426d2b71SDavid du Colombier int
e_warn(void)740*426d2b71SDavid du Colombier e_warn(void)
741*426d2b71SDavid du Colombier {
742*426d2b71SDavid du Colombier /* dispatch loop prints a warning for us */
743*426d2b71SDavid du Colombier return 0;
744*426d2b71SDavid du Colombier }
745*426d2b71SDavid du Colombier
746*426d2b71SDavid du Colombier int
e_nop(void)747*426d2b71SDavid du Colombier e_nop(void)
748*426d2b71SDavid du Colombier {
749*426d2b71SDavid du Colombier return 0;
750*426d2b71SDavid du Colombier }
751