diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | evaluate.c | 109 | ||||
| -rw-r--r-- | pre-process.c | 92 |
3 files changed, 112 insertions, 92 deletions
@@ -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); |
