GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: libexec/tradcpp/eval.c Lines: 0 319 0.0 %
Date: 2017-11-13 Branches: 0 265 0.0 %

Line Branch Exec Source
1
/*-
2
 * Copyright (c) 2010 The NetBSD Foundation, Inc.
3
 * All rights reserved.
4
 *
5
 * This code is derived from software contributed to The NetBSD Foundation
6
 * by David A. Holland.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
#include <stdlib.h>
31
#include <string.h>
32
#include <limits.h>
33
#include <errno.h>
34
35
//#define DEBUG
36
#ifdef DEBUG
37
#include <stdio.h>
38
#endif
39
40
#include "utils.h"
41
#include "array.h"
42
#include "mode.h"
43
#include "place.h"
44
#include "eval.h"
45
46
/*
47
 * e ::=
48
 *    e1 ? e2 : e3
49
 *    e1 || e2
50
 *    e1 && e2
51
 *    e1 | e2
52
 *    e1 ^ e2
53
 *    e1 & e2
54
 *    e1 == e2  |  e1 != e2
55
 *    e1 < e2   |  e1 <= e2  |  e1 > e2  |  e1 >= e2
56
 *    e1 << e2  |  e1 >> e2
57
 *    e1 + e2   |  e1 - e2
58
 *    e1 * e2   |  e1 / e2   |  e1 % e2
59
 *    !e  |  ~e  |  -e  |  +e
60
 *    ( e )  |  ident
61
 */
