diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 12:57:07 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 12:57:07 +0300 |
commit | 3ca7f0b16d0a5c105380b284a81c6a1b2c210908 (patch) | |
tree | c2153d226b9cba3ebca0c3556b19bf3e52cd20dd /eval.c | |
parent | f20ab7c3039a4023f41372bfe4bde3b16d481df7 (diff) | |
download | egawk-3ca7f0b16d0a5c105380b284a81c6a1b2c210908.tar.gz egawk-3ca7f0b16d0a5c105380b284a81c6a1b2c210908.tar.bz2 egawk-3ca7f0b16d0a5c105380b284a81c6a1b2c210908.zip |
Move to gawk-3.0.5.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 67 |
1 files changed, 47 insertions, 20 deletions
@@ -3,7 +3,7 @@ */ /* - * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc. + * Copyright (C) 1986, 1988, 1989, 1991-2000 the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. @@ -225,6 +225,7 @@ static char *nodetypes[] = { "Node_regex", "Node_hashnode", "Node_ahash", + "Node_array_ref", "Node_NF", "Node_NR", "Node_FNR", @@ -659,12 +660,18 @@ int iscond; if (tree->type == Node_param_list) { int paramnum = tree->param_cnt + 1; + if ((tree->flags & FUNC) != 0) + fatal("can't use function name `%s' as variable or array", + tree->vname); + tree = stack_ptr[tree->param_cnt]; if (tree == NULL) return Nnull_string; sprintf(namebuf, "parameter #%d", paramnum); tree->vname = namebuf; - } + } + if (tree->type == Node_array_ref) + tree = tree->orig_array; switch (tree->type) { case Node_var: @@ -984,11 +991,12 @@ register NODE *tree; * able to begin and end on a single input record, so this * isn't an ELSE IF, as noted above. */ - if (! tree->triggered) + if (! tree->triggered) { if (! eval_condition(tree->condpair->lnode)) return FALSE; else tree->triggered = TRUE; + } /* Else we are triggered */ if (eval_condition(tree->condpair->rnode)) tree->triggered = FALSE; @@ -1069,16 +1077,17 @@ register NODE *tree; NODE *tmp; Func_ptr after_assign = NULL; - lhs = get_lhs(tree->lnode, &after_assign); - lval = force_number(*lhs); - /* - * Can't unref *lhs until we know the type; doing so - * too early breaks x += x sorts of things. + * For ++ and --, get the lhs when doing the op and then + * return. For += etc, do the rhs first, since it can + * rearrange things, and *then* get the lhs. */ + switch(tree->type) { case Node_preincrement: case Node_predecrement: + lhs = get_lhs(tree->lnode, &after_assign); + lval = force_number(*lhs); unref(*lhs); *lhs = make_number(lval + (tree->type == Node_preincrement ? 1.0 : -1.0)); @@ -1089,6 +1098,8 @@ register NODE *tree; case Node_postincrement: case Node_postdecrement: + lhs = get_lhs(tree->lnode, &after_assign); + lval = force_number(*lhs); unref(*lhs); *lhs = make_number(lval + (tree->type == Node_postincrement ? 1.0 : -1.0)); @@ -1100,16 +1111,16 @@ register NODE *tree; break; /* handled below */ } + /* + * It's a += kind of thing. Do the rhs, then the lhs. + */ + tmp = tree_eval(tree->rnode); rval = force_number(tmp); free_temp(tmp); - /* - * Do this again; the lhs and the rhs could both be fields. - * Accessing the rhs could cause the lhs to have moved around. - * (Yet another special case. Gack.) - */ lhs = get_lhs(tree->lnode, &after_assign); + lval = force_number(*lhs); unref(*lhs); switch(tree->type) { @@ -1225,7 +1236,7 @@ pop_fcall() if (arg->type == Node_param_list) arg = stack_ptr[arg->param_cnt]; n = *sp++; - if ((arg->type == Node_var || arg->type == Node_var_array) + if ((arg->type == Node_var /* || arg->type == Node_var_array */) && n->type == Node_var_array) { /* should we free arg->var_value ? */ arg->var_array = n->var_array; @@ -1235,7 +1246,7 @@ pop_fcall() arg->flags = n->flags; } /* n->lnode overlays the array size, don't unref it if array */ - if (n->type != Node_var_array) + if (n->type != Node_var_array && n->type != Node_array_ref) unref(n->lnode); freenode(n); count--; @@ -1245,7 +1256,9 @@ pop_fcall() /* if n is a local array, all the elements should be freed */ if (n->type == Node_var_array) assoc_clear(n); - unref(n->lnode); + /* n->lnode overlays the array size, don't unref it if array */ + if (n->type != Node_var_array && n->type != Node_array_ref) + unref(n->lnode); freenode(n); } if (f->stack) @@ -1305,11 +1318,19 @@ char *func_name; r->type = Node_var; /* call by reference for arrays; see below also */ - if (arg->type == Node_param_list) + if (arg->type == Node_param_list) { + /* we must also reassign f here; see below */ + f = & fcall_list[curfcall]; arg = f->prevstack[arg->param_cnt]; - if (arg->type == Node_var_array) + } + if (arg->type == Node_var_array) { + r->type = Node_array_ref; + r->flags &= ~SCALAR; + r->orig_array = arg; + r->vname = arg->vname; + } else if (arg->type == Node_array_ref) { *r = *arg; - else { + } else { n = tree_eval(arg); r->lnode = dupnode(n); r->rnode = (NODE *) NULL; @@ -1443,6 +1464,7 @@ Func_ptr *assign; } switch (ptr->type) { + case Node_array_ref: case Node_var_array: fatal("attempt to use array `%s' in a scalar context", ptr->vname); @@ -1565,7 +1587,12 @@ Func_ptr *assign; n = stack_ptr[n->param_cnt]; if ((n->flags & SCALAR) != 0) fatal("attempt to use scalar parameter %d as an array", i); - } else if (n->type == Node_func) { + } + if (n->type == Node_array_ref) { + n = n->orig_array; + assert(n->type == Node_var_array || n->type == Node_var); + } + if (n->type == Node_func) { fatal("attempt to use function `%s' as array", n->lnode->param); } |