Blame interpret.h

Packit Service f629e6
/*
Packit Service f629e6
 * interpret.h ---  run a list of instructions.
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
/* 
Packit Service f629e6
 * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
Packit Service f629e6
 * 
Packit Service f629e6
 * This file is part of GAWK, the GNU implementation of the
Packit Service f629e6
 * AWK Programming Language.
Packit Service f629e6
 *
Packit Service f629e6
 * GAWK is free software; you can redistribute it and/or modify
Packit Service f629e6
 * it under the terms of the GNU General Public License as published by
Packit Service f629e6
 * the Free Software Foundation; either version 3 of the License, or
Packit Service f629e6
 * (at your option) any later version.
Packit Service f629e6
 *
Packit Service f629e6
 * GAWK is distributed in the hope that it will be useful,
Packit Service f629e6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service f629e6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service f629e6
 * GNU General Public License for more details.
Packit Service f629e6
 *
Packit Service f629e6
 * You should have received a copy of the GNU General Public License
Packit Service f629e6
 * along with this program; if not, write to the Free Software
Packit Service f629e6
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
Packit Service f629e6
 */
Packit Service f629e6
Packit Service f629e6
/*
Packit Service f629e6
 * If "r" is a field, valref should normally be > 1, because the field is
Packit Service f629e6
 * created initially with valref 1, and valref should be bumped when it is
Packit Service f629e6
 * pushed onto the stack by Op_field_spec. On the other hand, if we are
Packit Service f629e6
 * assigning to $n, then Op_store_field calls unref(*lhs) before assigning
Packit Service f629e6
 * the new value, so that decrements valref. So if the RHS is a field with
Packit Service f629e6
 * valref 1, that effectively means that this is an assignment like "$n = $n",
Packit Service f629e6
 * so a no-op, other than triggering $0 reconstitution.
Packit Service f629e6
 */
Packit Service f629e6
#define UNFIELD(l, r) \
Packit Service f629e6
{ \
Packit Service f629e6
	/* if was a field, turn it into a var */ \
Packit Service f629e6
	if ((r->flags & MALLOC) != 0 || r->valref == 1) { \
Packit Service f629e6
		l = r; \
Packit Service f629e6
	} else { \
Packit Service f629e6
		l = dupnode(r); \
Packit Service f629e6
		DEREF(r); \
Packit Service f629e6
	} \
Packit Service f629e6
}
Packit Service f629e6
int
Packit Service f629e6
r_interpret(INSTRUCTION *code)
Packit Service f629e6
{
Packit Service f629e6
	INSTRUCTION *pc;   /* current instruction */
Packit Service f629e6
	OPCODE op;	/* current opcode */
Packit Service f629e6
	NODE *r = NULL;
Packit Service f629e6
	NODE *m;
Packit Service f629e6
	INSTRUCTION *ni;
Packit Service f629e6
	NODE *t1, *t2;
Packit Service f629e6
	NODE **lhs;
Packit Service f629e6
	AWKNUM x, x2;
Packit Service f629e6
	int di;
Packit Service f629e6
	Regexp *rp;
Packit Service f629e6
	NODE *set_array = NULL;	/* array with a post-assignment routine */
Packit Service f629e6
	NODE *set_idx = NULL;	/* the index of the array element */
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
/* array subscript */
Packit Service f629e6
#define mk_sub(n)  	(n == 1 ? POP_SCALAR() : concat_exp(n, true))
Packit Service f629e6
Packit Service f629e6
#ifdef EXEC_HOOK
Packit Service f629e6
#define JUMPTO(x)	do { if (post_execute) post_execute(pc); pc = (x); goto top; } while (false)
Packit Service f629e6
#else
Packit Service f629e6
#define JUMPTO(x)	do { pc = (x); goto top; } while (false)
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
	pc = code;
Packit Service f629e6
Packit Service f629e6
	/* N.B.: always use JUMPTO for next instruction, otherwise bad things
Packit Service f629e6
	 * may happen. DO NOT add a real loop (for/while) below to
Packit Service f629e6
	 * replace ' forever {'; this catches failure to use JUMPTO to execute
Packit Service f629e6
	 * next instruction (e.g. continue statement).
Packit Service f629e6
	 */
Packit Service f629e6
Packit Service f629e6
	/* loop until hit Op_stop instruction */
Packit Service f629e6
Packit Service f629e6
	/* forever {  */
Packit Service f629e6
top:
Packit Service f629e6
		if (pc->source_line > 0)
Packit Service f629e6
			sourceline = pc->source_line;
Packit Service f629e6
Packit Service f629e6
#ifdef EXEC_HOOK
Packit Service f629e6
		for (di = 0; di < num_exec_hook; di++) {
Packit Service f629e6
			if (! pre_execute[di](& pc))
Packit Service f629e6
				goto top;
Packit Service f629e6
		}
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
		switch ((op = pc->opcode)) {
Packit Service f629e6
		case Op_rule:
Packit Service f629e6
			currule = pc->in_rule;   /* for sole use in Op_K_next, Op_K_nextfile, Op_K_getline */
Packit Service f629e6
			/* fall through */
Packit Service f629e6
		case Op_func:
Packit Service f629e6
			source = pc->source_file;
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_atexit:
Packit Service f629e6
		{
Packit Service f629e6
			bool stdio_problem = false;
Packit Service f629e6
Packit Service f629e6
			/* avoid false source indications */
Packit Service f629e6
			source = NULL;
Packit Service f629e6
			sourceline = 0;
Packit Service f629e6
			(void) nextfile(& curfile, true);	/* close input data file */
Packit Service f629e6
			/*
Packit Service f629e6
			 * This used to be:
Packit Service f629e6
			 *
Packit Service f629e6
			 * if (close_io() != 0 && ! exiting && exit_val == 0)
Packit Service f629e6
			 *      exit_val = 1;
Packit Service f629e6
			 *
Packit Service f629e6
			 * Other awks don't care about problems closing open files
Packit Service f629e6
			 * and pipes, in that it doesn't affect their exit status.
Packit Service f629e6
			 * So we no longer do either.
Packit Service f629e6
			 */
Packit Service f629e6
			(void) close_io(& stdio_problem);
Packit Service f629e6
			/*
Packit Service f629e6
			 * However, we do want to exit non-zero if there was a problem
Packit Service f629e6
			 * with stdout/stderr, so we reinstate a slightly different
Packit Service f629e6
			 * version of the above:
Packit Service f629e6
			 */
Packit Service f629e6
			if (stdio_problem && ! exiting && exit_val == 0)
Packit Service f629e6
				exit_val = 1;
Packit Service f629e6
Packit Service f629e6
			close_extensions();
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_stop:
Packit Service f629e6
			return 0;
Packit Service f629e6
Packit Service f629e6
		case Op_push_i:
Packit Service f629e6
			m = pc->memory;
Packit Service f629e6
			if (! do_traditional && (m->flags & INTLSTR) != 0) {
Packit Service f629e6
				char *orig, *trans, save;
Packit Service f629e6
Packit Service f629e6
				save = m->stptr[m->stlen];
Packit Service f629e6
				m->stptr[m->stlen] = '\0';
Packit Service f629e6
				orig = m->stptr;
Packit Service f629e6
				trans = dgettext(TEXTDOMAIN, orig);
Packit Service f629e6
				m->stptr[m->stlen] = save;
Packit Service f629e6
				m = make_string(trans, strlen(trans));
Packit Service f629e6
			} else
Packit Service f629e6
				UPREF(m);
Packit Service f629e6
			PUSH(m);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_push:
Packit Service f629e6
		case Op_push_arg:
Packit Service f629e6
		case Op_push_arg_untyped:
Packit Service f629e6
		{
Packit Service f629e6
			NODE *save_symbol;
Packit Service f629e6
			bool isparam = false;
Packit Service f629e6
Packit Service f629e6
			save_symbol = m = pc->memory;
Packit Service f629e6
			if (m->type == Node_param_list) {
Packit Service f629e6
				isparam = true;
Packit Service f629e6
				save_symbol = m = GET_PARAM(m->param_cnt);
Packit Service f629e6
				if (m->type == Node_array_ref) {
Packit Service f629e6
					if (m->orig_array->type == Node_var) {
Packit Service f629e6
						/* gawk 'func f(x) { a = 10; print x; } BEGIN{ f(a) }' */
Packit Service f629e6
						goto uninitialized_scalar;
Packit Service f629e6
					}
Packit Service f629e6
					m = m->orig_array;
Packit Service f629e6
				}
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			switch (m->type) {
Packit Service f629e6
			case Node_var:
Packit Service f629e6
				if (do_lint && var_uninitialized(m))
Packit Service f629e6
					lintwarn(isparam ?
Packit Service f629e6
						_("reference to uninitialized argument `%s'") :
Packit Service f629e6
						_("reference to uninitialized variable `%s'"),
Packit Service f629e6
								save_symbol->vname);
Packit Service f629e6
				m = m->var_value;
Packit Service f629e6
				UPREF(m);
Packit Service f629e6
				PUSH(m);
Packit Service f629e6
				break;
Packit Service f629e6
Packit Service f629e6
			case Node_var_new:
Packit Service f629e6
uninitialized_scalar:
Packit Service f629e6
				if (op != Op_push_arg_untyped) {
Packit Service f629e6
					/* convert untyped to scalar */
Packit Service f629e6
					m->type = Node_var;
Packit Service f629e6
					m->var_value = dupnode(Nnull_string);
Packit Service f629e6
				}
Packit Service f629e6
				if (do_lint)
Packit Service f629e6
					lintwarn(isparam ?
Packit Service f629e6
						_("reference to uninitialized argument `%s'") :
Packit Service f629e6
						_("reference to uninitialized variable `%s'"),
Packit Service f629e6
								save_symbol->vname);
Packit Service f629e6
				if (op != Op_push_arg_untyped)
Packit Service f629e6
					m = dupnode(Nnull_string);
Packit Service f629e6
				PUSH(m);
Packit Service f629e6
				break;
Packit Service f629e6
Packit Service f629e6
			case Node_var_array:
Packit Service f629e6
				if (op == Op_push_arg || op == Op_push_arg_untyped)
Packit Service f629e6
					PUSH(m);
Packit Service f629e6
				else
Packit Service f629e6
					fatal(_("attempt to use array `%s' in a scalar context"),
Packit Service f629e6
							array_vname(save_symbol));
Packit Service f629e6
				break;
Packit Service f629e6
Packit Service f629e6
			default:
Packit Service f629e6
				cant_happen();
Packit Service f629e6
			}
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_push_param:		/* function argument */
Packit Service f629e6
			m = pc->memory;
Packit Service f629e6
			if (m->type == Node_param_list)
Packit Service f629e6
				m = GET_PARAM(m->param_cnt);
Packit Service f629e6
			if (m->type == Node_var) {
Packit Service f629e6
				m = m->var_value;
Packit Service f629e6
				UPREF(m);
Packit Service f629e6
				PUSH(m);
Packit Service f629e6
		 		break;
Packit Service f629e6
			}
Packit Service f629e6
 			/* else
Packit Service f629e6
				fall through */
Packit Service f629e6
		case Op_push_array:
Packit Service f629e6
			PUSH(pc->memory);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_push_lhs:
Packit Service f629e6
			lhs = get_lhs(pc->memory, pc->do_reference);
Packit Service f629e6
			PUSH_ADDRESS(lhs);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_subscript:
Packit Service f629e6
			t2 = mk_sub(pc->sub_count);
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
Packit Service f629e6
			if (do_lint && in_array(t1, t2) == NULL) {
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
Packit Service f629e6
					array_vname(t1), (int) t2->stlen, t2->stptr);
Packit Service f629e6
				if (t2->stlen == 0)
Packit Service f629e6
					lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			/* for FUNCTAB, get the name as the element value */
Packit Service f629e6
			if (t1 == func_table) {
Packit Service f629e6
				static bool warned = false;
Packit Service f629e6
Packit Service f629e6
				if (do_lint && ! warned) {
Packit Service f629e6
					warned = true;
Packit Service f629e6
					lintwarn(_("FUNCTAB is a gawk extension"));
Packit Service f629e6
				}
Packit Service f629e6
				r = t2;
Packit Service f629e6
			} else {
Packit Service f629e6
				/* make sure stuff like NF, NR, are up to date */
Packit Service f629e6
				if (t1 == symbol_table)
Packit Service f629e6
					update_global_values();
Packit Service f629e6
Packit Service f629e6
				r = *assoc_lookup(t1, t2);
Packit Service f629e6
			}
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
Packit Service f629e6
			/* for SYMTAB, step through to the actual variable */
Packit Service f629e6
			if (t1 == symbol_table) {
Packit Service f629e6
				static bool warned = false;
Packit Service f629e6
Packit Service f629e6
				if (do_lint && ! warned) {
Packit Service f629e6
					warned = true;
Packit Service f629e6
					lintwarn(_("SYMTAB is a gawk extension"));
Packit Service f629e6
				}
Packit Service f629e6
				if (r->type == Node_var)
Packit Service f629e6
					r = r->var_value;
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (r->type == Node_val)
Packit Service f629e6
				UPREF(r);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_sub_array:
Packit Service f629e6
			t2 = mk_sub(pc->sub_count);
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
			r = in_array(t1, t2);
Packit Service f629e6
			if (r == NULL) {
Packit Service f629e6
				r = make_array();
Packit Service f629e6
				r->parent_array = t1;
Packit Service f629e6
				lhs = assoc_lookup(t1, t2);
Packit Service f629e6
				unref(*lhs);
Packit Service f629e6
				*lhs = r;
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				r->vname = estrdup(t2->stptr, t2->stlen);	/* the subscript in parent array */
Packit Service f629e6
Packit Service f629e6
				/* execute post-assignment routine if any */
Packit Service f629e6
				if (t1->astore != NULL)
Packit Service f629e6
					(*t1->astore)(t1, t2);
Packit Service f629e6
			} else if (r->type != Node_var_array) {
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"),
Packit Service f629e6
						array_vname(t1), (int) t2->stlen, t2->stptr);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_subscript_lhs:
Packit Service f629e6
			t2 = mk_sub(pc->sub_count);
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
			if (do_lint && in_array(t1, t2) == NULL) {
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				if (pc->do_reference)
Packit Service f629e6
					lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
Packit Service f629e6
						array_vname(t1), (int) t2->stlen, t2->stptr);
Packit Service f629e6
				if (t2->stlen == 0)
Packit Service f629e6
					lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			lhs = assoc_lookup(t1, t2);
Packit Service f629e6
			if ((*lhs)->type == Node_var_array) {
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
Packit Service f629e6
						array_vname(t1), (int) t2->stlen, t2->stptr);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			/*
Packit Service f629e6
			 * Changing something in FUNCTAB is not allowed.
Packit Service f629e6
			 *
Packit Service f629e6
			 * SYMTAB is a little more messy.  Three kinds of values may
Packit Service f629e6
			 * be stored in SYMTAB:
Packit Service f629e6
			 * 	1. Variables that don"t yet have a value (Node_var_new)
Packit Service f629e6
			 * 	2. Variables that have a value (Node_var)
Packit Service f629e6
			 * 	3. Values that awk code stuck into SYMTAB not related to variables (Node_value)
Packit Service f629e6
			 * For 1, since we are giving it a value, we have to change the type to Node_var.
Packit Service f629e6
			 * For 1 and 2, we have to step through the Node_var to get to the value.
Packit Service f629e6
			 * For 3, we just us the value we got from assoc_lookup(), above.
Packit Service f629e6
			 */
Packit Service f629e6
			if (t1 == func_table)
Packit Service f629e6
				fatal(_("cannot assign to elements of FUNCTAB"));
Packit Service f629e6
			else if (   t1 == symbol_table
Packit Service f629e6
				 && (   (*lhs)->type == Node_var
Packit Service f629e6
				     || (*lhs)->type == Node_var_new)) {
Packit Service f629e6
				update_global_values();		/* make sure stuff like NF, NR, are up to date */
Packit Service f629e6
				(*lhs)->type = Node_var;	/* in case was Node_var_new */
Packit Service f629e6
				lhs = & ((*lhs)->var_value);	/* extra level of indirection */
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			assert(set_idx == NULL);
Packit Service f629e6
Packit Service f629e6
			if (t1->astore) {
Packit Service f629e6
				/* array has post-assignment routine */
Packit Service f629e6
				set_array = t1;
Packit Service f629e6
				set_idx = t2;
Packit Service f629e6
			} else
Packit Service f629e6
				DEREF(t2);
Packit Service f629e6
Packit Service f629e6
			PUSH_ADDRESS(lhs);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_field_spec:
Packit Service f629e6
			t1 = TOP_SCALAR();
Packit Service f629e6
			lhs = r_get_field(t1, (Func_ptr *) 0, true);
Packit Service f629e6
			decr_sp();
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			r = *lhs;
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_field_spec_lhs:
Packit Service f629e6
			t1 = TOP_SCALAR();
Packit Service f629e6
			lhs = r_get_field(t1, &pc->target_assign->field_assign, pc->do_reference);
Packit Service f629e6
			decr_sp();
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			PUSH_ADDRESS(lhs);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_lint:
Packit Service f629e6
			if (do_lint) {
Packit Service f629e6
				switch (pc->lint_type) {
Packit Service f629e6
				case LINT_assign_in_cond:
Packit Service f629e6
					lintwarn(_("assignment used in conditional context"));
Packit Service f629e6
					break;
Packit Service f629e6
Packit Service f629e6
				case LINT_no_effect:
Packit Service f629e6
					lintwarn(_("statement has no effect"));
Packit Service f629e6
					break;
Packit Service f629e6
Packit Service f629e6
				default:
Packit Service f629e6
					cant_happen();
Packit Service f629e6
				}
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_break:
Packit Service f629e6
		case Op_K_continue:
Packit Service f629e6
		case Op_jmp:
Packit Service f629e6
			assert(pc->target_jmp != NULL);
Packit Service f629e6
			JUMPTO(pc->target_jmp);
Packit Service f629e6
Packit Service f629e6
		case Op_jmp_false:
Packit Service f629e6
			r = POP_SCALAR();
Packit Service f629e6
			di = eval_condition(r);
Packit Service f629e6
			DEREF(r);
Packit Service f629e6
			if (! di)
Packit Service f629e6
				JUMPTO(pc->target_jmp);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_jmp_true:
Packit Service f629e6
			r = POP_SCALAR();
Packit Service f629e6
			di = eval_condition(r);
Packit Service f629e6
			DEREF(r);
Packit Service f629e6
			if (di)
Packit Service f629e6
				JUMPTO(pc->target_jmp);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_and:
Packit Service f629e6
		case Op_or:
Packit Service f629e6
			t1 = POP_SCALAR();
Packit Service f629e6
			di = eval_condition(t1);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			if ((op == Op_and && di) || (op == Op_or && ! di))
Packit Service f629e6
				break;
Packit Service f629e6
			r = node_Boolean[di];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			ni = pc->target_jmp;
Packit Service f629e6
			JUMPTO(ni->nexti);
Packit Service f629e6
Packit Service f629e6
		case Op_and_final:
Packit Service f629e6
		case Op_or_final:
Packit Service f629e6
			t1 = TOP_SCALAR();
Packit Service f629e6
			r = node_Boolean[eval_condition(t1)];
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_not:
Packit Service f629e6
			t1 = TOP_SCALAR();
Packit Service f629e6
			r = node_Boolean[! eval_condition(t1)];
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_equal:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) == 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_notequal:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) != 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_less:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) < 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_greater:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) > 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_leq:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) <= 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_geq:
Packit Service f629e6
			r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) >= 0];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_plus_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto plus;
Packit Service f629e6
		case Op_plus:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
plus:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(t1->numbr + x2);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_minus_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto minus;
Packit Service f629e6
		case Op_minus:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
minus:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(t1->numbr - x2);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_times_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto times;
Packit Service f629e6
		case Op_times:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
times:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(t1->numbr * x2);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_exp_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto exp;
Packit Service f629e6
		case Op_exp:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
exp:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(calc_exp(t1->numbr, x2));
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_quotient_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto quotient;
Packit Service f629e6
		case Op_quotient:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
quotient:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			if (x2 == 0)
Packit Service f629e6
				fatal(_("division by zero attempted"));
Packit Service f629e6
			r = make_number(t1->numbr / x2);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_mod_i:
Packit Service f629e6
			x2 = force_number(pc->memory)->numbr;
Packit Service f629e6
			goto mod;
Packit Service f629e6
		case Op_mod:
Packit Service f629e6
			t2 = POP_NUMBER();
Packit Service f629e6
			x2 = t2->numbr;
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
mod:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			if (x2 == 0)
Packit Service f629e6
				fatal(_("division by zero attempted in `%%'"));
Packit Service f629e6
#ifdef HAVE_FMOD
Packit Service f629e6
			x = fmod(t1->numbr, x2);
Packit Service f629e6
#else	/* ! HAVE_FMOD */
Packit Service f629e6
			(void) modf(t1->numbr / x2, &x);
Packit Service f629e6
			x = t1->numbr - x * x2;
Packit Service f629e6
#endif	/* ! HAVE_FMOD */
Packit Service f629e6
			r = make_number(x);
Packit Service f629e6
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_preincrement:
Packit Service f629e6
		case Op_predecrement:
Packit Service f629e6
			x = op == Op_preincrement ? 1.0 : -1.0;
Packit Service f629e6
			lhs = TOP_ADDRESS();
Packit Service f629e6
			t1 = *lhs;
Packit Service f629e6
			force_number(t1);
Packit Service f629e6
			if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
Packit Service f629e6
				/* optimization */
Packit Service f629e6
				t1->numbr += x;
Packit Service f629e6
				r = t1;
Packit Service f629e6
			} else {
Packit Service f629e6
				r = *lhs = make_number(t1->numbr + x);
Packit Service f629e6
				unref(t1);
Packit Service f629e6
			}
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_postincrement:
Packit Service f629e6
		case Op_postdecrement:
