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 <u.h>
2
#include <libc.h>
3
#include <stdio.h>
4
#include "cpp.h"
5
 
6
#define	OUTS	16384
7
char	outbuf[OUTS];
8
char	*outp = outbuf;
9
Source	*cursource;
10
int	nerrs;
11
struct	token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
12
char	*curtime;
13
int	incdepth;
14
int	ifdepth;
15
int	ifsatisfied[NIF];
16
int	skipping;
17
 
18
int
19
main(int argc, char **argv)
20
{
21
	Tokenrow tr;
22
	long t;
23
	char ebuf[BUFSIZ];
24
 
25
	setbuf(stderr, ebuf);
26
	t = time(NULL);
27
	curtime = ctime(t);
28
	maketokenrow(3, &tr);
29
	expandlex();
30
	setup(argc, argv);
31
	fixlex();
32
	iniths();
33
	genline();
34
	process(&tr);
35
	flushout();
36
	fflush(stderr);
37
	exits(nerrs? "errors" : 0);
38
	return 0;
39
}
40
 
41
void
42
process(Tokenrow *trp)
43
{
44
	int anymacros = 0;
45
 
46
	for (;;) {
47
		if (trp->tp >= trp->lp) {
48
			trp->tp = trp->lp = trp->bp;
49
			outp = outbuf;
50
			anymacros |= gettokens(trp, 1);
51
			trp->tp = trp->bp;
52
		}
53
		if (trp->tp->type == END) {
54
			if (--incdepth>=0) {
55
				if (cursource->ifdepth)
56
					error(ERROR,
57
					 "Unterminated conditional in #include");
58
				unsetsource();
59
				cursource->line += cursource->lineinc;
60
				trp->tp = trp->lp;
61
				genline();
62
				continue;
63
			}
64
			if (ifdepth)
65
				error(ERROR, "Unterminated #if/#ifdef/#ifndef");
66
			break;
67
		}
68
		if (trp->tp->type==SHARP) {
69
			trp->tp += 1;
70
			control(trp);
71
		} else if (!skipping && anymacros)
72
			expandrow(trp, NULL, Notinmacro);
73
		if (skipping)
74
			setempty(trp);
75
		puttokens(trp);
76
		anymacros = 0;
77
		cursource->line += cursource->lineinc;
78
		if (cursource->lineinc>1) {
79
			genline();
80
		}
81
	}
82
}
83
 
84
void
85
control(Tokenrow *trp)
86
{
87
	Nlist *np;
88
	Token *tp;
89
 
90
	tp = trp->tp;
91
	if (tp->type!=NAME) {
92
		if (tp->type==NUMBER)
93
			goto kline;
94
		if (tp->type != NL)
95
			error(ERROR, "Unidentifiable control line");
96
		return;			/* else empty line */
97
	}
98
	if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
99
		error(WARNING, "Unknown preprocessor control %t", tp);
100
		return;
101
	}
102
	if (skipping) {
103
		if ((np->flag&ISKW)==0)
104
			return;
105
		switch (np->val) {
106
		case KENDIF:
107
			if (--ifdepth<skipping)
108
				skipping = 0;
109
			--cursource->ifdepth;
110
			setempty(trp);
111
			return;
112
 
113
		case KIFDEF:
114
		case KIFNDEF:
115
		case KIF:
116
			if (++ifdepth >= NIF)
117
				error(FATAL, "#if too deeply nested");
118
			++cursource->ifdepth;
119
			return;
120
 
121
		case KELIF:
122
		case KELSE:
123
			if (ifdepth<=skipping)
124
				break;
125
			return;
126
 
127
		default:
128
			return;
129
		}
130
	}
