Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Read input files.
3
 */
4
#include "a.h"
5
 
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
};
20
 
21
Istack *istack;
22
Istack *ibottom;
23
 
24
static void
25
setname(void)
26
{
27
	Rune *r, *p;
28
 
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
}
39
 
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
}
50
 
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
}
61
 
62
int
63
_inputfile(Rune *s, void (*push)(Istack*))
64
{
65
	Istack *is;
66
	Biobuf *b;
67
	char *t;
68
 
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
}
83
 
84
int
85
pushinputfile(Rune *s)
86
{
87
	return _inputfile(s, ipush);
88
}
89
 
90
int
91
queueinputfile(Rune *s)
92
{
93
	return _inputfile(s, iqueue);
94
}
95
 
96
int
97
_inputstdin(void (*push)(Istack*))
98
{	
99
	Biobuf *b;
100
	Istack *is;
101
 
102
	if((b = Bopen("/dev/null", OREAD)) == nil){
103
		fprint(2, "%s: open /dev/null: %r\n", argv0);
104
		return -1;
105
	}
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;
113
}
114
 
115
int
116
pushstdin(void)
117
{
118
	return _inputstdin(ipush);
119
}
120
 
121
int
122
queuestdin(void)
123
{
124
	return _inputstdin(iqueue);
125
}
126
 
127
void
128
_inputstring(Rune *s, void (*push)(Istack*))
129
{
130
	Istack *is;
131
 
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);
137
}
138
 
139
void
140
pushinputstring(Rune *s)
141
{
142
	_inputstring(s, ipush);
143
}
144
 
145
 
146
void
147
inputnotify(void (*fn)(void))
148
{
149
	if(istack)
150
		istack->fn = fn;
151
}
152
 
153
int
154
popinput(void)
155
{
156
	Istack *is;
157
 
158
	is = istack;
159
	if(is == nil)
160
		return 0;
161
 
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;
172
}
173
 
174
int
175
getrune(void)
176
{
177
	Rune r;
178
	int c;
179
 
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;
189
		}
190
		r = *istack->p++;
191
	}else if(istack->b){
192
		if((c = Bgetrune(istack->b)) < 0){
193
			popinput();
194
			goto top;
195
		}
196
		r = c;
197
	}else{
198
		r = 0;
199
		sysfatal("getrune - can't happen");
200
	}
201
	if(r == '\n')
202
		istack->lineno++;	
203
	return r;
204
}
205
 
206
void
207
ungetrune(Rune r)
208
{
209
	if(istack == nil || istack->nunget >= nelem(istack->unget))
210
		pushinputstring(L(""));
211
	istack->unget[istack->nunget++] = r;
212
}
213
 
214
int
215
linefmt(Fmt *f)
216
{
217
	Istack *is;
218
 
219
	for(is=istack; is && !is->b; is=is->next)
220
		;
221
	if(is)
222
		return fmtprint(f, "%S:%d", is->name, is->lineno);
223
	else
224
		return fmtprint(f, "<no input>");
225
}
226
 
227
void
228
setlinenumber(Rune *s, int n)
229
{
230
	Istack *is;
231
 
232
	for(is=istack; is && !is->name; is=is->next)
233
		;
234
	if(is){
235
		if(s){
236
			free(is->name);
237
			is->name = erunestrdup(s);
238
		}
239
		is->lineno = n;
240
	}
241
}