"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

eval.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "host.h"
#include "misc.h"
#include "eval.h"

Include dependency graph for eval.c:

Include dependency graph

Go to the source code of this file.

Functions

Variables


Function Documentation

struct eval_value_t constant struct eval_state_t   es [static]
 

Definition at line 873 of file eval.c.

References ERR_BADCONST, et_double, et_int, et_uint, eval_error, eval_value_t::type, and eval_value_t::value.

Referenced by factor().

00874 {
00875   struct eval_value_t val;
00876   int int_val;
00877   unsigned int uint_val;
00878   double double_val;
00879   char *endp;
00880 #ifdef HOST_HAS_QWORD
00881   sqword_t sqword_val;
00882   qword_t qword_val;
00883 #endif /* HOST_HAS_QWORD */
00884 
00885 #if !defined(__CYGWIN32__)
00886   extern int errno;
00887 #endif
00888 #if 0 /* no longer needed... */
00889 #if defined(sparc) && !defined(__svr4__)
00890   extern long strtol(char *, char **, int);
00891   extern double strtod(char *, char **);
00892 #endif /* sparc */
00893 #endif
00894 
00895   /*
00896    * attempt multiple conversions, from least to most precise, using
00897    * the value returned when the conversion is successful
00898    */
00899 
00900   /* attempt integer conversion */
00901   errno = 0;
00902   int_val = strtol(es->tok_buf, &endp, /* parse base */0);
00903   if (!errno && !*endp)
00904     {
00905       /* good conversion */
00906       val.type = et_int;
00907       val.value.as_int = int_val;
00908       return val;
00909     }
00910 
00911   /* else, not an integer, attempt unsigned int conversion */
00912   errno = 0;
00913   uint_val = strtoul(es->tok_buf, &endp, /* parse base */0);
00914   if (!errno && !*endp)
00915     {
00916       /* good conversion */
00917       val.type = et_uint;
00918       val.value.as_uint = uint_val;
00919       return val;
00920     }
00921 
00922 #ifdef HOST_HAS_QWORD
00923   /* else, not an int/uint, attempt sqword_t conversion */
00924   errno = 0;
00925   sqword_val = myatosq(es->tok_buf, &endp, /* parse base */0);
00926   if (!errno && !*endp)
00927     {
00928       /* good conversion */
00929       val.type = et_sqword;
00930       val.value.as_sqword = sqword_val;
00931       return val;
00932     }
00933 
00934   /* else, not an sqword_t, attempt qword_t conversion */
00935   errno = 0;
00936   qword_val = myatoq(es->tok_buf, &endp, /* parse base */0);
00937   if (!errno && !*endp)
00938     {
00939       /* good conversion */
00940       val.type = et_qword;
00941       val.value.as_qword = qword_val;
00942       return val;
00943     }
00944 #endif /* HOST_HAS_QWORD */
00945 
00946   /* else, not any type of integer, attempt double conversion (NOTE: no
00947      reliable float conversion is available on all machines) */
00948   errno = 0;
00949   double_val = strtod(es->tok_buf, &endp);
00950   if (!errno && !*endp)
00951     {
00952       /* good conversion */
00953       val.type = et_double;
00954       val.value.as_double = double_val;
00955       return val;
00956     }
00957 
00958   /* else, not a double value, therefore, could not convert constant,
00959      declare an error */
00960   eval_error = ERR_BADCONST;
00961   return err_value;
00962 }

md_addr_t eval_as_addr struct eval_value_t    val
 

Definition at line 437 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by dlite_break(), dlite_cont(), dlite_dbreak(), dlite_dis(), dlite_display(), dlite_dump(), f_add(), f_div(), f_mult(), f_sub(), md_reg_obj(), and simoo_reg_obj().

00438 {
00439   switch (val.type)
00440     {
00441     case et_double:
00442       return (md_addr_t)val.value.as_double;
00443     case et_float:
00444       return (md_addr_t)val.value.as_float;
00445 #ifdef HOST_HAS_QWORD
00446     case et_qword:
00447       return (md_addr_t)val.value.as_qword;
00448     case et_sqword:
00449       return (md_addr_t)val.value.as_sqword;
00450 #endif /* HOST_HAS_QWORD */
00451     case et_addr:
00452       return val.value.as_addr;
00453     case et_uint:
00454       return (md_addr_t)val.value.as_uint;
00455     case et_int:
00456       return (md_addr_t)val.value.as_int;
00457     case et_symbol:
00458       panic("symbol used in expression");
00459     default:
00460       panic("illegal arithmetic expression conversion");
00461     }
00462 }

double eval_as_double struct eval_value_t    val
 

