diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | awk.h | 4 | ||||
-rw-r--r-- | awkgram.c | 15 | ||||
-rw-r--r-- | awkgram.y | 15 | ||||
-rw-r--r-- | builtin.c | 18 | ||||
-rw-r--r-- | debug.c | 1 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | profile.c | 1 |
8 files changed, 63 insertions, 11 deletions
@@ -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. @@ -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); @@ -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; @@ -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; @@ -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")); @@ -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: @@ -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"), @@ -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: |