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 "cpp.h"
4
 
5
#define	NSTAK	1024
6
#define	SGN	0
7
#define	UNS	1
8
#define	UND	2
9
 
10
#define	UNSMARK	0x1000
11
 
12
struct value {
13
	long	val;
14
	int	type;
15
};
16
 
17
/* conversion types */
18
#define	RELAT	1
19
#define	ARITH	2
20
#define	LOGIC	3
21
#define	SPCL	4
22
#define	SHIFT	5
23
#define	UNARY	6
24
 
25
/* operator priority, arity, and conversion type, indexed by tokentype */
26
const struct pri {
27
	char	pri;
28
	char	arity;
29
	char	ctype;
30
} priority[] = {
31
	{ 0, 0, 0 },		/* END */
32
	{ 0, 0, 0 },		/* UNCLASS */
33
	{ 0, 0, 0 },		/* NAME */
34
	{ 0, 0, 0 },		/* NUMBER */
35
	{ 0, 0, 0 },		/* STRING */
36
	{ 0, 0, 0 },		/* CCON */
37
	{ 0, 0, 0 },		/* NL */
38
	{ 0, 0, 0 },		/* WS */
39
	{ 0, 0, 0 },		/* DSHARP */
40
	{ 11, 2, RELAT },	/* EQ */
41
	{ 11, 2, RELAT },	/* NEQ */
42
	{ 12, 2, RELAT },	/* LEQ */
43
	{ 12, 2, RELAT },	/* GEQ */
44
	{ 13, 2, SHIFT },	/* LSH */
45
	{ 13, 2, SHIFT },	/* RSH */
46
	{ 7, 2, LOGIC },	/* LAND */
47
	{ 6, 2, LOGIC },	/* LOR */
48
	{ 0, 0, 0 },		/* PPLUS */
49
	{ 0, 0, 0 },		/* MMINUS */
50
	{ 0, 0, 0 },		/* ARROW */
51
	{ 0, 0, 0 },		/* SBRA */
52
	{ 0, 0, 0 },		/* SKET */
53
	{ 3, 0, 0 },		/* LP */
54
	{ 3, 0, 0 },		/* RP */
55
	{ 0, 0, 0 },		/* DOT */
56
	{ 10, 2, ARITH },	/* AND */
57
	{ 15, 2, ARITH },	/* STAR */
58
	{ 14, 2, ARITH },	/* PLUS */
59
	{ 14, 2, ARITH },	/* MINUS */
60
	{ 16, 1, UNARY },	/* TILDE */
61
	{ 16, 1, UNARY },	/* NOT */
62
	{ 15, 2, ARITH },	/* SLASH */
63
	{ 15, 2, ARITH },	/* PCT */
64
	{ 12, 2, RELAT },	/* LT */
65
	{ 12, 2, RELAT },	/* GT */
66
	{ 9, 2, ARITH },	/* CIRC */
67
	{ 8, 2, ARITH },	/* OR */
68
	{ 5, 2, SPCL },		/* QUEST */
69
	{ 5, 2, SPCL },		/* COLON */
70
	{ 0, 0, 0 },		/* ASGN */
71
	{ 4, 2, 0 },		/* COMMA */
72
	{ 0, 0, 0 },		/* SHARP */
73
	{ 0, 0, 0 },		/* SEMIC */
74
	{ 0, 0, 0 },		/* CBRA */
75
	{ 0, 0, 0 },		/* CKET */
76
	{ 0, 0, 0 },		/* ASPLUS */
77
 	{ 0, 0, 0 },		/* ASMINUS */
78
 	{ 0, 0, 0 },		/* ASSTAR */
79
 	{ 0, 0, 0 },		/* ASSLASH */
80
 	{ 0, 0, 0 },		/* ASPCT */
81
 	{ 0, 0, 0 },		/* ASCIRC */
82
 	{ 0, 0, 0 },		/* ASLSH */
83
	{ 0, 0, 0 },		/* ASRSH */
84
 	{ 0, 0, 0 },		/* ASOR */
85
 	{ 0, 0, 0 },		/* ASAND */
86
	{ 0, 0, 0 },		/* ELLIPS */
87
	{ 0, 0, 0 },		/* DSHARP1 */
88
	{ 0, 0, 0 },		/* NAME1 */
89
	{ 16, 1, UNARY },	/* DEFINED */
90
	{ 16, 0, UNARY },	/* UMINUS */
91
};
92
 