62
63
enum tokens {
64
	T_EOF,		/* end of input */
65
	T_VAL,		/* value */
66
	T_LPAREN,	/* parens */
67
	T_RPAREN,
68
	T_PIPEPIPE,	/* operators */
69
	T_AMPAMP,
70
	T_EQEQ,
71
	T_BANGEQ,
72
	T_LTEQ,
73
	T_GTEQ,
74
	T_LTLT,
75
	T_GTGT,
76
	T_QUES,
77
	T_COLON,
78
	T_PIPE,
79
	T_CARET,
80
	T_AMP,
81
	T_LT,
82
	T_GT,
83
	T_PLUS,
84
	T_MINUS,
85
	T_STAR,
86
	T_SLASH,
87
	T_PCT,
88
	T_BANG,
89
	T_TILDE,
90
};
91
92
static const struct {
93
	char c1, c2;
94
	enum tokens tok;
95
} tokens_2[] = {
96
	{ '|', '|', T_PIPEPIPE },
97
	{ '&', '&', T_AMPAMP },
98
	{ '=', '=', T_EQEQ },
99
	{ '!', '=', T_BANGEQ },
100
	{ '<', '=', T_LTEQ },
101
	{ '>', '=', T_GTEQ },
102
	{ '<', '<', T_LTLT },
103
	{ '>', '>', T_GTGT },
104
};
105
static const unsigned num_tokens_2 = HOWMANY(tokens_2);
106
107
static const struct {
108
	char c1;
109
	enum tokens tok;
110
} tokens_1[] = {
111
	{ '?', T_QUES },
112
	{ ':', T_COLON },
113
	{ '|', T_PIPE },
114
	{ '^', T_CARET },
115
	{ '&', T_AMP },
116
	{ '<', T_LT },
117
	{ '>', T_GT },
118
	{ '+', T_PLUS },
119
	{ '-', T_MINUS },
120
	{ '*', T_STAR },
121
	{ '/', T_SLASH },
122
	{ '%', T_PCT },
123
	{ '!', T_BANG },
124
	{ '~', T_TILDE },
125
	{ '(', T_LPAREN },
126
	{ ')', T_RPAREN },
127
};
128
static const unsigned num_tokens_1 = HOWMANY(tokens_1);
129
130
struct token {
131
	struct place place;
132
	enum tokens tok;
133
	int val;
134
};
135
DECLARRAY(token, static UNUSED);
136
DEFARRAY(token, static);
137
138
static struct tokenarray tokens;
139
140
static
141
struct token *
142
token_create(const struct place *p, enum tokens tok, int val)
143
{
144
	struct token *t;
145
146
	t = domalloc(sizeof(*t));
147
	t->place = *p;
148
	t->tok = tok;
149
	t->val = val;
150
	return t;
151
}
152
153
static
154
void
155
token_destroy(struct token *t)
156
{
157
	dofree(t, sizeof(*t));
158
}
159
160
DESTROYALL_ARRAY(token, );
161
162
#ifdef DEBUG
163
static
164
void
165
printtokens(void)
166
{
167
	unsigned i, num;
168
	struct token *t;
169
170
	fprintf(stderr, "tokens:");
171
	num = tokenarray_num(&tokens);
172
	for (i=0; i<num; i++) {
173
		t = tokenarray_get(&tokens, i);
174
		switch (t->tok) {
175
		    case T_EOF: fprintf(stderr, " <eof>"); break;
176
		    case T_VAL: fprintf(stderr, " %d", t->val); break;
177
		    case T_LPAREN: fprintf(stderr, " ("); break;
178
		    case T_RPAREN: fprintf(stderr, " )"); break;
179
		    case T_PIPEPIPE: fprintf(stderr, " ||"); break;
180
		    case T_AMPAMP: fprintf(stderr, " &&"); break;
181
		    case T_EQEQ: fprintf(stderr, " =="); break;
182
		    case T_BANGEQ: fprintf(stderr, " !="); break;
183
		    case T_LTEQ: fprintf(stderr, " <="); break;
184
		    case T_GTEQ: fprintf(stderr, " >="); break;
185
		    case T_LTLT: fprintf(stderr, " <<"); break;
186
		    case T_GTGT: fprintf(stderr, " >>"); break;
187
		    case T_QUES: fprintf(stderr, " ?"); break;
188
		    case T_COLON: fprintf(stderr, " :"); break;
189
		    case T_PIPE: fprintf(stderr, " |"); break;
190
		    case T_CARET: fprintf(stderr, " ^"); break;
191
		    case T_AMP: fprintf(stderr, " &"); break;
192
		    case T_LT: fprintf(stderr, " <"); break;
193
		    case T_GT: fprintf(stderr, " >"); break;
194
		    case T_PLUS: fprintf(stderr, " +"); break;
195
		    case T_MINUS: fprintf(stderr, " -"); break;
196
		    case T_STAR: fprintf(stderr, " *"); break;
197
		    case T_SLASH: fprintf(stderr, " /"); break;
198
		    case T_PCT: fprintf(stderr, " %%"); break;
199
		    case T_BANG: fprintf(stderr, " !"); break;
200
		    case T_TILDE: fprintf(stderr, " ~"); break;
201
		}
202
	}
203
	fprintf(stderr, "\n");
204
}
205
#endif
206
207
static
208
bool
209
isuop(enum tokens tok)
210
{
211
	switch (tok) {
212
	    case T_BANG:
213
	    case T_TILDE:
214
	    case T_MINUS:
215
	    case T_PLUS:
216
		return true;
217
	    default:
218
		break;
219
	}
220
	return false;
221
}
222
223
static
224
bool
225
isbop(enum tokens tok)
226
{
227
	switch (tok) {
228
	    case T_EOF:
229
	    case T_VAL:
230
	    case T_LPAREN:
231
	    case T_RPAREN:
232
	    case T_COLON:
233
	    case T_QUES:
234
	    case T_BANG:
235
	    case T_TILDE:
236
		return false;
237
	    default:
238
		break;
239
	}
240
	return true;
241
}
242
243
static
244
bool
245
isop(enum tokens tok)
246
{
247
	switch (tok) {
248
	    case T_EOF:
249
	    case T_VAL:
250
	    case T_LPAREN:
251
	    case T_RPAREN:
252
		return false;
253
	    default:
254
		break;
255
	}
256
	return true;
257
}
258
259
static
260
int
261
getprec(enum tokens tok)
262
{
263
	switch (tok) {
264
	    case T_BANG: case T_TILDE: return -1;
265
	    case T_STAR: case T_SLASH: case T_PCT: return 0;
266
	    case T_PLUS: case T_MINUS: return 1;
267
	    case T_LTLT: case T_GTGT: return 2;
268
	    case T_LT: case T_LTEQ: case T_GT: case T_GTEQ: return 3;
269
	    case T_EQEQ: case T_BANGEQ: return 4;
270
	    case T_AMP: return 5;
271
	    case T_CARET: return 6;
272
	    case T_PIPE: return 7;
273
	    case T_AMPAMP: return 8;
274
	    case T_PIPEPIPE: return 9;
275
	    default: break;
276
	}
277
	return 10;
278
}
279
280
static
281
bool
282
looser(enum tokens t1, enum tokens t2)
283
{
284
	return getprec(t1) >= getprec(t2);
285
}
286
287
static
288
int
289
eval_uop(enum tokens op, int val)
290
{
291
	switch (op) {
292
	    case T_BANG: val = !val; break;
293
	    case T_TILDE: val = (int)~(unsigned)val; break;
294
	    case T_MINUS: val = -val; break;
295
	    case T_PLUS: break;
296
	    default: assert(0); break;
297
	}
298
	return val;
299
}
300
301
static
302
int
303
eval_bop(struct place *p, int lv, enum tokens op, int rv)
304
{
305
	unsigned mask;
306
307
	switch (op) {
308
	    case T_PIPEPIPE: return lv || rv;
309
	    case T_AMPAMP:   return lv && rv;
310
	    case T_PIPE:     return (int)((unsigned)lv | (unsigned)rv);
311
	    case T_CARET:    return (int)((unsigned)lv ^ (unsigned)rv);
312
	    case T_AMP:      return (int)((unsigned)lv & (unsigned)rv);
313
	    case T_EQEQ:     return lv == rv;
314
	    case T_BANGEQ:   return lv != rv;
315
	    case T_LT:       return lv < rv;
316
	    case T_GT:       return lv > rv;
317
	    case T_LTEQ:     return lv <= rv;
318
	    case T_GTEQ:     return lv >= rv;
319
320
	    case T_LTLT:
321
	    case T_GTGT:
322
		if (rv < 0) {
323
			complain(p, "Negative bit-shift");
324
			complain_fail();
325
			rv = 0;
326
		}
327
		if ((unsigned)rv >= CHAR_BIT * sizeof(unsigned)) {
328
			complain(p, "Bit-shift farther than type width");
329
			complain_fail();
330
			rv = 0;
331
		}
332
		if (op == T_LTLT) {
333
			return (int)((unsigned)lv << (unsigned)rv);
334
		}
335
		mask = ((unsigned)-1) << (CHAR_BIT * sizeof(unsigned) - rv);
336
		lv = (int)(((unsigned)lv >> (unsigned)rv) | mask);
337
		return lv;
338
339
	    case T_MINUS:
340
		if (rv == INT_MIN) {
341
			if (lv == INT_MIN) {
342
				return 0;
343
			}
344
			lv--;
345
			rv++;
346
		}
347
		rv = -rv;
348
		/* FALLTHROUGH */
349
	    case T_PLUS:
350
		if (rv > 0 && lv > (INT_MAX - rv)) {
351
			complain(p, "Integer overflow");
352
			complain_fail();
353
			return INT_MAX;
354
		}
355
		if (rv < 0 && lv < (INT_MIN - rv)) {
356
			complain(p, "Integer underflow");
357
			complain_fail();
358
			return INT_MIN;
359
		}
360
		return lv + rv;
361
362
	    case T_STAR:
363
		if (rv == 0) {
364
			return 0;
365
		}
366
		if (rv == 1) {
367
			return lv;
368
		}
369
		if (rv == -1 && lv == INT_MIN) {
370
			lv++;
371
			lv = -lv;
372
			if (lv == INT_MAX) {
373
				complain(p, "Integer overflow");
374
				complain_fail();
375
				return INT_MAX;
376
			}
377
			lv++;
378
			return lv;
379
		}
380
		if (lv == INT_MIN && rv < 0) {
381
			complain(p, "Integer overflow");
382
			complain_fail();
383
			return INT_MAX;
384
		}
385
		if (lv == INT_MIN && rv > 0) {
386
			complain(p, "Integer underflow");
387
			complain_fail();
388
			return INT_MIN;
389
		}
390
		if (rv < 0) {
391
			rv = -rv;
392
			lv = -lv;
393
		}
394
		if (lv > 0 && lv > INT_MAX / rv) {
395
			complain(p, "Integer overflow");
396
			complain_fail();
397
			return INT_MAX;
398
		}
399
		if (lv < 0 && lv < INT_MIN / rv) {
400
			complain(p, "Integer underflow");
401
			complain_fail();
402
			return INT_MIN;
403
		}
404
		return lv * rv;
405
406
	    case T_SLASH:
407
		if (rv == 0) {
408
			complain(p, "Division by zero");
409
			complain_fail();
410
			return 0;
411
		}
412
		return lv / rv;
413
414
	    case T_PCT:
415
		if (rv == 0) {
416
			complain(p, "Modulus by zero");
417
			complain_fail();
418
			return 0;
419
		}
420
		return lv % rv;
421
422
	    default: assert(0); break;
423
	}
424
	return 0;
425
}
426
427
static
428
void
429
tryreduce(void)
430
{
431
	unsigned num;
432
	struct token *t1, *t2, *t3, *t4, *t5, *t6;
433
434
	while (1) {
435
#ifdef DEBUG
436
		printtokens();
437
#endif
438
		num = tokenarray_num(&tokens);
439
		t1 = (num >= 1) ? tokenarray_get(&tokens, num-1) : NULL;
440
		t2 = (num >= 2) ? tokenarray_get(&tokens, num-2) : NULL;
441
		t3 = (num >= 3) ? tokenarray_get(&tokens, num-3) : NULL;
442
443
		if (num >= 3 &&
444
		    t3->tok == T_LPAREN &&
445
		    t2->tok == T_VAL &&
446
		    t1->tok == T_RPAREN) {
447
			/* (x) -> x */
448
			t2->place = t3->place;
449
			token_destroy(t1);
450
			token_destroy(t3);
451
			tokenarray_remove(&tokens, num-1);
452
			tokenarray_remove(&tokens, num-3);
453
			continue;
454
		}
455
456
		if (num >= 2 &&
457
		    (num == 2 || isop(t3->tok) || t3->tok == T_LPAREN) &&
458
		    isuop(t2->tok) &&
459
		    t1->tok == T_VAL) {
460
			/* unary operator */
461
			t1->val = eval_uop(t2->tok, t1->val);
462
			t1->place = t2->place;
463
			token_destroy(t2);
464
			tokenarray_remove(&tokens, num-2);
465
			continue;
466
		}
467
		if (num >= 2 &&
468
		    (num == 2 || isop(t3->tok) || t3->tok == T_LPAREN) &&
469
		    t2->tok != T_LPAREN && t2->tok != T_VAL &&
470
		    t1->tok == T_VAL) {
471
			complain(&t2->place, "Invalid unary operator");
472
			complain_fail();
473
			token_destroy(t2);
474
			tokenarray_remove(&tokens, num-2);
475
			continue;
476
		}
477
478
479
		t4 = (num >= 4) ? tokenarray_get(&tokens, num-4) : NULL;
480
481
		if (num >= 4 &&
482
		    t4->tok == T_VAL &&
483
		    isbop(t3->tok) &&
484
		    t2->tok == T_VAL) {
485
			/* binary operator */
486
			if (looser(t1->tok, t3->tok)) {
487
				t4->val = eval_bop(&t3->place,
488
						   t4->val, t3->tok, t2->val);
489
				token_destroy(t2);
490
				token_destroy(t3);
491
				tokenarray_remove(&tokens, num-2);
492
				tokenarray_remove(&tokens, num-3);
493
				continue;
494
			}
495
			break;
496
		}
497
498
		t5 = (num >= 5) ? tokenarray_get(&tokens, num-5) : NULL;
499
		t6 = (num >= 6) ? tokenarray_get(&tokens, num-6) : NULL;
500
501
		if (num >= 6 &&
502
		    t6->tok == T_VAL &&
503
		    t5->tok == T_QUES &&
504
		    t4->tok == T_VAL &&
505
		    t3->tok == T_COLON &&
506
		    t2->tok == T_VAL &&
507
		    !isop(t1->tok)) {
508
			/* conditional expression */
509
			t6->val = t6->val ? t4->val : t2->val;
510
			token_destroy(t2);
511
			token_destroy(t3);
512
			token_destroy(t4);
513
			token_destroy(t5);
514
			tokenarray_remove(&tokens, num-2);
515
			tokenarray_remove(&tokens, num-3);
516
			tokenarray_remove(&tokens, num-4);
517
			tokenarray_remove(&tokens, num-5);
518
			continue;
519
		}
520
521
		if (num >= 2 &&
522
		    t2->tok == T_LPAREN &&
523
		    t1->tok == T_RPAREN) {
524
			complain(&t1->place, "Value expected within ()");
525
			complain_fail();
526
			t1->tok = T_VAL;
527
			t1->val = 0;
528
			token_destroy(t1);
529
			tokenarray_remove(&tokens, num-1);
530
			continue;
531
		}
532
533
		if (num >= 2 &&
534
		    t2->tok == T_VAL &&
535
		    t1->tok == T_VAL) {
536
			complain(&t1->place, "Operator expected");
537
			complain_fail();
538
			token_destroy(t1);
539
			tokenarray_remove(&tokens, num-1);
540
			continue;
541
		}
542
543
		if (num >= 2 &&
544
		    isop(t2->tok) &&
545
		    t1->tok == T_EOF) {
546
			complain(&t1->place, "Value expected after operator");
547
			complain_fail();
548
			token_destroy(t2);
549
			tokenarray_remove(&tokens, num-2);
550
			continue;
551
		}
552
553
		if (num == 2 &&
554
		    t2->tok == T_VAL &&
555
		    t1->tok == T_RPAREN) {
556
			complain(&t1->place, "Excess right parenthesis");
557
			complain_fail();
558
			token_destroy(t1);
559
			tokenarray_remove(&tokens, num-1);
560
			continue;
561
		}
562
563
		if (num == 3 &&
564
		    t3->tok == T_LPAREN &&
565
		    t2->tok == T_VAL &&
566
		    t1->tok == T_EOF) {
567
			complain(&t1->place, "Unclosed left parenthesis");
568
			complain_fail();
569
			token_destroy(t3);
570
			tokenarray_remove(&tokens, num-3);
571
			continue;
572
		}
573
574
		if (num == 2 &&
575
		    t2->tok == T_VAL &&
576
		    t1->tok == T_EOF) {
577
			/* accepting state */
578
			break;
579
		}
580
581
		if (num >= 1 &&
582
		    t1->tok == T_EOF) {
583
			/* any other configuration at eof is an error */
584
			complain(&t1->place, "Parse error");
585
			complain_fail();
586
			break;
587
		}
588
589
		/* otherwise, wait for more input */
590
		break;
591
	}
592
}
593
594
static
595
void
596
token(struct place *p, enum tokens tok, int val)
597
{
598
	struct token *t;
599
600
	t = token_create(p, tok, val);
601
602
	tokenarray_add(&tokens, t, NULL);
603
	tryreduce();
604
}
605
606
static
607
int
608
wordval(struct place *p, char *word)
609
{
610
	unsigned long val;
611
	char *t;
612
613
	if (word[0] >= '0' && word[0] <= '9') {
614
		errno = 0;
615
		val = strtoul(word, &t, 0);
616
		if (errno) {
617
			complain(p, "Invalid integer constant");
618
			complain_fail();
619
			return 0;
620
		}
621
		while (*t == 'U' || *t == 'L') {
622
			t++;
623
		}
624
		if (*t != '\0') {
625
			complain(p, "Trailing garbage after integer constant");
626
			complain_fail();
627
			return 0;
628
		}
629
		if (val > INT_MAX) {
630
			complain(p, "Integer constant too large");
631
			complain_fail();
632
			return INT_MAX;
633
		}
634
		return val;
635
	}
636
637
	/* if it's a symbol, warn and substitute 0. */
638
	if (warns.undef) {
639
		complain(p, "Warning: value of undefined symbol %s is 0",
640
			 word);
641
		if (mode.werror) {
642
			complain_fail();
643
		}
644
	}
645
	return 0;
646
}
647
648
static
649
bool
650
check_word(struct place *p, char *expr, size_t pos, size_t *len_ret)
651
{
652
	size_t len;
653
	int val;
654
	char tmp;
655
656
	if (!strchr(alnum, expr[pos])) {
657
		return false;
658
	}
659
	len = strspn(expr + pos, alnum);
660
	tmp = expr[pos + len];
661
	expr[pos + len] = '\0';
662
	val = wordval(p, expr + pos);
663
	expr[pos + len] = tmp;
664
	token(p, T_VAL, val);
665
	*len_ret = len;
666
	return true;
667
}
668
669
static
670
bool
671
check_tokens_2(struct place *p, char *expr, size_t pos)
672
{
673
	unsigned i;
674
675
	for (i=0; i<num_tokens_2; i++) {
676
		if (expr[pos] == tokens_2[i].c1 &&
677
		    expr[pos+1] == tokens_2[i].c2) {
678
			token(p, tokens_2[i].tok, 0);
679
			return true;
680
		}
681
	}
682
	return false;
683
}
684
685
static
686
bool
687
check_tokens_1(struct place *p, char *expr, size_t pos)
688
{
689
	unsigned i;
690
691
	for (i=0; i<num_tokens_1; i++) {
692
		if (expr[pos] == tokens_1[i].c1) {
693
			token(p, tokens_1[i].tok, 0);
694
			return true;
695
		}
696
	}
697
	return false;
698
}
699
700
static
701
void
702
tokenize(struct place *p, char *expr)
703
{
704
	size_t pos, len;
705
706
	pos = 0;
707
	while (expr[pos] != '\0') {
708
		len = strspn(expr+pos, ws);
709
		pos += len;
710
		p->column += len;
711
		/* trailing whitespace is supposed to have been pruned */
712
		assert(expr[pos] != '\0');
713
		if (check_word(p, expr, pos, &len)) {
714
			pos += len;
715
			p->column += len;
716
			continue;
717
		}
718
		if (check_tokens_2(p, expr, pos)) {
719
			pos += 2;
720
			p->column += 2;
721
			continue;
722
		}
723
		if (check_tokens_1(p, expr, pos)) {
724
			pos++;
725
			p->column++;
726
			continue;
727
		}
728
		complain(p, "Invalid character %u in #if-expression",
729
			 (unsigned char)expr[pos]);
730
		complain_fail();
731
		pos++;
732
		p->column++;
733
	}
734
	token(p, T_EOF, 0);
735
}
736
737
bool
738
eval(struct place *p, char *expr)
739
{
740
	struct token *t1, *t2;
741
	unsigned num;
742
	bool result;
743
744
#ifdef DEBUG
745
	fprintf(stderr, "eval: %s\n", expr);
746
#endif
747
748
	tokenarray_init(&tokens);
749
	tokenize(p, expr);
750
751
	result = false;
752
	num = tokenarray_num(&tokens);
753
	if (num == 2) {
754
		t1 = tokenarray_get(&tokens, num-1);
755
		t2 = tokenarray_get(&tokens, num-2);
756
		if (t2->tok == T_VAL &&
757
		    t1->tok == T_EOF) {
758
			result = t2->val != 0;
759
		}
760
	}
761
762
	tokenarray_destroyall(&tokens);
763
	tokenarray_cleanup(&tokens);
764
	return result;
765
}