static void op_pop_arg(int byte, struct thread *thread) { pop_arg(thread, decode_arg(thread)); }
static void op_pop_arg_immed(int byte, struct thread *thread) { pop_arg(thread, byte & 0x0f); }
/* Evaluate stacked arguments and operands */ static int do_op(void) { double arg1, arg2; int op; if (E_ERROR == pop_op(&op)) return E_ERROR; pop_arg(&arg1); pop_arg(&arg2); switch (op) { case '+': push_arg(arg2 + arg1); break; case '-': push_arg(arg2 - arg1); break; case '*': push_arg(arg2 * arg1); break; case '/': if (0.0 == arg1) return(DIV_ZERO); push_arg(arg2 / arg1); break; case '\\': if (0.0 == arg1) return R_ERROR; push_arg(fmod(arg2, arg1)); break; case '^': push_arg(pow(arg2, arg1)); break; case 't': ++arg_sptr; push_arg(atan(arg1)); break; case 'S': ++arg_sptr; push_arg(sin(arg1)); break; case 's': if (0.0 > arg2) return R_ERROR; ++arg_sptr; push_arg(sqrt(arg1)); break; case 'C': ++arg_sptr; push_arg(cos(arg1)); break; case 'A': ++arg_sptr; push_arg(fabs(arg1)); break; case 'L': if (0.0 < arg1) { ++arg_sptr; push_arg(log(arg1)); break; } else return R_ERROR; case 'E': ++arg_sptr; push_arg(exp(arg1)); break; case '(': arg_sptr += 2; break; default: return E_ERROR; } if (1 > arg_sptr) return E_ERROR; else return op; }
int evaluate(char *line, double *val) //-------------------------------------------------------------------- // Evaluates an ASCII mathematical expression // INPUT: line: String to evaluate // val: Storage to receive double result // // RETURN: SUCCESS = 0 if successful // E_ERROR = -1 if syntax error // R_ERROR = -2 if runtime error // DUV_ZERO= -3 Division by 0 // // Side effects: Removes all whitespace from the string and converts // it to U.C. //-------------------------------------------------------------------- { double arg; char *ptr = line, *str, *endptr; int ercode; struct operator *op; strupr(line); rmallws(line); state = op_sptr = arg_sptr = parens = 0; while (*ptr) { switch (state) { case 0: if (NULL != (str = get_exp(ptr))) { if (NULL != (op = get_op(str)) && strlen(str) == op->taglen) { push_op(op->token); ptr += op->taglen; break; } if (SUCCESS == strcmp(str, "-")) { push_op(*str); ++ptr; break; } if (SUCCESS == strcmp(str, "PI")) push_arg(Pi); else { if (0.0 == (arg = strtod(str, &endptr)) && NULL == strchr(str, '0')) { return E_ERROR; } push_arg(arg); } ptr += strlen(str); } else return E_ERROR; state = 1; break; case 1: if (NULL != (op = get_op(ptr))) { if (')' == *ptr) { if (SUCCESS > (ercode = do_paren())) return ercode; } else { while (op_sptr && op->precedence <= getTOSprec()) { do_op(); } push_op(op->token); state = 0; } ptr += op->taglen; } else return E_ERROR; break; } } while (1 < arg_sptr) { if (SUCCESS > (ercode = do_op())) return ercode; } if (!op_sptr) return pop_arg(val); else return E_ERROR; }
struct Symbol* postfix_expression(struct PostfixExpression* node, struct Symbol** orig_symbol) { struct Symbol* symbol, *ref, *newSymbol = 0, *symbol1; switch (node->type) { case 0: return primary_expression(node->primaryExpression, orig_symbol); case 1: symbol = load_symbol(postfix_expression(node->postfixExpression, orig_symbol)); test_referenceable(symbol); ref = load_symbol(expression_func(node->expression)); *orig_symbol = new_symbol("", symbol->storage, 0, symbol->specifier, symbol->stars - 1, 0, 0); if (symbol->stars == 1) (*orig_symbol)->specifier = 32; ADDSTRING(" "); code_gen_symbol('%', *orig_symbol); ADDSTRING(" = getelementptr inbounds "); code_gen_type_specifier(symbol->specifier, 0, symbol->length, symbol->stars); ADDSTRING(" "); if (symbol->depth == 0) code_gen_symbol('@', symbol); else code_gen_symbol('%', symbol); if (symbol->length) ADDSTRING(", i32 0"); ADDSTRING(", "); test_integer(ref); code_gen_type_specifier(ref->specifier, 0, 0, 0); ADDSTRING(" "); code_gen_symbol('%', ref); ADDSTRING("\n"); ADDSTRING(" "); newSymbol = new_symbol("", 0, 2, symbol->specifier, symbol->stars - 1, 0, 0); newSymbol->reference = *orig_symbol; code_gen_symbol('%', newSymbol); ADDSTRING(" = load "); code_gen_type_specifier(symbol->specifier, 0, (*orig_symbol)->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', *orig_symbol); ADDSTRING(", align "); if (newSymbol->stars) { if (PTR_LENGTH == 8) { ADDSTRING("8\n"); } else { ADDSTRING("4\n"); } } else { int len = len_gen_type_specifier(newSymbol->specifier); sprintf(buf, "%d\n", len); ADDSTRING(buf); } return newSymbol; case 2: case 3: symbol = postfix_expression(node->postfixExpression, orig_symbol); test_functionable(symbol); if (node->type == 3) { argument_expression_list(node->argumentExpressionList, symbol->parameterlist); } if (!(symbol->specifier & 0x02)) { newSymbol = new_symbol("", symbol->storage, 2, symbol->specifier, symbol->stars, 0, symbol->length); ADDSTRING(" "); code_gen_symbol('%', newSymbol); ADDSTRING(" = call "); } else { ADDSTRING(" call "); newSymbol = symbol; } if (strcmp(symbol->name, "free") != 0) { code_gen_type_specifier(symbol->specifier, 0, symbol->length, symbol->stars); ADDSTRING(" "); if (strcmp(symbol->name, "printf") == 0 || strcmp(symbol->name, "scanf") == 0) { ADDSTRING("(i8*, ...)* "); } code_gen_symbol('@', symbol); } else { ADDSTRING("i32 ("); code_gen_type_specifier(symbol_arg[0]->specifier, 0, 0, symbol_arg[0]->stars); ADDSTRING(", ...)* bitcast (i32 (...)* @free to i32 ("); code_gen_type_specifier(symbol_arg[0]->specifier, 0, 0, symbol_arg[0]->stars); ADDSTRING(", ...)*)"); } ADDSTRING("("); if (node->type == 3) { pop_arg(); } ADDSTRING(")\n"); *orig_symbol = newSymbol; return newSymbol; case 4: case 5: // to do: struct return 0; case 6: case 7: symbol = load_symbol(postfix_expression(node->postfixExpression, orig_symbol)); test_changeable(*orig_symbol); symbol1 = new_symbol("", symbol->storage, 2, symbol->specifier, symbol->stars, 0, symbol->length); ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(" = "); if ((symbol->specifier & (3 << 6)) > 0) { ADDSTRING("f"); } if (node->type == 6) { ADDSTRING("add "); } else { ADDSTRING("sub "); } code_gen_type_specifier(symbol->specifier,1,symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol); ADDSTRING(", "); if ((symbol->specifier & (3 << 6)) > 0) { ADDSTRING("1.000000e+00\n"); } else { ADDSTRING("1\n"); } ADDSTRING(" store "); code_gen_type_specifier(symbol->specifier,0,symbol->length, symbol->stars); ADDSTRING(" "); code_gen_symbol('%', symbol1); ADDSTRING(", "); code_gen_type_specifier(symbol->specifier,0,symbol->length, symbol->stars); ADDSTRING("* "); code_gen_symbol('%', *orig_symbol); ADDSTRING(", align "); int l = len_gen_type_specifier(symbol->specifier); sprintf(buf, "%d", l); ADDSTRING(buf); ADDSTRING("\n"); return symbol; default: return 0; } }