Definition at line 305 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by f_add(), f_div(), f_mult(), f_sub(), md_reg_obj(), and print_val().

00306 {
00307   switch (val.type)
00308     {
00309     case et_double:
00310       return val.value.as_double;
00311     case et_float:
00312       return (double)val.value.as_float;
00313 #ifdef HOST_HAS_QWORD
00314     case et_qword:
00315 #ifdef _MSC_VER /* FIXME: MSC does not implement qword_t to dbl conversion */
00316       return (double)(sqword_t)val.value.as_qword;
00317 #else /* !_MSC_VER */
00318       return (double)val.value.as_qword;
00319 #endif /* _MSC_VER */
00320     case et_sqword:
00321       return (double)val.value.as_sqword;
00322 #endif /* HOST_HAS_QWORD */
00323     case et_addr:
00324 #if defined(_MSC_VER) && defined(TARGET_ALPHA)
00325       /* FIXME: MSC does not implement qword_t to double conversion */
00326       return (double)(sqword_t)val.value.as_addr;
00327 #else
00328       return (double)val.value.as_addr;
00329 #endif
00330     case et_uint:
00331       return (double)val.value.as_uint;
00332     case et_int:
00333       return (double)val.value.as_int;
00334     case et_symbol:
00335       panic("symbol used in expression");
00336     default:
00337       panic("illegal arithmetic expression conversion");
00338     }
00339 }

float eval_as_float struct eval_value_t    val
 

Definition at line 343 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by f_add(), f_div(), f_mult(), f_sub(), md_reg_obj(), and print_val().

00344 {
00345   switch (val.type)
00346     {
00347     case et_double:
00348       return (float)val.value.as_double;
00349     case et_float:
00350       return val.value.as_float;
00351 #ifdef HOST_HAS_QWORD
00352     case et_qword:
00353 #ifdef _MSC_VER /* FIXME: MSC does not implement qword_t to dbl conversion */
00354       return (float)(sqword_t)val.value.as_qword;
00355 #else /* !_MSC_VER */
00356       return (float)val.value.as_qword;
00357 #endif /* _MSC_VER */
00358     case et_sqword:
00359       return (float)val.value.as_sqword;
00360 #endif /* HOST_HAS_QWORD */
00361     case et_addr:
00362 #if defined(_MSC_VER) && defined(TARGET_ALPHA)
00363       /* FIXME: MSC does not implement qword_t to double conversion */
00364       return (float)(sqword_t)val.value.as_addr;
00365 #else
00366       return (float)val.value.as_addr;
00367 #endif
00368     case et_uint:
00369       return (float)val.value.as_uint;
00370     case et_int:
00371       return (float)val.value.as_int;
00372     case et_symbol:
00373       panic("symbol used in expression");
00374     default:
00375       panic("illegal arithmetic expression conversion");
00376     }
00377 }

int eval_as_int struct eval_value_t    val
 

Definition at line 495 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by f_add(), f_div(), f_mult(), and f_sub().

00496 {
00497   switch (val.type)
00498     {
00499     case et_double:
00500       return (int)val.value.as_double;
00501     case et_float:
00502       return (int)val.value.as_float;
00503 #ifdef HOST_HAS_QWORD
00504     case et_qword:
00505       return (int)val.value.as_qword;
00506     case et_sqword:
00507       return (int)val.value.as_sqword;
00508 #endif /* HOST_HAS_QWORD */
00509     case et_addr:
00510       return (int)val.value.as_addr;
00511     case et_uint:
00512       return (int)val.value.as_uint;
00513     case et_int:
00514       return val.value.as_int;
00515     case et_symbol:
00516       panic("symbol used in expression");
00517     default:
00518       panic("illegal arithmetic expression conversion");
00519     }
00520 }

unsigned int eval_as_uint struct eval_value_t    val
 

Definition at line 466 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by dlite_delete(), dlite_dis(), dlite_dump(), f_add(), f_div(), f_mult(), f_sub(), md_reg_obj(), print_val(), and simoo_reg_obj().

00467 {
00468   switch (val.type)
00469     {
00470     case et_double:
00471       return (unsigned int)val.value.as_double;
00472     case et_float:
00473       return (unsigned int)val.value.as_float;
00474 #ifdef HOST_HAS_QWORD
00475     case et_qword:
00476       return (unsigned int)val.value.as_qword;
00477     case et_sqword:
00478       return (unsigned int)val.value.as_sqword;
00479 #endif /* HOST_HAS_QWORD */
00480     case et_addr:
00481       return (unsigned int)val.value.as_addr;
00482     case et_uint:
00483       return val.value.as_uint;
00484     case et_int:
00485       return (unsigned int)val.value.as_int;
00486     case et_symbol:
00487       panic("symbol used in expression");
00488     default:
00489       panic("illegal arithmetic expression conversion");
00490     }
00491 }