93
int	evalop(struct pri);
94
struct	value tokval(Token *);
95
struct value vals[NSTAK + 1], *vp;
96
enum toktype ops[NSTAK + 1], *op;
97
 
98
/*
99
 * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
100
 */
101
long
102
eval(Tokenrow *trp, int kw)
103
{
104
	Token *tp;
105
	Nlist *np;
106
	int ntok, rand;
107
 
108
	trp->tp++;
109
	if (kw==KIFDEF || kw==KIFNDEF) {
110
		if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) {
111
			error(ERROR, "Syntax error in #ifdef/#ifndef");
112
			return 0;
113
		}
114
		np = lookup(trp->tp, 0);
115
		return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC));
116
	}
117
	ntok = trp->tp - trp->bp;
118
	kwdefined->val = KDEFINED;	/* activate special meaning of defined */
119
	expandrow(trp, "<if>", Notinmacro);
120
	kwdefined->val = NAME;
121
	vp = vals;
122
	op = ops;
123
	*op++ = END;
124
	for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) {
125
		if(op >= ops + NSTAK)
126
			sysfatal("cpp: can't evaluate #if: increase NSTAK");
127
		switch(tp->type) {
128
		case WS:
129
		case NL:
130
			continue;
131
 
132
		/* nilary */
133
		case NAME:
134
		case NAME1:
135
		case NUMBER:
136
		case CCON:
137
		case STRING:
138
			if (rand)
139
				goto syntax;
140
			*vp++ = tokval(tp);
141
			rand = 1;
142
			continue;
143
 
144
		/* unary */
145
		case DEFINED:
146
		case TILDE:
147
		case NOT:
148
			if (rand)
149
				goto syntax;
150
			*op++ = tp->type;
151
			continue;
152
 
153
		/* unary-binary */
154
		case PLUS: case MINUS: case STAR: case AND:
155
			if (rand==0) {
156
				if (tp->type==MINUS)
157
					*op++ = UMINUS;
158
				if (tp->type==STAR || tp->type==AND) {
159
					error(ERROR, "Illegal operator * or & in #if/#elif");
160
					return 0;
161
				}
162
				continue;
163
			}
164
			/* flow through */
165
 
166
		/* plain binary */
167
		case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:
168
		case LAND: case LOR: case SLASH: case PCT:
169
		case LT: case GT: case CIRC: case OR: case QUEST:
170
		case COLON: case COMMA:
171
			if (rand==0)
172
				goto syntax;
173
			if (evalop(priority[tp->type])!=0)
174
				return 0;
175
			*op++ = tp->type;
176
			rand = 0;
177
			continue;
178
 
179
		case LP:
180
			if (rand)
181
				goto syntax;
182
			*op++ = LP;
183
			continue;
184
 
185
		case RP:
186
			if (!rand)
187
				goto syntax;
188
			if (evalop(priority[RP])!=0)
189
				return 0;
190
			if (op<=ops || op[-1]!=LP) {
191
				goto syntax;
192
			}
193
			op--;
194
			continue;
195
 
196
		default:
197
			error(ERROR,"Bad operator (%t) in #if/#elif", tp);
198
			return 0;
199
		}
200
	}
201
	if (rand==0)
202
		goto syntax;
203
	if (evalop(priority[END])!=0)
204
		return 0;
205
	if (op!=&ops[1] || vp!=&vals[1]) {
206
		error(ERROR, "Botch in #if/#elif");
207
		return 0;
208
	}
209
	if (vals[0].type==UND)
210
		error(ERROR, "Undefined expression value");
211
	return vals[0].val;
212
syntax:
213
	error(ERROR, "Syntax error in #if/#elif");
214
	return 0;
215
}
216
 
