Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
#include "e.h"
2
#include "y.tab.h"
3
#include <ctype.h>
4
#include <errno.h>
5
 
6
Infile	infile[10];
7
Infile	*curfile = infile;
8
 
9
#define	MAXSRC	50
10
Src	src[MAXSRC];	/* input source stack */
11
Src	*srcp	= src;
12
 
13
extern int getarg(char *);
14
extern	void eprint(void);
15
 
16
void pushsrc(int type, char *ptr)	/* new input source */
17
{
18
	if (++srcp >= src + MAXSRC)
19
		ERROR "inputs nested too deep" FATAL;
20
	srcp->type = type;
21
	srcp->sp = ptr;
22
	if (dbg > 1) {
23
		printf("\n%3d ", srcp - src);
24
		switch (srcp->type) {
25
		case File:
26
			printf("push file %s\n", ((Infile *)ptr)->fname);
27
			break;
28
		case Macro:
29
			printf("push macro <%s>\n", ptr);
30
			break;
31
		case Char:
32
			printf("push char <%c>\n", *ptr);
33
			break;
34
		case String:
35
			printf("push string <%s>\n", ptr);
36
			break;
37
		case Free:
38
			printf("push free <%s>\n", ptr);
39
			break;
40
		default:
41
			ERROR "pushed bad type %d\n", srcp->type FATAL;
42
		}
43
	}
44
}
45
 
46
void popsrc(void)	/* restore an old one */
47
{
48
	if (srcp <= src)
49
		ERROR "too many inputs popped" FATAL;
50
	if (dbg > 1) {
51
		printf("%3d ", srcp - src);
52
		switch (srcp->type) {
53
		case File:
54
			printf("pop file\n");
55
			break;
56
		case Macro:
57
			printf("pop macro\n");
58
			break;
59
		case Char:
60
			printf("pop char <%c>\n", *srcp->sp);
61
			break;
62
		case String:
63
			printf("pop string\n");
64
			break;
65
		case Free:
66
			printf("pop free\n");
67
			break;
68
		default:
69
			ERROR "pop weird input %d\n", srcp->type FATAL;
70
		}
71
	}
72
	srcp--;
73
}
74
 
75
Arg	args[10];	/* argument frames */
76
Arg	*argfp = args;	/* frame pointer */
77
int	argcnt;		/* number of arguments seen so far */
78
 
79
void dodef(tbl *stp)	/* collect args and switch input to defn */
80
{
81
	int i, len;
82
	char *p;
83
	Arg *ap;
84
 
85
	ap = argfp+1;
86
	if (ap >= args+10)
87
		ERROR "more than arguments\n" FATAL;
88
	argcnt = 0;
89
	if (input() != '(')
90
		ERROR "disaster in dodef\n"FATAL;
91
	if (ap->argval == 0)
92
		ap->argval = malloc(1000);
93
	for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
94
		ap->argstk[argcnt++] = p;
95
		if (input() == ')')
96
			break;
97
	}
98
	for (i = argcnt; i < MAXARGS; i++)
99
		ap->argstk[i] = "";
100
	if (dbg)
101
		for (i = 0; i < argcnt; i++)
102
			printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
103
	argfp = ap;
104
	pushsrc(Macro, stp->cval);
105
}
106
 
107
getarg(char *p)	/* pick up single argument, store in p, return length */
108
{
109
	int n, c, npar;
110
 
111
	n = npar = 0;
112
	for ( ;; ) {
113
		c = input();
114
		if (c == EOF)
115
			ERROR "end of file in getarg!\n" FATAL;
116
		if (npar == 0 && (c == ',' || c == ')'))
117
			break;
118
		if (c == '"')	/* copy quoted stuff intact */
119
			do {
120
				*p++ = c;
121
				n++;
122
			} while ((c = input()) != '"' && c != EOF);
123
		else if (c == '(')
124
			npar++;
125
		else if (c == ')')
126
			npar--;
127
		n++;
128
		*p++ = c;
129
	}
130
	*p = 0;
131
	unput(c);
132
	return(n + 1);
133
}
134
 
135
#define	PBSIZE	2000
136
char	pbuf[PBSIZE];		/* pushback buffer */
137
char	*pb	= pbuf-1;	/* next pushed back character */
138
 
139
char	ebuf[200];		/* collect input here for error reporting */
140
char	*ep	= ebuf;
141
 
