gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, master, updated. f2b825c82aa6b0b2eabed73


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, master, updated. f2b825c82aa6b0b2eabed734244148206f3c01a5
Date: Wed, 04 May 2011 20:11:10 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, master has been updated
       via  f2b825c82aa6b0b2eabed734244148206f3c01a5 (commit)
       via  e7dced088c226280bcb1edb252011d6c186504e4 (commit)
       via  19093d5a231421594788d633e811859276d8f92f (commit)
      from  6af68343403a8d7d0fe5cf34827165c9545d57de (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=f2b825c82aa6b0b2eabed734244148206f3c01a5

commit f2b825c82aa6b0b2eabed734244148206f3c01a5
Author: Arnold D. Robbins <address@hidden>
Date:   Wed May 4 23:10:29 2011 +0300

    Bug fixes and new test, see nastyparm.

diff --git a/ChangeLog b/ChangeLog
index ac4c5fc..d9a27fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed May  4 23:06:17 2011  John Haque      <address@hidden>
+
+       * eval.c (setup_frame): Handle a Node_var in stack. Fixes
+       a problem when a Node_var_new as param becomes Node_var during
+       expresssion evaluation for a subsequent param.
+
 Wed May  4 23:04:06 2011  John Haque      <address@hidden>
 
        Fix the problem (crash) with disappearing array argument when
diff --git a/eval.c b/eval.c
index 850953f..dbd1c9f 100644
--- a/eval.c
+++ b/eval.c
@@ -1302,6 +1302,15 @@ setup_frame(INSTRUCTION *pc)
                        r->prev_array = m;
                        break;
 
+               case Node_var:
+                       /* Untyped (Node_var_new) variable as param became a
+                        * scalar during evaluation of expression for a
+                        * subsequent param.
+                        */
+                       r->type = Node_var;
+                       r->var_value = Nnull_string;
+                       break;
+
                case Node_val:
                        r->type = Node_var;
                        r->var_value = m;
diff --git a/test/ChangeLog b/test/ChangeLog
index ffaf462..b3e99c2 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+Wed May  4 23:07:39 2011  Arnold D. Robbins  <address@hidden>
+
+       * nastyparm.awk, nastyparm.ok: New files from John Haque.
+       * Makefile.am (nastyparm): New test.
+
 Wed May  4 23:03:06 2011  Arnold D. Robbins  <address@hidden>
 
        * delsub.awk, delsub.ok: New files.
diff --git a/test/Makefile.am b/test/Makefile.am
index c4cfceb..8564abe 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -413,6 +413,8 @@ EXTRA_DIST = \
        nasty.ok \
        nasty2.awk \
        nasty2.ok \
+       nastyparm.awk \
+       nastyparm.ok \
        negexp.awk \
        negexp.ok \
        negrange.awk \
@@ -782,7 +784,8 @@ GAWK_EXT_TESTS = \
        gnuops2 gnuops3 gnureops \
        icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall lint \
        lintwarn \
-       lintold manyfiles match1 match2 match3 mbstr1 nondec nondec2 patsplit \
+       lintold manyfiles match1 match2 match3 mbstr1 nondec \
+       nastyparm nondec2 patsplit \
        posix profile1 profile2 profile3 printfbad1 printfbad2 \
        procinfs rebuf regx8bit reint reint2 rsstart1 rsstart2 rsstart3 \
        rstest6 shadow sortfor sortu splitarg4 strftime strtonum switch2
diff --git a/test/Makefile.in b/test/Makefile.in
index 85b7e80..4fd7648 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -340,6 +340,8 @@ EXTRA_DIST = \
        delarpm2.ok \
        delfunc.awk \
        delfunc.ok \
+       delsub.awk \
+       delsub.ok \
        devfd.in1 \
        devfd.in2 \
        devfd.in4 \
@@ -596,6 +598,8 @@ EXTRA_DIST = \
        nasty.ok \
        nasty2.awk \
        nasty2.ok \
+       nastyparm.awk \
+       nastyparm.ok \
        negexp.awk \
        negexp.ok \
        negrange.awk \
@@ -959,12 +963,13 @@ GAWK_EXT_TESTS = \
        aadelete1 aadelete2 aarray1 aasort aasorti \
        arraysort \
        argtest backw badargs beginfile1 binmode1 clos1way \
-       devfd devfd1 devfd2 dumpvars \
+       delsub devfd devfd1 devfd2 dumpvars \
        fieldwdth fpat1 funlen fsfwfs fwtest fwtest2 gensub gensub2 getlndir \
        gnuops2 gnuops3 gnureops \
        icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall lint \
        lintwarn \
-       lintold manyfiles match1 match2 match3 mbstr1 nondec nondec2 patsplit \
+       lintold manyfiles match1 match2 match3 mbstr1 nondec \
+       nastyparm nondec2 patsplit \
        posix profile1 profile2 profile3 printfbad1 printfbad2 \
        procinfs rebuf regx8bit reint reint2 rsstart1 rsstart2 rsstart3 \
        rstest6 shadow sortfor sortu splitarg4 strftime strtonum switch2
@@ -2592,6 +2597,11 @@ clos1way:
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
 
+delsub:
+       @echo delsub
+       @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 fieldwdth:
        @echo fieldwdth
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  < $(srcdir)/address@hidden 
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2717,6 +2727,11 @@ nondec:
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
 
+nastyparm:
+       @echo nastyparm
+       @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 patsplit:
        @echo patsplit
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 772ee65..638f64f 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -885,6 +885,11 @@ clos1way:
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
 
+delsub:
+       @echo delsub
+       @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 fieldwdth:
        @echo fieldwdth
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  < $(srcdir)/address@hidden 
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1010,6 +1015,11 @@ nondec:
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
 
+nastyparm:
+       @echo nastyparm
+       @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 patsplit:
        @echo patsplit
        @AWKPATH=$(srcdir) $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/nastyparm.awk b/test/nastyparm.awk
new file mode 100644
index 0000000..a1f1c82
--- /dev/null
+++ b/test/nastyparm.awk
@@ -0,0 +1,41 @@
+function biz(baz, bar)
+{
+       print baz, bar
+}
+
+function buz(baz, bar)
+{
+       print length(baz), bar
+}
+
+function buz2(baz, baz1, bar, baz2)
+{
+       print length(baz), length(baz1), bar, length(baz2)
+       baz2[0] = "baz2"
+#      baz[0] = "baz"  # fatal
+}
+
+function buz3(baz)
+{
+       buz2(baz, baz, split("abc", baz, ""), baz)
+} 
+
+
+BEGIN {
+       biz(foo, foo != "")
+
+       biz(fy, fy = "fy")
+
+       biz(fi = 10, fi = 20)
+       print fi
+
+       buz(a, split("abc", a, ""))
+
+       buz2(c, c, split("abc", c, ""), c)
+       print c[0], length(c)
+
+       buz3(d)
+       print d[0], length(d)
+
+       biz(b, split("abc", b, ""))
+}
diff --git a/test/nastyparm.ok b/test/nastyparm.ok
new file mode 100644
index 0000000..c68a1c5
--- /dev/null
+++ b/test/nastyparm.ok
@@ -0,0 +1,11 @@
+ 0
+ fy
+10 20
+20
+3 3
+3 3 3 3
+baz2 4
+3 3 3 3
+baz2 4
+gawk: nastyparm.awk:3: fatal: attempt to use array `baz (from b)' in a scalar 
context
+EXIT CODE: 2

http://git.sv.gnu.org/cgit/gawk.git/commit/?id=e7dced088c226280bcb1edb252011d6c186504e4

commit e7dced088c226280bcb1edb252011d6c186504e4
Author: Arnold D. Robbins <address@hidden>
Date:   Wed May 4 23:05:28 2011 +0300

    Fix problem with subarray of deleted array.

diff --git a/ChangeLog b/ChangeLog
index b80e151..ac4c5fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+Wed May  4 23:04:06 2011  John Haque      <address@hidden>
+
+       Fix the problem (crash) with disappearing array argument when
+       it is a subarray of another deleted array argument.
+
+       * awk.h (struct exp_node): Nuke unused field sub.nodep.number.
+       New field sub.nodep.rn.
+       (parent_array): New definition for sub.nodep.rn to keep track
+       of the parent of a subarray.
+       * awkgram.y (mk_symbol): Initialize parent_array to NULL.
+       * eval.c (r_interpret): In the case Op_sub_array, assign
+       parent_array.
+       * array.c (get_array): Initialize parent_array to NULL when
+       a Node_var_new becomes a Node_var_array.
+       (assoc_find): Add a fourth argument for the previous node
+       of the returned bucket.
+       (in_array, assoc_lookup): Adjust calls to assoc_find().
+       (adjust_fcall_stack): New routine to change a soon-to-be deleted
+       subarray parameter in the function call stack to a local array.
+       (do_delete): Simplify code, remove recursive usage. Call
+       adjust_fcall_stack() where appropriate.
+       (do_delete_loop): Call adjust_fcall_stack() before clearing the
+       array.
+       (asort_actual): Don't accept an array and its subarray as
+       arguments for asort() or asorti().
+       (asort_actual, dup_table): For asort(), appropriately assign
+       parent_array when creating the result array.
+       * field.c (do_split, do_patsplit): An array and its subarray not
+       accepted for the second and the fourth arguments. Remove
+       unnecessary dupnode of the field seperator node.
+
+       Unrelated:
+       * awkgram.y (LEX_DELETE, simple_variable): Change type argument
+       from Node_var_array to Node_var_new for calls to variable().
+       * io.c (devopen): Fix parsing GAWK_MSEC_SLEEP env variable.
+
 Mon May  2 23:44:34 2011  Arnold D. Robbins  <address@hidden>
 
        * dfa.c (parse_bracket_exp): Sync with GNU grep, since we
diff --git a/array.c b/array.c
index ee8ac9e..380d4f3 100644
--- a/array.c
+++ b/array.c
@@ -45,7 +45,7 @@ static size_t AVG_CHAIN_MAX = 2;      /* Modern machines are 
bigger, reduce this from
 static size_t SUBSEPlen;
 static char *SUBSEP;
 
-static NODE *assoc_find(NODE *symbol, NODE *subs, unsigned long hash1);
+static NODE *assoc_find(NODE *symbol, NODE *subs, unsigned long hash1, NODE 
**last);
 static void grow_table(NODE *symbol);
 
 static unsigned long gst_hash_string(const char *str, size_t len, unsigned 
long hsize, size_t *code);
@@ -198,6 +198,7 @@ get_array(NODE *symbol, int canfatal)
        case Node_var_new:
                symbol->type = Node_var_array;
                symbol->var_array = NULL;
+               symbol->parent_array = NULL;    /* main array has no parent */
                /* fall through */
        case Node_var_array:
                break;
@@ -296,6 +297,7 @@ concat_exp(int nargs, int do_subsep)
        return make_str_node(str, len, ALREADY_MALLOCED);
 }
 
+
 /* assoc_clear --- flush all the values in symbol[] */
 
 void
@@ -317,6 +319,7 @@ assoc_clear(NODE *symbol)
                                freenode(r);
                        } else
                                unref(bucket->ahvalue);
+
                        unref(bucket);  /* unref() will free the ahname_str */
                }
                symbol->var_array[i] = NULL;
@@ -393,15 +396,15 @@ awk_hash(const char *s, size_t len, unsigned long hsize, 
size_t *code)
 /* assoc_find --- locate symbol[subs] */
 
 static NODE *                          /* NULL if not found */
-assoc_find(NODE *symbol, NODE *subs, unsigned long hash1)
+assoc_find(NODE *symbol, NODE *subs, unsigned long hash1, NODE **last)
 {
-       NODE *bucket;
+       NODE *bucket, *prev;
        const char *s1_str;
        size_t s1_len;
        NODE *s2;
 
-       for (bucket = symbol->var_array[hash1]; bucket != NULL;
-                       bucket = bucket->ahnext) {
+       for (prev = NULL, bucket = symbol->var_array[hash1]; bucket != NULL;
+                       prev = bucket, bucket = bucket->ahnext) {
                /*
                 * This used to use cmp_nodes() here.  That's wrong.
                 * Array indices are strings; compare as such, always!
@@ -413,10 +416,12 @@ assoc_find(NODE *symbol, NODE *subs, unsigned long hash1)
                if (s1_len == s2->stlen) {
                        if (s1_len == 0         /* "" is a valid index */
                            || memcmp(s1_str, s2->stptr, s1_len) == 0)
-                               return bucket;
+                               break;
                }
        }
-       return NULL;
+       if (last != NULL)
+               *last = prev;
+       return bucket;
 }
 
 /* in_array --- test whether the array element symbol[subs] exists or not,
@@ -435,7 +440,7 @@ in_array(NODE *symbol, NODE *subs)
                return NULL;
 
        hash1 = hash(subs->stptr, subs->stlen, (unsigned long) 
symbol->array_size, NULL);
-       ret = assoc_find(symbol, subs, hash1);
+       ret = assoc_find(symbol, subs, hash1, NULL);
        return (ret ? ret->ahvalue : NULL);
 }
 
@@ -468,7 +473,7 @@ assoc_lookup(NODE *symbol, NODE *subs, int reference)
        } else {
                hash1 = hash(subs->stptr, subs->stlen,
                                (unsigned long) symbol->array_size, & code);
-               bucket = assoc_find(symbol, subs, hash1);
+               bucket = assoc_find(symbol, subs, hash1, NULL);
                if (bucket != NULL)
                        return &(bucket->ahvalue);
        }
@@ -532,6 +537,94 @@ assoc_lookup(NODE *symbol, NODE *subs, int reference)
        return &(bucket->ahvalue);
 }
 
+
+/* adjust_fcall_stack: remove subarray(s) of symbol[] from
+ *     function call stack.
+ */
+
+static void
+adjust_fcall_stack(NODE *symbol, int nsubs)
+{
+       NODE *func, *r, *n;
+       NODE **sp;
+       int pcount;
+
+       /*
+        * Solve the nasty problem of disappearing subarray arguments:
+        *
+        *  function f(c, d) { delete c; .. use non-existent array d .. }
+        *  BEGIN { a[0][0] = 1; f(a, a[0]); .. }
+        *
+        * The fix is to convert 'd' to a local empty array; This has
+        * to be done before clearing the parent array to avoid referring to
+        * already free-ed memory.
+        *
+        * Similar situations exist for builtins accepting more than
+        * one array argument: split, patsplit, asort and asorti. For example:
+        *
+        *  BEGIN { a[0][0] = 1; split("abc", a, "", a[0]) }
+        *
+        * These cases do not involve the function call stack, and are
+        * handled individually in their respective routines.
+        */
+
+       func = frame_ptr->func_node;
+       if (func == NULL)       /* in main */
+               return;
+       pcount = func->lnode->param_cnt;
+       sp = frame_ptr->stack;
+
+       for (; pcount > 0; pcount--) {
+               r = *sp++;
+               if (r->type != Node_array_ref
+                               || r->orig_array->type != Node_var_array)
+                       continue;
+               n = r->orig_array;
+
+               /* Case 1 */
+               if (n == symbol
+                       && symbol->parent_array != NULL
+                       && nsubs > 0
+               ) {
+                       /* 'symbol' is a subarray, and 'r' is the same subarray:
+                        *
+                        *   function f(c, d) { delete c[0]; .. }
+                        *   BEGIN { a[0][0] = 1; f(a, a[0]); .. }
+                        *
+                        * But excludes cases like (nsubs = 0):
+                        *
+                        *   function f(c, d) { delete c; ..}
+                        *   BEGIN { a[0][0] = 1; f(a[0], a[0]); ...}  
+                        */
+                       char *save;
+local_array:
+                       save = r->vname;
+                       memset(r, '\0', sizeof(NODE));
+                       r->vname = save;
+                       r->type = Node_var_array;
+                       continue;
+               }                       
+
+               /* Case 2 */
+               for (n = n->parent_array; n != NULL; n = n->parent_array) {
+                       assert(n->type == Node_var_array);
+                       if (n == symbol) {
+                               /* 'r' is a subarray of 'symbol':
+                                *
+                                *    function f(c, d) { delete c; .. use d as 
array .. }
+                                *    BEGIN { a[0][0] = 1; f(a, a[0]); .. }
+                                *      OR
+                                *    BEGIN { a[0][0][0][0] = 1; f(a[0], 
a[0][0][0]); .. }
+                                *
+                                */
+
+                               goto local_array;
+                       }
+               }
+       }
+}
+
+
 /* do_delete --- perform `delete array[s]' */
 
 /*
@@ -543,8 +636,8 @@ void
 do_delete(NODE *symbol, int nsubs)
 {
        unsigned long hash1;
-       NODE *bucket, *last;
-       NODE *subs;
+       NODE *subs, *bucket, *last, *r;
+       int i;
 
        assert(symbol->type == Node_var_array);
 
@@ -568,81 +661,63 @@ do {                                                      
        \
 } while (--n > 0)
 
        if (nsubs == 0) {       /* delete array */
+               adjust_fcall_stack(symbol, 0);  /* fix function call stack; See 
above. */
                assoc_clear(symbol);
                return;
        }
 
        /* NB: subscripts are in reverse order on stack */
