aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--awk.h4
-rw-r--r--awkgram.c15
-rw-r--r--awkgram.y15
-rw-r--r--builtin.c18
-rw-r--r--debug.c1
-rw-r--r--eval.c6
-rw-r--r--profile.c1
8 files changed, 63 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index dd7d16ab..ba1b127e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Sun Jan 30 21:49:53 2011 John Haque <j.eh@mchsi.com>
+
+ Add `isarray' built-in function.
+
+ * awk.h (enum opcodeval): Op_push_arg: new opcode.
+ (do_isarray): Add declaration.
+ * awkgram.y (tokentab): Add new entry for `isarray' function.
+ (snode): Add handling for it.
+ * builtin.c (do_isarray): New function.
+ (do_length): Die if posix and get an array argument.
+ * debug.c (print_instruction): Handle Op_push_arg.
+ * profile.c (pprint): Likewise.
+ * eval.c (optypes, r_interpret): Likewise.
+
Sun Jan 30 21:13:01 2011 Arnold D. Robbins <arnold@skeeve.com>
* hard-locale.h: Synced to GNU grep.
diff --git a/awk.h b/awk.h
index 2baf4812..0bd7f8d9 100644
--- a/awk.h
+++ b/awk.h
@@ -524,7 +524,8 @@ typedef enum opcodeval {
Op_func_call,
Op_indirect_func_call,
- Op_push, /* variable */
+ Op_push, /* scalar variable */
+ Op_push_arg, /* variable type (scalar or array) argument to built-in */
Op_push_i, /* number, string */
Op_push_re, /* regex */
Op_push_array,
@@ -1146,6 +1147,7 @@ extern NODE *do_exp(int nargs);
extern NODE *do_fflush(int nargs);
extern NODE *do_index(int nargs);
extern NODE *do_int(int nargs);
+extern NODE *do_isarray(int nargs);
extern NODE *do_length(int nargs);
extern NODE *do_log(int nargs);
extern NODE *do_mktime(int nargs);
diff --git a/awkgram.c b/awkgram.c
index f1fa9dd2..c97684f3 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -4513,6 +4513,7 @@ static const struct token tokentab[] = {
{"include", Op_symbol, LEX_INCLUDE, GAWKX, 0},
{"index", Op_builtin, LEX_BUILTIN, A(2), do_index},
{"int", Op_builtin, LEX_BUILTIN, A(1), do_int},
+{"isarray", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_isarray},
{"length", Op_builtin, LEX_LENGTH, A(0)|A(1), do_length},
{"log", Op_builtin, LEX_BUILTIN, A(1), do_log},
{"lshift", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_lshift},
@@ -6152,7 +6153,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (subn != NULL) {
INSTRUCTION *tp;
for (tp = subn->nexti; tp; tp = tp->nexti) {
- /* assert(tp->opcode == Op_list); */
tp = tp->lasti;
nexp++;
}
@@ -6172,15 +6172,24 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
/* special case processing for a few builtins */
if (r->builtin == do_length) {
if (nexp == 0) {
- INSTRUCTION *list; /* no args. Use $0 */
+ /* no args. Use $0 */
+ INSTRUCTION *list;
r->expr_count = 1;
list = list_create(r);
(void) list_prepend(list, instruction(Op_field_spec));
(void) list_prepend(list, instruction(Op_push_i));
list->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
return list;
- }
+ } else {
+ arg = subn->nexti;
+ 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) {
+ arg = subn->nexti;
+ 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_match) {
static short warned = FALSE;
diff --git a/awkgram.y b/awkgram.y
index 26a692ca..aae04a70 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -1864,6 +1864,7 @@ static const struct token tokentab[] = {
{"include", Op_symbol, LEX_INCLUDE, GAWKX, 0},
{"index", Op_builtin, LEX_BUILTIN, A(2), do_index},
{"int", Op_builtin, LEX_BUILTIN, A(1), do_int},
+{"isarray", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_isarray},
{"length", Op_builtin, LEX_LENGTH, A(0)|A(1), do_length},
{"log", Op_builtin, LEX_BUILTIN, A(1), do_log},
{"lshift", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_lshift},
@@ -3503,7 +3504,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
if (subn != NULL) {
INSTRUCTION *tp;
for (tp = subn->nexti; tp; tp = tp->nexti) {
- /* assert(tp->opcode == Op_list); */
tp = tp->lasti;
nexp++;
}
@@ -3523,15 +3523,24 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
/* special case processing for a few builtins */
if (r->builtin == do_length) {
if (nexp == 0) {
- INSTRUCTION *list; /* no args. Use $0 */
+ /* no args. Use $0 */
+ INSTRUCTION *list;
r->expr_count = 1;
list = list_create(r);
(void) list_prepend(list, instruction(Op_field_spec));
(void) list_prepend(list, instruction(Op_push_i));
list->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
return list;
- }
+ } else {
+ arg = subn->nexti;
+ 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) {
+ arg = subn->nexti;
+ 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_match) {
static short warned = FALSE;
diff --git a/builtin.c b/builtin.c
index 7156601e..dc811022 100644
--- a/builtin.c
+++ b/builtin.c
@@ -458,6 +458,21 @@ do_int(int nargs)
return make_number((AWKNUM) d);
}
+/* do_isarray --- check if argument is array */
+
+NODE *
+do_isarray(int nargs)
+{
+ NODE *tmp;
+ int ret = 1;
+
+ tmp = POP();
+ if (tmp->type != Node_var_array) {
+ ret = 0;
+ DEREF(tmp);
+ }
+ return make_number((AWKNUM) ret);
+}
/* do_length --- length of a string, array or $0 */
@@ -468,10 +483,11 @@ do_length(int nargs)
size_t len;
tmp = POP();
-
if (tmp->type == Node_var_array) {
static short warned = FALSE;
+ if (do_posix)
+ fatal(_("length: received array argument"));
if (do_lint && ! warned) {
warned = TRUE;
lintwarn(_("`length(array)' is a gawk extension"));
diff --git a/debug.c b/debug.c
index 9573e1fb..854278c5 100644
--- a/debug.c
+++ b/debug.c
@@ -3939,6 +3939,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_param:
case Op_push_array:
case Op_push_re:
diff --git a/eval.c b/eval.c
index b9c84afd..59574633 100644
--- a/eval.c
+++ b/eval.c
@@ -351,6 +351,7 @@ static struct optypetab {
{ "Op_func_call", NULL },
{ "Op_indirect_func_call", NULL },
{ "Op_push", NULL },
+ { "Op_push_arg", NULL },
{ "Op_push_i", NULL },
{ "Op_push_re", NULL },
{ "Op_push_array", NULL },
@@ -1700,6 +1701,7 @@ top:
break;
case Op_push:
+ case Op_push_arg:
{
NODE *save_symbol;
int isparam = FALSE;
@@ -1739,9 +1741,7 @@ top:
break;
case Node_var_array:
- if (! do_posix
- && pc->nexti->opcode == Op_builtin
- && pc->nexti->builtin == do_length) /* length(array) */
+ if (pc->opcode == Op_push_arg)
PUSH(m);
else
fatal(_("attempt to use array `%s' in a scalar context"),
diff --git a/profile.c b/profile.c
index 291247c9..201d7360 100644
--- a/profile.c
+++ b/profile.c
@@ -263,6 +263,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int in_for_header)
case Op_push_param:
case Op_push_array:
case Op_push:
+ case Op_push_arg:
m = pc->memory;
switch (m->type) {
case Node_param_list: