Blob


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