void eval_delete struct eval_state_t   es
 

Definition at line 1117 of file eval.c.

Referenced by ident_evaluator(), stat_delete(), stat_eval_ident(), and stat_print_stat().

01118 {
01119   free(es);
01120 }

struct eval_value_t eval_expr struct eval_state_t   es,
char *    p,
char **    endp
 

Definition at line 1125 of file eval.c.

References ERR_NOERR, eval_error, expr(), and tok_invalid.

Referenced by dlite_exec(), ident_evaluator(), stat_eval_ident(), and stat_print_stat().

01128 {
01129   struct eval_value_t val;
01130 
01131   /* initialize the evaluator state */
01132   eval_error = ERR_NOERR;
01133   es->p = p;
01134   *es->tok_buf = '\0';
01135   es->peek_tok = tok_invalid;
01136 
01137   /* evaluate the expression */
01138   val = expr(es);
01139 
01140   /* return a pointer to the first character not used in the expression */
01141   if (endp)
01142     {
01143       if (es->peek_tok != tok_invalid)
01144         {
01145           /* did not consume peek'ed token, so return last p */
01146           *endp = es->lastp;
01147         }
01148       else
01149         *endp = es->p;
01150     }
01151 
01152   return val;
01153 }

struct eval_state_t* eval_new eval_ident_t    f_eval_ident,
void *    user_ptr
 

Definition at line 1100 of file eval.c.

References eval_state_t::f_eval_ident, fatal(), and eval_state_t::user_ptr.

Referenced by dlite_init(), ident_evaluator(), stat_eval_ident(), stat_new(), and stat_print_stat().

01102 {
01103   struct eval_state_t *es;
01104 
01105   es = calloc(1, sizeof(struct eval_state_t));
01106   if (!es)
01107     fatal("out of virtual memory");
01108 
01109   es->f_eval_ident = f_eval_ident;
01110   es->user_ptr = user_ptr;
01111 
01112   return es;
01113 }

void eval_print FILE *    stream,
struct eval_value_t    val
 

Definition at line 1157 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, myfprintf(), panic(), eval_value_t::type, and eval_value_t::value.

01159 {
01160   switch (val.type)
01161     {
01162     case et_double:
01163       fprintf(stream, "%f [double]", val.value.as_double);
01164       break;
01165     case et_float:
01166       fprintf(stream, "%f [float]", (double)val.value.as_float);
01167       break;
01168 #ifdef HOST_HAS_QWORD
01169     case et_qword:
01170       myfprintf(stream, "%lu [qword_t]", val.value.as_qword);
01171       break;
01172     case et_sqword:
01173       myfprintf(stream, "%ld [sqword_t]", val.value.as_sqword);
01174       break;
01175 #endif /* HOST_HAS_QWORD */
01176     case et_addr:
01177       myfprintf(stream, "0x%p [md_addr_t]", val.value.as_addr);
01178       break;
01179     case et_uint:
01180       fprintf(stream, "%u [uint]", val.value.as_uint);
01181       break;
01182     case et_int:
01183       fprintf(stream, "%d [int]", val.value.as_int);
01184       break;
01185     case et_symbol:
01186       fprintf(stream, "\"%s\" [symbol]", val.value.as_symbol);
01187       break;
01188     default:
01189       panic("bogus expression type");
01190     }
01191 }

struct eval_value_t expr struct eval_state_t   es [static]
 

Definition at line 1066 of file eval.c.

References eval_token_t, f_add(), f_sub(), get_next_token(), peek_next_token(), term(), tok_minus, and tok_plus.

Referenced by eval_expr(), and factor().

01067 {
01068   enum eval_token_t tok;
01069   struct eval_value_t val;
01070 
01071   val = term(es);
01072   if (eval_error)
01073     return err_value;
01074 
01075   tok = peek_next_token(es);
01076   switch (tok)
01077     {
01078     case tok_plus:
01079       (void)get_next_token(es);
01080       val = f_add(val, expr(es));
01081       if (eval_error)
01082         return err_value;
01083       break;
01084 
01085     case tok_minus:
01086       (void)get_next_token(es);
01087       val = f_sub(val, expr(es));
01088       if (eval_error)
01089         return err_value;
01090       break;
01091 
01092     default:;
01093     }
01094 
01095   return val;
01096 }

struct eval_value_t f_add struct eval_value_t    val1,
struct eval_value_t    val2
[static]
 

