?? eval.c
字號:
/* * expr.c - expression evaluator routines * * This file is a part of the SimpleScalar tool suite written by * Todd M. Austin as a part of the Multiscalar Research Project. * * The tool suite is currently maintained by Doug Burger and Todd M. Austin. * * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful. The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use. * * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: * * This source code is distributed for non-commercial use only. * Please contact the maintainer for restrictions applying to * commercial use. * * Permission is granted to anyone to make or distribute copies * of this source code, either as received or modified, in any * medium, provided that all copyright notices, permission and * nonwarranty notices are preserved, and that the distributor * grants the recipient permission for further redistribution as * permitted by this document. * * Permission is granted to distribute this file in compiled * or executable form under the same conditions that apply for * source code, provided that either: * * A. it is accompanied by the corresponding machine-readable * source code, * B. it is accompanied by a written offer, with no time limit, * to give anyone a machine-readable copy of the corresponding * source code in return for reimbursement of the cost of * distribution. This written offer must permit verbatim * duplication by anyone, or * C. it is distributed by someone who received only the * executable form, and is accompanied by a copy of the * written offer of source code that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file. You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail: 1210 W. Dayton Street, Madison, WI 53706 * * $Id: eval.c,v 1.1 1997/03/11 01:31:26 taustin Exp taustin $ * * $Log: eval.c,v $ * Revision 1.1 1997/03/11 01:31:26 taustin * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <ctype.h>#if defined(__CYGWIN32__)#include <errno.h>#endif#include "misc.h"#include "eval.h"#if defined(sparc) && !defined(__svr4__)#define strtoul strtol#endif /* sparc *//* expression evaluation error, this must be a global */enum eval_err_t eval_error = ERR_NOERR;/* enum eval_err_t -> error description string map */char *eval_err_str[ERR_NUM] = { /* ERR_NOERR */ "!! no error!!", /* ERR_UPAREN */ "unmatched parenthesis", /* ERR_NOTERM */ "expression term is missing", /* ERR_DIV0 */ "divide by zero", /* ERR_BADCONST */ "badly formed constant", /* ERR_BADEXPR */ "badly formed expression", /* ERR_UNDEFVAR */ "variable is undefined", /* ERR_EXTRA */ "extra characters at end of expression"};/* *first* token character -> enum eval_token_t map */static enum eval_token_t tok_map[256];static int tok_map_initialized = FALSE;/* builds the first token map */static voidinit_tok_map(void){ int i; for (i=0; i<256; i++) tok_map[i] = tok_invalid; /* identifier characters */ for (i='a'; i<='z'; i++) tok_map[i] = tok_ident; for (i='A'; i<='Z'; i++) tok_map[i] = tok_ident; tok_map[(int)'_'] = tok_ident; tok_map[(int)'$'] = tok_ident; /* numeric characters */ for (i='0'; i<='9'; i++) tok_map[i] = tok_const; tok_map[(int)'.'] = tok_const; /* operator characters */ tok_map[(int)'+'] = tok_plus; tok_map[(int)'-'] = tok_minus; tok_map[(int)'*'] = tok_mult; tok_map[(int)'/'] = tok_div; tok_map[(int)'('] = tok_oparen; tok_map[(int)')'] = tok_cparen; /* whitespace characers */ tok_map[(int)' '] = tok_whitespace; tok_map[(int)'\t'] = tok_whitespace;}/* get next token from the expression string */static enum eval_token_t /* token parsed */get_next_token(struct eval_state_t *es) /* expression evaluator */{ int allow_hex; enum eval_token_t tok; char *ptok_buf, last_char; /* initialize the token map, if needed */ if (!tok_map_initialized) { init_tok_map(); tok_map_initialized = TRUE; } /* use the peek'ed token, if available, tok_buf should still be valid */ if (es->peek_tok != tok_invalid) { tok = es->peek_tok; es->peek_tok = tok_invalid; return tok; } /* set up the token string space */ ptok_buf = es->tok_buf; *ptok_buf = '\0'; /* skip whitespace */ while (*es->p && tok_map[(int)*es->p] == tok_whitespace) es->p++; /* end of token stream? */ if (*es->p == '\0') return tok_eof; *ptok_buf++ = *es->p; tok = tok_map[(int)*es->p++]; switch (tok) { case tok_ident: /* parse off next identifier */ while (*es->p && (tok_map[(int)*es->p] == tok_ident || tok_map[(int)*es->p] == tok_const)) { *ptok_buf++ = *es->p++; } break; case tok_const: /* parse off next numeric literal */ last_char = '\0'; allow_hex = FALSE; while (*es->p && (tok_map[(int)*es->p] == tok_const || (*es->p == '-' && last_char == 'e') || (*es->p == '+' && last_char == 'e') || tolower(*es->p) == 'e' || tolower(*es->p) == 'x' || (tolower(*es->p) == 'a' && allow_hex) || (tolower(*es->p) == 'b' && allow_hex) || (tolower(*es->p) == 'c' && allow_hex) || (tolower(*es->p) == 'd' && allow_hex) || (tolower(*es->p) == 'e' && allow_hex) || (tolower(*es->p) == 'f' && allow_hex))) { last_char = tolower(*es->p); if (*es->p == 'x' || *es->p == 'X') allow_hex = TRUE; *ptok_buf++ = *es->p++; } break; case tok_plus: case tok_minus: case tok_mult: case tok_div: case tok_oparen: case tok_cparen: /* just pass on the token */ break; default: tok = tok_invalid; break; } /* terminate the token string buffer */ *ptok_buf = '\0'; return tok;}/* peek ahead at the next token from the expression stream, currently only the next token can be peek'ed at */static enum eval_token_t /* next token in expression */peek_next_token(struct eval_state_t *es) /* expression evalutor */{ /* if there is no peek ahead token, get one */ if (es->peek_tok == tok_invalid) { es->lastp = es->p; es->peek_tok = get_next_token(es); } /* return peek ahead token */ return es->peek_tok;}/* forward declaration */static struct eval_value_t expr(struct eval_state_t *es);/* default expression error value, eval_err is also set */static struct eval_value_t err_value = { et_int, { 0 } };/* expression type strings */char *eval_type_str[et_NUM] = { /* et_int */ "int", /* et_uint */ "unsigned int", /* et_float */ "float", /* et_double */ "double", /* et_symbol */ "symbol"};/* determine necessary arithmetic conversion on T1 <op> T2 */static enum eval_type_t /* type of expression result */result_type(enum eval_type_t t1, /* left operand type */ enum eval_type_t t2) /* right operand type */{ /* sanity check, symbols should not show up in arithmetic exprs */ if (t1 == et_symbol || t2 == et_symbol) panic("symbol used in expression"); /* using C rules, i.e., A6.5 */ if (t1 == et_double || t2 == et_double) return et_double; else if (t1 == et_float || t2 == et_float) return et_float; else if (t1 == et_uint || t2 == et_uint) return et_uint; else return et_int;}/* * expression value arithmetic conversions *//* eval_value_t (any numeric type) -> double */doubleeval_as_double(struct eval_value_t val){ switch (val.type) { case et_double: return val.value.as_double; case et_float: return (double)val.value.as_float; case et_uint: return (double)val.value.as_uint; case et_int: return (double)val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}/* eval_value_t (any numeric type) -> float */floateval_as_float(struct eval_value_t val){ switch (val.type) { case et_double: return (float)val.value.as_double; case et_float: return val.value.as_float; case et_uint: return (float)val.value.as_uint; case et_int: return (float)val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}/* eval_value_t (any numeric type) -> unsigned int */unsigned inteval_as_uint(struct eval_value_t val){ switch (val.type) { case et_double: return (unsigned int)val.value.as_double; case et_float: return (unsigned int)val.value.as_float; case et_uint: return val.value.as_uint; case et_int: return (unsigned int)val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}/* eval_value_t (any numeric type) -> int */inteval_as_int(struct eval_value_t val){ switch (val.type) { case et_double: return (int)val.value.as_double; case et_float: return (int)val.value.as_float; case et_uint: return (int)val.value.as_uint; case et_int: return val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}/* * arithmetic intrinsics operations, used during expression evaluation *//* compute <val1> + <val2> */static struct eval_value_tf_add(struct eval_value_t val1, struct eval_value_t val2){ enum eval_type_t et; struct eval_value_t val; /* symbols are not allowed in arithmetic expressions */ if (val1.type == et_symbol || val2.type == et_symbol) { eval_error = ERR_BADEXPR; return err_value; } /* get result type, and perform operation in that type */ et = result_type(val1.type, val2.type); switch (et) { case et_double: val.type = et_double; val.value.as_double = eval_as_double(val1) + eval_as_double(val2); break; case et_float: val.type = et_float; val.value.as_float = eval_as_float(val1) + eval_as_float(val2); break; case et_uint: val.type = et_uint; val.value.as_uint = eval_as_uint(val1) + eval_as_uint(val2); break; case et_int: val.type = et_int; val.value.as_int = eval_as_int(val1) + eval_as_int(val2); break; default: panic("bogus expression type"); } return val;}/* compute <val1> - <val2> */static struct eval_value_tf_sub(struct eval_value_t val1, struct eval_value_t val2){ enum eval_type_t et; struct eval_value_t val; /* symbols are not allowed in arithmetic expressions */ if (val1.type == et_symbol || val2.type == et_symbol) { eval_error = ERR_BADEXPR; return err_value; } /* get result type, and perform operation in that type */ et = result_type(val1.type, val2.type); switch (et) { case et_double: val.type = et_double; val.value.as_double = eval_as_double(val1) - eval_as_double(val2); break; case et_float: val.type = et_float; val.value.as_float = eval_as_float(val1) - eval_as_float(val2); break; case et_uint: val.type = et_uint; val.value.as_uint = eval_as_uint(val1) - eval_as_uint(val2); break; case et_int: val.type = et_int; val.value.as_int = eval_as_int(val1) - eval_as_int(val2); break; default: panic("bogus expression type"); } return val;}/* compute <val1> * <val2> */static struct eval_value_tf_mult(struct eval_value_t val1, struct eval_value_t val2){ enum eval_type_t et; struct eval_value_t val; /* symbols are not allowed in arithmetic expressions */ if (val1.type == et_symbol || val2.type == et_symbol) { eval_error = ERR_BADEXPR; return err_value; } /* get result type, and perform operation in that type */ et = result_type(val1.type, val2.type); switch (et) { case et_double: val.type = et_double; val.value.as_double = eval_as_double(val1) * eval_as_double(val2); break; case et_float: val.type = et_float; val.value.as_float = eval_as_float(val1) * eval_as_float(val2); break; case et_uint: val.type = et_uint; val.value.as_uint = eval_as_uint(val1) * eval_as_uint(val2); break; case et_int: val.type = et_int; val.value.as_int = eval_as_int(val1) * eval_as_int(val2); break; default: panic("bogus expression type"); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -