gawk-diffs
[Top][All Lists]
Advanced

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

[SCM] gawk branch, feature/mdim, created. gawk-4.1.0-4592-g367920b


From: Andrew J. Schorr
Subject: [SCM] gawk branch, feature/mdim, created. gawk-4.1.0-4592-g367920b
Date: Fri, 10 Dec 2021 14:44:38 -0500 (EST)

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, feature/mdim has been created
        at  367920b8f40dc4c8dd62411f007d1fcfe653a5d9 (commit)

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

commit 367920b8f40dc4c8dd62411f007d1fcfe653a5d9
Author: Andrew J. Schorr <aschorr@telemetry-investments.com>
Date:   Fri Dec 10 14:43:18 2021 -0500

    Introduce Nnull_array_value to allow array elements that were merely 
referenced to be converted to subarrays later instead of being stuck as scalars.

diff --git a/ChangeLog b/ChangeLog
index 6f4907b..8fe1b2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2021-12-10         Andrew J. Schorr      <aschorr@telemetry-investments.com>
+
+       Introduce new Nnull_array_value NODE equivalent to Nnull_string that
+       is used to mark an array element that was referenced without assigning
+       a value. We can then recognize Nnull_array_value to allow a subarray
+       to be instantiated later instead of requiring it to be scalar. This
+       eliminates a class of fatal errors that make tricky to work with
+       multidimensional arrays.
+
+       * awk.h (isnull): New macro to test whether a NODE is either
+       Nnull_string or Nnull_array_value.
+       (Nnull_array_value): Declare new special node.
+       (var_uninitialized): Use isnull instead of comparing to Nnull_string.
+       * array.c (value_info): Ditto.
+       * awkgram.y (valinfo): Add case for Nnull_array_value.
+       * builtin.c (do_typeof): Show Nnull_array_value as untyped.
+       * cint_array.c (leaf_lookup): Initialize element value to
+       Nnull_array_value instead of Nnull_string.
+       * debug.c (print_memory): Add case for Nnull_array_value.
+       * gawkapi.c (node_to_awk_value): Eliminate paranoid tests that
+       values with both NUMBER and STRING set are actually Nnull_string,
+       since they could now also be Nnull_array_value.
+       * int_array.c (is_integer): Use isnull instead of comparing to
+       Nnull_string.
+       (int_insert): Initialize element value to Nnull_array_value instead of
+       Nnull_string.
+       * interpret.h (Op_sub_array): If the current node value is
+       Nnull_array_value, create an array instead of issuing a fatal error
+       about using a scalar as an array.
+       * main.c (main): Initialize Nnull_array_value.
+       * node.c (str2wstr): Use isnull instead of comparing to Nnull_string.
+       * str_array.c (str_lookup): Ditto, and initialize new element values
+       to Nnull_array_value instead of Nnull_string.
+
 2021-12-02         Andrew J. Schorr      <aschorr@telemetry-investments.com>
 
        * builtin.c (efwrite): Don't use return in call of function
diff --git a/array.c b/array.c
index cbed125..0347b29 100644
--- a/array.c
+++ b/array.c
@@ -654,7 +654,7 @@ value_info(NODE *n)
 
 #define PREC_NUM -1
 
-       if (n == Nnull_string || n == Null_field) {
+       if (isnull(n) || n == Null_field) {
                fprintf(output_fp, "<(null)>");
                return;
        }
diff --git a/awk.h b/awk.h
index 581b977..7e958e6 100644
--- a/awk.h
+++ b/awk.h
@@ -396,8 +396,8 @@ typedef struct exp_node {
                /*
                 * STRING and NUMBER are mutually exclusive, except for the 
special
                 * case of an uninitialized value, represented internally by
-                * Nnull_string. They represent the type of a value as assigned.
-                * Nnull_string has both STRING and NUMBER attributes, but all 
other
+                * Nnull_string or Nnull_array_value. They represent the type 
of a value as assigned.
+                * Nnull_string and Nnull_array_value have both STRING and 
NUMBER attributes, but all other
                 * scalar values should have precisely one of these bits set.
                 *
                 * STRCUR and NUMCUR are not mutually exclusive. They represent 
that
@@ -472,6 +472,15 @@ typedef struct exp_node {
        long valref;
 } NODE;
 
+/*
+ * This is actually faster, but I don't like that it evaluates the argument
+ * twice:
+ *   #define isnull(x) ((x) == Nnull_string || (x) == Nnull_array_value)
+ * I also tried an inline function, but that was slower; 
+ * I guess gcc did not honor the inline request in all cases.
+ */
+#define isnull(x) (((x)->flags & (STRING|NUMBER)) == (STRING|NUMBER))
+
 #define vname sub.nodep.name
 
 #define lnode  sub.nodep.l.lptr
@@ -1135,6 +1144,7 @@ extern NODE *RSTART_node, *RS_node, *RT_node, 
*SUBSEP_node, *PROCINFO_node;
 extern NODE *LINT_node, *ERRNO_node, *TEXTDOMAIN_node, *FPAT_node;
 extern NODE *PREC_node, *ROUNDMODE_node;
 extern NODE *Nnull_string;
+extern NODE *Nnull_array_value;
 extern NODE *Null_field;
 extern NODE **fields_arr;
 extern int sourceline;
@@ -1346,7 +1356,7 @@ DEREF(NODE *r)
 #define is_zero(n)             ((n)->numbr == 0.0)
 #endif
 
-#define var_uninitialized(n)   ((n)->var_value == Nnull_string)
+#define var_uninitialized(n)   isnull((n)->var_value)
 
 #define get_lhs(n, r)   (n)->type == Node_var && ! var_uninitialized(n) ? \
                                &((n)->var_value) : r_get_lhs((n), (r))
diff --git a/awkgram.c b/awkgram.c
index 7bd2f18..5efc868 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -7402,6 +7402,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
 {
        if (n == Nnull_string)
                print_func(fp, "uninitialized scalar\n");
+       else if (n == Nnull_array_value)
+               print_func(fp, "uninitialized array value\n");
        else if ((n->flags & REGEX) != 0)
                print_func(fp, "@/%.*s/\n", n->stlen, n->stptr);
        else if ((n->flags & STRING) != 0) {
diff --git a/awkgram.y b/awkgram.y
index f4a8124..24869fa 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -4894,6 +4894,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
 {
        if (n == Nnull_string)
                print_func(fp, "uninitialized scalar\n");
+       else if (n == Nnull_array_value)
+               print_func(fp, "uninitialized array value\n");
        else if ((n->flags & REGEX) != 0)
                print_func(fp, "@/%.*s/\n", n->stlen, n->stptr);
        else if ((n->flags & STRING) != 0) {
diff --git a/builtin.c b/builtin.c
index a1f0969..20c059a 100644
--- a/builtin.c
+++ b/builtin.c
@@ -4190,6 +4190,10 @@ do_typeof(int nargs)
                                res = "unassigned";
                                break;
                        }
+                       if (arg == Nnull_array_value) {
+                               res = "untyped";
+                               break;
+                       }
                        /* fall through */
                default:
                        if (res == NULL) {
diff --git a/cint_array.c b/cint_array.c
index 63c477b..d243bf7 100644
--- a/cint_array.c
+++ b/cint_array.c
@@ -1068,7 +1068,7 @@ leaf_lookup(NODE *symbol, NODE *array, long k, long size, 
long base)
        lhs = array->nodes + (k - base); /* leaf element */
        if (*lhs == NULL) {
                array->table_size++;    /* one more element in leaf array */
-               *lhs = dupnode(Nnull_string);
+               *lhs = dupnode(Nnull_array_value);
        }
        return lhs;
 }
diff --git a/debug.c b/debug.c
index cf0946e..fe623a8 100644
--- a/debug.c
+++ b/debug.c
@@ -3716,6 +3716,8 @@ print_memory(NODE *m, NODE *func, Func_print print_func, 
FILE *fp)
        case Node_val:
                if (m == Nnull_string)
                        print_func(fp, "Nnull_string");
+               else if (m == Nnull_array_value)
+                       print_func(fp, "Nnull_array_value");
                else if ((m->flags & NUMBER) != 0) {
 #ifdef HAVE_MPFR
                        if ((m->flags & MPFN) != 0)
diff --git a/gawkapi.c b/gawkapi.c
index c42803b..7a24ab3 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -618,11 +618,8 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
                                val->val_type = AWK_REGEX;
                                break;
                        case NUMBER|STRING:
-                               if (node == Nnull_string) {
-                                       val->val_type = AWK_UNDEFINED;
-                                       break;
-                               }
-                               /* fall through */
+                               val->val_type = AWK_UNDEFINED;
+                               break;
                        default:
                                warning(_("node_to_awk_value detected invalid 
flags combination `%s'; please file a bug report"), flags2str(node->flags));
                                val->val_type = AWK_UNDEFINED;
@@ -655,11 +652,8 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
                                ret = awk_true;
                                break;
                        case NUMBER|STRING:
-                               if (node == Nnull_string) {
-                                       val->val_type = AWK_UNDEFINED;
-                                       break;
-                               }
-                               /* fall through */
+                               val->val_type = AWK_UNDEFINED;
+                               break;
                        default:
                                warning(_("node_to_awk_value detected invalid 
flags combination `%s'; please file a bug report"), flags2str(node->flags));
                                val->val_type = AWK_UNDEFINED;
@@ -685,11 +679,8 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
                                val->val_type = AWK_REGEX;
                                break;
                        case NUMBER|STRING:
-                               if (node == Nnull_string) {
-                                       val->val_type = AWK_UNDEFINED;
-                                       break;
-                               }
-                               /* fall through */
+                               val->val_type = AWK_UNDEFINED;
+                               break;
                        default:
                                warning(_("node_to_awk_value detected invalid 
flags combination `%s'; please file a bug report"), flags2str(node->flags));
                                val->val_type = AWK_UNDEFINED;
@@ -721,12 +712,9 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
                                ret = awk_true;
                                break;
                        case NUMBER|STRING:
-                               if (node == Nnull_string) {
-                                       val->val_type = AWK_UNDEFINED;
-                                       ret = awk_true;
-                                       break;
-                               }
-                               /* fall through */
+                               val->val_type = AWK_UNDEFINED;
+                               ret = awk_true;
+                               break;
                        default:
                                warning(_("node_to_awk_value detected invalid 
flags combination `%s'; please file a bug report"), flags2str(node->flags));
                                val->val_type = AWK_UNDEFINED;
diff --git a/int_array.c b/int_array.c
index 382aa79..2a264e6 100644
--- a/int_array.c
+++ b/int_array.c
@@ -122,7 +122,7 @@ is_integer(NODE *symbol, NODE *subs)
                /* quick exit */
                return & success_node;
 
-       if (subs == Nnull_string || do_mpfr)
+       if (isnull(subs) || do_mpfr)
                return NULL;
 
 #ifdef CHECK_INTEGER_USING_FORCE_NUMBER
@@ -792,7 +792,7 @@ int_insert(NODE *symbol, long k, uint32_t hash1)
        }
 
        b->ainum[i] = k;
-       b->aivalue[i] = dupnode(Nnull_string);
+       b->aivalue[i] = dupnode(Nnull_array_value);
        b->aicount++;
        return & b->aivalue[i];
 }
diff --git a/interpret.h b/interpret.h
index df70bd0..52371dd 100644
--- a/interpret.h
+++ b/interpret.h
@@ -328,7 +328,7 @@ uninitialized_scalar:
                        t2 = mk_sub(pc->sub_count);
                        t1 = POP_ARRAY(false);
                        r = in_array(t1, t2);
-                       if (r == NULL) {
+                       if (r == NULL || r == Nnull_array_value) {
                                r = make_array();
                                r->parent_array = t1;
                                t2 = force_string(t2);
diff --git a/main.c b/main.c
index 2ca0dc8..44f61aa 100644
--- a/main.c
+++ b/main.c
@@ -99,6 +99,7 @@ char *TEXTDOMAIN;
 const char *CONVFMT = "%.6g";
 
 NODE *Nnull_string;            /* The global null string */
+NODE *Nnull_array_value;
 
 #if defined(HAVE_LOCALE_H)
 struct lconv loc;              /* current locale */
@@ -291,6 +292,7 @@ main(int argc, char **argv)
 
        /* initialize the null string */
        Nnull_string = make_string("", 0);
+       Nnull_array_value = make_string("", 0);
 
        /* Robustness: check that file descriptors 0, 1, 2 are open */
        init_fds();
@@ -386,12 +388,15 @@ main(int argc, char **argv)
        if (do_mpfr) {
                mpz_init(Nnull_string->mpg_i);
                Nnull_string->flags = (MALLOC|STRCUR|STRING|MPZN|NUMCUR|NUMBER);
+               mpz_init(Nnull_array_value->mpg_i);
        } else
 #endif
        {
                Nnull_string->numbr = 0.0;
                Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER);
+               Nnull_array_value->numbr = 0.0;
        }
+       Nnull_array_value->flags = Nnull_string->flags;
 
        /*
         * Tell the regex routines how they should work.
diff --git a/node.c b/node.c
index cbf5c56..f687106 100644
--- a/node.c
+++ b/node.c
@@ -713,7 +713,7 @@ str2wstr(NODE *n, size_t **ptr)
         * This also avoids future double-free errors while releasing
         * shallow copies, eg. *tmp = *Null_field; free_wstr(tmp);
         */
-       if (n == Nnull_string || n == Null_field)
+       if (isnull(n) || n == Null_field)
                return n;
 
        if ((n->flags & WSTRCUR) != 0) {
diff --git a/str_array.c b/str_array.c
index ba8c214..dcaee3e 100644
--- a/str_array.c
+++ b/str_array.c
@@ -178,7 +178,7 @@ str_lookup(NODE *symbol, NODE *subs)
        // 3. The string was from a straight number, perniciously, from MPFR
        // 4. The string was from an unassigned field.
        if (   subs->stfmt != STFMT_UNUSED
-           || subs == Nnull_string
+           || isnull(subs)
            || (subs->flags & STRING) == 0
            || (subs->flags & NULL_FIELD) != 0) {
                NODE *tmp;
@@ -217,7 +217,7 @@ str_lookup(NODE *symbol, NODE *subs)
        b->ahname = subs;
        b->ahname_str = subs->stptr;
        b->ahname_len = subs->stlen;
-       b->ahvalue = dupnode(Nnull_string);
+       b->ahvalue = dupnode(Nnull_array_value);
        b->ahcode = code1;
        return & (b->ahvalue);
 }
diff --git a/test/ChangeLog b/test/ChangeLog
index 1a7b917..b3b3c8e 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,12 @@
+2021-12-10         Andrew J. Schorr      <aschorr@telemetry-investments.com>
+
+       * aadelete1.ok: Update since it is no longer a fatal error to
+       access the subarray.
+       * typeof3.awk: Remove comment, since it's no longer a fatal error
+       to access the subarray.
+       * typeof3.ok: Update to show that the uninitialized array element
+       is untyped and we can access a subarray.
+
 2021-11-21         Arnold D. Robbins     <arnold@skeeve.com>
 
        * Makefile.am (EXTRA_DIST): stupid5, new test.
diff --git a/test/aadelete1.ok b/test/aadelete1.ok
index d4b678b..c3e29d2 100644
--- a/test/aadelete1.ok
+++ b/test/aadelete1.ok
@@ -2,5 +2,3 @@
 1
 1 1
 0 0 1
-gawk: aadelete1.awk:11: fatal: attempt to use scalar `a["1"]' as an array
-EXIT CODE: 2
diff --git a/test/typeof3.awk b/test/typeof3.awk
index d148f37..7d03210 100644
--- a/test/typeof3.awk
+++ b/test/typeof3.awk
@@ -15,5 +15,5 @@ BEGIN {
 BEGIN {
        print typeof(x)
        print typeof(a[1])
-       a[1][2] # fatals on this
+       a[1][2]
 }
diff --git a/test/typeof3.ok b/test/typeof3.ok
index a6cd6c4..f9026b0 100644
--- a/test/typeof3.ok
+++ b/test/typeof3.ok
@@ -4,6 +4,4 @@ regexp
 number
 4
 number
-unassigned
-gawk: typeof3.awk:18: fatal: attempt to use scalar `a["1"]' as an array
-EXIT CODE: 2
+untyped

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


hooks/post-receive
-- 
gawk



reply via email to

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