summaryrefslogtreecommitdiff
path: root/usr.bin/pcc/cpp
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2007-10-21 18:58:03 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2007-10-21 18:58:03 +0000
commit2199baff6c0b67d53787c4fce52cc98089a42cde (patch)
tree8457089fd11d7047b93c165f5a50ddfdef2501b3 /usr.bin/pcc/cpp
parent09f3b25eee454f2baab3dd509e8fd1837728fa19 (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.h33
-rw-r--r--usr.bin/pcc/cpp/cpy.y256
-rw-r--r--usr.bin/pcc/cpp/scanner.l58
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