-       subs = PEEK(nsubs - 1);
-       if (subs->type != Node_val) {
-               if (--nsubs > 0)
-                       free_subs(nsubs);
-               fatal(_("attempt to use array `%s' in a scalar context"), 
array_vname(subs));
-       }
-       (void) force_string(subs);
 
-       last = NULL;    /* shut up gcc -Wall */
-       hash1 = 0;      /* ditto */
+       for (i = nsubs; i > 0; i--) {
+               subs = PEEK(i - 1);
+               if (subs->type != Node_val) {
+                       free_subs(i);
+                       fatal(_("attempt to use array `%s' in a scalar 
context"), array_vname(subs));
+               }
+               (void) force_string(subs);
 
-       if (symbol->var_array != NULL) {
-               hash1 = hash(subs->stptr, subs->stlen,
-                               (unsigned long) symbol->array_size, NULL);
-               last = NULL;
-               for (bucket = symbol->var_array[hash1]; bucket != NULL;
-                               last = bucket, bucket = bucket->ahnext) {
-                       /*
-                        * This used to use cmp_nodes() here.  That's wrong.
-                        * Array indices are strings; compare as such, always!
-                        */
-                       const char *s1_str;
-                       size_t s1_len;
-                       NODE *s2;
+               last = NULL;    /* shut up gcc -Wall */
+               hash1 = 0;      /* ditto */
+               bucket = NULL;  /* array may be empty */
 
-                       s1_str = bucket->ahname_str;
-                       s1_len = bucket->ahname_len;
-                       s2 = subs;
-       
-                       if (s1_len == s2->stlen) {
-                               if (s1_len == 0         /* "" is a valid index 
*/
-                                   || memcmp(s1_str, s2->stptr, s1_len) == 0)
-                                       break;
-                       }
+               if (symbol->var_array != NULL) {
+                       hash1 = hash(subs->stptr, subs->stlen,
+                                       (unsigned long) symbol->array_size, 
NULL);
+                       bucket = assoc_find(symbol, subs, hash1, &last);
                }
-       } else
-               bucket = NULL;  /* The array is empty.  */
 
-       if (bucket == NULL) {
-               if (do_lint)
-                       lintwarn(_("delete: index `%s' not in array `%s'"),
-                               subs->stptr, array_vname(symbol));
-               DEREF(subs);
+               if (bucket == NULL) {
+                       if (do_lint)
+                               lintwarn(_("delete: index `%s' not in array 
`%s'"),
+                                       subs->stptr, array_vname(symbol));
+                       /* avoid memory leak, free all subs */
+                       free_subs(i);
+                       return;
+               }
 
-               /* avoid memory leak, free rest of the subs */
-               if (--nsubs > 0)
-                       free_subs(nsubs);
-               return;
+               if (i > 1) {
+                       if (bucket->ahvalue->type != Node_var_array) {
+                               /* e.g.: a[1] = 1; delete a[1][1] */
+                               free_subs(i);
+                               fatal(_("attempt to use scalar `%s[\"%.*s\"]' 
as an array"),
+                                       symbol->vname,
+                                       (int) bucket->ahname_len,
+                                       bucket->ahname_str);
+                       }
+                       symbol = bucket->ahvalue;
+               }
+               DEREF(subs);
        }
 
-       DEREF(subs);
-       if (bucket->ahvalue->type == Node_var_array) {
-               NODE *r = bucket->ahvalue;
-               do_delete(r, nsubs - 1);
-               if (r->var_array != NULL || nsubs > 1)
-                       return;
-               /* else
-                       cleared a sub-array, free the array node
-                       and the bucket in parent array */
+       r = bucket->ahvalue;
+       if (r->type == Node_var_array) {
+               adjust_fcall_stack(r, nsubs);   /* fix function call stack; See 
above. */
+               assoc_clear(r);
+               /* cleared a sub-array, free Node_var_array */
                efree(r->vname);
                freenode(r);
-       } else if (--nsubs > 0) {
-               /* e.g.: a[1] = 1; delete a[1][1] */
-               free_subs(nsubs);
-               fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"),
-                                       symbol->vname,
-                                       (int) bucket->ahname_len,
-                                       bucket->ahname_str);
        } else
-               unref(bucket->ahvalue);
+               unref(r);
 
        if (last != NULL)
                last->ahnext = bucket->ahnext;
@@ -663,6 +738,7 @@ do {                                                        
        \
 #undef free_subs
 }
 
+
 /* do_delete_loop --- simulate ``for (iggy in foo) delete foo[iggy]'' */
 
 /*
@@ -692,6 +768,7 @@ do_delete_loop(NODE *symbol, NODE **lhs)
        }
 
        /* blast the array in one shot */
+       adjust_fcall_stack(symbol, 0);
        assoc_clear(symbol);
 }
 
@@ -923,6 +1000,7 @@ dup_table(NODE *symbol, NODE *newsymb)
                                                emalloc(aname, char *, 
aname_len + 2, "dup_table");
                                                sprintf(aname, "%s[\"%.*s\"]", 
newsymb->vname, (int) chain->ahname_len, chain->ahname_str);
                                                r->vname = aname;
+                                               r->parent_array = newsymb;
                                                bucket->ahvalue = 
dup_table(chain->ahvalue, r);
                                        } else
                                                bucket->ahvalue = 
dupnode(chain->ahvalue);
@@ -979,6 +1057,21 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                        _("asorti: first argument not an array"));
        }
 
+       if (dest != NULL) {
+               for (r = dest->parent_array; r != NULL; r = r->parent_array) {
+                       if (r == array)
+                               fatal(ctxt == ASORT ?
+                                       _("asort: cannot use a subarray of 
first arg for second arg") :
+                                       _("asorti: cannot use a subarray of 
first arg for second arg"));
+               }
+               for (r = array->parent_array; r != NULL; r = r->parent_array) {
+                       if (r == dest)
+                               fatal(ctxt == ASORT ?
+                                       _("asort: cannot use a subarray of 
second arg for first arg") :
+                                       _("asorti: cannot use a subarray of 
second arg for first arg"));
+                }
+       }
+
        num_elems = array->table_size;
        if (num_elems == 0 || array->var_array == NULL) {       /* source array 
is empty */
                if (dest != NULL && dest != array)
@@ -1005,6 +1098,7 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                memset(result, '\0', sizeof(NODE));
                result->type = Node_var_array;
                result->vname = array->vname;
+               result->parent_array = array->parent_array;
        }
 
        subs = make_str_node(buf, TSIZE, ALREADY_MALLOCED);   /* fake it */
@@ -1041,6 +1135,7 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                                arr->type = Node_var_array;
                                arr->var_array = NULL;
                                arr->vname = estrdup(arr_name, 
strlen(arr_name));
+                               arr->parent_array = array; /* actual parent, 
not the temporary one. */
                                *assoc_lookup(result, subs, FALSE) = 
dup_table(val, arr);
                        }
                }
diff --git a/awk.h b/awk.h
index add30f9..fb56748 100644
--- a/awk.h
+++ b/awk.h
@@ -319,7 +319,7 @@ typedef struct exp_node {
                                char **param_list;
                        } x;
                        char *name;
-                       short number;
+                       struct exp_node *rn;
                        unsigned long reflags;
 #                              define  CASE            1
 #                              define  CONSTANT        2
@@ -375,8 +375,8 @@ typedef struct exp_node {
                                         * function name; see awkgram.y */
 #              define  FIELD   512     /* this is a field */
 #              define  INTLSTR 1024    /* use localized version */
-#              define  WSTRCUR 2048    /* wide str value is current */
-#              define  NUMIND  4096    /* numeric val of index is current */
+#              define  NUMIND  2048    /* numeric val of index is current */
+#              define  WSTRCUR 4096    /* wide str value is current */
 } NODE;
 
 
@@ -419,9 +419,10 @@ typedef struct exp_node {
 #define var_assign      sub.nodep.x.aptr
 
 /* Node_var_array: */
-#define var_array sub.nodep.r.av
-#define array_size sub.nodep.l.ll
-#define table_size sub.nodep.x.xl
+#define var_array    sub.nodep.r.av
+#define array_size   sub.nodep.l.ll
+#define table_size   sub.nodep.x.xl
+#define parent_array sub.nodep.rn
 
 /* Node_array_ref: */
 #define orig_array lnode
diff --git a/awkgram.c b/awkgram.c
index 9b56293..0962840 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -3005,7 +3005,7 @@ regular_loop:
                char *arr = (yyvsp[(2) - (4)])->lextok;
 
                (yyvsp[(2) - (4)])->opcode = Op_push_array;
-               (yyvsp[(2) - (4)])->memory = variable(arr, Node_var_array);
+               (yyvsp[(2) - (4)])->memory = variable(arr, Node_var_new);
 
                if ((yyvsp[(4) - (4)]) == NULL) {
                        static short warned = FALSE;
@@ -3044,7 +3044,7 @@ regular_loop:
                        error_ln((yyvsp[(1) - (4)])->source_line,
                                _("`delete array' is a gawk extension"));
                }
-               (yyvsp[(3) - (4)])->memory = variable(arr, Node_var_array);
+               (yyvsp[(3) - (4)])->memory = variable(arr, Node_var_new);
                (yyvsp[(3) - (4)])->opcode = Op_push_array;
                (yyvsp[(1) - (4)])->expr_count = 0;
                (yyval) = list_append(list_create((yyvsp[(3) - (4)])), 
(yyvsp[(1) - (4)]));
@@ -4115,7 +4115,7 @@ regular_loop:
                char *arr = (yyvsp[(1) - (2)])->lextok;
                if ((n = lookup(arr)) != NULL && ! isarray(n))
                        yyerror(_("use of non-array as array"));
-               (yyvsp[(1) - (2)])->memory = variable(arr, Node_var_array);
+               (yyvsp[(1) - (2)])->memory = variable(arr, Node_var_new);
                (yyvsp[(1) - (2)])->opcode = Op_push_array;
                (yyval) = list_prepend((yyvsp[(2) - (2)]), (yyvsp[(1) - (2)]));
          }
@@ -6219,6 +6219,7 @@ mk_symbol(NODETYPE type, NODE *value)
        r->flags = MALLOC;
        r->lnode = value;
        r->rnode = NULL;
+       r->parent_array = NULL;
        r->var_assign = (Func_ptr) 0;
        return r;
 }
diff --git a/awkgram.y b/awkgram.y
index cf8b9e9..f739f1d 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -986,7 +986,7 @@ simple_stmt
                char *arr = $2->lextok;
 
                $2->opcode = Op_push_array;
-               $2->memory = variable(arr, Node_var_array);
+               $2->memory = variable(arr, Node_var_new);
 
                if ($4 == NULL) {
                        static short warned = FALSE;
@@ -1024,7 +1024,7 @@ simple_stmt
                        error_ln($1->source_line,
                                _("`delete array' is a gawk extension"));
                }
-               $3->memory = variable(arr, Node_var_array);
+               $3->memory = variable(arr, Node_var_new);
                $3->opcode = Op_push_array;
                $1->expr_count = 0;
                $$ = list_append(list_create($3), $1);
@@ -1711,7 +1711,7 @@ simple_variable
                char *arr = $1->lextok;
                if ((n = lookup(arr)) != NULL && ! isarray(n))
                        yyerror(_("use of non-array as array"));
-               $1->memory = variable(arr, Node_var_array);
+               $1->memory = variable(arr, Node_var_new);
                $1->opcode = Op_push_array;
                $$ = list_prepend($2, $1);
          }
@@ -3572,6 +3572,7 @@ mk_symbol(NODETYPE type, NODE *value)
        r->flags = MALLOC;
        r->lnode = value;
        r->rnode = NULL;
+       r->parent_array = NULL;
        r->var_assign = (Func_ptr) 0;
        return r;
 }
diff --git a/command.c b/command.c
index fa79571..2b3b349 100644
--- a/command.c
+++ b/command.c
@@ -3020,7 +3020,7 @@ again:
                                /* force a quit, and let do_quit (in debug.c) 
exit */
                                if (! seen_eof) {
                                        if (errno != 0) {
-                                               fprintf(stderr, _("can't read 
command (%s)"), strerror(errno));
+                                               fprintf(stderr, _("can't read 
command (%s)\n"), strerror(errno));
                                                exit_val = EXIT_FAILURE;
                                        } /* else
                                                exit_val = EXIT_SUCCESS; */
diff --git a/command.y b/command.y
index d9ecd0a..bcaa74f 100644
--- a/command.y
+++ b/command.y
@@ -1047,7 +1047,7 @@ again:
                                /* force a quit, and let do_quit (in debug.c) 
exit */
                                if (! seen_eof) {
                                        if (errno != 0) {
-                                               fprintf(stderr, _("can't read 
command (%s)"), strerror(errno));
+                                               fprintf(stderr, _("can't read 
command (%s)\n"), strerror(errno));
                                                exit_val = EXIT_FAILURE;
                                        } /* else
                                                exit_val = EXIT_SUCCESS; */
diff --git a/eval.c b/eval.c
index f4d66b1..850953f 100644
--- a/eval.c
+++ b/eval.c
@@ -455,6 +455,7 @@ flags2str(int flagval)
                { FUNC, "FUNC" },
                { FIELD, "FIELD" },
                { INTLSTR, "INTLSTR" },
+               { NUMIND, "NUMIND" },
 #ifdef WSTRCUR
                { WSTRCUR, "WSTRCUR" },
 #endif
@@ -1758,6 +1759,7 @@ top:
                                r->type = Node_var_array;
                                r->var_array = NULL;
                                r->vname = estrdup(arr_name, strlen(arr_name));
+                               r->parent_array = t1;
                                *assoc_lookup(t1, t2, FALSE) = r;
                        } else if (r->type != Node_var_array) {
                                const char *arr_name = make_aname(t1, t2);
diff --git a/field.c b/field.c
index 659574e..09e06e9 100644
--- a/field.c
+++ b/field.c
@@ -956,12 +956,20 @@ do_split(int nargs)
        if (arr->type != Node_var_array)
                fatal(_("split: second argument is not an array"));
 
-       assoc_clear(arr);
        if (sep_arr != NULL) {
                if (sep_arr == arr)
-                       fatal(_("split: can not use the same array for second 
and fourth args")); 
+                       fatal(_("split: cannot use the same array for second 
and fourth args")); 
+
+               /* This checks need to be done before clearing any of the 
arrays */
+               for (tmp = sep_arr->parent_array; tmp != NULL; tmp = 
tmp->parent_array)
+                       if (tmp == arr)
+                               fatal(_("split: cannot use a subarray of second 
arg for fourth arg"));  
+               for (tmp = arr->parent_array; tmp != NULL; tmp = 
tmp->parent_array)
+                       if (tmp == sep_arr)
+                               fatal(_("split: cannot use a subarray of fourth 
arg for second arg"));
                assoc_clear(sep_arr);
        }
+       assoc_clear(arr);
 
        src = TOP_STRING();
        if (src->stlen == 0) {
@@ -975,10 +983,10 @@ do_split(int nargs)
 
        if ((sep->re_flags & FS_DFLT) != 0 && current_field_sep() != 
Using_FIELDWIDTHS && ! RS_is_null) {
                parseit = parse_field;
-               fs = dupnode(force_string(FS_node->var_value));
+               fs = force_string(FS_node->var_value);
                rp = FS_regexp;
        } else {
-               fs = dupnode(sep->re_exp);
+               fs = sep->re_exp;
 
                if (fs->stlen == 0) {
                        static short warned = FALSE;
@@ -1009,7 +1017,6 @@ do_split(int nargs)
 
        decr_sp();
        DEREF(src);
-       unref(fs);
        return tmp;
 }
 
@@ -1036,39 +1043,41 @@ do_patsplit(int nargs)
                fatal(_("patsplit: second argument is not an array"));
 
        src = TOP_STRING();
-       if (src->stlen == 0) {
-               /*
-                * Skip the work if first arg is the null string.
-                */
-               assoc_clear(arr);
-               if (sep_arr != NULL)
-                       assoc_clear(sep_arr);
-               decr_sp();
-               DEREF(src);
-               return make_number((AWKNUM) 0);
-       }
 
-       fpat = dupnode(sep->re_exp);
-       if (fpat->stlen == 0) {
-               unref(fpat);
+       fpat = sep->re_exp;
+       if (fpat->stlen == 0)
                fatal(_("patsplit: third argument must be non-null"));
-       }
-       assoc_clear(arr);
+
        if (sep_arr != NULL) {
                if (sep_arr == arr)
-                       fatal(_("patsplit: can not use the same array for 
second and fourth args")); 
+                       fatal(_("patsplit: cannot use the same array for second 
and fourth args")); 
+
+               /* This checks need to be done before clearing any of the 
arrays */
+               for (tmp = sep_arr->parent_array; tmp != NULL; tmp = 
tmp->parent_array)
+                       if (tmp == arr)
+                               fatal(_("patsplit: cannot use a subarray of 
second arg for fourth arg"));
+               for (tmp = arr->parent_array; tmp != NULL; tmp = 
tmp->parent_array)
+                       if (tmp == sep_arr)
+                               fatal(_("patsplit: cannot use a subarray of 
fourth arg for second arg"));
                assoc_clear(sep_arr);
        }
+       assoc_clear(arr);
 
-       rp = re_update(sep);
-
-       s = src->stptr;
-       tmp = make_number((AWKNUM) fpat_parse_field(UNLIMITED, &s,
+       if (src->stlen == 0) {
+               /*
+                * Skip the work if first arg is the null string.
+                */
+               tmp =  make_number((AWKNUM) 0);
+       } else {
+               rp = re_update(sep);
+               s = src->stptr;
+               tmp = make_number((AWKNUM) fpat_parse_field(UNLIMITED, &s,
                                (int) src->stlen, fpat, rp,
                                set_element, arr, sep_arr, FALSE));
-       decr_sp();
+       }
+
+       decr_sp();      /* 1st argument not POP-ed */
        DEREF(src);
-       unref(fpat);
        return tmp;
 }
 
diff --git a/io.c b/io.c
index 6fc921c..401b4de 100644
--- a/io.c
+++ b/io.c
@@ -1504,7 +1504,7 @@ devopen(const char *name, const char *mode)
                                 */
                                if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) {
                                        msleep = strtol(ms2, &end, 10);
-                                       if (end != cp && msleep < 0)
+                                       if (end == ms2 || msleep < 0)
                                                msleep = 1000;
                                        else
                                                msleep *= 1000;
diff --git a/test/ChangeLog b/test/ChangeLog
index 3754c55..ffaf462 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+Wed May  4 23:03:06 2011  Arnold D. Robbins  <address@hidden>
+
+       * delsub.awk, delsub.ok: New files.
+       * Makefile.am (delsub): New test.
+
 Fri Apr 22 16:07:01 2011  John Haque         <address@hidden>
 
        * sortu.awk, sortu.ok: New files.
diff --git a/test/Makefile.am b/test/Makefile.am
index 8eeb80d..c4cfceb 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -155,6 +155,8 @@ EXTRA_DIST = \
        delarpm2.ok \
        delfunc.awk \
        delfunc.ok \
+       delsub.awk \
+       delsub.ok \
        devfd.in1 \
        devfd.in2 \
        devfd.in4 \
@@ -775,7 +777,7 @@ GAWK_EXT_TESTS = \
        aadelete1 aadelete2 aarray1 aasort aasorti \
        arraysort \
        argtest backw badargs beginfile1 binmode1 clos1way \
-       devfd devfd1 devfd2 dumpvars \
+       delsub devfd devfd1 devfd2 dumpvars \
        fieldwdth fpat1 funlen fsfwfs fwtest fwtest2 gensub gensub2 getlndir \
        gnuops2 gnuops3 gnureops \
        icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall lint \
diff --git a/test/delsub.awk b/test/delsub.awk
new file mode 100644
index 0000000..0c3ffb0
--- /dev/null
+++ b/test/delsub.awk
@@ -0,0 +1,2 @@
+function f(c, d, x) { delete c; x = d[0] }
+BEGIN { a[0][0] = 1; f(a, a[0]); print "still here" }
diff --git a/test/delsub.ok b/test/delsub.ok
new file mode 100644
index 0000000..ae3eb5b
--- /dev/null
+++ b/test/delsub.ok
@@ -0,0 +1 @@
+still here

http://git.sv.gnu.org/cgit/gawk.git/commit/?id=19093d5a231421594788d633e811859276d8f92f

commit 19093d5a231421594788d633e811859276d8f92f
Author: Arnold D. Robbins <address@hidden>
Date:   Wed May 4 22:58:20 2011 +0300

    Minor addition to FUTURES.

diff --git a/FUTURES b/FUTURES
index 12b9dfa..f5562f4 100644
--- a/FUTURES
+++ b/FUTURES
@@ -22,6 +22,8 @@ For 4.1
 
        Merge xmlgawk XML extensions
 
+       Continue code reviews / code cleanup
+
 For 4.2
 =======
        Implement designed API for loadable modules

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog          |   42 +++++++++
 FUTURES            |    2 +
 array.c            |  235 ++++++++++++++++++++++++++++++++++++----------------
 awk.h              |   13 ++--
 awkgram.c          |    7 +-
 awkgram.y          |    7 +-
 command.c          |    2 +-
 command.y          |    2 +-
 eval.c             |   11 +++
 field.c            |   65 ++++++++------
 io.c               |    2 +-
 test/ChangeLog     |   10 ++
 test/Makefile.am   |    9 ++-
 test/Makefile.in   |   19 ++++-
 test/Maketests     |   10 ++
 test/delsub.awk    |    2 +
 test/delsub.ok     |    1 +
 test/nastyparm.awk |   41 +++++++++
 test/nastyparm.ok  |   11 +++
 19 files changed, 374 insertions(+), 117 deletions(-)
 create mode 100644 test/delsub.awk
 create mode 100644 test/delsub.ok
 create mode 100644 test/nastyparm.awk
 create mode 100644 test/nastyparm.ok


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]