📄 eval.c
字号:
/* expr.c - expression evaluator routines *//* SimpleScalar(TM) Tool Suite * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. * All Rights Reserved. * * THIS IS A LEGAL DOCUMENT, BY USING SIMPLESCALAR, * YOU ARE AGREEING TO THESE TERMS AND CONDITIONS. * * No portion of this work may be used by any commercial entity, or for any * commercial purpose, without the prior, written permission of SimpleScalar, * LLC (info@simplescalar.com). Nonprofit and noncommercial use is permitted * as described below. * * 1. SimpleScalar is provided AS IS, with no warranty of any kind, express * or implied. The user of the program accepts full responsibility for the * application of the program and the use of any results. * * 2. Nonprofit and noncommercial use is encouraged. SimpleScalar may be * downloaded, compiled, executed, copied, and modified solely for nonprofit, * educational, noncommercial research, and noncommercial scholarship * purposes provided that this notice in its entirety accompanies all copies. * Copies of the modified software can be delivered to persons who use it * solely for nonprofit, educational, noncommercial research, and * noncommercial scholarship purposes provided that this notice in its * entirety accompanies all copies. * * 3. ALL COMMERCIAL USE, AND ALL USE BY FOR PROFIT ENTITIES, IS EXPRESSLY * PROHIBITED WITHOUT A LICENSE FROM SIMPLESCALAR, LLC (info@simplescalar.com). * * 4. No nonprofit user may place any restrictions on the use of this software, * including as modified by the user, by any other authorized user. * * 5. Noncommercial and nonprofit users may distribute copies of SimpleScalar * in compiled or executable form as set forth in Section 2, provided that * either: (A) it is accompanied by the corresponding machine-readable source * code, or (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. * * 6. SimpleScalar was developed by Todd M. Austin, Ph.D. The tool suite is * currently maintained by SimpleScalar LLC (info@simplescalar.com). US Mail: * 2395 Timbercrest Court, Ann Arbor, MI 48105. * * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. */#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <errno.h>#include "host.h"#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_addr */ "md_addr_t",#ifdef HOST_HAS_QWORD /* et_qword */ "qword_t", /* et_sqword */ "sqword_t",#endif /* HOST_HAS_QWORD */ /* 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;#ifdef HOST_HAS_QWORD else if (t1 == et_qword || t2 == et_qword) return et_qword; else if (t1 == et_sqword || t2 == et_sqword) return et_sqword;#endif /* HOST_HAS_QWORD */ else if (t1 == et_addr || t2 == et_addr) return et_addr; 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;#ifdef HOST_HAS_QWORD case et_qword:#ifdef _MSC_VER /* FIXME: MSC does not implement qword_t to dbl conversion */ return (double)(sqword_t)val.value.as_qword;#else /* !_MSC_VER */ return (double)val.value.as_qword;#endif /* _MSC_VER */ case et_sqword: return (double)val.value.as_sqword;#endif /* HOST_HAS_QWORD */ case et_addr:#if defined(_MSC_VER) && defined(TARGET_ALPHA) /* FIXME: MSC does not implement qword_t to double conversion */ return (double)(sqword_t)val.value.as_addr;#else return (double)val.value.as_addr;#endif 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;#ifdef HOST_HAS_QWORD case et_qword:#ifdef _MSC_VER /* FIXME: MSC does not implement qword_t to dbl conversion */ return (float)(sqword_t)val.value.as_qword;#else /* !_MSC_VER */ return (float)val.value.as_qword;#endif /* _MSC_VER */ case et_sqword: return (float)val.value.as_sqword;#endif /* HOST_HAS_QWORD */ case et_addr:#if defined(_MSC_VER) && defined(TARGET_ALPHA) /* FIXME: MSC does not implement qword_t to double conversion */ return (float)(sqword_t)val.value.as_addr;#else return (float)val.value.as_addr;#endif 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"); }}#ifdef HOST_HAS_QWORD/* eval_value_t (any numeric type) -> qword_t */qword_teval_as_qword(struct eval_value_t val){ switch (val.type) { case et_double: return (qword_t)val.value.as_double; case et_float: return (qword_t)val.value.as_float; case et_qword: return val.value.as_qword; case et_sqword: return (qword_t)val.value.as_sqword; case et_addr: return (qword_t)val.value.as_addr; case et_uint: return (qword_t)val.value.as_uint; case et_int: return (qword_t)val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}/* eval_value_t (any numeric type) -> sqword_t */sqword_teval_as_sqword(struct eval_value_t val){ switch (val.type) { case et_double: return (sqword_t)val.value.as_double; case et_float: return (sqword_t)val.value.as_float; case et_qword: return (sqword_t)val.value.as_qword; case et_sqword: return val.value.as_sqword; case et_addr: return (sqword_t)val.value.as_addr; case et_uint: return (sqword_t)val.value.as_uint; case et_int: return (sqword_t)val.value.as_int; case et_symbol: panic("symbol used in expression"); default: panic("illegal arithmetic expression conversion"); }}#endif /* HOST_HAS_QWORD *//* eval_value_t (any numeric type) -> unsigned int */md_addr_teval_as_addr(struct eval_value_t val){ switch (val.type) { case et_double:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -