aboutsummaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c155
1 files changed, 65 insertions, 90 deletions
diff --git a/eval.c b/eval.c
index 36dab2fb..284bf2eb 100644
--- a/eval.c
+++ b/eval.c
@@ -1,23 +1,23 @@
/*
- * eval.c - gawk bytecode interpreter
+ * eval.c - gawk bytecode interpreter
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -25,7 +25,6 @@
#include "awk.h"
-extern void after_beginfile(IOBUF **curfile);
extern double pow(double x, double y);
extern double modf(double x, double *yp);
extern double fmod(double x, double y);
@@ -54,7 +53,7 @@ static NODE *node_Boolean[2];
#ifdef C
#undef C
#endif
-#define C(c) ((char)c)
+#define C(c) ((char)c)
/*
* This table is used by the regexp routines to do case independent
* matching. Basically, every ascii character maps to itself, except
@@ -243,7 +242,6 @@ static const char *const nodetypes[] = {
"Node_param_list",
"Node_func",
"Node_ext_func",
- "Node_old_ext_func",
"Node_builtin_func",
"Node_array_ref",
"Node_array_tree",
@@ -289,6 +287,7 @@ static struct optypetab {
{ "Op_postincrement", "++" },
{ "Op_postdecrement", "--" },
{ "Op_unary_minus", "-" },
+ { "Op_unary_plus", "+" },
{ "Op_field_spec", "$" },
{ "Op_not", "! " },
{ "Op_assign", " = " },
@@ -315,7 +314,7 @@ static struct optypetab {
{ "Op_match", " ~ " },
{ "Op_match_rec", NULL },
{ "Op_nomatch", " !~ " },
- { "Op_rule", NULL },
+ { "Op_rule", NULL },
{ "Op_K_case", "case" },
{ "Op_K_default", "default" },
{ "Op_K_break", "break" },
@@ -334,12 +333,12 @@ static struct optypetab {
{ "Op_builtin", NULL },
{ "Op_sub_builtin", NULL },
{ "Op_ext_builtin", NULL },
- { "Op_old_ext_builtin", NULL }, /* temporary */
{ "Op_in_array", " in " },
{ "Op_func_call", NULL },
{ "Op_indirect_func_call", NULL },
{ "Op_push", NULL },
{ "Op_push_arg", NULL },
+ { "Op_push_arg_untyped", NULL },
{ "Op_push_i", NULL },
{ "Op_push_re", NULL },
{ "Op_push_array", NULL },
@@ -364,6 +363,7 @@ static struct optypetab {
{ "Op_after_beginfile", NULL },
{ "Op_after_endfile", NULL },
{ "Op_func", NULL },
+ { "Op_comment", NULL },
{ "Op_exec_count", NULL },
{ "Op_breakpoint", NULL },
{ "Op_lint", NULL },
@@ -444,10 +444,12 @@ flags2str(int flagval)
{ WSTRCUR, "WSTRCUR" },
{ MPFN, "MPFN" },
{ MPZN, "MPZN" },
+ { NO_EXT_SET, "NO_EXT_SET" },
{ NULL_FIELD, "NULL_FIELD" },
{ ARRAYMAXED, "ARRAYMAXED" },
{ HALFHAT, "HALFHAT" },
{ XARRAY, "XARRAY" },
+ { NUMCONSTSTR, "NUMCONSTSTR" },
{ 0, NULL },
};
@@ -575,7 +577,7 @@ posix_compare(NODE *s1, NODE *s2)
/* cmp_nodes --- compare two nodes, returning negative, 0, positive */
int
-cmp_nodes(NODE *t1, NODE *t2)
+cmp_nodes(NODE *t1, NODE *t2, bool use_strcmp)
{
int ret = 0;
size_t len1, len2;
@@ -584,14 +586,8 @@ cmp_nodes(NODE *t1, NODE *t2)
if (t1 == t2)
return 0;
- if ((t1->flags & MAYBE_NUM) != 0)
- (void) force_number(t1);
- if ((t2->flags & MAYBE_NUM) != 0)
- (void) force_number(t2);
- if ((t1->flags & INTIND) != 0)
- t1 = force_string(t1);
- if ((t2->flags & INTIND) != 0)
- t2 = force_string(t2);
+ (void) fixtype(t1);
+ (void) fixtype(t2);
if ((t1->flags & NUMBER) != 0 && (t2->flags & NUMBER) != 0)
return cmp_numbers(t1, t2);
@@ -604,7 +600,7 @@ cmp_nodes(NODE *t1, NODE *t2)
if (len1 == 0 || len2 == 0)
return ldiff;
- if (do_posix)
+ if (do_posix && ! use_strcmp)
return posix_compare(t1, t2);
l = (ldiff <= 0 ? len1 : len2);
@@ -646,7 +642,7 @@ push_frame(NODE *f)
}
if (fcall_count > 1)
- memmove(fcall_list + 2, fcall_list + 1, (fcall_count - 1) * sizeof(NODE *));
+ memmove(fcall_list + 2, fcall_list + 1, (fcall_count - 1) * sizeof(NODE *));
fcall_list[1] = f;
}
@@ -657,7 +653,7 @@ static void
pop_frame()
{
if (fcall_count > 1)
- memmove(fcall_list + 1, fcall_list + 2, (fcall_count - 1) * sizeof(NODE *));
+ memmove(fcall_list + 1, fcall_list + 2, (fcall_count - 1) * sizeof(NODE *));
fcall_count--;
assert(fcall_count >= 0);
if (do_debug)
@@ -700,7 +696,6 @@ void
set_IGNORECASE()
{
static bool warned = false;
- NODE *n = IGNORECASE_node->var_value;
if ((do_lint || do_traditional) && ! warned) {
warned = true;
@@ -709,19 +704,8 @@ set_IGNORECASE()
load_casetable();
if (do_traditional)
IGNORECASE = false;
- else if ((n->flags & (NUMCUR|NUMBER)) != 0)
- IGNORECASE = ! iszero(n);
- else if ((n->flags & (STRING|STRCUR)) != 0) {
- if ((n->flags & MAYBE_NUM) == 0) {
- (void) force_string(n);
- IGNORECASE = (n->stlen > 0);
- } else {
- (void) force_number(n);
- IGNORECASE = ! iszero(n);
- }
- } else
- IGNORECASE = false; /* shouldn't happen */
-
+ else
+ IGNORECASE = boolval(IGNORECASE_node->var_value);
set_RS(); /* set_RS() calls set_FS() if need be, for us */
}
@@ -732,7 +716,7 @@ set_BINMODE()
{
static bool warned = false;
char *p;
- NODE *v = BINMODE_node->var_value;
+ NODE *v = fixtype(BINMODE_node->var_value);
if ((do_lint || do_traditional) && ! warned) {
warned = true;
@@ -741,7 +725,6 @@ set_BINMODE()
if (do_traditional)
BINMODE = TEXT_TRANSLATE;
else if ((v->flags & NUMBER) != 0) {
- (void) force_number(v);
BINMODE = get_number_si(v);
/* Make sure the value is rational. */
if (BINMODE < TEXT_TRANSLATE)
@@ -829,9 +812,9 @@ set_OFS()
new_ofs_len = OFS_node->var_value->stlen;
if (OFS == NULL)
- emalloc(OFS, char *, new_ofs_len + 2, "set_OFS");
+ emalloc(OFS, char *, new_ofs_len + 1, "set_OFS");
else if (OFSlen < new_ofs_len)
- erealloc(OFS, char *, new_ofs_len + 2, "set_OFS");
+ erealloc(OFS, char *, new_ofs_len + 1, "set_OFS");
memcpy(OFS, OFS_node->var_value->stptr, OFS_node->var_value->stlen);
OFSlen = new_ofs_len;
@@ -904,7 +887,7 @@ fmt_index(NODE *n)
emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");
n = force_string(n);
while (ix < fmt_hiwater) {
- if (cmp_nodes(fmt_list[ix], n) == 0)
+ if (cmp_nodes(fmt_list[ix], n, true) == 0)
return ix;
ix++;
}
@@ -949,36 +932,28 @@ set_LINT()
{
#ifndef NO_LINT
int old_lint = do_lint;
- NODE *n = LINT_node->var_value;
+ NODE *n = fixtype(LINT_node->var_value);
/* start with clean defaults */
lintfunc = r_warning;
do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID);
- if ((n->flags & (STRING|STRCUR)) != 0) {
- if ((n->flags & MAYBE_NUM) == 0) {
- const char *lintval;
- size_t lintlen;
-
- n = force_string(LINT_node->var_value);
- lintval = n->stptr;
- lintlen = n->stlen;
- if (lintlen > 0) {
- if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0)
- do_flags |= DO_LINT_INVALID;
- else {
- do_flags |= DO_LINT_ALL;
- if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0)
- lintfunc = r_fatal;
- }
- }
- } else {
- (void) force_number(n);
- if (! iszero(n))
+ if ((n->flags & STRING) != 0) {
+ const char *lintval;
+ size_t lintlen;
+
+ lintval = n->stptr;
+ lintlen = n->stlen;
+ if (lintlen > 0) {
+ if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0)
+ do_flags |= DO_LINT_INVALID;
+ else {
do_flags |= DO_LINT_ALL;
+ if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0)
+ lintfunc = r_fatal;
+ }
}
- } else if ((n->flags & (NUMCUR|NUMBER)) != 0) {
- (void) force_number(n);
+ } else {
if (! iszero(n))
do_flags |= DO_LINT_ALL;
}
@@ -1017,6 +992,7 @@ update_ERRNO_int(int errcode)
{
char *cp;
+ update_PROCINFO_num("errno", errcode);
if (errcode) {
cp = strerror(errcode);
cp = gettext(cp);
@@ -1031,6 +1007,7 @@ update_ERRNO_int(int errcode)
void
update_ERRNO_string(const char *string)
{
+ update_PROCINFO_num("errno", 0);
unref(ERRNO_node->var_value);
ERRNO_node->var_value = make_string(string, strlen(string));
}
@@ -1040,6 +1017,7 @@ update_ERRNO_string(const char *string)
void
unset_ERRNO(void)
{
+ update_PROCINFO_num("errno", 0);
unref(ERRNO_node->var_value);
ERRNO_node->var_value = dupnode(Nnull_string);
}
@@ -1099,7 +1077,7 @@ STACK_ITEM *stack_bottom;
STACK_ITEM *stack_top;
static unsigned long STACK_SIZE = 256; /* initial size of stack */
int max_args = 0; /* maximum # of arguments to printf, print, sprintf,
- * or # of array subscripts, or adjacent strings
+ * or # of array subscripts, or adjacent strings
* to be concatenated.
*/
NODE **args_array = NULL;
@@ -1171,7 +1149,7 @@ r_get_lhs(NODE *n, bool reference)
/* r_get_field --- get the address of a field node */
-
+
NODE **
r_get_field(NODE *n, Func_ptr *assign, bool reference)
{
@@ -1181,7 +1159,7 @@ r_get_field(NODE *n, Func_ptr *assign, bool reference)
if (assign)
*assign = NULL;
if (do_lint) {
- if ((n->flags & NUMBER) == 0) {
+ if ((fixtype(n)->flags & NUMBER) == 0) {
lintwarn(_("attempt to field reference from non-numeric value"));
if (n->stlen == 0)
lintwarn(_("attempt to field reference from null string"));
@@ -1243,7 +1221,7 @@ calc_exp(AWKNUM x1, AWKNUM x2)
}
-/* setup_frame --- setup new frame for function call */
+/* setup_frame --- setup new frame for function call */
static INSTRUCTION *
setup_frame(INSTRUCTION *pc)
@@ -1285,7 +1263,7 @@ setup_frame(INSTRUCTION *pc)
}
- /* check for extra args */
+ /* check for extra args */
if (arg_count > pcount) {
warning(
_("function `%s' called with more arguments than declared"),
@@ -1379,7 +1357,7 @@ setup_frame(INSTRUCTION *pc)
/* setup new frame */
getnode(frame_ptr);
- frame_ptr->type = Node_frame;
+ frame_ptr->type = Node_frame;
frame_ptr->stack = sp;
frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the previous stack frame */
frame_ptr->func_node = f;
@@ -1497,7 +1475,7 @@ unwind_stack(long n)
if (in_main_context() && ! exiting)
fatal(_("unwind_stack: unexpected type `%s'"),
nodetype2str(r->type));
- /* else
+ /* else
* Node_var_array,
* Node_param_list,
* Node_var (e.g: trying to use scalar for array)
@@ -1511,7 +1489,7 @@ unwind_stack(long n)
break;
}
return cp;
-}
+}
/* pop_fcall --- pop off the innermost frame */
@@ -1530,21 +1508,18 @@ eval_condition(NODE *t)
if (t == node_Boolean[true])
return true;
- if ((t->flags & MAYBE_NUM) != 0)
- force_number(t);
- else if ((t->flags & INTIND) != 0)
- force_string(t);
-
- if ((t->flags & NUMBER) != 0)
- return ! iszero(t);
-
- return (t->stlen != 0);
+ return boolval(t);
}
+typedef enum {
+ SCALAR_EQ_NEQ,
+ SCALAR_RELATIONAL
+} scalar_cmp_t;
+
/* cmp_scalars -- compare two nodes on the stack */
static inline int
-cmp_scalars()
+cmp_scalars(scalar_cmp_t comparison_type)
{
NODE *t1, *t2;
int di;
@@ -1555,14 +1530,14 @@ cmp_scalars()
DEREF(t2);
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t1));
}
- di = cmp_nodes(t1, t2);
+ di = cmp_nodes(t1, t2, comparison_type == SCALAR_EQ_NEQ);
DEREF(t1);
DEREF(t2);
return di;
}
/* op_assign --- assignment operators excluding = */
-
+
static void
op_assign(OPCODE op)
{
@@ -1664,9 +1639,9 @@ POP_CODE()
typedef struct exec_state {
struct exec_state *next;
- INSTRUCTION *cptr; /* either getline (Op_K_getline) or the
+ INSTRUCTION *cptr; /* either getline (Op_K_getline) or the
* implicit "open-file, read-record" loop (Op_newfile).
- */
+ */
int rule; /* rule for the INSTRUCTION */
@@ -1732,7 +1707,7 @@ register_exec_hook(Func_pre_exec preh, Func_post_exec posth)
/*
* multiple post-exec hooks aren't supported. post-exec hook is mainly
* for use by the debugger.
- */
+ */
if (! preh || (post_execute && posth))
return false;
@@ -1760,7 +1735,7 @@ register_exec_hook(Func_pre_exec preh, Func_post_exec posth)
}
-/* interpreter routine when not debugging */
+/* interpreter routine when not debugging */
#include "interpret.h"
/* interpreter routine with exec hook(s). Used when debugging and/or with MPFR. */
@@ -1808,6 +1783,6 @@ init_interpret()
if (num_exec_hook > 0)
interpret = h_interpret;
else
- interpret = r_interpret;
+ interpret = r_interpret;
}