diff options
Diffstat (limited to 'interpret.h')
-rw-r--r-- | interpret.h | 237 |
1 files changed, 134 insertions, 103 deletions
diff --git a/interpret.h b/interpret.h index 67a702e3..009e6e10 100644 --- a/interpret.h +++ b/interpret.h @@ -1,37 +1,48 @@ /* - * interpret: - * code is a list of instructions to run. returns the exit value - * from the awk code. + * interpret.h --- run a list of instructions. */ - - /* N.B.: - * 1) reference counting done for both number and string values. - * 2) Stack operations: - * Use REPLACE[_XX] if last stack operation was TOP[_XX], - * PUSH[_XX] if last operation was POP[_XX] instead. - * 3) UPREF and DREF -- see awk.h + +/* + * Copyright (C) 1986, 1988, 1989, 1991-2012 the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + int r_interpret(INSTRUCTION *code) { INSTRUCTION *pc; /* current instruction */ + OPCODE op; /* current opcode */ NODE *r = NULL; NODE *m; INSTRUCTION *ni; NODE *t1, *t2; - NODE *f; /* function definition */ NODE **lhs; - AWKNUM x, x1, x2; + AWKNUM x, x2; int di; Regexp *rp; - int stdio_problem = FALSE; /* array subscript */ #define mk_sub(n) (n == 1 ? POP_SCALAR() : concat_exp(n, TRUE)) -#ifdef DEBUGGING -#define JUMPTO(x) do { post_execute(pc); pc = (x); goto top; } while (FALSE) +#ifdef EXEC_HOOK +#define JUMPTO(x) do { if (post_execute) post_execute(pc); pc = (x); goto top; } while (FALSE) #else #define JUMPTO(x) do { pc = (x); goto top; } while (FALSE) #endif @@ -51,12 +62,14 @@ top: if (pc->source_line > 0) sourceline = pc->source_line; -#ifdef DEBUGGING - if (! pre_execute(&pc)) - goto top; +#ifdef EXEC_HOOK + for (di = 0; di < num_exec_hook; di++) { + if (! pre_execute[di](& pc)) + goto top; + } #endif - switch (pc->opcode) { + switch ((op = pc->opcode)) { case Op_rule: currule = pc->in_rule; /* for sole use in Op_K_next, Op_K_nextfile, Op_K_getline */ /* fall through */ @@ -65,6 +78,9 @@ top: break; case Op_atexit: + { + int stdio_problem = FALSE; + /* avoid false source indications */ source = NULL; sourceline = 0; @@ -87,6 +103,7 @@ top: */ if (stdio_problem && ! exiting && exit_val == 0) exit_val = 1; + } break; case Op_stop: @@ -147,7 +164,7 @@ top: break; case Node_var_array: - if (pc->opcode == Op_push_arg) + if (op == Op_push_arg) PUSH(m); else fatal(_("attempt to use array `%s' in a scalar context"), @@ -303,8 +320,7 @@ top: t1 = POP_SCALAR(); di = eval_condition(t1); DEREF(t1); - if ((pc->opcode == Op_and && di) - || (pc->opcode == Op_or && ! di)) + if ((op == Op_and && di) || (op == Op_or && ! di)) break; r = node_Boolean[di]; UPREF(r); @@ -330,164 +346,175 @@ top: break; case Op_equal: - r = node_Boolean[cmp_scalar() == 0]; + r = node_Boolean[cmp_scalars() == 0]; UPREF(r); REPLACE(r); break; case Op_notequal: - r = node_Boolean[cmp_scalar() != 0]; + r = node_Boolean[cmp_scalars() != 0]; UPREF(r); REPLACE(r); break; case Op_less: - r = node_Boolean[cmp_scalar() < 0]; + r = node_Boolean[cmp_scalars() < 0]; UPREF(r); REPLACE(r); break; case Op_greater: - r = node_Boolean[cmp_scalar() > 0]; + r = node_Boolean[cmp_scalars() > 0]; UPREF(r); REPLACE(r); break; case Op_leq: - r = node_Boolean[cmp_scalar() <= 0]; + r = node_Boolean[cmp_scalars() <= 0]; UPREF(r); REPLACE(r); break; case Op_geq: - r = node_Boolean[cmp_scalar() >= 0]; + r = node_Boolean[cmp_scalars() >= 0]; UPREF(r); REPLACE(r); break; case Op_plus_i: - x2 = force_number(pc->memory); + x2 = force_number(pc->memory)->numbr; goto plus; - case Op_plus: - POP_NUMBER(x2); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); plus: - TOP_NUMBER(x1); - r = make_number(x1 + x2); + t1 = TOP_NUMBER(); + r = make_number(t1->numbr + x2); + DEREF(t1); REPLACE(r); break; case Op_minus_i: - x2 = force_number(pc->memory); + x2 = force_number(pc->memory)->numbr; goto minus; - case Op_minus: - POP_NUMBER(x2); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); minus: - TOP_NUMBER(x1); - r = make_number(x1 - x2); + t1 = TOP_NUMBER(); + r = make_number(t1->numbr - x2); + DEREF(t1); REPLACE(r); break; case Op_times_i: - x2 = force_number(pc->memory); + x2 = force_number(pc->memory)->numbr; goto times; - case Op_times: - POP_NUMBER(x2); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); times: - TOP_NUMBER(x1); - r = make_number(x1 * x2); + t1 = TOP_NUMBER(); + r = make_number(t1->numbr * x2); + DEREF(t1); REPLACE(r); break; case Op_exp_i: - x2 = force_number(pc->memory); - goto exponent; - + x2 = force_number(pc->memory)->numbr; + goto exp; case Op_exp: - POP_NUMBER(x2); -exponent: - TOP_NUMBER(x1); - x = calc_exp(x1, x2); - r = make_number(x); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); +exp: + t1 = TOP_NUMBER(); + r = make_number(calc_exp(t1->numbr, x2)); + DEREF(t1); REPLACE(r); break; case Op_quotient_i: - x2 = force_number(pc->memory); + x2 = force_number(pc->memory)->numbr; goto quotient; - case Op_quotient: - POP_NUMBER(x2); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); quotient: + t1 = TOP_NUMBER(); if (x2 == 0) fatal(_("division by zero attempted")); - - TOP_NUMBER(x1); - x = x1 / x2; - r = make_number(x); + r = make_number(t1->numbr / x2); + DEREF(t1); REPLACE(r); break; case Op_mod_i: - x2 = force_number(pc->memory); + x2 = force_number(pc->memory)->numbr; goto mod; - case Op_mod: - POP_NUMBER(x2); + t2 = POP_NUMBER(); + x2 = t2->numbr; + DEREF(t2); mod: + t1 = TOP_NUMBER(); if (x2 == 0) fatal(_("division by zero attempted in `%%'")); - - TOP_NUMBER(x1); #ifdef HAVE_FMOD - x = fmod(x1, x2); + x = fmod(t1->numbr, x2); #else /* ! HAVE_FMOD */ - (void) modf(x1 / x2, &x); - x = x1 - x * x2; + (void) modf(t1->numbr / x2, &x); + x = t1->numbr - x * x2; #endif /* ! HAVE_FMOD */ r = make_number(x); + + DEREF(t1); REPLACE(r); - break; + break; case Op_preincrement: case Op_predecrement: - x2 = pc->opcode == Op_preincrement ? 1.0 : -1.0; + x = op == Op_preincrement ? 1.0 : -1.0; lhs = TOP_ADDRESS(); t1 = *lhs; - x1 = force_number(t1); + force_number(t1); if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) { /* optimization */ - t1->numbr = x1 + x2; + t1->numbr += x; + r = t1; } else { + r = *lhs = make_number(t1->numbr + x); unref(t1); - t1 = *lhs = make_number(x1 + x2); } - UPREF(t1); - REPLACE(t1); + UPREF(r); + REPLACE(r); break; case Op_postincrement: case Op_postdecrement: - x2 = pc->opcode == Op_postincrement ? 1.0 : -1.0; + x = op == Op_postincrement ? 1.0 : -1.0; lhs = TOP_ADDRESS(); t1 = *lhs; - x1 = force_number(t1); + force_number(t1); + r = make_number(t1->numbr); if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) { - /* optimization */ - t1->numbr = x1 + x2; + /* optimization */ + t1->numbr += x; } else { + *lhs = make_number(t1->numbr + x); unref(t1); - *lhs = make_number(x1 + x2); } - r = make_number(x1); REPLACE(r); break; case Op_unary_minus: - TOP_NUMBER(x1); - r = make_number(-x1); + t1 = TOP_NUMBER(); + r = make_number(-t1->numbr); + DEREF(t1); REPLACE(r); break; @@ -532,7 +559,7 @@ mod: Func_ptr assign; t1 = TOP_SCALAR(); - lhs = r_get_field(t1, &assign, FALSE); + lhs = r_get_field(t1, & assign, FALSE); decr_sp(); DEREF(t1); unref(*lhs); @@ -555,7 +582,7 @@ mod: *lhs = dupnode(t1); } - if (t1 != t2 && t1->valref == 1) { + if (t1 != t2 && t1->valref == 1 && (t1->flags & MPFN) == 0) { size_t nlen = t1->stlen + t2->stlen; erealloc(t1->stptr, char *, nlen + 2, "r_interpret"); @@ -592,7 +619,7 @@ mod: case Op_assign_quotient: case Op_assign_mod: case Op_assign_exp: - op_assign(pc->opcode); + op_assign(op); break; case Op_var_update: /* update value of NR, FNR or NF */ @@ -601,8 +628,9 @@ mod: case Op_var_assign: case Op_field_assign: + r = TOP(); if (pc->assign_ctxt == Op_sub_builtin - && TOP()->numbr == 0.0 /* top of stack has a number == 0 */ + && get_number_si(r) == 0 /* top of stack has a number == 0 */ ) { /* There wasn't any substitutions. If the target is a FIELD, * this means no field re-splitting or $0 reconstruction. @@ -612,14 +640,14 @@ mod: break; } else if ((pc->assign_ctxt == Op_K_getline || pc->assign_ctxt == Op_K_getline_redir) - && TOP()->numbr <= 0.0 /* top of stack has a number <= 0 */ + && get_number_si(r) <= 0 /* top of stack has a number <= 0 */ ) { /* getline returned EOF or error */ break; } - if (pc->opcode == Op_var_assign) + if (op == Op_var_assign) pc->assign_var(); else pc->field_assign(); @@ -649,7 +677,6 @@ mod: if (di) { /* match found */ - t2 = POP_SCALAR(); DEREF(t2); JUMPTO(pc->target_jmp); @@ -671,9 +698,10 @@ mod: case Op_in_array: t1 = POP_ARRAY(); t2 = mk_sub(pc->expr_count); - di = (in_array(t1, t2) != NULL); + r = node_Boolean[(in_array(t1, t2) != NULL)]; DEREF(t2); - PUSH(make_number((AWKNUM) di)); + UPREF(r); + PUSH(r); break; case Op_arrayfor_init: @@ -816,8 +844,8 @@ match_re: di = research(rp, t1->stptr, 0, t1->stlen, avoid_dfa(m, t1->stptr, t1->stlen)); - di = (di == -1) ^ (pc->opcode != Op_nomatch); - if(pc->opcode != Op_match_rec) { + di = (di == -1) ^ (op != Op_nomatch); + if (op != Op_match_rec) { decr_sp(); DEREF(t1); } @@ -842,9 +870,9 @@ match_re: case Op_indirect_func_call: { + NODE *f = NULL; int arg_count; - f = NULL; arg_count = (pc + 1)->expr_count; t1 = PEEK(arg_count); /* indirect var */ assert(t1->type == Node_val); /* @a[1](p) not allowed in grammar */ @@ -855,7 +883,8 @@ match_re: if (f != NULL && strcmp(f->vname, t1->stptr) == 0) { /* indirect var hasn't been reassigned */ - goto func_call; + ni = setup_frame(pc); + JUMPTO(ni); /* Op_func */ } f = lookup(t1->stptr); } @@ -865,10 +894,14 @@ match_re: pc->func_name); pc->func_body = f; /* save for next call */ - goto func_call; + ni = setup_frame(pc); + JUMPTO(ni); /* Op_func */ } case Op_func_call: + { + NODE *f; + /* retrieve function definition node */ f = pc->func_body; if (f == NULL) { @@ -894,11 +927,9 @@ match_re: JUMPTO(ni); } -func_call: ni = setup_frame(pc); - - /* run the function instructions */ - JUMPTO(ni); /* Op_func */ + JUMPTO(ni); /* Op_func */ + } case Op_K_return: m = POP_SCALAR(); /* return value */ @@ -1074,8 +1105,9 @@ func_call: fatal(_("`exit' cannot be called in the current context")); exiting = TRUE; - POP_NUMBER(x1); - exit_val = (int) x1; + t1 = POP_NUMBER(); + exit_val = (int) get_number_si(t1); + DEREF(t1); #ifdef VMS if (exit_val == 0) exit_val = EXIT_SUCCESS; @@ -1171,7 +1203,7 @@ func_call: break; default: - fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(pc->opcode)); + fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(op)); } JUMPTO(pc->nexti); @@ -1184,4 +1216,3 @@ func_call: #undef mk_sub #undef JUMPTO } - |