Packit Service f629e6
			x = op == Op_postincrement ? 1.0 : -1.0;
Packit Service f629e6
			lhs = TOP_ADDRESS();
Packit Service f629e6
			t1 = *lhs;
Packit Service f629e6
			force_number(t1);
Packit Service f629e6
			r = make_number(t1->numbr);
Packit Service f629e6
			if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) {
Packit Service f629e6
 				/* optimization */
Packit Service f629e6
				t1->numbr += x;
Packit Service f629e6
			} else {
Packit Service f629e6
				*lhs = make_number(t1->numbr + x);
Packit Service f629e6
				unref(t1);
Packit Service f629e6
			}
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_unary_minus:
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(-t1->numbr);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_unary_plus:
Packit Service f629e6
			// Force argument to be numeric
Packit Service f629e6
			t1 = TOP_NUMBER();
Packit Service f629e6
			r = make_number(t1->numbr);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_store_sub:
Packit Service f629e6
			/*
Packit Service f629e6
			 * array[sub] assignment optimization,
Packit Service f629e6
			 * see awkgram.y (optimize_assignment)
Packit Service f629e6
			 */
Packit Service f629e6
			t1 = force_array(pc->memory, true);	/* array */
Packit Service f629e6
			t2 = mk_sub(pc->expr_count);	/* subscript */
Packit Service f629e6
 			lhs = assoc_lookup(t1, t2);
Packit Service f629e6
			if ((*lhs)->type == Node_var_array) {
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				fatal(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
Packit Service f629e6
						array_vname(t1), (int) t2->stlen, t2->stptr);
Packit Service f629e6
			}
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
Packit Service f629e6
			/*
Packit Service f629e6
			 * Changing something in FUNCTAB is not allowed.
Packit Service f629e6
			 *
Packit Service f629e6
			 * SYMTAB is a little more messy.  Three kinds of values may
Packit Service f629e6
			 * be stored in SYMTAB:
Packit Service f629e6
			 * 	1. Variables that don"t yet have a value (Node_var_new)
Packit Service f629e6
			 * 	2. Variables that have a value (Node_var)
Packit Service f629e6
			 * 	3. Values that awk code stuck into SYMTAB not related to variables (Node_value)
Packit Service f629e6
			 * For 1, since we are giving it a value, we have to change the type to Node_var.
Packit Service f629e6
			 * For 1 and 2, we have to step through the Node_var to get to the value.
Packit Service f629e6
			 * For 3, we just us the value we got from assoc_lookup(), above.
Packit Service f629e6
			 */
Packit Service f629e6
			if (t1 == func_table)
Packit Service f629e6
				fatal(_("cannot assign to elements of FUNCTAB"));