217
int
218
evalop(struct pri pri)
219
{
220
	struct value v1, v2;
221
	long rv1, rv2;
222
	int rtype, oper;
223
 
224
	rv2=0;
225
	rtype=0;
226
	while (pri.pri < priority[op[-1]].pri) {
227
		oper = *--op;
228
		if (priority[oper].arity==2) {
229
			v2 = *--vp;
230
			rv2 = v2.val;
231
		}
232
		v1 = *--vp;
233
		rv1 = v1.val;
234
		switch (priority[oper].ctype) {
235
		case 0:
236
		default:
237
			error(WARNING, "Syntax error in #if/#endif");
238
			return 1;
239
		case ARITH:
240
		case RELAT:
241
			if (v1.type==UNS || v2.type==UNS)
242
				rtype = UNS;
243
			else
244
				rtype = SGN;
245
			if (v1.type==UND || v2.type==UND)
246
				rtype = UND;
247
			if (priority[oper].ctype==RELAT && rtype==UNS) {
248
				oper |= UNSMARK;
249
				rtype = SGN;
250
			}
251
			break;
252
		case SHIFT:
253
			if (v1.type==UND || v2.type==UND)
254
				rtype = UND;
255
			else
256
				rtype = v1.type;
257
			if (rtype==UNS)
258
				oper |= UNSMARK;
259
			break;
260
		case UNARY:
261
			rtype = v1.type;
262
			break;
263
		case LOGIC:
264
		case SPCL:
265
			break;
266
		}
267
		switch (oper) {
268
		case EQ: case EQ|UNSMARK:
269
			rv1 = rv1==rv2; break;
270
		case NEQ: case NEQ|UNSMARK:
271
			rv1 = rv1!=rv2; break;
272
		case LEQ:
273
			rv1 = rv1<=rv2; break;
274
		case GEQ:
275
			rv1 = rv1>=rv2; break;
276
		case LT:
277
			rv1 = rv1<rv2; break;
278
		case GT:
279
			rv1 = rv1>rv2; break;
280
		case LEQ|UNSMARK:
281
			rv1 = (unsigned long)rv1<=rv2; break;
282
		case GEQ|UNSMARK:
283
			rv1 = (unsigned long)rv1>=rv2; break;
284
		case LT|UNSMARK:
285
			rv1 = (unsigned long)rv1<rv2; break;
286
		case GT|UNSMARK:
287
			rv1 = (unsigned long)rv1>rv2; break;
288
		case LSH:
289
			rv1 <<= rv2; break;
290
		case LSH|UNSMARK:
291
			rv1 = (unsigned long)rv1<<rv2; break;
292
		case RSH:
293
			rv1 >>= rv2; break;
294
		case RSH|UNSMARK:
295
			rv1 = (unsigned long)rv1>>rv2; break;
296
		case LAND:
297
			rtype = UND;
298
			if (v1.type==UND)
299
				break;
300
			if (rv1!=0) {
301
				if (v2.type==UND)
302
					break;
303
				rv1 = rv2!=0;
304
			} else
305
				rv1 = 0;
306
			rtype = SGN;
307
			break;
308
		case LOR:
309
			rtype = UND;
310
			if (v1.type==UND)
311
				break;
312
			if (rv1==0) {
313
				if (v2.type==UND)
314
					break;
315
				rv1 = rv2!=0;
316
			} else
317
				rv1 = 1;
318
			rtype = SGN;
319
			break;
320
		case AND:
321
			rv1 &= rv2; break;
322
		case STAR:
323
			rv1 *= rv2; break;
324
		case PLUS:
325
			rv1 += rv2; break;
326
		case MINUS:
327
			rv1 -= rv2; break;
328
		case UMINUS:
329
			if (v1.type==UND)
330
				rtype = UND;
331
			rv1 = -rv1; break;
332
		case OR:
333
			rv1 |= rv2; break;
334
		case CIRC:
335
			rv1 ^= rv2; break;
336
		case TILDE:
337
			rv1 = ~rv1; break;
338
		case NOT:
339
			rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
340
		case SLASH:
341
			if (rv2==0) {
342
				rtype = UND;
343
				break;
344
			}
345
			if (rtype==UNS)
346
				rv1 /= (unsigned long)rv2;
347
			else
348
				rv1 /= rv2;
349
			break;
350
		case PCT:
351
			if (rv2==0) {
352
				rtype = UND;
353
				break;
354
			}
355
			if (rtype==UNS)
356
				rv1 %= (unsigned long)rv2;
357
			else
358
				rv1 %= rv2;
359
			break;
360
		case COLON:
361
			if (op[-1] != QUEST)
362
				error(ERROR, "Bad ?: in #if/endif");
363
			else {
364
				op--;
365
				if ((--vp)->val==0)
366
					v1 = v2;
367
				rtype = v1.type;
368
				rv1 = v1.val;
369
			}
370
			break;
371
		case DEFINED:
372
			break;
373
		default:
374
			error(ERROR, "Eval botch (unknown operator)");
375
			return 1;
376
		}
377
		v1.val = rv1;
378
		v1.type = rtype;
379
		*vp++ = v1;
380
	}
381
	return 0;
382
}
383
 