Definition at line 528 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_as_addr(), eval_as_double(), eval_as_float(), eval_as_int(), eval_as_uint(), eval_error, eval_type_t, panic(), result_type(), eval_value_t::type, and eval_value_t::value.

Referenced by expr().

00529 {
00530   enum eval_type_t et;
00531   struct eval_value_t val;
00532 
00533   /* symbols are not allowed in arithmetic expressions */
00534   if (val1.type == et_symbol || val2.type == et_symbol)
00535     {
00536       eval_error = ERR_BADEXPR;
00537       return err_value;
00538     }
00539 
00540   /* get result type, and perform operation in that type */
00541   et = result_type(val1.type, val2.type);
00542   switch (et)
00543     {
00544     case et_double:
00545       val.type = et_double;
00546       val.value.as_double = eval_as_double(val1) + eval_as_double(val2);
00547       break;
00548     case et_float:
00549       val.type = et_float;
00550       val.value.as_float = eval_as_float(val1) + eval_as_float(val2);
00551       break;
00552 #ifdef HOST_HAS_QWORD
00553     case et_qword:
00554       val.type = et_qword;
00555       val.value.as_qword = eval_as_qword(val1) + eval_as_qword(val2);
00556       break;
00557     case et_sqword:
00558       val.type = et_sqword;
00559       val.value.as_sqword = eval_as_sqword(val1) + eval_as_sqword(val2);
00560       break;
00561 #endif /* HOST_HAS_QWORD */
00562     case et_addr:
00563       val.type = et_addr;
00564       val.value.as_addr = eval_as_addr(val1) + eval_as_addr(val2);
00565       break;
00566     case et_uint:
00567       val.type = et_uint;
00568       val.value.as_uint = eval_as_uint(val1) + eval_as_uint(val2);
00569       break;
00570     case et_int:
00571       val.type = et_int;
00572       val.value.as_int = eval_as_int(val1) + eval_as_int(val2);
00573       break;
00574     default:
00575       panic("bogus expression type");
00576     }
00577 
00578   return val;
00579 }

struct eval_value_t f_div struct eval_value_t    val1,
struct eval_value_t    val2
[static]
 

Definition at line 693 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_as_addr(), eval_as_double(), eval_as_float(), eval_as_int(), eval_as_uint(), eval_error, eval_type_t, panic(), result_type(), eval_value_t::type, and eval_value_t::value.

Referenced by term().

00694 {
00695   enum eval_type_t et;
00696   struct eval_value_t val;
00697 
00698   /* symbols are not allowed in arithmetic expressions */
00699   if (val1.type == et_symbol || val2.type == et_symbol)
00700     {
00701       eval_error = ERR_BADEXPR;
00702       return err_value;
00703     }
00704 
00705   /* get result type, and perform operation in that type */
00706   et = result_type(val1.type, val2.type);
00707   switch (et)
00708     {
00709     case et_double:
00710       val.type = et_double;
00711       val.value.as_double = eval_as_double(val1) / eval_as_double(val2);
00712       break;
00713     case et_float:
00714       val.type = et_float;
00715       val.value.as_float = eval_as_float(val1) / eval_as_float(val2);
00716       break;
00717 #ifdef HOST_HAS_QWORD
00718     case et_qword:
00719       val.type = et_qword;
00720       val.value.as_qword = eval_as_qword(val1) / eval_as_qword(val2);
00721       break;
00722     case et_sqword:
00723       val.type = et_sqword;
00724       val.value.as_sqword = eval_as_sqword(val1) / eval_as_sqword(val2);
00725       break;
00726 #endif /* HOST_HAS_QWORD */
00727     case et_addr:
00728       val.type = et_addr;
00729       val.value.as_addr = eval_as_addr(val1) / eval_as_addr(val2);
00730       break;
00731     case et_uint:
00732       val.type = et_uint;
00733       val.value.as_uint = eval_as_uint(val1) / eval_as_uint(val2);
00734       break;
00735     case et_int:
00736       val.type = et_int;
00737       val.value.as_int = eval_as_int(val1) / eval_as_int(val2);
00738       break;
00739     default:
00740       panic("bogus expression type");
00741     }
00742 
00743   return val;
00744 }

int f_eq_zero struct eval_value_t    val1 [static]
 

Definition at line 826 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_error, FALSE, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by term().

