⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 体系机构仿真
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -