aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2015-06-25 23:12:55 +0300
committerArnold D. Robbins <arnold@skeeve.com>2015-06-25 23:12:55 +0300
commit056cd074c60d940d5bb46410f114a6c2584daaae (patch)
treee2b095b3740b35cc95a8b25fd10ee5d81288565e
parent5b246a31d63a31180136934adbed361651f325ba (diff)
parent3712ad29b6cddcf49bf1507f5677a49ccfcff83d (diff)
downloadegawk-056cd074c60d940d5bb46410f114a6c2584daaae.tar.gz
egawk-056cd074c60d940d5bb46410f114a6c2584daaae.tar.bz2
egawk-056cd074c60d940d5bb46410f114a6c2584daaae.zip
Merge branch 'master' into feature/cmake
-rw-r--r--ChangeLog51
-rw-r--r--awk.h2
-rw-r--r--awkgram.c4
-rw-r--r--awkgram.y4
-rw-r--r--builtin.c16
-rw-r--r--debug.c9
-rw-r--r--eval.c1
-rw-r--r--interpret.h13
-rw-r--r--profile.c1
-rw-r--r--test/ChangeLog19
-rw-r--r--test/Makefile.am20
-rw-r--r--test/Makefile.in35
-rw-r--r--test/Maketests15
-rw-r--r--test/dbugtypedre.awk1
-rw-r--r--test/dbugtypedre.in4
-rw-r--r--test/dbugtypedre.ok17
-rw-r--r--test/typeof2.awk20
-rw-r--r--test/typeof2.ok6
-rw-r--r--test/typeof3.awk19
-rw-r--r--test/typeof3.ok9
-rw-r--r--test/typeof4.awk13
-rw-r--r--test/typeof4.ok1
22 files changed, 264 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 586ea3ee..3b872bdd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+2015-06-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ Further work straightening out memory management for typeof.
+
+ * awk.h (DEREF): Add an assert.
+ * builtin.c (do_typeof): Add comments, cases where not to deref.
+ * debug.c (print_instruction): Add Op_push_arg_untyped.
+ * interpret.h (r_interpret): Additional comments / tweaks for
+ Op_push_arg_untyped.
+
+ Unrelated. Make `x = @/foo/ ; print x' print something.
+
+ * builtin.c (do_print): Check for Node_typedregex and handle it.
+ Needed for adding test code.
+
+ Unrelated. Typo fix.
+
+ * debug.c (initialize_watch_item): Dupnode the right thing.
+
+2015-06-22 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awkgram.y (snode): Make isarray not scalarize untyped parameters
+ also.
+ * profile.c (pprint): Add Op_push_arg_untyped.
+
+ Improve debugger support for typed regexps.
+ Thanks to Hermann Peifer for the bug report.
+
+ * awkgram.y (valinfo): Add support for Node_typedregex.
+ * debug.c (watchpoint_triggerred): Handle Node_typedregex.
+ (initialize_watch_item): Ditto.
+ (print_memory): Ditto.
+
+ Fix typeof to work on subarrays. Thanks, yet again, to
+ Hermann Peifer for the bug report.
+
+ * builtin.c (do_typeof): Don't deref Node_var_array.
+
+2015-06-21 Arnold D. Robbins <arnold@skeeve.com>
+
+ Fixes for typeof - Don't let typeof change an untyped variable
+ into a scalar.
+
+ * awk.h (opcodeval): Add Op_push_arg_untyped.
+ * awkgram.y (snode): Separate out case for do_typeof, use
+ Op_push_arg_untyped.
+ * builtin.c (do_typeof): Arg will be equal to Nnull_string
+ if it's untyped.
+ * eval.c (optypes): Add Op_push_arg_untyped.
+ * interpret.h (r_interpret): Add Op_push_arg_untyped handling.
+
2015-06-19 Arnold D. Robbins <arnold@skeeve.com>
* builtin.c (do_isarray): Minor edit to lint warning.
diff --git a/awk.h b/awk.h
index 5acd33d8..220dba95 100644
--- a/awk.h
+++ b/awk.h
@@ -643,6 +643,7 @@ typedef enum opcodeval {
Op_push, /* scalar variable */
Op_push_arg, /* variable type (scalar or array) argument to built-in */
+ Op_push_arg_untyped, /* like Op_push_arg, but for typeof */
Op_push_i, /* number, string */
Op_push_re, /* regex */
Op_push_array,
@@ -1181,6 +1182,7 @@ extern void r_unref(NODE *tmp);
static inline void
DEREF(NODE *r)
{
+ assert(r->valref > 0);
if (--r->valref == 0)
r_unref(r);
}
diff --git a/awkgram.c b/awkgram.c
index 12f648ed..a1a055b6 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -6700,7 +6700,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
} else if (r->builtin == do_isarray || r->builtin == do_typeof) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
- arg->nexti->opcode = Op_push_arg; /* argument may be array */
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
|| r->builtin == MPF(intdiv)
@@ -6895,6 +6895,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
{
if (n == Nnull_string)
print_func(fp, "uninitialized scalar\n");
+ else if (n->type == Node_typedregex)
+ print_func(fp, "@/%.*s/\n", n->re_exp->stlen, n->re_exp->stptr);
else if ((n->flags & STRING) != 0) {
pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false);
print_func(fp, "\n");
diff --git a/awkgram.y b/awkgram.y
index 28541f86..50fd90a0 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -4280,7 +4280,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
} else if (r->builtin == do_isarray || r->builtin == do_typeof) {
arg = subn->nexti;
if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push)
- arg->nexti->opcode = Op_push_arg; /* argument may be array */
+ arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */
} else if (r->builtin == do_intdiv
#ifdef HAVE_MPFR
|| r->builtin == MPF(intdiv)
@@ -4475,6 +4475,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp)
{
if (n == Nnull_string)
print_func(fp, "uninitialized scalar\n");
+ else if (n->type == Node_typedregex)
+ print_func(fp, "@/%.*s/\n", n->re_exp->stlen, n->re_exp->stptr);
else if ((n->flags & STRING) != 0) {
pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false);
print_func(fp, "\n");
diff --git a/builtin.c b/builtin.c
index 61a4398b..1dd7dcbe 100644
--- a/builtin.c
+++ b/builtin.c
@@ -2144,7 +2144,9 @@ do_print(int nargs, int redirtype)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(tmp));
}
- if ((tmp->flags & (NUMBER|STRING)) == NUMBER) {
+ if (tmp->type == Node_typedregex)
+ args_array[i] = force_string(tmp);
+ else if ((tmp->flags & (NUMBER|STRING)) == NUMBER) {
if (OFMTidx == CONVFMTidx)
args_array[i] = force_string(tmp);
else
@@ -3872,19 +3874,23 @@ do_typeof(int nargs)
{
NODE *arg;
char *res = "unknown";
- int null_str_flags = (STRCUR|STRING|NUMCUR|NUMBER);
+ bool deref = true;
arg = POP();
switch (arg->type) {
case Node_var_array:
+ /* Node_var_array is never UPREF'ed */
res = "array";
+ deref = false;
break;
case Node_typedregex:
+ /* Op_push_re does not UPREF */
res = "regexp";
+ deref = false;
break;
case Node_val:
case Node_var:
- if ((arg->flags & null_str_flags) == null_str_flags)
+ if (arg == Nnull_string)
res = "untyped";
else if ((arg->flags & STRING) != 0)
res = "scalar_s";
@@ -3893,6 +3899,7 @@ do_typeof(int nargs)
break;
case Node_var_new:
res = "untyped";
+ deref = false;
break;
default:
fatal(_("typeof: unknown argument type `%s'"),
@@ -3900,7 +3907,8 @@ do_typeof(int nargs)
break;
}
- DEREF(arg);
+ if (deref)
+ DEREF(arg);
return make_string(res, strlen(res));
}
diff --git a/debug.c b/debug.c
index 6aaba099..2bb6e53a 100644
--- a/debug.c
+++ b/debug.c
@@ -1736,6 +1736,8 @@ watchpoint_triggered(struct list_item *w)
/* new != NULL */
if (t2->type == Node_val)
w->cur_value = dupnode(t2);
+ else if (t2->type == Node_typedregex)
+ w->cur_value = dupnode(t2);
else {
w->flags |= CUR_IS_ARRAY;
w->cur_size = (t2->type == Node_var_array) ? assoc_length(t2) : 0;
@@ -1748,6 +1750,7 @@ watchpoint_triggered(struct list_item *w)
w->flags |= CUR_IS_ARRAY;
w->cur_size = assoc_length(t2);
} else
+ /* works for Node_typedregex too */
w->cur_value = dupnode(t2);
}
@@ -1790,6 +1793,8 @@ initialize_watch_item(struct list_item *w)
} else if (symbol->type == Node_var_array) {
w->flags |= CUR_IS_ARRAY;
w->cur_size = assoc_length(symbol);
+ } else if (symbol->type == Node_typedregex) {
+ w->cur_value = dupnode(symbol);
} /* else
can't happen */
}
@@ -3703,6 +3708,9 @@ print_memory(NODE *m, NODE *func, Func_print print_func, FILE *fp)
print_func(fp, " [%s]", flags2str(m->flags));
break;
+ case Node_typedregex:
+ print_func(fp, "@");
+ /* fall through */
case Node_regex:
pp_string_fp(print_func, fp, m->re_exp->stptr, m->re_exp->stlen, '/', false);
break;
@@ -3982,6 +3990,7 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
case Op_push_i:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
case Op_push_param:
case Op_push_array:
case Op_push_re:
diff --git a/eval.c b/eval.c
index 73bd56cb..c6008580 100644
--- a/eval.c
+++ b/eval.c
@@ -338,6 +338,7 @@ static struct optypetab {
{ "Op_indirect_func_call", NULL },
{ "Op_push", NULL },
{ "Op_push_arg", NULL },
+ { "Op_push_arg_untyped", NULL },
{ "Op_push_i", NULL },
{ "Op_push_re", NULL },
{ "Op_push_array", NULL },
diff --git a/interpret.h b/interpret.h
index 03532f43..1005174a 100644
--- a/interpret.h
+++ b/interpret.h
@@ -144,6 +144,7 @@ top:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
{
NODE *save_symbol;
bool isparam = false;
@@ -175,19 +176,23 @@ top:
case Node_var_new:
uninitialized_scalar:
- m->type = Node_var;
- m->var_value = dupnode(Nnull_string);
+ if (op != Op_push_arg_untyped) {
+ /* convert untyped to scalar */
+ m->type = Node_var;
+ m->var_value = dupnode(Nnull_string);
+ }
if (do_lint)
lintwarn(isparam ?
_("reference to uninitialized argument `%s'") :
_("reference to uninitialized variable `%s'"),
save_symbol->vname);
- m = dupnode(Nnull_string);
+ if (op != Op_push_arg_untyped)
+ m = dupnode(Nnull_string);
PUSH(m);
break;
case Node_var_array:
- if (op == Op_push_arg)
+ if (op == Op_push_arg || op == Op_push_arg_untyped)
PUSH(m);
else
fatal(_("attempt to use array `%s' in a scalar context"),
diff --git a/profile.c b/profile.c
index 0f686768..90f01c07 100644
--- a/profile.c
+++ b/profile.c
@@ -317,6 +317,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool in_for_header)
case Op_push_array:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
m = pc->memory;
switch (m->type) {
case Node_param_list:
diff --git a/test/ChangeLog b/test/ChangeLog
index b57a756f..b92d8ae7 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,22 @@
+2015-06-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (negtime): Fix out-of-tree test run.
+
+ Unrelated:
+
+ * Makefile.am (typeof3, typeof4): New tests.
+ * typeof2.awk, typeof2.ok, typeof3.awk, typeof3.ok: New files.
+
+ Unrelated:
+
+ * Makefile.am (dbugtypedre): New tests.
+ * dbugtypedre.awk, dbugtypedre.in, dbugtypedre.ok: New files.
+
+2015-06-21 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (typeof2): New test.
+ * typeof2.awk, typeof2.ok: New files.
+
2015-06-19 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (gsubind, typedregex1, typeof1): New tests.
diff --git a/test/Makefile.am b/test/Makefile.am
index 537a5655..03d28f21 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -177,6 +177,9 @@ EXTRA_DIST = \
datanonl.ok \
dbugeval.in \
dbugeval.ok \
+ dbugtypedre.awk \
+ dbugtypedre.in \
+ dbugtypedre.ok \
defref.awk \
defref.ok \
delargv.awk \
@@ -985,6 +988,12 @@ EXTRA_DIST = \
typedregex1.ok \
typeof1.awk \
typeof1.ok \
+ typeof2.awk \
+ typeof2.ok \
+ typeof3.awk \
+ typeof3.ok \
+ typeof4.awk \
+ typeof4.ok \
uninit2.awk \
uninit2.ok \
uninit3.awk \
@@ -1079,7 +1088,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
- colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \
+ colonwarn clos1way crlf dbugeval dbugtypedre delsub devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth fpat1 fpat2 fpat3 fpat4 fpatnull fsfwfs funlen \
functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \
@@ -1099,7 +1108,7 @@ GAWK_EXT_TESTS = \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
symtab7 symtab8 symtab9 \
- typedregex1 typeof1
+ typedregex1 typeof1 typeof2 typeof3 typeof4
timeout
EXTRA_TESTS = inftest regtest
@@ -2124,7 +2133,12 @@ paramasfunc2::
negtime::
@echo $@
@TZ=GMT AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk $@.ok _$@ && rm -f _$@
+ @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+dbugtypedre:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < $@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
# Targets generated for other tests:
include Maketests
diff --git a/test/Makefile.in b/test/Makefile.in
index a8895ed7..294c60c0 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -434,6 +434,9 @@ EXTRA_DIST = \
datanonl.ok \
dbugeval.in \
dbugeval.ok \
+ dbugtypedre.awk \
+ dbugtypedre.in \
+ dbugtypedre.ok \
defref.awk \
defref.ok \
delargv.awk \
@@ -1242,6 +1245,12 @@ EXTRA_DIST = \
typedregex1.ok \
typeof1.awk \
typeof1.ok \
+ typeof2.awk \
+ typeof2.ok \
+ typeof3.awk \
+ typeof3.ok \
+ typeof4.awk \
+ typeof4.ok \
uninit2.awk \
uninit2.ok \
uninit3.awk \
@@ -1335,7 +1344,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
- colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \
+ colonwarn clos1way crlf dbugeval dbugtypedre delsub devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth fpat1 fpat2 fpat3 fpat4 fpatnull fsfwfs funlen \
functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \
@@ -1355,7 +1364,7 @@ GAWK_EXT_TESTS = \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
symtab7 symtab8 symtab9 \
- typedregex1 typeof1
+ typedregex1 typeof1 typeof2 typeof3 typeof4
EXTRA_TESTS = inftest regtest
INET_TESTS = inetdayu inetdayt inetechu inetecht
@@ -2560,7 +2569,12 @@ paramasfunc2::
negtime::
@echo $@
@TZ=GMT AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk $@.ok _$@ && rm -f _$@
+ @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+dbugtypedre:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < $@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
Gt-dummy:
# file Maketests, generated from Makefile.am by the Gentests program
addcomma:
@@ -3905,6 +3919,21 @@ typeof1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+typeof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+typeof3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+typeof4:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index a674d5d0..e4cea0de 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1342,6 +1342,21 @@ typeof1:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+typeof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+typeof3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+typeof4:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/dbugtypedre.awk b/test/dbugtypedre.awk
new file mode 100644
index 00000000..b8c0b6d7
--- /dev/null
+++ b/test/dbugtypedre.awk
@@ -0,0 +1 @@
+@include "typeof1.awk"
diff --git a/test/dbugtypedre.in b/test/dbugtypedre.in
new file mode 100644
index 00000000..00158c65
--- /dev/null
+++ b/test/dbugtypedre.in
@@ -0,0 +1,4 @@
+watch e
+run
+next
+p e
diff --git a/test/dbugtypedre.ok b/test/dbugtypedre.ok
new file mode 100644
index 00000000..de3c8bcd
--- /dev/null
+++ b/test/dbugtypedre.ok
@@ -0,0 +1,17 @@
+Watchpoint 1: e
+Starting program:
+scalar_n
+untyped
+regexp
+scalar_s
+array scalar_n
+Stopping in BEGIN ...
+Watchpoint 1: e
+ Old value: untyped variable
+ New value: @/foo/
+main() at `typeof1.awk':7
+7 e = @/foo/ ; print typeof(e)
+regexp
+8 print typeof(@/bar/)
+e = @/foo/
+EXIT CODE: 2
diff --git a/test/typeof2.awk b/test/typeof2.awk
new file mode 100644
index 00000000..25da02e4
--- /dev/null
+++ b/test/typeof2.awk
@@ -0,0 +1,20 @@
+BEGIN {
+ print typeof(x)
+ x[1] = 3
+ print typeof(x)
+}
+
+function test1() {
+}
+
+function test2(p) {
+ p[1] = 1
+}
+
+BEGIN {
+ print typeof(a)
+ test1(a)
+ print typeof(a)
+ test2(a)
+ print typeof(a)
+}
diff --git a/test/typeof2.ok b/test/typeof2.ok
new file mode 100644
index 00000000..cc032a83
--- /dev/null
+++ b/test/typeof2.ok
@@ -0,0 +1,6 @@
+untyped
+array
+untyped
+gawk: typeof2.awk:16: warning: function `test1' called with more arguments than declared
+untyped
+array
diff --git a/test/typeof3.awk b/test/typeof3.awk
new file mode 100644
index 00000000..d148f373
--- /dev/null
+++ b/test/typeof3.awk
@@ -0,0 +1,19 @@
+BEGIN {
+ x = @/xx/
+ print typeof(x)
+ print x
+}
+
+# this set may not really be needed for the test
+BEGIN {
+ x = 4
+ print typeof(@/xxx/)
+ print typeof(3)
+ print x
+}
+
+BEGIN {
+ print typeof(x)
+ print typeof(a[1])
+ a[1][2] # fatals on this
+}
diff --git a/test/typeof3.ok b/test/typeof3.ok
new file mode 100644
index 00000000..8186ad9e
--- /dev/null
+++ b/test/typeof3.ok
@@ -0,0 +1,9 @@
+regexp
+xx
+regexp
+scalar_n
+4
+scalar_n
+untyped
+gawk: typeof3.awk:18: fatal: attempt to use scalar `a["1"]' as an array
+EXIT CODE: 2
diff --git a/test/typeof4.awk b/test/typeof4.awk
new file mode 100644
index 00000000..62c2905c
--- /dev/null
+++ b/test/typeof4.awk
@@ -0,0 +1,13 @@
+BEGIN{ a["x"]["y"]["z"]="scalar" ; walk_array(a, "a")}
+function walk_array(arr, name, i, r)
+{
+ for (i in arr) {
+ r = typeof(arr[i])
+# printf("typeof(%s[%s]) = %s\n", name, i, r) > "/dev/stderr"
+ if (r == "array") {
+ walk_array(arr[i], name "[" i "]")
+ } else {
+ printf "%s[%s] = %s\n", name, i, arr[i]
+ }
+ }
+}
diff --git a/test/typeof4.ok b/test/typeof4.ok
new file mode 100644
index 00000000..fca0263d
--- /dev/null
+++ b/test/typeof4.ok
@@ -0,0 +1 @@
+a[x][y][z] = scalar