00827 {
00828   int val;
00829 
00830   /* symbols are not allowed in arithmetic expressions */
00831   if (val1.type == et_symbol)
00832     {
00833       eval_error = ERR_BADEXPR;
00834       return FALSE;
00835     }
00836 
00837   switch (val1.type)
00838     {
00839     case et_double:
00840       val = val1.value.as_double == 0.0;
00841       break;
00842     case et_float:
00843       val = val1.value.as_float == 0.0;
00844       break;
00845 #ifdef HOST_HAS_QWORD
00846     case et_qword:
00847       val = val1.value.as_qword == 0;
00848       break;
00849     case et_sqword:
00850       val = val1.value.as_sqword == 0;
00851       break;
00852 #endif /* HOST_HAS_QWORD */
00853     case et_addr:
00854       val = val1.value.as_addr == 0;
00855       break;
00856     case et_uint:
00857       val = val1.value.as_uint == 0;
00858       break;
00859     case et_int:
00860       val = val1.value.as_int == 0;
00861       break;
00862     default:
00863       panic("bogus expression type");
00864     }
00865 
00866   return val;
00867 }

struct eval_value_t f_mult struct eval_value_t    val1,
struct eval_value_t    val2
[static]
 

Definition at line 638 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_as_addr(), eval_as_double(), eval_as_float(), eval_as_int(), eval_as_uint(), eval_error, eval_type_t, panic(), result_type(), eval_value_t::type, and eval_value_t::value.

Referenced by term().

00639 {
00640   enum eval_type_t et;
00641   struct eval_value_t val;
00642 
00643   /* symbols are not allowed in arithmetic expressions */
00644   if (val1.type == et_symbol || val2.type == et_symbol)
00645     {
00646       eval_error = ERR_BADEXPR;
00647       return err_value;
00648     }
00649 
00650   /* get result type, and perform operation in that type */
00651   et = result_type(val1.type, val2.type);
00652   switch (et)
00653     {
00654     case et_double:
00655       val.type = et_double;
00656       val.value.as_double = eval_as_double(val1) * eval_as_double(val2);
00657       break;
00658     case et_float:
00659       val.type = et_float;
00660       val.value.as_float = eval_as_float(val1) * eval_as_float(val2);
00661       break;
00662 #ifdef HOST_HAS_QWORD
00663     case et_qword:
00664       val.type = et_qword;
00665       val.value.as_qword = eval_as_qword(val1) * eval_as_qword(val2);
00666       break;
00667     case et_sqword:
00668       val.type = et_sqword;
00669       val.value.as_sqword = eval_as_sqword(val1) * eval_as_sqword(val2);
00670       break;
00671 #endif /* HOST_HAS_QWORD */
00672     case et_addr:
00673       val.type = et_addr;
00674       val.value.as_addr = eval_as_addr(val1) * eval_as_addr(val2);
00675       break;
00676     case et_uint:
00677       val.type = et_uint;
00678       val.value.as_uint = eval_as_uint(val1) * eval_as_uint(val2);
00679       break;
00680     case et_int:
00681       val.type = et_int;
00682       val.value.as_int = eval_as_int(val1) * eval_as_int(val2);
00683       break;
00684     default:
00685       panic("bogus expression type");
00686     }
00687 
00688   return val;
00689 }

struct eval_value_t f_neg struct eval_value_t    val1 [static]
 

Definition at line 748 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_error, panic(), eval_value_t::type, and eval_value_t::value.

Referenced by factor().

00749 {
00750   struct eval_value_t val;
00751 
00752   /* symbols are not allowed in arithmetic expressions */
00753   if (val1.type == et_symbol)
00754     {
00755       eval_error = ERR_BADEXPR;
00756       return err_value;
00757     }
00758 
00759   /* result type is the same as the operand type */
00760   switch (val1.type)
00761     {
00762     case et_double:
00763       val.type = et_double;
00764       val.value.as_double = - val1.value.as_double;
00765       break;
00766     case et_float:
00767       val.type = et_float;
00768       val.value.as_float = - val1.value.as_float;
00769       break;
00770 #ifdef HOST_HAS_QWORD
00771     case et_qword:
00772       val.type = et_sqword;
00773       val.value.as_qword = - (sqword_t)val1.value.as_qword;
00774       break;
00775     case et_sqword:
00776       val.type = et_sqword;
00777       val.value.as_sqword = - val1.value.as_sqword;
00778       break;
00779 #endif /* HOST_HAS_QWORD */
00780     case et_addr:
00781       val.type = et_addr;
00782       val.value.as_addr = - val1.value.as_addr;
00783       break;
00784     case et_uint:
00785       if ((unsigned int)val1.value.as_uint > 2147483648U)
00786         {
00787           /* promote type */
00788 #ifdef HOST_HAS_QWORD
00789           val.type = et_sqword;
00790           val.value.as_sqword = - ((sqword_t)val1.value.as_uint);
00791 #else /* !HOST_HAS_QWORD */
00792           val.type = et_double;
00793           val.value.as_double = - ((double)val1.value.as_uint);
00794 #endif /* HOST_HAS_QWORD */
00795         }
00796       else
00797         {
00798           /* don't promote type */
00799           val.type = et_int;
00800           val.value.as_int = - ((int)val1.value.as_uint);
00801         }
00802       break;
00803     case et_int:
00804       if ((unsigned int)val1.value.as_int == 0x80000000U)
00805         {
00806           /* promote type */
00807           val.type = et_uint;
00808           val.value.as_uint = 2147483648U;
00809         }
00810       else
00811         {
00812           /* don't promote type */
00813           val.type = et_int;
00814           val.value.as_int = - val1.value.as_int;
00815         }
00816       break;
00817     default:
00818       panic("bogus expression type");
00819     }
00820 
00821   return val;
00822 }