142
input(void)
143
{
144
	register int c = 0;
145
 
146
  loop:
147
	switch (srcp->type) {
148
	case File:
149
		c = getc(curfile->fin);
150
		if (c == EOF) {
151
			if (curfile == infile)
152
				break;
153
			if (curfile->fin != stdin) {
154
				fclose(curfile->fin);
155
				free(curfile->fname);	/* assumes allocated */
156
			}
157
			curfile--;
158
			printf(".lf %d %s\n", curfile->lineno, curfile->fname);
159
			popsrc();
160
			goto loop;
161
		}
162
		if (c == '\n')
163
			curfile->lineno++;
164
		break;
165
	case Char:
166
		if (pb >= pbuf) {
167
			c = *pb--;
168
			popsrc();
169
			break;
170
		} else {	/* can't happen? */
171
			popsrc();
172
			goto loop;
173
		}
174
	case String:
175
		c = *srcp->sp++;
176
		if (c == '\0') {
177
			popsrc();
178
			goto loop;
179
		} else {
180
			if (*srcp->sp == '\0')	/* empty, so pop */
181
				popsrc();
182
			break;
183
		}
184
	case Macro:
185
		c = *srcp->sp++;
186
		if (c == '\0') {
187
			if (--argfp < args)
188
				ERROR "argfp underflow" FATAL;
189
			popsrc();
190
			goto loop;
191
		} else if (c == '$' && isdigit(*srcp->sp)) {
192
			int n = 0;
193
			while (isdigit(*srcp->sp))
194
				n = 10 * n + *srcp->sp++ - '0';
195
			if (n > 0 && n <= MAXARGS)
196
				pushsrc(String, argfp->argstk[n-1]);
197
			goto loop;
198
		}
199
		break;
200
	case Free:	/* free string */
201
		free(srcp->sp);
202
		popsrc();
203
		goto loop;
204
	}
205
	if (ep >= ebuf + sizeof ebuf)
206
		ep = ebuf;
207
	*ep++ = c;
208
	return c;
209
}
210
 
211
 
212
unput(int c)
213
{
214
	if (++pb >= pbuf + sizeof pbuf)
215
		ERROR "pushback overflow\n"FATAL;
216
	if (--ep < ebuf)
217
		ep = ebuf + sizeof(ebuf) - 1;
218
	*pb = c;
219
	pushsrc(Char, pb);
220
	return c;
221
}
222
 
223
void pbstr(char *s)
224
{
225
	pushsrc(String, s);
226
}
227
 
228
void error(int die, char *s)
229
{
230
	extern char *cmdname;
231
 
232
	if (synerr)
233
		return;
234
	fprintf(stderr, "%s: ", cmdname);
235
	fprintf(stderr, s);
236
	if (errno > 0)
237
		perror("???");
238
	if (curfile->fin)
239
		fprintf(stderr, " near %s:%d",
240
			curfile->fname, curfile->lineno+1);
241
	fprintf(stderr, "\n");
242
	eprint();
243
	synerr = 1;
244
	errno = 0;
245
	if (die) {
246
		if (dbg)
247
			abort();
248
		else
249
			exit(1);
250
	}
251
}
252
 
253
void yyerror(char *s)
254
{
255
	error(0, s);	/* temporary */
256
}
257
 
258
char errbuf[200];
259
 
260
void eprint(void)	/* try to print context around error */
261
{
262
	char *p, *q;
263
 
264
	if (ep == ebuf)
265
		return;				/* no context */
266
	p = ep - 1;
267
	if (p > ebuf && *p == '\n')
268
		p--;
269
	for ( ; p >= ebuf && *p != '\n'; p--)
270
		;
271
	while (*p == '\n')
272
		p++;
273
	fprintf(stderr, " context is\n\t");
274
	for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
275
		;
276
	while (p < q)
277
		putc(*p++, stderr);
278
	fprintf(stderr, " >>> ");
279
	while (p < ep)
280
		putc(*p++, stderr);
281
	fprintf(stderr, " <<< ");
282
	while (pb >= pbuf)
283
		putc(*pb--, stderr);
284
	if (curfile->fin)
285
		fgets(ebuf, sizeof ebuf, curfile->fin);
286
	fprintf(stderr, "%s", ebuf);
287
	pbstr("\n.EN\n");	/* safety first */
288
	ep = ebuf;
289
}