Packit Service f629e6
			else if (   t1 == symbol_table
Packit Service f629e6
				 && (   (*lhs)->type == Node_var
Packit Service f629e6
				     || (*lhs)->type == Node_var_new)) {
Packit Service f629e6
				(*lhs)->type = Node_var;	/* in case was Node_var_new */
Packit Service f629e6
				lhs = & ((*lhs)->var_value);	/* extra level of indirection */
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			unref(*lhs);
Packit Service f629e6
			r = POP_SCALAR();
Packit Service f629e6
			UNFIELD(*lhs, r);
Packit Service f629e6
Packit Service f629e6
			/* execute post-assignment routine if any */
Packit Service f629e6
			if (t1->astore != NULL)
Packit Service f629e6
				(*t1->astore)(t1, t2);
Packit Service f629e6
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_store_var:
Packit Service f629e6
			/*
Packit Service f629e6
			 * simple variable assignment optimization,
Packit Service f629e6
			 * see awkgram.y (optimize_assignment)
Packit Service f629e6
			 */
Packit Service f629e6
Packit Service f629e6
			lhs = get_lhs(pc->memory, false);
Packit Service f629e6
			unref(*lhs);
Packit Service f629e6
			r = pc->initval;	/* constant initializer */
Packit Service f629e6
			if (r != NULL) {
Packit Service f629e6
				UPREF(r);
Packit Service f629e6
				*lhs = r;
Packit Service f629e6
			} else {
Packit Service f629e6
				r = POP_SCALAR();
Packit Service f629e6
				UNFIELD(*lhs, r);
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_store_field:
Packit Service f629e6
		{
Packit Service f629e6
			/* field assignment optimization,
Packit Service f629e6
			 * see awkgram.y (optimize_assignment)
Packit Service f629e6
			 */
Packit Service f629e6
Packit Service f629e6
			Func_ptr assign;
Packit Service f629e6
			t1 = TOP_SCALAR();
Packit Service f629e6
			lhs = r_get_field(t1, & assign, false);
Packit Service f629e6
			decr_sp();
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
			/*
Packit Service f629e6
			 * N.B. We must call assign() before unref, since
Packit Service f629e6
			 * we may need to copy $n values before freeing the
Packit Service f629e6
			 * $0 buffer.
Packit Service f629e6
			 */
Packit Service f629e6
			assert(assign != NULL);
Packit Service f629e6
			assign();
Packit Service f629e6
			unref(*lhs);
Packit Service f629e6
			r = POP_SCALAR();
Packit Service f629e6
			UNFIELD(*lhs, r);
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_assign_concat:
Packit Service f629e6
			/* x = x ... string concatenation optimization */
Packit Service f629e6
			lhs = get_lhs(pc->memory, false);
Packit Service f629e6
			t1 = force_string(*lhs);
Packit Service f629e6
			t2 = POP_STRING();
Packit Service f629e6
Packit Service f629e6
			if (t1 != *lhs) {
Packit Service f629e6
				unref(*lhs);
Packit Service f629e6
				*lhs = dupnode(t1);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (t1 != t2 && t1->valref == 1 && (t1->flags & (MALLOC|MPFN|MPZN)) == MALLOC) {
Packit Service f629e6
				size_t nlen = t1->stlen + t2->stlen;
Packit Service f629e6
Packit Service f629e6
				erealloc(t1->stptr, char *, nlen + 1, "r_interpret");
Packit Service f629e6
				memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen);
Packit Service f629e6
				t1->stlen = nlen;
Packit Service f629e6
				t1->stptr[nlen] = '\0';
Packit Service f629e6
				/* clear flags except WSTRCUR (used below) */
Packit Service f629e6
				t1->flags &= WSTRCUR;
Packit Service f629e6
				/* configure as a string as in make_str_node */
Packit Service f629e6
				t1->flags |= (MALLOC|STRING|STRCUR);
Packit Service f629e6
				t1->stfmt = STFMT_UNUSED;
Packit Service f629e6
#ifdef HAVE_MPFR
Packit Service f629e6
				t1->strndmode = MPFR_round_mode;
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
				if ((t1->flags & WSTRCUR) != 0 && (t2->flags & WSTRCUR) != 0) {
Packit Service f629e6
					size_t wlen = t1->wstlen + t2->wstlen;
Packit Service f629e6
Packit Service f629e6
					erealloc(t1->wstptr, wchar_t *,
Packit Service f629e6
							sizeof(wchar_t) * (wlen + 1), "r_interpret");
Packit Service f629e6
					memcpy(t1->wstptr + t1->wstlen, t2->wstptr, t2->wstlen * sizeof(wchar_t));
Packit Service f629e6
					t1->wstlen = wlen;
Packit Service f629e6
					t1->wstptr[wlen] = L'\0';
Packit Service f629e6
				} else
Packit Service f629e6
					free_wstr(*lhs);
Packit Service f629e6
			} else {
Packit Service f629e6
				size_t nlen = t1->stlen + t2->stlen;
Packit Service f629e6
				char *p;
Packit Service f629e6
Packit Service f629e6
				emalloc(p, char *, nlen + 1, "r_interpret");
Packit Service f629e6
				memcpy(p, t1->stptr, t1->stlen);
Packit Service f629e6
				memcpy(p + t1->stlen, t2->stptr, t2->stlen);
Packit Service f629e6
				/* N.B. No NUL-termination required, since make_str_node will do it. */
Packit Service f629e6
				unref(*lhs);
Packit Service f629e6
				t1 = *lhs = make_str_node(p, nlen, ALREADY_MALLOCED);
Packit Service f629e6
			}
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_assign:
Packit Service f629e6
			lhs = POP_ADDRESS();
Packit Service f629e6
			r = TOP_SCALAR();
Packit Service f629e6
			unref(*lhs);
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			UNFIELD(*lhs, r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_subscript_assign:
Packit Service f629e6
			/* conditionally execute post-assignment routine for an array element */
Packit Service f629e6
Packit Service f629e6
			if (set_idx != NULL) {
Packit Service f629e6
				di = true;
Packit Service f629e6
				if (pc->assign_ctxt == Op_sub_builtin
Packit Service f629e6
					&& (r = TOP())
Packit Service f629e6
					&& get_number_si(r) == 0	/* no substitution performed */
Packit Service f629e6
				)
Packit Service f629e6
					di = false;
Packit Service f629e6
				else if ((pc->assign_ctxt == Op_K_getline
Packit Service f629e6
						|| pc->assign_ctxt == Op_K_getline_redir)
Packit Service f629e6
					&& (r = TOP())
Packit Service f629e6
					&& get_number_si(r) <= 0 	/* EOF or error */
Packit Service f629e6
				)
Packit Service f629e6
					di = false;
Packit Service f629e6
Packit Service f629e6
				if (di)
Packit Service f629e6
					(*set_array->astore)(set_array, set_idx);
Packit Service f629e6
				unref(set_idx);
Packit Service f629e6
				set_idx = NULL;
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		/* numeric assignments */
Packit Service f629e6
		case Op_assign_plus:
Packit Service f629e6
		case Op_assign_minus:
Packit Service f629e6
		case Op_assign_times:
Packit Service f629e6
		case Op_assign_quotient:
Packit Service f629e6
		case Op_assign_mod:
Packit Service f629e6
		case Op_assign_exp:
Packit Service f629e6
			op_assign(op);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_var_update:        /* update value of NR, FNR or NF */
Packit Service f629e6
			pc->update_var();
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_var_assign:
Packit Service f629e6
		case Op_field_assign:
Packit Service f629e6
			r = TOP();
Packit Service f629e6
			if (pc->assign_ctxt == Op_sub_builtin
Packit Service f629e6
				&& get_number_si(r) == 0	/* top of stack has a number == 0 */
Packit Service f629e6
			) {
Packit Service f629e6
				/* There wasn't any substitutions. If the target is a FIELD,
Packit Service f629e6
				 * this means no field re-splitting or $0 reconstruction.
Packit Service f629e6
				 * Skip the set_FOO routine if the target is a special variable.
Packit Service f629e6
				 */
Packit Service f629e6
Packit Service f629e6
				break;
Packit Service f629e6
			} else if ((pc->assign_ctxt == Op_K_getline
Packit Service f629e6
					|| pc->assign_ctxt == Op_K_getline_redir)
Packit Service f629e6
				&& get_number_si(r) <= 0 	/* top of stack has a number <= 0 */
Packit Service f629e6
			) {
Packit Service f629e6
				/* getline returned EOF or error */
Packit Service f629e6
Packit Service f629e6
				break;
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (op == Op_var_assign)
Packit Service f629e6
				pc->assign_var();
Packit Service f629e6
			else
Packit Service f629e6
				pc->field_assign();
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_concat:
Packit Service f629e6
			r = concat_exp(pc->expr_count, pc->concat_flag & CSUBSEP);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_case:
Packit Service f629e6
			if ((pc + 1)->match_exp) {
Packit Service f629e6
				/* match a constant regex against switch expression instead of $0. */
Packit Service f629e6
Packit Service f629e6
				m = POP();	/* regex */
Packit Service f629e6
				t2 = TOP_SCALAR();	/* switch expression */
Packit Service f629e6
				t2 = force_string(t2);
Packit Service f629e6
				rp = re_update(m);
Packit Service f629e6
				di = (research(rp, t2->stptr, 0, t2->stlen, RE_NO_FLAGS) >= 0);
Packit Service f629e6
			} else {
Packit Service f629e6
				t1 = POP_SCALAR();	/* case value */
Packit Service f629e6
				t2 = TOP_SCALAR();	/* switch expression */
Packit Service f629e6
				di = (cmp_nodes(t2, t1, true) == 0);
Packit Service f629e6
				DEREF(t1);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (di) {
Packit Service f629e6
				/* match found */
Packit Service f629e6
				t2 = POP_SCALAR();
Packit Service f629e6
				DEREF(t2);
Packit Service f629e6
				JUMPTO(pc->target_jmp);
Packit Service f629e6
			}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_delete:
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
			do_delete(t1, pc->expr_count);
Packit Service f629e6
			stack_adj(-pc->expr_count);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_delete_loop:
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
			lhs = POP_ADDRESS();	/* item */
Packit Service f629e6
			do_delete_loop(t1, lhs);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_in_array:
Packit Service f629e6
			t1 = POP_ARRAY();
Packit Service f629e6
			t2 = mk_sub(pc->expr_count);
Packit Service f629e6
			r = node_Boolean[(in_array(t1, t2) != NULL)];
Packit Service f629e6
			DEREF(t2);
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_arrayfor_init:
Packit Service f629e6
		{
Packit Service f629e6
			NODE **list = NULL;
Packit Service f629e6
			NODE *array, *sort_str;
Packit Service f629e6
			size_t num_elems = 0;
Packit Service f629e6
			static NODE *sorted_in = NULL;
Packit Service f629e6
			const char *how_to_sort = "@unsorted";
Packit Service f629e6
			char save;
Packit Service f629e6
			bool saved_end = false;
Packit Service f629e6
Packit Service f629e6
			/* get the array */
Packit Service f629e6
			array = POP_ARRAY();
Packit Service f629e6
Packit Service f629e6
			/* sanity: check if empty */
Packit Service f629e6
			num_elems = assoc_length(array);
Packit Service f629e6
			if (num_elems == 0)
Packit Service f629e6
				goto arrayfor;
Packit Service f629e6
Packit Service f629e6
			if (sorted_in == NULL)		/* do this once */
Packit Service f629e6
				sorted_in = make_string("sorted_in", 9);
Packit Service f629e6
Packit Service f629e6
			sort_str = NULL;
Packit Service f629e6
			/*
Packit Service f629e6
			 * If posix, or if there's no PROCINFO[],
Packit Service f629e6
			 * there's no ["sorted_in"], so no sorting
Packit Service f629e6
			 */
Packit Service f629e6
			if (! do_posix && PROCINFO_node != NULL)
Packit Service f629e6
				sort_str = in_array(PROCINFO_node, sorted_in);
Packit Service f629e6
Packit Service f629e6
			if (sort_str != NULL) {
Packit Service f629e6
				sort_str = force_string(sort_str);
Packit Service f629e6
				if (sort_str->stlen > 0) {
Packit Service f629e6
					how_to_sort = sort_str->stptr;
Packit Service f629e6
					str_terminate(sort_str, save);
Packit Service f629e6
					saved_end = true;
Packit Service f629e6
				}
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			list = assoc_list(array, how_to_sort, SORTED_IN);
Packit Service f629e6
			if (saved_end)
Packit Service f629e6
				str_restore(sort_str, save);
Packit Service f629e6
Packit Service f629e6
arrayfor:
Packit Service f629e6
			getnode(r);
Packit Service f629e6
			r->type = Node_arrayfor;
Packit Service f629e6
			r->for_list = list;
Packit Service f629e6
			r->for_list_size = num_elems;		/* # of elements in list */
Packit Service f629e6
			r->cur_idx = -1;			/* current index */
Packit Service f629e6
			r->for_array = array;		/* array */
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
Packit Service f629e6
			if (num_elems == 0)
Packit Service f629e6
				JUMPTO(pc->target_jmp);   /* Op_arrayfor_final */
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_arrayfor_incr:
Packit Service f629e6
			r = TOP();	/* Node_arrayfor */
Packit Service f629e6
			if (++r->cur_idx == r->for_list_size) {
Packit Service f629e6
				NODE *array;
Packit Service f629e6
				array = r->for_array;	/* actual array */
Packit Service f629e6
				if (do_lint && array->table_size != r->for_list_size)
Packit Service f629e6
					lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
Packit Service f629e6
						array_vname(array), (long) r->for_list_size, (long) array->table_size);
Packit Service f629e6
				JUMPTO(pc->target_jmp);	/* Op_arrayfor_final */
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			t1 = r->for_list[r->cur_idx];
Packit Service f629e6
			lhs = get_lhs(pc->array_var, false);
Packit Service f629e6
			unref(*lhs);
Packit Service f629e6
			*lhs = dupnode(t1);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_arrayfor_final:
Packit Service f629e6
			r = POP();
Packit Service f629e6
			assert(r->type == Node_arrayfor);
Packit Service f629e6
			free_arrayfor(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_builtin:
Packit Service f629e6
			r = pc->builtin(pc->expr_count);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_ext_builtin:
Packit Service f629e6
		{
Packit Service f629e6
			size_t arg_count = pc->expr_count;
Packit Service f629e6
			awk_ext_func_t *f = pc[1].c_function;
Packit Service f629e6
			size_t min_req = f->min_required_args;
Packit Service f629e6
			size_t max_expect = f->max_expected_args;
Packit Service f629e6
			awk_value_t result;
Packit Service f629e6
Packit Service f629e6
			if (arg_count < min_req)
Packit Service f629e6
				fatal(_("%s: called with %lu arguments, expecting at least %lu"),
Packit Service f629e6
						pc[1].func_name,
Packit Service f629e6
						(unsigned long) arg_count,
Packit Service f629e6
						(unsigned long) min_req);
Packit Service f629e6
Packit Service f629e6
			if (do_lint && ! f->suppress_lint && arg_count > max_expect)
Packit Service f629e6
				lintwarn(_("%s: called with %lu arguments, expecting no more than %lu"),
Packit Service f629e6
						pc[1].func_name,
Packit Service f629e6
						(unsigned long) arg_count,
Packit Service f629e6
						(unsigned long) max_expect);
Packit Service f629e6
Packit Service f629e6
			PUSH_CODE(pc);
Packit Service f629e6
			r = awk_value_to_node(pc->extfunc(arg_count, & result, f));
Packit Service f629e6
			(void) POP_CODE();
Packit Service f629e6
			while (arg_count-- > 0) {
Packit Service f629e6
				t1 = POP();
Packit Service f629e6
				if (t1->type == Node_val)
Packit Service f629e6
					DEREF(t1);
Packit Service f629e6
			}
Packit Service f629e6
			free_api_string_copies();
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_sub_builtin:	/* sub, gsub and gensub */
Packit Service f629e6
			r = do_sub(pc->expr_count, pc->sub_flags);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_print:
Packit Service f629e6
			do_print(pc->expr_count, pc->redir_type);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_printf:
Packit Service f629e6
			do_printf(pc->expr_count, pc->redir_type);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_print_rec:
Packit Service f629e6
			do_print_rec(pc->expr_count, pc->redir_type);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_push_re:
Packit Service f629e6
			m = pc->memory;
Packit Service f629e6
			if (m->type == Node_dynregex) {
Packit Service f629e6
				r = POP_STRING();
Packit Service f629e6
				unref(m->re_exp);
Packit Service f629e6
				m->re_exp = r;
Packit Service f629e6
			} else if (m->type == Node_val) {
Packit Service f629e6
				assert((m->flags & REGEX) != 0);
Packit Service f629e6
				UPREF(m);
Packit Service f629e6
			}
Packit Service f629e6
			PUSH(m);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_match_rec:
Packit Service f629e6
			m = pc->memory;
Packit Service f629e6
			t1 = *get_field(0, (Func_ptr *) 0);
Packit Service f629e6
match_re:
Packit Service f629e6
			rp = re_update(m);
Packit Service f629e6
			di = research(rp, t1->stptr, 0, t1->stlen, RE_NO_FLAGS);
Packit Service f629e6
			di = (di == -1) ^ (op != Op_nomatch);
Packit Service f629e6
			if (op != Op_match_rec) {
Packit Service f629e6
				decr_sp();
Packit Service f629e6
				DEREF(t1);
Packit Service f629e6
			}
Packit Service f629e6
			r = node_Boolean[di];
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_nomatch:
Packit Service f629e6
			/* fall through */
Packit Service f629e6
		case Op_match:
Packit Service f629e6
			m = pc->memory;
Packit Service f629e6
			t1 = TOP_STRING();
Packit Service f629e6
			if (m->type == Node_dynregex) {
Packit Service f629e6
				unref(m->re_exp);
Packit Service f629e6
				m->re_exp = t1;
Packit Service f629e6
				decr_sp();
Packit Service f629e6
				t1 = TOP_STRING();
Packit Service f629e6
			}
Packit Service f629e6
			goto match_re;
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_indirect_func_call:
Packit Service f629e6
		{
Packit Service f629e6
			NODE *f = NULL;
Packit Service f629e6
			int arg_count;
Packit Service f629e6
			char save;
Packit Service f629e6
Packit Service f629e6
			arg_count = (pc + 1)->expr_count;
Packit Service f629e6
			t1 = PEEK(arg_count);	/* indirect var */
Packit Service f629e6
Packit Service f629e6
			if (t1->type != Node_val)	/* @a[1](p) not allowed in grammar */
Packit Service f629e6
				fatal(_("indirect function call requires a simple scalar value"));
Packit Service f629e6
Packit Service f629e6
			t1 = force_string(t1);
Packit Service f629e6
			str_terminate(t1, save);
Packit Service f629e6
			if (t1->stlen > 0) {
Packit Service f629e6
				/* retrieve function definition node */
Packit Service f629e6
				f = pc->func_body;
Packit Service f629e6
				if (f != NULL && strcmp(f->vname, t1->stptr) == 0) {
Packit Service f629e6
					/* indirect var hasn't been reassigned */
Packit Service f629e6
Packit Service f629e6
					str_restore(t1, save);
Packit Service f629e6
					ni = setup_frame(pc);
Packit Service f629e6
					JUMPTO(ni);	/* Op_func */
Packit Service f629e6
				}
Packit Service f629e6
				f = lookup(t1->stptr);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (f == NULL) {
Packit Service f629e6
				fatal(_("`%s' is not a function, so it cannot be called indirectly"),
Packit Service f629e6
						t1->stptr);
Packit Service f629e6
			} else if (f->type == Node_builtin_func) {
Packit Service f629e6
				int arg_count = (pc + 1)->expr_count;
Packit Service f629e6
				builtin_func_t the_func = lookup_builtin(t1->stptr);
Packit Service f629e6
Packit Service f629e6
				assert(the_func != NULL);
Packit Service f629e6
Packit Service f629e6
				/* call it */
Packit Service f629e6
				if (the_func == (builtin_func_t) do_sub)
Packit Service f629e6
					r = call_sub(t1->stptr, arg_count);
Packit Service f629e6
				else if (the_func == do_match)
Packit Service f629e6
					r = call_match(arg_count);
Packit Service f629e6
				else if (the_func == do_split || the_func == do_patsplit)
Packit Service f629e6
					r = call_split_func(t1->stptr, arg_count);
Packit Service f629e6
				else
Packit Service f629e6
					r = the_func(arg_count);
Packit Service f629e6
				str_restore(t1, save);
Packit Service f629e6
Packit Service f629e6
				PUSH(r);
Packit Service f629e6
				break;
Packit Service f629e6
			} else if (f->type != Node_func) {
Packit Service f629e6
				str_restore(t1, save);
Packit Service f629e6
				if (f->type == Node_ext_func) {
Packit Service f629e6
					/* code copied from below, keep in sync */
Packit Service f629e6
					INSTRUCTION *bc;
Packit Service f629e6
					char *fname = pc->func_name;
Packit Service f629e6
					int arg_count = (pc + 1)->expr_count;
Packit Service f629e6
					static INSTRUCTION npc[2];
Packit Service f629e6
Packit Service f629e6
					npc[0] = *pc;
Packit Service f629e6
Packit Service f629e6
					bc = f->code_ptr;
Packit Service f629e6
					assert(bc->opcode == Op_symbol);
Packit Service f629e6
					npc[0].opcode = Op_ext_builtin;	/* self modifying code */
Packit Service f629e6
					npc[0].extfunc = bc->extfunc;
Packit Service f629e6
					npc[0].expr_count = arg_count;		/* actual argument count */
Packit Service f629e6
					npc[1] = pc[1];
Packit Service f629e6
					npc[1].func_name = fname;	/* name of the builtin */
Packit Service f629e6
					npc[1].c_function = bc->c_function;
Packit Service f629e6
					ni = npc;
Packit Service f629e6
					JUMPTO(ni);
Packit Service f629e6
				} else
Packit Service f629e6
					fatal(_("function called indirectly through `%s' does not exist"),
Packit Service f629e6
							pc->func_name);
Packit Service f629e6
			}
Packit Service f629e6
			pc->func_body = f;     /* save for next call */
Packit Service f629e6
			str_restore(t1, save);
Packit Service f629e6
Packit Service f629e6
			ni = setup_frame(pc);
Packit Service f629e6
			JUMPTO(ni);	/* Op_func */
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		case Op_func_call:
Packit Service f629e6
		{
Packit Service f629e6
			NODE *f;
Packit Service f629e6
Packit Service f629e6
			/* retrieve function definition node */
Packit Service f629e6
			f = pc->func_body;
Packit Service f629e6
			if (f == NULL) {
Packit Service f629e6
				f = lookup(pc->func_name);
Packit Service f629e6
				if (f == NULL || (f->type != Node_func && f->type != Node_ext_func))
Packit Service f629e6
					fatal(_("function `%s' not defined"), pc->func_name);
Packit Service f629e6
				pc->func_body = f;     /* save for next call */
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (f->type == Node_ext_func) {
Packit Service f629e6
				/* keep in sync with indirect call code */
Packit Service f629e6
				INSTRUCTION *bc;
Packit Service f629e6
				char *fname = pc->func_name;
Packit Service f629e6
				int arg_count = (pc + 1)->expr_count;
Packit Service f629e6
Packit Service f629e6
				bc = f->code_ptr;
Packit Service f629e6
				assert(bc->opcode == Op_symbol);
Packit Service f629e6
				pc->opcode = Op_ext_builtin;	/* self modifying code */
Packit Service f629e6
				pc->extfunc = bc->extfunc;
Packit Service f629e6
				pc->expr_count = arg_count;	/* actual argument count */
Packit Service f629e6
				(pc + 1)->func_name = fname;	/* name of the builtin */
Packit Service f629e6
				(pc + 1)->c_function = bc->c_function;	/* min and max args */
Packit Service f629e6
				ni = pc;
Packit Service f629e6
				JUMPTO(ni);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			ni = setup_frame(pc);
Packit Service f629e6
			JUMPTO(ni);	/* Op_func */
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		case Op_K_return:
Packit Service f629e6
			m = POP_SCALAR();       /* return value */
Packit Service f629e6
Packit Service f629e6
			ni = pop_fcall();
Packit Service f629e6
Packit Service f629e6
			/* put the return value back on stack */
Packit Service f629e6
			PUSH(m);
Packit Service f629e6
Packit Service f629e6
			JUMPTO(ni);
Packit Service f629e6
Packit Service f629e6
		case Op_K_getline_redir:
Packit Service f629e6
			r = do_getline_redir(pc->into_var, pc->redir_type);
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_getline:	/* no redirection */
Packit Service f629e6
			if (! currule || currule == BEGINFILE || currule == ENDFILE)
Packit Service f629e6
				fatal(_("non-redirected `getline' invalid inside `%s' rule"),
Packit Service f629e6
						ruletab[currule]);
Packit Service f629e6
Packit Service f629e6
			do {
Packit Service f629e6
				int ret;
Packit Service f629e6
				ret = nextfile(& curfile, false);
Packit Service f629e6
				if (ret <= 0)
Packit Service f629e6
					r = do_getline(pc->into_var, curfile);
Packit Service f629e6
				else {
Packit Service f629e6
Packit Service f629e6
					/* Save execution state so that we can return to it
Packit Service f629e6
					 * from Op_after_beginfile or Op_after_endfile.
Packit Service f629e6
					 */
Packit Service f629e6
Packit Service f629e6
					push_exec_state(pc, currule, source, stack_ptr);
Packit Service f629e6
Packit Service f629e6
					if (curfile == NULL)
Packit Service f629e6
						JUMPTO((pc + 1)->target_endfile);
Packit Service f629e6
					else
Packit Service f629e6
						JUMPTO((pc + 1)->target_beginfile);
Packit Service f629e6
				}
Packit Service f629e6
			} while (r == NULL);	/* EOF */
Packit Service f629e6
Packit Service f629e6
			PUSH(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_after_endfile:
Packit Service f629e6
			/* Find the execution state to return to */
Packit Service f629e6
			ni = pop_exec_state(& currule, & source, NULL);
Packit Service f629e6
Packit Service f629e6
			assert(ni->opcode == Op_newfile || ni->opcode == Op_K_getline);
Packit Service f629e6
			JUMPTO(ni);
Packit Service f629e6
Packit Service f629e6
		case Op_after_beginfile:
Packit Service f629e6
			after_beginfile(& curfile);
Packit Service f629e6
Packit Service f629e6
			/* Find the execution state to return to */
Packit Service f629e6
			ni = pop_exec_state(& currule, & source, NULL);
Packit Service f629e6
Packit Service f629e6
			assert(ni->opcode == Op_newfile || ni->opcode == Op_K_getline);
Packit Service f629e6
			if (ni->opcode == Op_K_getline
Packit Service f629e6
					|| curfile == NULL      /* skipping directory argument */
Packit Service f629e6
			)
Packit Service f629e6
				JUMPTO(ni);
Packit Service f629e6
Packit Service f629e6
			break;	/* read a record, Op_get_record */
Packit Service f629e6
Packit Service f629e6
		case Op_newfile:
Packit Service f629e6
		{
Packit Service f629e6
			int ret;
Packit Service f629e6
Packit Service f629e6
			ret = nextfile(& curfile, false);
Packit Service f629e6
Packit Service f629e6
			if (ret < 0)	/* end of input */
Packit Service f629e6
				JUMPTO(pc->target_jmp);	/* end block or Op_atexit */
Packit Service f629e6
Packit Service f629e6
			if (ret == 0) /* read a record */
Packit Service f629e6
				JUMPTO((pc + 1)->target_get_record);
Packit Service f629e6
Packit Service f629e6
			/* ret > 0 */
Packit Service f629e6
			/* Save execution state for use in Op_after_beginfile or Op_after_endfile. */
Packit Service f629e6
Packit Service f629e6
			push_exec_state(pc, currule, source, stack_ptr);
Packit Service f629e6
Packit Service f629e6
			if (curfile == NULL)	/* EOF */
Packit Service f629e6
				JUMPTO(pc->target_endfile);
Packit Service f629e6
			/* else
Packit Service f629e6
				execute beginfile block */
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_get_record:
Packit Service f629e6
		{
Packit Service f629e6
			int errcode = 0;
Packit Service f629e6
Packit Service f629e6
			ni = pc->target_newfile;
Packit Service f629e6
			if (curfile == NULL) {
Packit Service f629e6
				/* from non-redirected getline, e.g.:
Packit Service f629e6
				 *  {
Packit Service f629e6
				 *		while (getline > 0) ;
Packit Service f629e6
				 *  }
Packit Service f629e6
				 */
Packit Service f629e6
Packit Service f629e6
				ni = ni->target_jmp;	/* end_block or Op_atexit */
Packit Service f629e6
				JUMPTO(ni);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			if (! inrec(curfile, & errcode)) {
Packit Service f629e6
				if (errcode > 0) {
Packit Service f629e6
					update_ERRNO_int(errcode);
Packit Service f629e6
					if (do_traditional || ! pc->has_endfile)
Packit Service f629e6
						fatal(_("error reading input file `%s': %s"),
Packit Service f629e6
						curfile->public.name, strerror(errcode));
Packit Service f629e6
				}
Packit Service f629e6
Packit Service f629e6
				JUMPTO(ni);
Packit Service f629e6
			} /* else
Packit Service f629e6
				prog (rule) block */
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_nextfile:
Packit Service f629e6
		{
Packit Service f629e6
			int ret;
Packit Service f629e6
Packit Service f629e6
			if (currule != Rule && currule != BEGINFILE)
Packit Service f629e6
				fatal(_("`nextfile' cannot be called from a `%s' rule"),
Packit Service f629e6
					ruletab[currule]);
Packit Service f629e6
Packit Service f629e6
			ret = nextfile(& curfile, true);	/* skip current file */
Packit Service f629e6
Packit Service f629e6
			if (currule == BEGINFILE) {
Packit Service f629e6
				long stack_size = 0;
Packit Service f629e6
Packit Service f629e6
				ni = pop_exec_state(& currule, & source, & stack_size);
Packit Service f629e6
Packit Service f629e6
				assert(ni->opcode == Op_K_getline || ni->opcode == Op_newfile);
Packit Service f629e6
Packit Service f629e6
				/* pop stack returning to the state of Op_K_getline or Op_newfile. */
Packit Service f629e6
				unwind_stack(stack_size);
Packit Service f629e6
Packit Service f629e6
				if (ret == 0) {
Packit Service f629e6
					/* There was an error opening the file;
Packit Service f629e6
					 * don't run ENDFILE block(s).
Packit Service f629e6
					 */
Packit Service f629e6
Packit Service f629e6
					JUMPTO(ni);
Packit Service f629e6
				} else {
Packit Service f629e6
					/* do run ENDFILE block(s) first. */
Packit Service f629e6
Packit Service f629e6
					/* Execution state to return to in Op_after_endfile. */
Packit Service f629e6
					push_exec_state(ni, currule, source, stack_ptr);
Packit Service f629e6
Packit Service f629e6
					JUMPTO(pc->target_endfile);
Packit Service f629e6
				}
Packit Service f629e6
			} /* else
Packit Service f629e6
				Start over with the first rule. */
Packit Service f629e6
Packit Service f629e6
			/* empty the run-time stack to avoid memory leak */
Packit Service f629e6
			pop_stack();
Packit Service f629e6
Packit Service f629e6
			/* Push an execution state for Op_after_endfile to return to */
Packit Service f629e6
			push_exec_state(pc->target_newfile, currule, source, stack_ptr);
Packit Service f629e6
Packit Service f629e6
			JUMPTO(pc->target_endfile);
Packit Service f629e6
		}
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_K_exit:
Packit Service f629e6
			/* exit not allowed in user-defined comparison functions for "sorted_in";
Packit Service f629e6
			 * This is done so that END blocks aren't executed more than once.
Packit Service f629e6
			 */
Packit Service f629e6
			if (! currule)
Packit Service f629e6
				fatal(_("`exit' cannot be called in the current context"));
Packit Service f629e6
Packit Service f629e6
			exiting = true;
Packit Service f629e6
			if ((t1 = POP_NUMBER()) != Nnull_string) {
Packit Service f629e6
				exit_val = (int) get_number_si(t1);
Packit Service f629e6
#ifdef VMS
Packit Service f629e6
				if (exit_val == 0)
Packit Service f629e6
					exit_val = EXIT_SUCCESS;
Packit Service f629e6
				else if (exit_val == 1)
Packit Service f629e6
					exit_val = EXIT_FAILURE;
Packit Service f629e6
				/* else
Packit Service f629e6
					just pass anything else on through */
Packit Service f629e6
#endif
Packit Service f629e6
			}
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
Packit Service f629e6
			if (currule == BEGINFILE || currule == ENDFILE) {
Packit Service f629e6
Packit Service f629e6
				/* Find the rule of the saved execution state (Op_K_getline/Op_newfile).
Packit Service f629e6
				 * This is needed to prevent multiple execution of any END rules:
Packit Service f629e6
				 * 	gawk 'BEGINFILE { exit(1) } \
Packit Service f629e6
				 *         END { while (getline > 0); }' in1 in2
Packit Service f629e6
				 */
Packit Service f629e6
Packit Service f629e6
				(void) pop_exec_state(& currule, & source, NULL);
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			pop_stack();	/* empty stack, don't leak memory */
Packit Service f629e6
Packit Service f629e6
			/* Jump to either the first END block instruction
Packit Service f629e6
			 * or to Op_atexit.
Packit Service f629e6
			 */
Packit Service f629e6
Packit Service f629e6
			if (currule == END)
Packit Service f629e6
				ni = pc->target_atexit;
Packit Service f629e6
			else
Packit Service f629e6
				ni = pc->target_end;
Packit Service f629e6
			JUMPTO(ni);
Packit Service f629e6
Packit Service f629e6
		case Op_K_next:
Packit Service f629e6
			if (currule != Rule)
Packit Service f629e6
				fatal(_("`next' cannot be called from a `%s' rule"), ruletab[currule]);
Packit Service f629e6
Packit Service f629e6
			pop_stack();
Packit Service f629e6
			JUMPTO(pc->target_jmp);	/* Op_get_record, read next record */
Packit Service f629e6
Packit Service f629e6
		case Op_pop:
Packit Service f629e6
			r = POP_SCALAR();
Packit Service f629e6
			DEREF(r);
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_line_range:
Packit Service f629e6
			if (pc->triggered)		/* evaluate right expression */
Packit Service f629e6
				JUMPTO(pc->target_jmp);
Packit Service f629e6
			/* else
Packit Service f629e6
				evaluate left expression */
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_cond_pair:
Packit Service f629e6
		{
Packit Service f629e6
			int result;
Packit Service f629e6
			INSTRUCTION *ip;
Packit Service f629e6
Packit Service f629e6
			t1 = TOP_SCALAR();   /* from right hand side expression */
Packit Service f629e6
			di = (eval_condition(t1) != 0);
Packit Service f629e6
			DEREF(t1);
Packit Service f629e6
Packit Service f629e6
			ip = pc->line_range;            /* Op_line_range */
Packit Service f629e6
Packit Service f629e6
			if (! ip->triggered && di) {
Packit Service f629e6
				/* not already triggered and left expression is true */
Packit Service f629e6
				decr_sp();
Packit Service f629e6
				ip->triggered = true;
Packit Service f629e6
				JUMPTO(ip->target_jmp);	/* evaluate right expression */
Packit Service f629e6
			}
Packit Service f629e6
Packit Service f629e6
			result = ip->triggered || di;
Packit Service f629e6
			ip->triggered ^= di;          /* update triggered flag */
Packit Service f629e6
			r = node_Boolean[result];      /* final value of condition pair */
Packit Service f629e6
			UPREF(r);
Packit Service f629e6
			REPLACE(r);
Packit Service f629e6
			JUMPTO(pc->target_jmp);
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		case Op_exec_count:
Packit Service f629e6
			if (do_profile)
Packit Service f629e6
				pc->exec_count++;
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		case Op_no_op:
Packit Service f629e6
		case Op_K_do:
Packit Service f629e6
		case Op_K_while:
Packit Service f629e6
		case Op_K_for:
Packit Service f629e6
		case Op_K_arrayfor:
Packit Service f629e6
		case Op_K_switch:
Packit Service f629e6
		case Op_K_default:
Packit Service f629e6
		case Op_K_if:
Packit Service f629e6
		case Op_K_else:
Packit Service f629e6
		case Op_cond_exp:
Packit Service f629e6
		case Op_comment:
Packit Service f629e6
		case Op_parens:
Packit Service f629e6
			break;
Packit Service f629e6
Packit Service f629e6
		default:
Packit Service f629e6
			fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(op));
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
		JUMPTO(pc->nexti);
Packit Service f629e6
Packit Service f629e6
/*	} forever */
Packit Service f629e6
Packit Service f629e6
	/* not reached */
Packit Service f629e6
	return 0;
Packit Service f629e6
Packit Service f629e6
#undef mk_sub
Packit Service f629e6
#undef JUMPTO
Packit Service f629e6
}