xref: /plan9/sys/src/cmd/htmlroff/input.c (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1*426d2b71SDavid du Colombier /*
2*426d2b71SDavid du Colombier  * Read input files.
3*426d2b71SDavid du Colombier  */
4*426d2b71SDavid du Colombier #include "a.h"
5*426d2b71SDavid du Colombier 
6*426d2b71SDavid du Colombier typedef struct Istack Istack;
7*426d2b71SDavid du Colombier struct Istack
8*426d2b71SDavid du Colombier {
9*426d2b71SDavid du Colombier 	Rune unget[3];
10*426d2b71SDavid du Colombier 	int nunget;
11*426d2b71SDavid du Colombier 	Biobuf *b;
12*426d2b71SDavid du Colombier 	Rune *p;
13*426d2b71SDavid du Colombier 	Rune *ep;
14*426d2b71SDavid du Colombier 	Rune *s;
15*426d2b71SDavid du Colombier 	int lineno;
16*426d2b71SDavid du Colombier 	Rune *name;
17*426d2b71SDavid du Colombier 	Istack *next;
18*426d2b71SDavid du Colombier 	void (*fn)(void);
19*426d2b71SDavid du Colombier };
20*426d2b71SDavid du Colombier 
21*426d2b71SDavid du Colombier Istack *istack;
22*426d2b71SDavid du Colombier Istack *ibottom;
23*426d2b71SDavid du Colombier 
24*426d2b71SDavid du Colombier static void
setname(void)25*426d2b71SDavid du Colombier setname(void)
26*426d2b71SDavid du Colombier {
27*426d2b71SDavid du Colombier 	Rune *r, *p;
28*426d2b71SDavid du Colombier 
29*426d2b71SDavid du Colombier 	if(istack == nil || istack->name == nil)
30*426d2b71SDavid du Colombier 		return;
31*426d2b71SDavid du Colombier 	_nr(L(".F"), istack->name);
32*426d2b71SDavid du Colombier 	r = erunestrdup(istack->name);
33*426d2b71SDavid du Colombier 	p = runestrchr(r, '.');
34*426d2b71SDavid du Colombier 	if(p)
35*426d2b71SDavid du Colombier 		*p = 0;
36*426d2b71SDavid du Colombier 	_nr(L(".B"), r);
37*426d2b71SDavid du Colombier 	free(r);
38*426d2b71SDavid du Colombier }
39*426d2b71SDavid du Colombier 
40*426d2b71SDavid du Colombier static void
ipush(Istack * is)41*426d2b71SDavid du Colombier ipush(Istack *is)
42*426d2b71SDavid du Colombier {
43*426d2b71SDavid du Colombier 	if(istack == nil)
44*426d2b71SDavid du Colombier 		ibottom = is;
45*426d2b71SDavid du Colombier 	else
46*426d2b71SDavid du Colombier 		is->next = istack;
47*426d2b71SDavid du Colombier 	istack = is;
48*426d2b71SDavid du Colombier 	setname();
49*426d2b71SDavid du Colombier }
50*426d2b71SDavid du Colombier 
51*426d2b71SDavid du Colombier static void
iqueue(Istack * is)52*426d2b71SDavid du Colombier iqueue(Istack *is)
53*426d2b71SDavid du Colombier {
54*426d2b71SDavid du Colombier 	if(ibottom == nil){
55*426d2b71SDavid du Colombier 		istack = is;
56*426d2b71SDavid du Colombier 		setname();
57*426d2b71SDavid du Colombier 	}else
58*426d2b71SDavid du Colombier 		ibottom->next = is;
59*426d2b71SDavid du Colombier 	ibottom = is;
60*426d2b71SDavid du Colombier }
61*426d2b71SDavid du Colombier 
62*426d2b71SDavid du Colombier int
_inputfile(Rune * s,void (* push)(Istack *))63*426d2b71SDavid du Colombier _inputfile(Rune *s, void (*push)(Istack*))
64*426d2b71SDavid du Colombier {
65*426d2b71SDavid du Colombier 	Istack *is;
66*426d2b71SDavid du Colombier 	Biobuf *b;
67*426d2b71SDavid du Colombier 	char *t;
68*426d2b71SDavid du Colombier 
69*426d2b71SDavid du Colombier 	t = esmprint("%S", s);
70*426d2b71SDavid du Colombier 	if((b = Bopen(t, OREAD)) == nil){
71*426d2b71SDavid du Colombier 		free(t);
72*426d2b71SDavid du Colombier 		fprint(2, "%s: open %S: %r\n", argv0, s);
73*426d2b71SDavid du Colombier 		return -1;
74*426d2b71SDavid du Colombier 	}
75*426d2b71SDavid du Colombier 	free(t);
76*426d2b71SDavid du Colombier 	is = emalloc(sizeof *is);
77*426d2b71SDavid du Colombier 	is->b = b;
78*426d2b71SDavid du Colombier 	is->name = erunestrdup(s);
79*426d2b71SDavid du Colombier 	is->lineno = 1;
80*426d2b71SDavid du Colombier 	push(is);
81*426d2b71SDavid du Colombier 	return 0;
82*426d2b71SDavid du Colombier }
83*426d2b71SDavid du Colombier 
84*426d2b71SDavid du Colombier int
pushinputfile(Rune * s)85*426d2b71SDavid du Colombier pushinputfile(Rune *s)
86*426d2b71SDavid du Colombier {
87*426d2b71SDavid du Colombier 	return _inputfile(s, ipush);
88*426d2b71SDavid du Colombier }
89*426d2b71SDavid du Colombier 
90*426d2b71SDavid du Colombier int
queueinputfile(Rune * s)91*426d2b71SDavid du Colombier queueinputfile(Rune *s)
92*426d2b71SDavid du Colombier {
93*426d2b71SDavid du Colombier 	return _inputfile(s, iqueue);
94*426d2b71SDavid du Colombier }
95*426d2b71SDavid du Colombier 
96*426d2b71SDavid du Colombier int
_inputstdin(void (* push)(Istack *))97*426d2b71SDavid du Colombier _inputstdin(void (*push)(Istack*))
98*426d2b71SDavid du Colombier {
99*426d2b71SDavid du Colombier 	Biobuf *b;
100*426d2b71SDavid du Colombier 	Istack *is;
101*426d2b71SDavid du Colombier 
102*426d2b71SDavid du Colombier 	if((b = Bopen("/dev/null", OREAD)) == nil){
103*426d2b71SDavid du Colombier 		fprint(2, "%s: open /dev/null: %r\n", argv0);
104*426d2b71SDavid du Colombier 		return -1;
105*426d2b71SDavid du Colombier 	}
106*426d2b71SDavid du Colombier 	dup(0, b->fid);
107*426d2b71SDavid du Colombier 	is = emalloc(sizeof *is);
108*426d2b71SDavid du Colombier 	is->b = b;
109*426d2b71SDavid du Colombier 	is->name = erunestrdup(L("stdin"));
110*426d2b71SDavid du Colombier 	is->lineno = 1;
111*426d2b71SDavid du Colombier 	push(is);
112*426d2b71SDavid du Colombier 	return 0;
113*426d2b71SDavid du Colombier }
114*426d2b71SDavid du Colombier 
115*426d2b71SDavid du Colombier int
pushstdin(void)116*426d2b71SDavid du Colombier pushstdin(void)
117*426d2b71SDavid du Colombier {
118*426d2b71SDavid du Colombier 	return _inputstdin(ipush);
119*426d2b71SDavid du Colombier }
120*426d2b71SDavid du Colombier 
121*426d2b71SDavid du Colombier int
queuestdin(void)122*426d2b71SDavid du Colombier queuestdin(void)
123*426d2b71SDavid du Colombier {
124*426d2b71SDavid du Colombier 	return _inputstdin(iqueue);
125*426d2b71SDavid du Colombier }
126*426d2b71SDavid du Colombier 
127*426d2b71SDavid du Colombier void
_inputstring(Rune * s,void (* push)(Istack *))128*426d2b71SDavid du Colombier _inputstring(Rune *s, void (*push)(Istack*))
129*426d2b71SDavid du Colombier {
130*426d2b71SDavid du Colombier 	Istack *is;
131*426d2b71SDavid du Colombier 
132*426d2b71SDavid du Colombier 	is = emalloc(sizeof *is);
133*426d2b71SDavid du Colombier 	is->s = erunestrdup(s);
134*426d2b71SDavid du Colombier 	is->p = is->s;
135*426d2b71SDavid du Colombier 	is->ep = is->p+runestrlen(is->p);
136*426d2b71SDavid du Colombier 	push(is);
137*426d2b71SDavid du Colombier }
138*426d2b71SDavid du Colombier 
139*426d2b71SDavid du Colombier void
pushinputstring(Rune * s)140*426d2b71SDavid du Colombier pushinputstring(Rune *s)
141*426d2b71SDavid du Colombier {
142*426d2b71SDavid du Colombier 	_inputstring(s, ipush);
143*426d2b71SDavid du Colombier }
144*426d2b71SDavid du Colombier 
145*426d2b71SDavid du Colombier 
146*426d2b71SDavid du Colombier void
inputnotify(void (* fn)(void))147*426d2b71SDavid du Colombier inputnotify(void (*fn)(void))
148*426d2b71SDavid du Colombier {
149*426d2b71SDavid du Colombier 	if(istack)
150*426d2b71SDavid du Colombier 		istack->fn = fn;
151*426d2b71SDavid du Colombier }
152*426d2b71SDavid du Colombier 
153*426d2b71SDavid du Colombier int
popinput(void)154*426d2b71SDavid du Colombier popinput(void)
155*426d2b71SDavid du Colombier {
156*426d2b71SDavid du Colombier 	Istack *is;
157*426d2b71SDavid du Colombier 
158*426d2b71SDavid du Colombier 	is = istack;
159*426d2b71SDavid du Colombier 	if(is == nil)
160*426d2b71SDavid du Colombier 		return 0;
161*426d2b71SDavid du Colombier 
162*426d2b71SDavid du Colombier 	istack = istack->next;
163*426d2b71SDavid du Colombier 	if(is->b)
164*426d2b71SDavid du Colombier 		Bterm(is->b);
165*426d2b71SDavid du Colombier 	free(is->s);
166*426d2b71SDavid du Colombier 	free(is->name);
167*426d2b71SDavid du Colombier 	if(is->fn)
168*426d2b71SDavid du Colombier 		is->fn();
169*426d2b71SDavid du Colombier 	free(is);
170*426d2b71SDavid du Colombier 	setname();
171*426d2b71SDavid du Colombier 	return 1;
172*426d2b71SDavid du Colombier }
173*426d2b71SDavid du Colombier 
174*426d2b71SDavid du Colombier int
getrune(void)175*426d2b71SDavid du Colombier getrune(void)
176*426d2b71SDavid du Colombier {
177*426d2b71SDavid du Colombier 	Rune r;
178*426d2b71SDavid du Colombier 	int c;
179*426d2b71SDavid du Colombier 
180*426d2b71SDavid du Colombier top:
181*426d2b71SDavid du Colombier 	if(istack == nil)
182*426d2b71SDavid du Colombier 		return -1;
183*426d2b71SDavid du Colombier 	if(istack->nunget)
184*426d2b71SDavid du Colombier 		return istack->unget[--istack->nunget];
185*426d2b71SDavid du Colombier 	else if(istack->p){
186*426d2b71SDavid du Colombier 		if(istack->p >= istack->ep){
187*426d2b71SDavid du Colombier 			popinput();
188*426d2b71SDavid du Colombier 			goto top;
189*426d2b71SDavid du Colombier 		}
190*426d2b71SDavid du Colombier 		r = *istack->p++;
191*426d2b71SDavid du Colombier 	}else if(istack->b){
192*426d2b71SDavid du Colombier 		if((c = Bgetrune(istack->b)) < 0){
193*426d2b71SDavid du Colombier 			popinput();
194*426d2b71SDavid du Colombier 			goto top;
195*426d2b71SDavid du Colombier 		}
196*426d2b71SDavid du Colombier 		r = c;
197*426d2b71SDavid du Colombier 	}else{
198*426d2b71SDavid du Colombier 		r = 0;
199*426d2b71SDavid du Colombier 		sysfatal("getrune - can't happen");
200*426d2b71SDavid du Colombier 	}
201*426d2b71SDavid du Colombier 	if(r == '\n')
202*426d2b71SDavid du Colombier 		istack->lineno++;
203*426d2b71SDavid du Colombier 	return r;
204*426d2b71SDavid du Colombier }
205*426d2b71SDavid du Colombier 
206*426d2b71SDavid du Colombier void
ungetrune(Rune r)207*426d2b71SDavid du Colombier ungetrune(Rune r)
208*426d2b71SDavid du Colombier {
209*426d2b71SDavid du Colombier 	if(istack == nil || istack->nunget >= nelem(istack->unget))
210*426d2b71SDavid du Colombier 		pushinputstring(L(""));
211*426d2b71SDavid du Colombier 	istack->unget[istack->nunget++] = r;
212*426d2b71SDavid du Colombier }
213*426d2b71SDavid du Colombier 
214*426d2b71SDavid du Colombier int
linefmt(Fmt * f)215*426d2b71SDavid du Colombier linefmt(Fmt *f)
216*426d2b71SDavid du Colombier {
217*426d2b71SDavid du Colombier 	Istack *is;
218*426d2b71SDavid du Colombier 
219*426d2b71SDavid du Colombier 	for(is=istack; is && !is->b; is=is->next)
220*426d2b71SDavid du Colombier 		;
221*426d2b71SDavid du Colombier 	if(is)
222*426d2b71SDavid du Colombier 		return fmtprint(f, "%S:%d", is->name, is->lineno);
223*426d2b71SDavid du Colombier 	else
224*426d2b71SDavid du Colombier 		return fmtprint(f, "<no input>");
225*426d2b71SDavid du Colombier }
226*426d2b71SDavid du Colombier 
227*426d2b71SDavid du Colombier void
setlinenumber(Rune * s,int n)228*426d2b71SDavid du Colombier setlinenumber(Rune *s, int n)
229*426d2b71SDavid du Colombier {
230*426d2b71SDavid du Colombier 	Istack *is;
231*426d2b71SDavid du Colombier 
232*426d2b71SDavid du Colombier 	for(is=istack; is && !is->name; is=is->next)
233*426d2b71SDavid du Colombier 		;
234*426d2b71SDavid du Colombier 	if(is){
235*426d2b71SDavid du Colombier 		if(s){
236*426d2b71SDavid du Colombier 			free(is->name);
237*426d2b71SDavid du Colombier 			is->name = erunestrdup(s);
238*426d2b71SDavid du Colombier 		}
239*426d2b71SDavid du Colombier 		is->lineno = n;
240*426d2b71SDavid du Colombier 	}
241*426d2b71SDavid du Colombier }
242