struct eval_value_t f_sub struct eval_value_t    val1,
struct eval_value_t    val2
[static]
 

Definition at line 583 of file eval.c.

References ERR_BADEXPR, et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_as_addr(), eval_as_double(), eval_as_float(), eval_as_int(), eval_as_uint(), eval_error, eval_type_t, panic(), result_type(), eval_value_t::type, and eval_value_t::value.

Referenced by expr().

00584 {
00585   enum eval_type_t et;
00586   struct eval_value_t val;
00587 
00588   /* symbols are not allowed in arithmetic expressions */
00589   if (val1.type == et_symbol || val2.type == et_symbol)
00590     {
00591       eval_error = ERR_BADEXPR;
00592       return err_value;
00593     }
00594 
00595   /* get result type, and perform operation in that type */
00596   et = result_type(val1.type, val2.type);
00597   switch (et)
00598     {
00599     case et_double:
00600       val.type = et_double;
00601       val.value.as_double = eval_as_double(val1) - eval_as_double(val2);
00602       break;
00603     case et_float:
00604       val.type = et_float;
00605       val.value.as_float = eval_as_float(val1) - eval_as_float(val2);
00606       break;
00607 #ifdef HOST_HAS_QWORD
00608     case et_qword:
00609       val.type = et_qword;
00610       val.value.as_qword = eval_as_qword(val1) - eval_as_qword(val2);
00611       break;
00612     case et_sqword:
00613       val.type = et_sqword;
00614       val.value.as_sqword = eval_as_sqword(val1) - eval_as_sqword(val2);
00615       break;
00616 #endif /* HOST_HAS_QWORD */
00617     case et_addr:
00618       val.type = et_addr;
00619       val.value.as_addr = eval_as_addr(val1) - eval_as_addr(val2);
00620       break;
00621     case et_uint:
00622       val.type = et_uint;
00623       val.value.as_uint = eval_as_uint(val1) - eval_as_uint(val2);
00624       break;
00625     case et_int:
00626       val.type = et_int;
00627       val.value.as_int = eval_as_int(val1) - eval_as_int(val2);
00628       break;
00629     default:
00630       panic("bogus expression type");
00631     }
00632 
00633   return val;
00634 }

struct eval_value_t factor struct eval_state_t   es [static]
 

Definition at line 967 of file eval.c.

References constant(), ERR_NOTERM, ERR_UPAREN, eval_error, eval_token_t, expr(), f_neg(), get_next_token(), peek_next_token(), tok_const, tok_cparen, tok_ident, tok_minus, and tok_oparen.

Referenced by term().

00968 {
00969   enum eval_token_t tok;
00970   struct eval_value_t val;
00971 
00972   tok = peek_next_token(es);
00973   switch (tok)
00974     {
00975     case tok_oparen:
00976       (void)get_next_token(es);
00977       val = expr(es);
00978       if (eval_error)
00979         return err_value;
00980 
00981       tok = peek_next_token(es);
00982       if (tok != tok_cparen)
00983         {
00984           eval_error = ERR_UPAREN;
00985           return err_value;
00986         }
00987       (void)get_next_token(es);
00988       break;
00989 
00990     case tok_minus:
00991       /* negation operator */
00992       (void)get_next_token(es);
00993       val = factor(es);
00994       if (eval_error)
00995         return err_value;
00996       val = f_neg(val);
00997       break;
00998 
00999     case tok_ident:
01000       (void)get_next_token(es);
01001       /* evaluate the identifier in TOK_BUF */
01002       val = es->f_eval_ident(es);
01003       if (eval_error)
01004         return err_value;
01005       break;
01006 
01007     case tok_const:
01008       (void)get_next_token(es);
01009       val = constant(es);
01010       if (eval_error)
01011         return err_value;
01012       break;
01013 
01014     default:
01015       eval_error = ERR_NOTERM;
01016       return err_value;
01017     }
01018 
01019   return val;
01020 }

