[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] gawk branch, feature/mdim, created. gawk-4.1.0-4592-g367920b,
Andrew J. Schorr <=