aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xChangeLog7
-rw-r--r--awkgram.c14
-rw-r--r--awkgram.y14
-rw-r--r--builtin.c22
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/gawk.texi9
-rw-r--r--doc/gawktexi.in9
-rw-r--r--test/ChangeLog5
-rw-r--r--test/Makefile.am3
-rw-r--r--test/Makefile.in8
-rw-r--r--test/Maketests5
-rw-r--r--test/arraytype.awk35
-rw-r--r--test/arraytype.ok16
13 files changed, 147 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 27fee925..23f1bf7b 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2019-01-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awkgram.y (tokentab): Indicate that typeof may take 2 arguments.
+ (snode): Add support for typeof's optional 2nd array argument.
+ * builtin.c (do_typeof): Add support for optional 2nd array arg,
+ returning flag info for scalars and backend array type for arrays.
+
2019-01-08 Arnold D. Robbins <arnold@skeeve.com>
* interpret.h (r_interpret): For a translatable string, only copy
diff --git a/awkgram.c b/awkgram.c
index 36955071..993dfc4c 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -4745,7 +4745,7 @@ static const struct token tokentab[] = {
{"systime", Op_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime, 0},
{"tolower", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower, 0},
{"toupper", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper, 0},
-{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_typeof, 0},
+{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_typeof, 0},
{"while", Op_K_while, LEX_WHILE, BREAK|CONTINUE, 0, 0},
{"xor", Op_builtin, LEX_BUILTIN, GAWKX, do_xor, MPF(xor)},
};
@@ -7034,10 +7034,20 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
}
- } else if (r->builtin == do_isarray || r->builtin == do_typeof) {
+ } else if (r->builtin == do_isarray) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
+ } else if (r->builtin == do_typeof) {
+ arg = subn->nexti;
+ if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
+ if (nexp == 2) { /* 2nd argument there */
+ arg = subn->nexti->lasti->nexti; /* 2nd arg list */
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
#ifdef SUPPLY_INTDIV
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
diff --git a/awkgram.y b/awkgram.y
index d925e750..e0af4c1a 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -2280,7 +2280,7 @@ static const struct token tokentab[] = {
{"systime", Op_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime, 0},
{"tolower", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower, 0},
{"toupper", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper, 0},
-{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_typeof, 0},
+{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_typeof, 0},
{"while", Op_K_while, LEX_WHILE, BREAK|CONTINUE, 0, 0},
{"xor", Op_builtin, LEX_BUILTIN, GAWKX, do_xor, MPF(xor)},
};
@@ -4569,10 +4569,20 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg; /* argument may be array */
}
- } else if (r->builtin == do_isarray || r->builtin == do_typeof) {
+ } else if (r->builtin == do_isarray) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
+ } else if (r->builtin == do_typeof) {
+ arg = subn->nexti;
+ if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
+ if (nexp == 2) { /* 2nd argument there */
+ arg = subn->nexti->lasti->nexti; /* 2nd arg list */
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
#ifdef SUPPLY_INTDIV
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
diff --git a/builtin.c b/builtin.c
index f2d31059..c92a5982 100644
--- a/builtin.c
+++ b/builtin.c
@@ -4069,13 +4069,28 @@ do_typeof(int nargs)
NODE *arg;
char *res = NULL;
bool deref = true;
+ NODE *dbg;
+ if (nargs == 2) { /* 2nd optional arg for debugging */
+ dbg = POP_PARAM();
+ if (dbg->type != Node_var_array)
+ fatal(_("typeof: second argument is not an array"));
+ assoc_clear(dbg);
+ }
+ else
+ dbg = NULL;
arg = POP();
switch (arg->type) {
case Node_var_array:
/* Node_var_array is never UPREF'ed */
res = "array";
deref = false;
+ if (dbg) {
+ NODE *sub = make_string("array_type", 10);
+ NODE **lhs = assoc_lookup(dbg, sub);
+ unref(*lhs);
+ *lhs = make_string(arg->array_funcs->name, strlen(arg->array_funcs->name));
+ }
break;
case Node_val:
switch (fixtype(arg)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) {
@@ -4104,6 +4119,13 @@ do_typeof(int nargs)
}
break;
}
+ if (dbg) {
+ const char *s = flags2str(arg->flags);
+ NODE *sub = make_string("flags", 5);
+ NODE **lhs = assoc_lookup(dbg, sub);
+ unref(*lhs);
+ *lhs = make_string(s, strlen(s));
+ }
break;
case Node_var_new:
res = "untyped";
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 4bbc906c..287f2cd1 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2019-01-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawktexi.in (Undocumented): Discuss typeof's optional 2nd argument.
+
2019-01-08 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in (I18N Example): Add more explanation of how to
diff --git a/doc/gawk.texi b/doc/gawk.texi
index e661c6fa..44c00d00 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -4997,6 +4997,15 @@ NaN and Infinity values, instead of the special values @command{gawk}
usually produces, as described in @ref{POSIX Floating Point Problems}.
This is mainly useful for the included unit tests.
+The @code{typeof()} built-in function
+(@pxref{Type Functions})
+takes an optional second array argument that, if present, will be cleared
+and populated with some information about the internal implementation of
+the variable. This can be useful for debugging. At the moment, this
+returns a textual version of the flags for scalar variables, and the
+array back-end implementation type for arrays. This interface is subject
+to change and may not be stable.
+
@end ignore
@node Invoking Summary
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index f8850d9a..ac099ccc 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -4907,6 +4907,15 @@ NaN and Infinity values, instead of the special values @command{gawk}
usually produces, as described in @ref{POSIX Floating Point Problems}.
This is mainly useful for the included unit tests.
+The @code{typeof()} built-in function
+(@pxref{Type Functions})
+takes an optional second array argument that, if present, will be cleared
+and populated with some information about the internal implementation of
+the variable. This can be useful for debugging. At the moment, this
+returns a textual version of the flags for scalar variables, and the
+array back-end implementation type for arrays. This interface is subject
+to change and may not be stable.
+
@end ignore
@node Invoking Summary
diff --git a/test/ChangeLog b/test/ChangeLog
index b1d2e340..7f17f725 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2019-01-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): New test: arraytype.
+ * arraytype.awk, arraytype.ok: New files.
+
2018-12-24 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (inetdayt, inetdayu, inetecht, inetechu): Add
diff --git a/test/Makefile.am b/test/Makefile.am
index 7b42f8db..b4f50cec 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -76,6 +76,8 @@ EXTRA_DIST = \
arraysort.ok \
arraysort2.awk \
arraysort2.ok \
+ arraytype.awk \
+ arraytype.ok \
arrdbg.awk \
arrymem1.awk \
arrymem1.ok \
@@ -1294,6 +1296,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort arraysort2 \
+ arraytype \
backw badargs beginfile1 beginfile2 binmode1 \
charasbytes colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 \
clos1way6 crlf \
diff --git a/test/Makefile.in b/test/Makefile.in
index f2fa6c8e..b6adabdd 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -334,6 +334,8 @@ EXTRA_DIST = \
arraysort.ok \
arraysort2.awk \
arraysort2.ok \
+ arraytype.awk \
+ arraytype.ok \
arrdbg.awk \
arrymem1.awk \
arrymem1.ok \
@@ -1552,6 +1554,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort arraysort2 \
+ arraytype \
backw badargs beginfile1 beginfile2 binmode1 \
charasbytes colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 \
clos1way6 crlf \
@@ -3945,6 +3948,11 @@ arraysort2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+arraytype:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
backw:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 08d92ba3..9ad8ade9 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1269,6 +1269,11 @@ arraysort2:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+arraytype:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
backw:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/arraytype.awk b/test/arraytype.awk
new file mode 100644
index 00000000..70fd72b0
--- /dev/null
+++ b/test/arraytype.awk
@@ -0,0 +1,35 @@
+BEGIN {
+ # N.B. This relies upon the undocumented 2nd argument to typeof
+ x[0] = 0
+ print typeof(x, a)
+ print a["array_type"]
+
+ # make sure it resets
+ delete x[0]
+ print typeof(x, a)
+ print a["array_type"]
+
+ x["fubar"] = 0
+ print typeof(x, a)
+ print a["array_type"]
+
+ delete x["fubar"]
+ print typeof(x, a)
+ print a["array_type"]
+
+ x[-2] = 0
+ print typeof(x, a)
+ print a["array_type"]
+
+ delete x[-2]
+ print typeof(x, a)
+ print a["array_type"]
+
+ x[2] = 0
+ print typeof(x, a)
+ print a["array_type"]
+
+ delete x
+ print typeof(x, a)
+ print a["array_type"]
+}
diff --git a/test/arraytype.ok b/test/arraytype.ok
new file mode 100644
index 00000000..6595bb89
--- /dev/null
+++ b/test/arraytype.ok
@@ -0,0 +1,16 @@
+array
+cint
+array
+null
+array
+str
+array
+null
+array
+int
+array
+null
+array
+cint
+array
+null