void stack_minus() { if (num_stack_items() < 2) { eprintf("stack underflow error."); return; } bool arg1_success; bool arg2_success; int arg1 = get_stack_int(&arg1_success); int arg2 = get_stack_int(&arg2_success); /* Error is handled and printed in get_stack_int */ if (!arg1_success || !arg2_success) { return; } push_stack_int(arg2 - arg1); }
int scriptlet_run(hscriptlet *r) { r->it_stack = 0; r->it_syms = r->it_syms_save; r->level = 0; r->it = 0; double result = 1.0; int bc, nbr_params = 0, dummy = 0; bytecode value = NULL; bytecode val1 = NULL; bytecode val2 = NULL; int type1 = 0, type2 = 0; int done = 0; while (!done && (bc = nextbytecode_(r, &value, &nbr_params, &r->level)) != 0) { DEBUG printf("run level=%d, bc=%d nbr_params=%d\n", r->level, bc, nbr_params); if (nbr_params) { nextbytecode_(r, &val1, &dummy, &dummy); val1 = substitute(r, val1); type1 = val1->tc; nbr_params--; } if (nbr_params) { nextbytecode_(r, &val2, &dummy, &dummy); val2 = substitute(r, val2); type2 = val2->tc; nbr_params--; } switch(bc) { case empty_tc: { break; } case multiply_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1*v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "*", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (double)(type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=v1*v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "*", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "*", val2->str_val, result); } break; } case power_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=(long long)pow((double)v1,(double)v2)); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "*", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (double)(type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=pow(v1,v2)); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "*", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "*", val2->str_val, result); } break; } case divide_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "/", (double)v2, result); if (v2 == 0) return result = 0.0; push_stack_int(r, result=v1/v2); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (double)(type2==int_tc?val2->int_val:val2->real_val); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "/", (double)v2, result); if (v2 == 0.0) return 0.0; push_stack_real(r, result=v1/v2); } else { return result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "/", val2->str_val, result); } break; } case modulo_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1%v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "%", (double)v2, result); } else if (type1 == real_tc) { long long v1 = (long long)val1->real_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1%v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "%", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "%", val2->str_val, result); } break; } case assign_tc: { if (type2 == int_tc) { long long v2 = (long long)val2->int_val; sb_string_set(r->symtab, val1->str_val, (void*)val2); push_stack_int(r, result=v2); DEBUG printf("run %s %s '%g'\n", val1->str_val, "=", (double)v2); } else if (type2 == real_tc) { double v2 = val2->real_val; sb_string_set(r->symtab, val1->str_val, (void*)val2); push_stack_real(r, result=v2); DEBUG printf("run %s %s '%g'\n", val1->str_val, "=", (double)v2); } else if (type2 == string_tc) { const char *v2 = val2->str_val; void *v3 = NULL; if (sb_string_get(r->symtab, v2, &v3)) sb_string_set(r->symtab, val1->str_val, v3); else sb_string_set(r->symtab, val1->str_val, (void*)val2); push_stack_string(r, v2); result=0.0; DEBUG printf("run %s %s %s\n", val1->str_val, "=", v2); } else { push_stack_real(r, result=0.0); DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "+", val2->str_val, result); } break; } case add_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1+v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "+", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=v1+v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "+", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "+", val2->str_val, result); } break; } case subtract_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1-v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "-", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=v1-v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "-", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "-", val2->str_val, result); } break; } case eq_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1==v2?1:0); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "==", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1==v2?1:0); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "==", (double)v2, result); } else { const char *v1 = val1->str_val; const char *v2 = val2->str_val; push_stack_int(r, !strcmp(v1,v2)); DEBUG printf("run '%s' %s '%s' = %g\n", val1->str_val, "==", val2->str_val, result); } break; } case neq_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1!=v2?1:0); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "!=", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, result=v1!=v2?1:0); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "!=", (double)v2, result); } else { const char *v1 = val1->str_val; const char *v2 = val2->str_val; push_stack_int(r, strcmp(v1,v2)); DEBUG printf("run '%s' %s '%s' = %g\n", val1->str_val, "!=", val2->str_val, result); } break; } case if_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; result = (double)v1; DEBUG printf("run '%g' %s = %g\n", (double)v1, "if", result); } else { result = 0.0; DEBUG printf("runstr '%s' %s = %g\n", val1->str_val, "if", result); } if (!result) { int skip = 0, tmp_level = 0, tmp_code; while ((tmp_code = peekbytecode_(r, &tmp_level)) != 0) { if (tmp_level <= r->level) break; skipbytecode_(r); skip++; } } break; } case else_tc: { if (result) { int skip = 0, tmp_level = 0, tmp_code; while ((tmp_code = peekbytecode_(r, &tmp_level)) != 0) { if (tmp_level <= r->level) break; skipbytecode_(r); skip++; } } DEBUG printf("runstr %s = %g\n", "else", result); break; } case fi_tc: { DEBUG printf("runstr %s = %g\n", "fi", result); break; } case not_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; result = (double)!v1; DEBUG printf("run '%g' %s = %g\n", (double)v1, "!", result); if (!v1) done = 1; } else { result = 0.0; DEBUG printf("runstr '%s' %s = %g\n", val1->str_val, "!", result); } break; } case and_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1&&v2); result=(double)v1&&v2; DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "&&", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=v1&&v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "&&", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "&&", val2->str_val, result); } break; } case or_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1||v2); result=(double)(v1||v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "||", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=v1||v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "||", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "||", val2->str_val, result); } break; } case xor_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, (v1&&!v2) || (v2&&!v1)); result=(double)((v1&&!v2) || (v2&&!v1)); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "^^", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_real(r, result=(v1&&!v2) || (v2&&!v1)); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "^^", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "^^", val2->str_val, result); } break; } case bit_negate_tc: { if (type1 == int_tc) { unsigned long long v1 = val1->int_val; push_stack_int(r, ~v1); result=(double)~v1; DEBUG printf("run %s '%g' = %g\n", "~", (double)v1, result); } else { result = 0.0; DEBUG printf("runstr %s '%s' = %g\n", "~", val1->str_val, result); } break; } case bit_and_tc: { if (type1 == int_tc) { unsigned long long v1 = val1->int_val; unsigned long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1&v2); result=(double)(v1&v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "&", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "&", val2->str_val, result); } break; } case bit_or_tc: { if (type1 == int_tc) { unsigned long long v1 = val1->int_val; unsigned long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1|v2); result=(double)(v1|v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "|", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "|", val2->str_val, result); } break; } case bit_xor_tc: { if (type1 == int_tc) { unsigned long long v1 = val1->int_val; unsigned long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1^v2); result=(double)(v1^v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "^", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "^", val2->str_val, result); } break; } case lt_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1<v2); result=(double)(v1<v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "<", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1<v2); result=(double)(v1<v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "<", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "<", val2->str_val, result); } break; } case leq_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1<=v2); result=(double)(v1<=v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "<=", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1<=v2); result=(double)(v1<=v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "<=", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "<", val2->str_val, result); } break; } case gt_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1>v2); result=(double)(v1>v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1>v2); result=(double)(v1>v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, ">", val2->str_val, result); } break; } case geq_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1>=v2); result=(double)(v1>=v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">=", (double)v2, result); } else if (type1 == real_tc) { double v1 = val1->real_val; double v2 = (type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1>=v2); result=(double)(v1>=v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">=", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, ">=", val2->str_val, result); } break; } case shift_left_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1<<v2); result=(double)(v1<<v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, "<<", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, "<<", val2->str_val, result); } break; } case shift_right_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, v1>>v2); result=(double)(v1>>v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">>", (double)v2, result); } else { result = 0.0; DEBUG printf("runstr '%s' %s '%s' = %g\n", val1->str_val, ">>", val2->str_val, result); } break; } case logical_shift_right_tc: { if (type1 == int_tc) { long long v1 = val1->int_val; long long v2 = (long long)(type2==int_tc?val2->int_val:val2->real_val); push_stack_int(r, ((unsigned long long)v1)>>v2); result=(double)(((unsigned long long)v1)>>v2); DEBUG printf("run '%g' %s '%g' = %g\n", (double)v1, ">>>", (double)v2, result); } else {