131
	switch (np->val) {
132
	case KDEFINE:
133
		dodefine(trp);
134
		break;
135
 
136
	case KUNDEF:
137
		tp += 1;
138
		if (tp->type!=NAME || trp->lp - trp->bp != 4) {
139
			error(ERROR, "Syntax error in #undef");
140
			break;
141
		}
142
		if ((np = lookup(tp, 0))) {
143
			if (np->flag&ISUNCHANGE) {
144
				error(ERROR, "#defined token %t can't be undefined", tp);
145
				return;
146
			}
147
			np->flag &= ~ISDEFINED;
148
		}
149
		break;
150
 
151
	case KPRAGMA:
152
		return;
153
 
154
	case KIFDEF:
155
	case KIFNDEF:
156
	case KIF:
157
		if (++ifdepth >= NIF)
158
			error(FATAL, "#if too deeply nested");
159
		++cursource->ifdepth;
160
		ifsatisfied[ifdepth] = 0;
161
		if (eval(trp, np->val))
162
			ifsatisfied[ifdepth] = 1;
163
		else
164
			skipping = ifdepth;
165
		break;
166
 
167
	case KELIF:
168
		if (ifdepth==0) {
169
			error(ERROR, "#elif with no #if");
170
			return;
171
		}
172
		if (ifsatisfied[ifdepth]==2)
173
			error(ERROR, "#elif after #else");
174
		if (eval(trp, np->val)) {
175
			if (ifsatisfied[ifdepth])
176
				skipping = ifdepth;
177
			else {
178
				skipping = 0;
179
				ifsatisfied[ifdepth] = 1;
180
			}
181
		} else
182
			skipping = ifdepth;
183
		break;
184
 
185
	case KELSE:
186
		if (ifdepth==0 || cursource->ifdepth==0) {
187
			error(ERROR, "#else with no #if");
188
			return;
189
		}
190
		if (ifsatisfied[ifdepth]==2)
191
			error(ERROR, "#else after #else");
192
		if (trp->lp - trp->bp != 3)
193
			error(ERROR, "Syntax error in #else");
194
		skipping = ifsatisfied[ifdepth]? ifdepth: 0;
195
		ifsatisfied[ifdepth] = 2;
196
		break;
197
 
198
	case KENDIF:
199
		if (ifdepth==0 || cursource->ifdepth==0) {
200
			error(ERROR, "#endif with no #if");
201
			return;
202
		}
203
		--ifdepth;
204
		--cursource->ifdepth;
205
		if (trp->lp - trp->bp != 3)
206
			error(WARNING, "Syntax error in #endif");
207
		break;
208
 
209
	case KERROR:
210
		trp->tp = tp+1;
211
		error(ERROR, "#error directive: %r", trp);
212
		break;
213
 
214
	case KWARNING:
215
		trp->tp = tp+1;
216
		error(WARNING, "#warning directive: %r", trp);
217
		break;
218
 
219
	case KLINE:
220
		trp->tp = tp+1;
221
		expandrow(trp, "<line>", Notinmacro);
222
		tp = trp->bp+2;
223
	kline:
224
		if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
225
		 || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
226
			error(ERROR, "Syntax error in #line");
227
			return;
228
		}
229
		cursource->line = atol((char*)tp->t)-1;
230
		if (cursource->line<0 || cursource->line>=32768)
231
			error(WARNING, "#line specifies number out of range");
232
		tp = tp+1;
233
		if (tp+1<trp->lp)
234
			cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
235
		return;
236
 
237
	case KDEFINED:
238
		error(ERROR, "Bad syntax for control line");
239
		break;
240
 
241
	case KINCLUDE:
242
		doinclude(trp);
243
		trp->lp = trp->bp;
244
		return;
245
 
246
	case KEVAL:
247
		eval(trp, np->val);
248
		break;
249
 
250
	default:
251
		error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
252
		break;
253
	}
254
	setempty(trp);
255
	return;
256
}
257
 
258
void *
259
dorealloc(void *ptr, int size)
260
{
261
	void *p = realloc(ptr, size);
262
 
263
	if (p==NULL)
264
		error(FATAL, "Out of memory from realloc");
265
	return p;
266
}
267
 
268
void *
269
domalloc(int size)
270
{
271
	void *p = malloc(size);
272
 
273
	if (p==NULL)
274
		error(FATAL, "Out of memory from malloc");
275
	return p;
276
}
277
 
278
void
279
dofree(void *p)
280
{
281
	free(p);
282
}
283
 
284
void
285
error(enum errtype type, char *string, ...)
286
{
287
	va_list ap;
288
	char *cp, *ep;
289
	Token *tp;
290
	Tokenrow *trp;
291
	Source *s;
292
	int i;
293
	void *p;
294
 
295
	fprintf(stderr, "cpp: ");
296
	for (s=cursource; s; s=s->next)
297
		if (*s->filename)
298
			fprintf(stderr, "%s:%d ", s->filename, s->line);
299
	va_start(ap, string);
300
	for (ep=string; *ep; ep++) {
301
		if (*ep=='%') {
302
			switch (*++ep) {
303
 
304
			case 's':
305
				cp = va_arg(ap, char *);
306
				fprintf(stderr, "%s", cp);
307
				break;
308
			case 'd':
309
				i = va_arg(ap, int);
310
				fprintf(stderr, "%d", i);
311
				break;
312
			case 'p':
313
				p = va_arg(ap, void *);
314
				fprintf(stderr, "%p", p);
315
				break;
316
			case 't':
317
				tp = va_arg(ap, Token *);
318
				fprintf(stderr, "%.*s", tp->len, tp->t);
319
				break;
320
 
321
			case 'r':
322
				trp = va_arg(ap, Tokenrow *);
323
				for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
324
					if (tp>trp->tp && tp->wslen)
325
						fputc(' ', stderr);
326
					fprintf(stderr, "%.*s", tp->len, tp->t);
327
				}
328
				break;
329
 
330
			default:
331
				fputc(*ep, stderr);
332
				break;
333
			}
334
		} else
335
			fputc(*ep, stderr);
336
	}
337
	va_end(ap);
338
	fputc('\n', stderr);
339
	if (type==FATAL)
340
		exits("error");
341
	if (type!=WARNING)
342
		nerrs = 1;
343
	fflush(stderr);
344
}