diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-10-21 18:58:03 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-10-21 18:58:03 +0000 |
commit | 2199baff6c0b67d53787c4fce52cc98089a42cde (patch) | |
tree | 8457089fd11d7047b93c165f5a50ddfdef2501b3 /usr.bin/pcc/cpp | |
parent | 09f3b25eee454f2baab3dd509e8fd1837728fa19 (diff) |
Pull from ragge's repo:
More fixes to cpp arithmetic, sanitychecked by otto and stefan.
Diffstat (limited to 'usr.bin/pcc/cpp')
-rw-r--r-- | usr.bin/pcc/cpp/cpp.h | 33 | ||||
-rw-r--r-- | usr.bin/pcc/cpp/cpy.y | 256 | ||||
-rw-r--r-- | usr.bin/pcc/cpp/scanner.l | 58 |
3 files changed, 108 insertions, 239 deletions
diff --git a/usr.bin/pcc/cpp/cpp.h b/usr.bin/pcc/cpp/cpp.h index d9cd672e8e5..8b94abe9ac9 100644 --- a/usr.bin/pcc/cpp/cpp.h +++ b/usr.bin/pcc/cpp/cpp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpp.h,v 1.4 2007/10/12 21:40:49 stefan Exp $ */ +/* $OpenBSD: cpp.h,v 1.5 2007/10/21 18:58:02 otto Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -90,33 +90,22 @@ struct initar { char *str; }; -struct val { +/* + * Struct used in parse tree evaluation. + * op is one of: + * - number type (NUMBER, UNUMBER) + * - zero (0) if divided by zero. + */ +struct nd { + int op; union { long long val; unsigned long long uval; - } v; - int type; -}; - -struct nd { - union { - struct { - struct nd *left; - struct nd *right; - } t; - struct val v; } n; - int op; }; -#define nd_left n.t.left -#define nd_right n.t.right -#define nd_val n.v.v.val -#define nd_uval n.v.v.uval -#define nd_type n.v.type - -struct nd *mknode(int, struct nd *, struct nd *); -struct nd *mknum(struct val); +#define nd_val n.val +#define nd_uval n.uval struct recur; /* not used outside cpp.c */ int subst(struct symtab *, struct recur *); diff --git a/usr.bin/pcc/cpp/cpy.y b/usr.bin/pcc/cpp/cpy.y index 37ba7371fbc..c4ff14092f4 100644 --- a/usr.bin/pcc/cpp/cpy.y +++ b/usr.bin/pcc/cpp/cpy.y @@ -1,4 +1,4 @@ -/* $OpenBSD: cpy.y,v 1.3 2007/10/12 18:14:14 stefan Exp $ */ +/* $OpenBSD: cpy.y,v 1.4 2007/10/21 18:58:02 otto Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -62,27 +62,34 @@ */ %{ -#include <stdlib.h> -#include <string.h> -#include <ctype.h> #include "cpp.h" void yyerror(char *); int yylex(void); -struct val eval(struct nd *); +int setd(int l, int r); + +#define EVALUNARY(tok, l, r) l.nd_val = tok r.nd_val; l.op = r.op +#define EVALBIN(tok, d, l, r) \ + d.op = setd(l.op, r.op); d.nd_val = l.nd_val tok r.nd_val +#define EVALUBIN(tok, d, l, r, t) \ + d.op = setd(l.op, r.op); \ + if (d.op == NUMBER) d.nd_val = l.nd_val tok r.nd_val; \ + else d.nd_uval = l.nd_uval tok r.nd_uval; \ + if (t && d.op) d.op = NUMBER +#define XEVALUBIN(tok, d, l, r) \ + if (r.nd_val) { EVALUBIN(tok, d, l, r, 0); } else d.op = 0 %} %term stop %term EQ NE LE GE LS RS -%term ANDAND OROR IDENT NUMBER +%term ANDAND OROR IDENT NUMBER UNUMBER /* * The following terminals are not used in the yacc code. */ %term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS %left ',' -%right '=' %right '?' ':' %left OROR %left ANDAND @@ -94,76 +101,99 @@ struct val eval(struct nd *); %left '+' '-' %left '*' '/' '%' %right '!' '~' UMINUS -%left '(' '.' +%left '(' %union { - struct val val; - struct nd *node; + struct nd node; } -%type <val> NUMBER -%type <node> term e +%type <node> term e NUMBER UNUMBER %% -S: e '\n' { return(eval($1).v.val != 0);} - +S: e '\n' { + if ($1.op == 0) + error("division by zero"); + return $1.nd_val; + } e: e '*' e - {$$ = mknode('*', $1, $3);} + { EVALUBIN(*, $$, $1, $3, 0); } | e '/' e - {$$ = mknode('/', $1, $3);} + { XEVALUBIN(/, $$, $1, $3); } | e '%' e - {$$ = mknode('%', $1, $3);} + { XEVALUBIN(%, $$, $1, $3); } | e '+' e - {$$ = mknode('+', $1, $3);} + { EVALBIN(+, $$, $1, $3); } | e '-' e - {$$ = mknode('-', $1, $3);} + { EVALBIN(-, $$, $1, $3); } | e LS e - {$$ = mknode(LS, $1, $3);} + { EVALBIN(<<, $$, $1, $3); } | e RS e - {$$ = mknode(RS, $1, $3);} + { EVALUBIN(>>, $$, $1, $3, 0); } | e '<' e - {$$ = mknode('<', $1, $3);} + { EVALUBIN(<, $$, $1, $3, 1); } | e '>' e - {$$ = mknode('>', $1, $3);} + { EVALUBIN(>, $$, $1, $3, 1); } | e LE e - {$$ = mknode(LE, $1, $3);} + { EVALUBIN(<=, $$, $1, $3, 1); } | e GE e - {$$ = mknode(GE, $1, $3);} + { EVALUBIN(>=, $$, $1, $3, 1); } | e EQ e - {$$ = mknode(EQ, $1, $3);} + { EVALUBIN(==, $$, $1, $3, 1); } | e NE e - {$$ = mknode(NE, $1, $3);} + { EVALUBIN(!=, $$, $1, $3, 1); } | e '&' e - {$$ = mknode('&', $1, $3);} + { EVALBIN(&, $$, $1, $3); } | e '^' e - {$$ = mknode('^', $1, $3);} + { EVALBIN(^, $$, $1, $3); } | e '|' e - {$$ = mknode('|', $1, $3);} - | e ANDAND e - {$$ = mknode(ANDAND, $1, $3);} - | e OROR e - {$$ = mknode(OROR, $1, $3);} + { EVALBIN(|, $$, $1, $3); } + | e ANDAND e { + $$ = $1; + if ($1.nd_val) { + $$.op = setd($1.op, $3.op); + $$.nd_val = ($3.nd_val != 0); + } + if ($$.op == UNUMBER) $$.op = NUMBER; + } + | e OROR e { + if ($1.nd_val != 0) { + $$.nd_val = ($1.nd_val != 0); + $$.op = $1.op; + } else { + $$.nd_val = ($3.nd_val != 0); + $$.op = setd($1.op, $3.op); + } + if ($$.op == UNUMBER) $$.op = NUMBER; + } | e '?' e ':' e { - struct nd *n = mknode(':', $3, $5); - $$ = mknode('?', $1, n);} - | e ',' e - {$$ = mknode(',', $1, $3);} + if ($1.op == 0) + $$ = $1; + else if ($1.nd_val) + $$ = $3; + else + $$ = $5; + } + | e ',' e { + $$.op = setd($1.op, $3.op); + $$.nd_val = $3.nd_val; + if ($$.op) $$.op = $3.op; + } | term {$$ = $1;} term: '-' term %prec UMINUS - {$$ = mknode(UMINUS, $2, NULL);} + { EVALUNARY(-, $$, $2); } | '+' term %prec UMINUS {$$ = $2;} | '!' term - {$$ = mknode('!', $2, NULL);} + { $$.nd_val = ! $2.nd_val; $$.op = $2.op ? NUMBER : 0; } | '~' term - {$$ = mknode('~', $2, NULL);} + { EVALUNARY(~, $$, $2); } | '(' e ')' {$$ = $2;} | NUMBER - {$$= mknum($1);} + {$$ = $1;} %% void @@ -172,138 +202,16 @@ yyerror(char *err) error(err); } -struct nd * -mknode(int op, struct nd *left, struct nd *right) +/* + * Set return type of an expression. + */ +int +setd(int l, int r) { - struct nd *r = malloc(sizeof(*r)); - if (r == NULL) - error("out of mem"); - - r->op = op; - r->nd_left = left; - r->nd_right = right; - - return r; + if (!l || !r) + return 0; /* div by zero involved */ + if (l == UNUMBER || r == UNUMBER) + return UNUMBER; + return NUMBER; } -struct nd * -mknum(struct val val) -{ - struct nd *r = malloc(sizeof(*r)); - if (r == NULL) - error("out of mem"); - - r->op = NUMBER; - r->n.v = val; - return r; -} - -#define EVALUNARY(tok, op, t, x) \ - case (tok): if (t) ret.v.uval = op x.v.uval; \ - else ret.v.val = op x.v.val; \ - ret.type = t; \ - break; - -#define EVALBIN(tok, op, t, x, y, r) \ - case (tok): if (t) ret.v.uval = x.v.uval op y.v.uval; \ - else ret.v.val = x.v.val op y.v.val; \ - ret.type = r; \ - break; - -struct val -eval(struct nd *tree) -{ - struct val ret, l, r; - int t; - - switch (tree->op) { - case NUMBER: - ret.type = tree->nd_type; - if (ret.type) - ret.v.uval = tree->nd_uval; - else - ret.v.val = tree->nd_val; - goto out; - case LS: - case RS: - r = eval(tree->nd_right); - /* FALLTHROUGH */ - case UMINUS: - case '~': - case '!': - l = eval(tree->nd_left); - switch (tree->op) { - EVALBIN(LS, <<, l.type, l, r, l.type); - EVALBIN(RS, >>, l.type, l, r, l.type); - EVALUNARY(UMINUS, -, l.type, l); - EVALUNARY('~', ~, l.type, l); - EVALUNARY('!', !, 0, l); - } - goto out; - case '?': - l = eval(tree->nd_left); - // XXX mem leak - if (l.v.val) - ret = eval(tree->nd_right->nd_left); - else - ret = eval(tree->nd_right->nd_right); - goto out; - case OROR: - l = eval(tree->nd_left); - // XXX mem leak - if (l.v.val) - ret = l; - else - ret = eval(tree->nd_right); - ret.type = 0; - goto out; - case ANDAND: - l = eval(tree->nd_left); - // XXX mem leak - if (l.v.val) - ret = eval(tree->nd_right); - else - ret = l; - ret.type = 0; - goto out; - case ',': - // XXX mem leak - ret = eval(tree->nd_right); - goto out; - } - - l = eval(tree->nd_left); - r = eval(tree->nd_right); - t = l.type || r.type; - if (tree->op == '/' || tree->op == '%') { - if ((t && r.v.uval == 0) || (!t && r.v.val == 0)) { - warning(tree->op == '/' ? "division by zero" : - "modulus by zero"); - if (t) - ret.v.uval = 0; - else - ret.v.val = 0; - ret.type = t; - goto out; - } - } - switch (tree->op) { - EVALBIN(EQ, ==, t, l, r, 0); - EVALBIN(NE, !=, t, l, r, 0); - EVALBIN('<', <, t, l, r, 0); - EVALBIN('>', >, t, l, r, 0); - EVALBIN(GE, >=, t, l, r, 0); - EVALBIN(LE, <=, t, l, r, 0); - EVALBIN('+', +, t, l, r, t); - EVALBIN('-', -, t, l, r, t); - EVALBIN('*', *, t, l, r, t); - EVALBIN('/', /, t, l, r, t); - EVALBIN('%', %, t, l, r, t); - EVALBIN('&', &, t, l, r, t); - EVALBIN('|', |, t, l, r, t); - EVALBIN('^', ^, t, l, r, t); - } -out: - free(tree); - return ret; -} diff --git a/usr.bin/pcc/cpp/scanner.l b/usr.bin/pcc/cpp/scanner.l index 13297fdeade..5deea79eff1 100644 --- a/usr.bin/pcc/cpp/scanner.l +++ b/usr.bin/pcc/cpp/scanner.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scanner.l,v 1.2 2007/10/12 07:22:44 otto Exp $ */ +/* $Id: scanner.l,v 1.3 2007/10/21 18:58:02 otto Exp $ */ /* * Copyright (c) 2004 Anders Magnusson. All rights reserved. @@ -38,8 +38,7 @@ %} %{ -static long long cvtdig(int rad); -static unsigned long long cvtdigu(int rad); +static void cvtdig(int rad); static int charcon(void); static void elsestmt(void); static void ifdefstmt(void); @@ -51,7 +50,6 @@ static void pragmastmt(void); static void undefstmt(void); static void cpperror(void); static void elifstmt(void); -//static void linestmt(void); static void storepb(void); void include(void); void define(void); @@ -161,39 +159,29 @@ WS [\t ] <IFR>{WS}+ { ; } <IFR>{L}({L}|{D})* { + yylval.node.op = NUMBER; if (gotdef) { - yylval.val.type = 0; - yylval.val.v.val = - lookup((usch *)yytext, FIND) != 0; + yylval.node.nd_val + = lookup((usch *)yytext, FIND) != 0; gotdef = 0; return IDENT; } - yylval.val.type = 0; - yylval.val.v.val = 0; + yylval.node.nd_val = 0; return NUMBER; } [1-9][0-9]* { if (slow && !YYSTATE) return IDENT; scale = 10; goto num; } 0[xX]{H}+{IS}? { scale = 16; - num: if (YYSTATE) { - yylval.val.type = - strrchr(yytext, 'U') != NULL || - strrchr(yytext, 'u') != NULL; - if (yylval.val.type) - yylval.val.v.uval = - cvtdigu(scale); - else - yylval.val.v.val = - cvtdig(scale); - } + num: if (YYSTATE) + cvtdig(scale); PRTOUT(NUMBER); } 0{D}+{IS}? { scale = 8; goto num; } {D}+{IS}? { scale = 10; goto num; } L?'(\\.|[^\\'])+' { if (YYSTATE) { - yylval.val.type = 0; - yylval.val.v.val = charcon(); + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon(); } PRTOUT(NUMBER); } @@ -504,7 +492,7 @@ dig2num(int c) /* * Convert some string numbers to long long. */ -static long long +void cvtdig(int rad) { long long rv = 0; @@ -518,27 +506,11 @@ cvtdig(int rad) rv = rv * rad + dig2num(c); c = *y++; } - return rv; -} - -/* - * Convert some string numbers to unsigned long long. - */ -static unsigned long long -cvtdigu(int rad) -{ - unsigned long long rv = 0; - char *y = yytext; - int c; - - c = *y++; - if (rad == 16) + y--; + while (*y == 'l' || *y == 'L') y++; - while (isxdigit(c)) { - rv = rv * rad + dig2num(c); - c = *y++; - } - return rv; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_val = rv; } static int |