enum eval_token_t get_next_token struct eval_state_t   es [static]
 

Definition at line 147 of file eval.c.

References eval_token_t, FALSE, init_tok_map(), eval_state_t::p, eval_state_t::peek_tok, eval_state_t::tok_buf, tok_const, tok_cparen, tok_div, tok_eof, tok_ident, tok_invalid, tok_map, tok_map_initialized, tok_minus, tok_mult, tok_oparen, tok_plus, tok_whitespace, and TRUE.

Referenced by expr(), factor(), peek_next_token(), and term().

00148 {
00149   int allow_hex;
00150   enum eval_token_t tok;
00151   char *ptok_buf, last_char;
00152 
00153   /* initialize the token map, if needed */
00154   if (!tok_map_initialized)
00155     {
00156       init_tok_map();
00157       tok_map_initialized = TRUE;
00158     }
00159 
00160   /* use the peek'ed token, if available, tok_buf should still be valid */
00161   if (es->peek_tok != tok_invalid)
00162     {
00163       tok = es->peek_tok;
00164       es->peek_tok = tok_invalid;
00165       return tok;
00166     }
00167 
00168   /* set up the token string space */
00169   ptok_buf = es->tok_buf;
00170   *ptok_buf = '\0';
00171 
00172   /* skip whitespace */
00173   while (*es->p && tok_map[(int)*es->p] == tok_whitespace)
00174     es->p++;
00175 
00176   /* end of token stream? */
00177   if (*es->p == '\0')
00178     return tok_eof;
00179 
00180   *ptok_buf++ = *es->p;
00181   tok = tok_map[(int)*es->p++];
00182   switch (tok)
00183     {
00184     case tok_ident:
00185       /* parse off next identifier */
00186       while (*es->p
00187              && (tok_map[(int)*es->p] == tok_ident
00188                  || tok_map[(int)*es->p] == tok_const))
00189         {
00190           *ptok_buf++ = *es->p++;
00191         }
00192       break;
00193     case tok_const:
00194       /* parse off next numeric literal */
00195       last_char = '\0';
00196       allow_hex = FALSE;
00197       while (*es->p &&
00198              (tok_map[(int)*es->p] == tok_const
00199               || (*es->p == '-' && last_char == 'e')
00200               || (*es->p == '+' && last_char == 'e')
00201               || tolower(*es->p) == 'e'
00202               || tolower(*es->p) == 'x'
00203               || (tolower(*es->p) == 'a' && allow_hex)
00204               || (tolower(*es->p) == 'b' && allow_hex)
00205               || (tolower(*es->p) == 'c' && allow_hex)
00206               || (tolower(*es->p) == 'd' && allow_hex)
00207               || (tolower(*es->p) == 'e' && allow_hex)
00208               || (tolower(*es->p) == 'f' && allow_hex)))
00209         {
00210           last_char = tolower(*es->p);
00211           if (*es->p == 'x' || *es->p == 'X')
00212             allow_hex = TRUE;
00213           *ptok_buf++ = *es->p++;
00214         }
00215       break;
00216     case tok_plus:
00217     case tok_minus:
00218     case tok_mult:
00219     case tok_div:
00220     case tok_oparen:
00221     case tok_cparen:
00222       /* just pass on the token */
00223       break;
00224     default:
00225       tok = tok_invalid;
00226       break;
00227     }
00228 
00229   /* terminate the token string buffer */
00230   *ptok_buf = '\0';
00231 
00232   return tok;
00233 }

void init_tok_map void    [static]
 

Definition at line 112 of file eval.c.

References tok_const, tok_cparen, tok_div, tok_ident, tok_invalid, tok_map, tok_minus, tok_mult, tok_oparen, tok_plus, and tok_whitespace.

Referenced by get_next_token().

00113 {
00114   int i;
00115 
00116   for (i=0; i<256; i++)
00117     tok_map[i] = tok_invalid;
00118 
00119   /* identifier characters */
00120   for (i='a'; i<='z'; i++)
00121     tok_map[i] = tok_ident;
00122   for (i='A'; i<='Z'; i++)
00123     tok_map[i] = tok_ident;
00124   tok_map[(int)'_'] = tok_ident;
00125   tok_map[(int)'$'] = tok_ident;
00126 
00127   /* numeric characters */
00128   for (i='0'; i<='9'; i++)
00129     tok_map[i] = tok_const;
00130   tok_map[(int)'.'] = tok_const;
00131 
00132   /* operator characters */
00133   tok_map[(int)'+'] = tok_plus;
00134   tok_map[(int)'-'] = tok_minus;
00135   tok_map[(int)'*'] = tok_mult;
00136   tok_map[(int)'/'] = tok_div;
00137   tok_map[(int)'('] = tok_oparen;
00138   tok_map[(int)')'] = tok_cparen;
00139 
00140   /* whitespace characers */
00141   tok_map[(int)' '] = tok_whitespace;
00142   tok_map[(int)'\t'] = tok_whitespace;
00143 }

