aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--Makefile3
-rw-r--r--evaluate.c109
-rw-r--r--pre-process.c92
3 files changed, 112 insertions, 92 deletions
diff --git a/Makefile b/Makefile
index 814241fb..d96c0bad 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ PROGRAMS=test-lexing test-parsing
HEADERS=token.h parse.h lib.h symbol.h scope.h expression.h
COMMON= parse.o tokenize.o pre-process.o symbol.o lib.o scope.o \
- expression.o show-parse.o
+ expression.o show-parse.o evaluate.o
all: $(PROGRAMS)
@@ -16,6 +16,7 @@ test-lexing: test-lexing.o $(COMMON)
test-parsing: test-parsing.o $(COMMON)
gcc -o $@ $< $(COMMON)
+evaluate.o: $(HEADERS)
expression.o: $(HEADERS)
lib.o: $(HEADERS)
parse.o: $(HEADERS)
diff --git a/evaluate.c b/evaluate.c
new file mode 100644
index 00000000..952917b1
--- /dev/null
+++ b/evaluate.c
@@ -0,0 +1,109 @@
+/*
+ * sparse/evaluate.c
+ *
+ * Copyright (C) 2003 Linus Torvalds, all rights reserved.
+ *
+ * Evaluate constant expressions.
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include "lib.h"
+#include "parse.h"
+#include "token.h"
+#include "symbol.h"
+#include "expression.h"
+
+static unsigned long long get_int_value(const char *str)
+{
+ unsigned long long value = 0;
+ unsigned int base = 10, digit;
+
+ switch (str[0]) {
+ case 'x':
+ base = 18; // the -= 2 for the octal case will
+ str++; // skip the 'x'
+ /* fallthrough */
+ case 'o':
+ str++; // skip the 'o' or 'x/X'
+ base -= 2; // the fall-through will make this 8
+ }
+ while ((digit = hexval(*str)) < base) {
+ value = value * base + digit;
+ str++;
+ }
+ return value;
+}
+
+static long long primary_value(struct token *token)
+{
+ switch (token->type) {
+ case TOKEN_INTEGER:
+ return get_int_value(token->integer);
+ }
+ error(token, "bad constant expression");
+ return 0;
+}
+
+long long get_expression_value(struct expression *expr)
+{
+ long long left, middle, right;
+
+ switch (expr->type) {
+ case EXPR_CONSTANT:
+ return primary_value(expr->token);
+ case EXPR_SYMBOL: {
+ struct symbol *sym = expr->symbol;
+ if (!sym || !sym->ctype.base_type || sym->ctype.base_type->type != SYM_ENUM) {
+ warn(expr->token, "undefined identifier in constant expression");
+ return 0;
+ }
+ return sym->value;
+ }
+
+#define OP(x,y) case x: return left y right;
+ case EXPR_BINOP:
+ left = get_expression_value(expr->left);
+ if (!left && expr->op == SPECIAL_LOGICAL_AND)
+ return 0;
+ if (left && expr->op == SPECIAL_LOGICAL_OR)
+ return 1;
+ right = get_expression_value(expr->right);
+ switch (expr->op) {
+ OP('+',+); OP('-',-); OP('*',*); OP('/',/);
+ OP('%',%); OP('<',<); OP('>',>);
+ OP('&',&);OP('|',|);OP('^',^);
+ OP(SPECIAL_EQUAL,==); OP(SPECIAL_NOTEQUAL,!=);
+ OP(SPECIAL_LTE,<=); OP(SPECIAL_LEFTSHIFT,<<);
+ OP(SPECIAL_RIGHTSHIFT,>>); OP(SPECIAL_GTE,>=);
+ OP(SPECIAL_LOGICAL_AND,&&);OP(SPECIAL_LOGICAL_OR,||);
+ }
+ break;
+
+#undef OP
+#define OP(x,y) case x: return y left;
+ case EXPR_PREOP:
+ left = get_expression_value(expr->unop);
+ switch (expr->op) {
+ OP('+', +); OP('-', -); OP('!', !); OP('~', ~); OP('(', );
+ }
+ break;
+
+ case EXPR_CONDITIONAL:
+ left = get_expression_value(expr->conditional);
+ if (!expr->cond_true)
+ middle = left;
+ else
+ middle = get_expression_value(expr->cond_true);
+ right = get_expression_value(expr->cond_false);
+ return left ? middle : right;
+ }
+ error(expr->token, "bad constant expression");
+ return 0;
+}
diff --git a/pre-process.c b/pre-process.c
index df1ddd2f..8715a77f 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -625,96 +625,6 @@ static int handle_ifndef(struct stream *stream, struct token *head, struct token
return preprocessor_if(token, !token_defined(next));
}
-static unsigned long long get_int_value(const char *str)
-{
- unsigned long long value = 0;
- unsigned int base = 10, digit;
-
- switch (str[0]) {
- case 'x':
- base = 18; // the -= 2 for the octal case will
- str++; // skip the 'x'
- /* fallthrough */
- case 'o':
- str++; // skip the 'o' or 'x/X'
- base -= 2; // the fall-through will make this 8
- }
- while ((digit = hexval(*str)) < base) {
- value = value * base + digit;
- str++;
- }
- return value;
-}
-
-static long long primary_value(struct token *token)
-{
- switch (token->type) {
- case TOKEN_INTEGER:
- return get_int_value(token->integer);
- }
- error(token, "bad constant expression");
- return 0;
-}
-
-long long get_expression_value(struct expression *expr)
-{
- long long left, middle, right;
-
- switch (expr->type) {
- case EXPR_CONSTANT:
- return primary_value(expr->token);
- case EXPR_SYMBOL: {
- struct symbol *sym = expr->symbol;
- if (!sym || !sym->ctype.base_type || sym->ctype.base_type->type != SYM_ENUM) {
- warn(expr->token, "undefined identifier in constant expression");
- return 0;
- }
- return sym->value;
- }
-
-#define OP(x,y) case x: return left y right;
- case EXPR_BINOP:
- left = get_expression_value(expr->left);
- if (!left && expr->op == SPECIAL_LOGICAL_AND)
- return 0;
- if (left && expr->op == SPECIAL_LOGICAL_OR)
- return 1;
- right = get_expression_value(expr->right);
- switch (expr->op) {
- OP('+',+); OP('-',-); OP('*',*); OP('/',/);
- OP('%',%); OP('<',<); OP('>',>);
- OP('&',&);OP('|',|);OP('^',^);
- OP(SPECIAL_EQUAL,==); OP(SPECIAL_NOTEQUAL,!=);
- OP(SPECIAL_LTE,<=); OP(SPECIAL_LEFTSHIFT,<<);
- OP(SPECIAL_RIGHTSHIFT,>>); OP(SPECIAL_GTE,>=);
- OP(SPECIAL_LOGICAL_AND,&&);OP(SPECIAL_LOGICAL_OR,||);
- }
- break;
-
-#undef OP
-#define OP(x,y) case x: return y left;
- case EXPR_PREOP:
- left = get_expression_value(expr->unop);
- switch (expr->op) {
- OP('+', +); OP('-', -); OP('!', !); OP('~', ~); OP('(', );
- }
- break;
-
- case EXPR_CONDITIONAL:
- left = get_expression_value(expr->conditional);
- if (!expr->cond_true)
- middle = left;
- else
- middle = get_expression_value(expr->cond_true);
- right = get_expression_value(expr->cond_false);
- return left ? middle : right;
- }
- error(expr->token, "bad constant expression");
- return 0;
-}
-
-extern struct token *conditional_expression(struct token *token, struct expression **tree);
-
static int expression_value(struct token *head)
{
struct expression *expr;
@@ -723,7 +633,7 @@ static int expression_value(struct token *head)
expand_defined(head);
expand_list(head);
- token = conditional_expression(head->next, &expr);
+ token = constant_expression(head->next, &expr);
if (!eof_token(token))
warn(token, "garbage at end: %s", show_token_sequence(token));
value = get_expression_value(expr);