384
struct value
385
tokval(Token *tp)
386
{
387
	struct value v;
388
	Nlist *np;
389
	int i, base, c, longcc;
390
	unsigned long n;
391
	Rune r;
392
	uchar *p;
393
 
394
	v.type = SGN;
395
	v.val = 0;
396
	switch (tp->type) {
397
 
398
	case NAME:
399
		v.val = 0;
400
		break;
401
 
402
	case NAME1:
403
		if ((np = lookup(tp, 0)) && np->flag&(ISDEFINED|ISMAC))
404
			v.val = 1;
405
		break;
406
 
407
	case NUMBER:
408
		n = 0;
409
		base = 10;
410
		p = tp->t;
411
		c = p[tp->len];
412
		p[tp->len] = '\0';
413
		if (*p=='0') {
414
			base = 8;
415
			if (p[1]=='x' || p[1]=='X') {
416
				base = 16;
417
				p++;
418
			}
419
			p++;
420
		}
421
		for (;; p++) {
422
			if ((i = digit(*p)) < 0)
423
				break;
424
			if (i>=base)
425
				error(WARNING,
426
				  "Bad digit in number %t", tp);
427
			n *= base;
428
			n += i;
429
		}
430
		if (n>=0x80000000 && base!=10)
431
			v.type = UNS;
432
		for (; *p; p++) {
433
			if (*p=='u' || *p=='U')
434
				v.type = UNS;
435
			else if (*p=='l' || *p=='L')
436
				{}
437
			else {
438
				error(ERROR,
439
				  "Bad number %t in #if/#elif", tp);
440
				break;
441
			}
442
		}
443
		v.val = n;
444
		tp->t[tp->len] = c;
445
		break;
446
 
447
	case CCON:
448
		n = 0;
449
		p = tp->t;
450
		longcc = 0;
451
		if (*p=='L') {
452
			p += 1;
453
			longcc = 1;
454
		}
455
		p += 1;
456
		if (*p=='\\') {
457
			p += 1;
458
			if ((i = digit(*p))>=0 && i<=7) {
459
				n = i;
460
				p += 1;
461
				if ((i = digit(*p))>=0 && i<=7) {
462
					p += 1;
463
					n <<= 3;
464
					n += i;
465
					if ((i = digit(*p))>=0 && i<=7) {
466
						p += 1;
467
						n <<= 3;
468
						n += i;
469
					}
470
				}
471
			} else if (*p=='x') {
472
				p += 1;
473
				while ((i = digit(*p))>=0 && i<=15) {
474
					p += 1;
475
					n <<= 4;
476
					n += i;
477
				}
478
			} else {
479
				static char cvcon[]
480
				  = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\";
481
				for (i=0; i<sizeof(cvcon); i+=2) {
482
					if (*p == cvcon[i]) {
483
						n = cvcon[i+1];
484
						break;
485
					}
486
				}
487
				p += 1;
488
				if (i>=sizeof(cvcon))
489
					error(WARNING,
490
					 "Undefined escape in character constant");
491
			}
492
		} else if (*p=='\'')
493
			error(ERROR, "Empty character constant");
494
		else {
495
			i = chartorune(&r, (char*)p);
496
			n = r;
497
			p += i;
498
			if (i>1 && longcc==0)
499
				error(WARNING, "Undefined character constant");
500
		}
501
		if (*p!='\'')
502
			error(WARNING, "Multibyte character constant undefined");
503
		else if (n>127 && longcc==0)
504
			error(WARNING, "Character constant taken as not signed");
505
		v.val = n;
506
		break;
507
 
508
	case STRING:
509
		error(ERROR, "String in #if/#elif");
510
		break;
511
	}
512
	return v;
513
}
514
 
515
int
516
digit(int i)
517
{
518
	if ('0'<=i && i<='9')
519
		i -= '0';
520
	else if ('a'<=i && i<='f')
521
		i -= 'a'-10;
522
	else if ('A'<=i && i<='F')
523
		i -= 'A'-10;
524
	else
525
		i = -1;
526
	return i;
527
}