enum eval_token_t peek_next_token struct eval_state_t   es [static]
 

Definition at line 238 of file eval.c.

References get_next_token(), eval_state_t::lastp, eval_state_t::p, eval_state_t::peek_tok, and tok_invalid.

Referenced by expr(), factor(), and term().

00239 {
00240   /* if there is no peek ahead token, get one */
00241   if (es->peek_tok == tok_invalid)
00242     {
00243       es->lastp = es->p;
00244       es->peek_tok = get_next_token(es);
00245     }
00246 
00247   /* return peek ahead token */
00248   return es->peek_tok;
00249 }

enum eval_type_t result_type enum eval_type_t    t1,
enum eval_type_t    t2
[static]
 

Definition at line 273 of file eval.c.

References et_addr, et_double, et_float, et_int, et_symbol, et_uint, eval_type_t, and panic().

Referenced by f_add(), f_div(), f_mult(), and f_sub().

00275 {
00276   /* sanity check, symbols should not show up in arithmetic exprs */
00277   if (t1 == et_symbol || t2 == et_symbol)
00278     panic("symbol used in expression");
00279 
00280   /* using C rules, i.e., A6.5 */
00281   if (t1 == et_double || t2 == et_double)
00282     return et_double;
00283   else if (t1 == et_float || t2 == et_float)
00284     return et_float;
00285 #ifdef HOST_HAS_QWORD
00286   else if (t1 == et_qword || t2 == et_qword)
00287     return et_qword;
00288   else if (t1 == et_sqword || t2 == et_sqword)
00289     return et_sqword;
00290 #endif /* HOST_HAS_QWORD */
00291   else if (t1 == et_addr || t2 == et_addr)
00292     return et_addr;
00293   else if (t1 == et_uint || t2 == et_uint)
00294     return et_uint;
00295   else
00296     return et_int;
00297 }

struct eval_value_t term struct eval_state_t   es [static]
 

Definition at line 1025 of file eval.c.

References ERR_DIV0, eval_error, eval_token_t, f_div(), f_eq_zero(), f_mult(), factor(), get_next_token(), peek_next_token(), tok_div, and tok_mult.

Referenced by expr().

01026 {
01027   enum eval_token_t tok;
01028   struct eval_value_t val, val1;
01029 
01030   val = factor(es);
01031   if (eval_error)
01032     return err_value;
01033 
01034   tok = peek_next_token(es);
01035   switch (tok)
01036     {
01037     case tok_mult:
01038       (void)get_next_token(es);
01039       val = f_mult(val, term(es));
01040       if (eval_error)
01041         return err_value;
01042       break;
01043 
01044     case tok_div:
01045       (void)get_next_token(es);
01046       val1 = term(es);
01047       if (eval_error)
01048         return err_value;
01049       if (f_eq_zero(val1))
01050         {
01051           eval_error = ERR_DIV0;
01052           return err_value;
01053         }
01054       val = f_div(val, val1);
01055       break;
01056 
01057     default:;
01058     }
01059 
01060   return val;
01061 }


Variable Documentation

struct eval_value_t err_value = { et_int, { 0 } } [static]
 

Definition at line 255 of file eval.c.

char* eval_err_str[ERR_NUM]
 

Initial value:

 {
        "!! no error!!",
        "unmatched parenthesis",
        "expression term is missing",
        "divide by zero",
        "badly formed constant",
        "badly formed expression",
        "variable is undefined",
        "extra characters at end of expression"
}

Definition at line 95 of file eval.c.

enum eval_err_t eval_error = ERR_NOERR
 

Definition at line 92 of file eval.c.

Referenced by constant(), eval_expr(), f_add(), f_div(), f_eq_zero(), f_mult(), f_neg(), f_sub(), factor(), and term().

char* eval_type_str[et_NUM]
 

Initial value:

 {
                "int",
                "unsigned int",
                "md_addr_t",



 
        "float",
        "double",
        "symbol"
}

Definition at line 258 of file eval.c.

enum eval_token_t tok_map[256] [static]
 

Definition at line 107 of file eval.c.

Referenced by get_next_token(), and init_tok_map().

int tok_map_initialized = FALSE [static]
 

Definition at line 108 of file eval.c.

Referenced by get_next_token().



UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214