gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, array-iface, updated. 87dc23679566c5ad96


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, array-iface, updated. 87dc23679566c5ad96f4869de6aec39c2a4c3aa7
Date: Thu, 19 Apr 2012 10:49:47 +0000

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, array-iface has been updated
       via  87dc23679566c5ad96f4869de6aec39c2a4c3aa7 (commit)
      from  c3033f11415c6323ad6b4503c220d20d68c841a3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=87dc23679566c5ad96f4869de6aec39c2a4c3aa7

commit 87dc23679566c5ad96f4869de6aec39c2a4c3aa7
Author: john haque <address@hidden>
Date:   Thu Apr 19 05:27:31 2012 -0500

    Improve array interface.

diff --git a/ChangeLog b/ChangeLog
index aaba8b4..5c6b811 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2012-04-19         John Haque      <address@hidden>
+
+       Enhanced array interface to support transparent implementation
+       using external storage and ...
+
+       * awk.h (astore): Optional post-assignment store routine for
+       array subscripts.
+       (Op_subscript_assign): New opcode to support the store routine.
+       (alength): New array interface routine for array length.
+       (assoc_length): New macro.
+       (assoc_empty): Renamed from array_empty.
+       * awkgram.y (snode): Append Op_subscript_assign opcode if
+       (g)sub variable is an array element.
+       (mk_getline): Same for getline variable.
+       (mk_assignment): Same if assigning to an array element.
+       * field.c (set_element): Call store routine if needed.
+       * builtin.c (do_match): Ditto.
+       (do_length): Use length routine for array size.
+       * symbol.c (print_vars): Ditto.
+       * array.c (null_length): Default function for array length interface.
+       (asort_actual): Call store routine if defined.
+       (asort_actual, assoc_list): Use length routine for array size.
+       (null_array_func): Add length and store routine entries.
+       * str_array.c (str_array_func): Same.
+       * cint_array.c (cint_array_func): Same.
+       * int_array.c (int_array_func): Same. 
+       * eval.c (optypetab): Add Op_subscript_assign.
+       * profile.c (pprint): Add case Op_subscript_assign.
+       * interpret.h (set_array, set_idx): New variables to keep track
+       of an array element with store routine.
+       (Op_sub_array, Op_subscript_lhs, Op_store_sub, Op_subscript_assign):
+       Add code to handle array store routine.
+       * debug.c (print_symbol, print_array, cmp_val, watchpoint_triggered,
+       initialize_watch_item): Use length routine for array size.
+
+       * awk.h (assoc_kind_t): New typedef for enum assoc_list_flags.
+       (sort_context_t): Renamed from SORT_CONTEXT.
+       * array.c (asort_actual, assoc_sort): Adjust.
+       * cint_array.c (cint_list, tree_list, leaf_list): Adjust.
+       * int_array.c (int_list): Adjust.
+       * str_array.c (str_list): Adjust.
+
 2012-04-18         John Haque      <address@hidden>
 
        * awk.h (atypeof, AFUNC): New macros.
diff --git a/array.c b/array.c
index 67712b9..66a1460 100644
--- a/array.c
+++ b/array.c
@@ -37,6 +37,7 @@ static NODE **null_dump(NODE *symbol, NODE *subs);
 static afunc_t null_array_func[] = {
        (afunc_t) 0,
        (afunc_t) 0,
+       null_length,
        null_lookup,
        null_afunc,
        null_afunc,
@@ -44,6 +45,7 @@ static afunc_t null_array_func[] = {
        null_afunc,
        null_afunc,
        null_dump,
+       (afunc_t) 0,
 };
 
 #define MAX_ATYPE 10
@@ -140,6 +142,15 @@ null_lookup(NODE *symbol, NODE *subs)
        return symbol->alookup(symbol, subs);
 }
 
+/* null_length --- default function for array length interface */ 
+
+NODE **
+null_length(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED)
+{
+       static NODE *tmp;
+       tmp = symbol;
+       return & tmp;
+}
 
 /* null_afunc --- default function for array interface */
 
@@ -630,14 +641,13 @@ void
 do_delete_loop(NODE *symbol, NODE **lhs)
 {
        NODE **list;
-       NODE fl;
+       NODE akind;
 
-       if (array_empty(symbol))
-               return;
+       akind.flags = AINDEX|ADELETE;   /* need a single index */
+       list = symbol->alist(symbol, & akind);
 
-       fl.flags = AINDEX|ADELETE;      /* need a single index */
-       list = symbol->alist(symbol, & fl);
-       assert(list != NULL);
+       if (assoc_empty(symbol))
+               return;
 
        unref(*lhs);
        *lhs = list[0];
@@ -785,7 +795,7 @@ do_adump(int nargs)
 /* asort_actual --- do the actual work to sort the input array */
 
 static NODE *
-asort_actual(int nargs, SORT_CTXT ctxt)
+asort_actual(int nargs, sort_context_t ctxt)
 {
        NODE *array, *dest = NULL, *result;
        NODE *r, *subs, *s;
@@ -838,11 +848,11 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                }
        }
 
-       num_elems = array->table_size;
-       if (num_elems > 0)      /* sorting happens inside assoc_list */
-               list = assoc_list(array, sort_str, ctxt);
+       /* sorting happens inside assoc_list */
+       list = assoc_list(array, sort_str, ctxt);
        DEREF(s);
 
+       num_elems = assoc_length(array);
        if (num_elems == 0 || list == NULL) {
                /* source array is empty */
                if (dest != NULL && dest != array)
@@ -874,6 +884,8 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                        lhs = assoc_lookup(result, subs);
                        unref(*lhs);
                        *lhs = *ptr;
+                       if (result->astore != NULL)
+                               (*result->astore)(result, subs);
                        unref(subs);
                }
        } else {
@@ -905,6 +917,8 @@ asort_actual(int nargs, SORT_CTXT ctxt)
                                unref(*lhs);
                                *lhs = assoc_copy(r, arr);
                        }
+                       if (result->astore != NULL)
+                               (*result->astore)(result, subs);
                        unref(subs);
                }
        }
@@ -1237,14 +1251,14 @@ sort_user_func(const void *p1, const void *p2)
 /* assoc_list -- construct, and optionally sort, a list of array elements */  
 
 NODE **
-assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT sort_ctxt)
+assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
 {
        typedef int (*qsort_compfunc)(const void *, const void *);
 
        static const struct qsort_funcs {
                const char *name;
                qsort_compfunc comp_func;
-               enum assoc_list_flags flags;
+               assoc_kind_t kind;
        } sort_funcs[] = {
 { "@ind_str_asc",      sort_up_index_string,   AINDEX|AISTR|AASC },
 { "@ind_num_asc",      sort_up_index_number,   AINDEX|AINUM|AASC },
@@ -1265,20 +1279,16 @@ assoc_list(NODE *symbol, const char *sort_str, 
SORT_CTXT sort_ctxt)
         */
 
        NODE **list;
-       NODE fl;
+       NODE akind;
        unsigned long num_elems, j;
        int elem_size, qi;
        qsort_compfunc cmp_func = 0;
        INSTRUCTION *code = NULL;
        extern int currule;
        int save_rule = 0;
+       assoc_kind_t assoc_kind = 0;
        
-       num_elems = symbol->table_size;
-       if (num_elems == 0)
-               return NULL;
-
        elem_size = 1;
-       fl.flags = 0;
 
        for (qi = 0, j = sizeof(sort_funcs)/sizeof(sort_funcs[0]); qi < j; 
qi++) {
                if (strcmp(sort_funcs[qi].name, sort_str) == 0)
@@ -1287,15 +1297,15 @@ assoc_list(NODE *symbol, const char *sort_str, 
SORT_CTXT sort_ctxt)
 
        if (qi < j) {
                cmp_func = sort_funcs[qi].comp_func;
-               fl.flags = sort_funcs[qi].flags;
+               assoc_kind = sort_funcs[qi].kind;
 
                if (symbol->array_funcs != cint_array_func)
-                       fl.flags &= ~(AASC|ADESC);
+                       assoc_kind &= ~(AASC|ADESC);
 
-               if (sort_ctxt != SORTED_IN || (fl.flags & AVALUE) != 0) {
+               if (sort_ctxt != SORTED_IN || (assoc_kind & AVALUE) != 0) {
                        /* need index and value pair in the list */
 
-                       fl.flags |= (AINDEX|AVALUE);
+                       assoc_kind |= (AINDEX|AVALUE);
                        elem_size = 2;
                }
 
@@ -1303,8 +1313,7 @@ assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT 
sort_ctxt)
                NODE *f;
                const char *sp; 
 
-               for (sp = sort_str; *sp != '\0'
-                    && ! isspace((unsigned char) *sp); sp++)
+               for (sp = sort_str; *sp != '\0' && ! isspace((unsigned char) 
*sp); sp++)
                        continue;
 
                /* empty string or string with space(s) not valid as function 
name */
@@ -1318,7 +1327,7 @@ assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT 
sort_ctxt)
                cmp_func = sort_user_func;
 
                /* need index and value pair in the list */
-               fl.flags |= (AVALUE|AINDEX);
+               assoc_kind |= (AVALUE|AINDEX);
                elem_size = 2;
 
                /* make function call instructions */
@@ -1340,11 +1349,15 @@ assoc_list(NODE *symbol, const char *sort_str, 
SORT_CTXT sort_ctxt)
                PUSH_CODE(code);
        }
 
-       list = symbol->alist(symbol, & fl);
+       akind.flags = (unsigned int) assoc_kind;        /* kludge */
+       list = symbol->alist(symbol, & akind);
+       assoc_kind = (assoc_kind_t) akind.flags;        /* symbol->alist can 
modify it */
 
-       if (list == NULL || ! cmp_func || (fl.flags & (AASC|ADESC)) != 0)
+       if (list == NULL || ! cmp_func || (assoc_kind & (AASC|ADESC)) != 0)
                return list;    /* empty list or unsorted, or list already 
sorted */
 
+       num_elems = assoc_length(symbol);
+
        qsort(list, num_elems, elem_size * sizeof(NODE *), cmp_func); /* 
shazzam! */
 
        if (cmp_func == sort_user_func) {
@@ -1354,7 +1367,7 @@ assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT 
sort_ctxt)
                bcfree(code);                   /* Op_func_call */
        }
 
-       if (sort_ctxt == SORTED_IN && (fl.flags & (AINDEX|AVALUE)) == 
(AINDEX|AVALUE)) {
+       if (sort_ctxt == SORTED_IN && (assoc_kind & (AINDEX|AVALUE)) == 
(AINDEX|AVALUE)) {
                /* relocate all index nodes to the first half of the list. */
                for (j = 1; j < num_elems; j++)
                        list[j] = list[2 * j];
diff --git a/awk.h b/awk.h
index d522911..8b9861b 100644
--- a/awk.h
+++ b/awk.h
@@ -361,6 +361,7 @@ typedef struct exp_node {
                                Regexp *preg;
                                struct exp_node **av;
                                BUCKET **bv;
+                               void *aq;
                                void (*uptr)(void);
                                struct exp_instruction *iptr;
                        } r;
@@ -497,6 +498,7 @@ typedef struct exp_node {
 /* Node_var_array: */
 #define buckets                sub.nodep.r.bv
 #define nodes          sub.nodep.r.av
+#define a_opaque       sub.nodep.r.aq
 #define array_funcs    sub.nodep.l.lp
 #define array_base     sub.nodep.l.ll
 #define table_size     sub.nodep.reflags
@@ -507,14 +509,16 @@ typedef struct exp_node {
 
 #define ainit          array_funcs[0]
 #define atypeof                array_funcs[1]
-#define alookup        array_funcs[2]
-#define aexists        array_funcs[3]
-#define aclear         array_funcs[4]
-#define aremove                array_funcs[5]
-#define alist          array_funcs[6]
-#define acopy          array_funcs[7]
-#define adump          array_funcs[8]
-#define NUM_AFUNCS     9               /* # of entries in array_funcs */
+#define alength                array_funcs[2]
+#define alookup        array_funcs[3]
+#define aexists        array_funcs[4]
+#define aclear         array_funcs[5]
+#define aremove                array_funcs[6]
+#define alist          array_funcs[7]
+#define acopy          array_funcs[8]
+#define adump          array_funcs[9]
+#define astore         array_funcs[10]
+#define NUM_AFUNCS     11              /* # of entries in array_funcs */
 
 /* array func to index mapping */
 #define AFUNC(F) (& ((NODE *) 0)->F - ((NODE *) 0)->array_funcs)
@@ -654,6 +658,7 @@ typedef enum opcodeval {
        Op_var_update,          /* update value of NR, NF or FNR */
        Op_var_assign,
        Op_field_assign,
+       Op_subscript_assign,
        Op_after_beginfile,
        Op_after_endfile,
 
@@ -1337,7 +1342,8 @@ if (val++) \
 if (--val) \
        memcpy((char *) tag, (const char *) (stack), sizeof(jmp_buf))
 
-#define array_empty(a) ((a)->table_size == 0)
+#define assoc_length(a)        (*((a)->alength(a, NULL)))->table_size
+#define assoc_empty(a) (assoc_length(a) == 0)
 #define assoc_lookup(a, s)     (a)->alookup(a, s)
 
 /* assoc_clear --- flush all the values in symbol[] */
@@ -1348,7 +1354,7 @@ if (--val) \
 
 
 #if __GNUC__ >= 2
-#define in_array(a, s) ({ NODE **_l; _l = (a)->aexists(a, s); _l ? *_l : NULL; 
})
+#define in_array(a, s) ({ NODE **_l = (a)->aexists(a, s); _l ? *_l : NULL; })
 #else /* not __GNUC__ */
 #define in_array(a, s) r_in_array(a, s)
 #endif /* __GNUC__ */
@@ -1356,18 +1362,18 @@ if (--val) \
 
 /* ------------- Function prototypes or defs (as appropriate) ------------- */
 /* array.c */
-typedef enum sort_context { SORTED_IN = 1, ASORT, ASORTI } SORT_CTXT;
-enum assoc_list_flags {
-AINDEX = 0x01,         /* list of indices */ 
-AVALUE = 0x02,         /* list of values */
-AINUM = 0x04,          /* numeric index */
-AISTR = 0x08,          /* string index */
-AVNUM = 0x10,          /* numeric scalar value */
-AVSTR = 0x20,          /* string scalar value */
-AASC = 0x40,           /* ascending order */
-ADESC = 0x80,          /* descending order */
-ADELETE = 0x100,       /* need a single index; for use in do_delete_loop */
-};
+typedef enum { SORTED_IN = 1, ASORT, ASORTI } sort_context_t;
+typedef enum {
+       AINDEX = 0x01,          /* list of indices */ 
+       AVALUE = 0x02,          /* list of values */
+       AINUM = 0x04,           /* numeric index */
+       AISTR = 0x08,           /* string index */
+       AVNUM = 0x10,           /* numeric scalar value */
+       AVSTR = 0x20,           /* string scalar value */
+       AASC = 0x40,            /* ascending order */
+       ADESC = 0x80,           /* descending order */
+       ADELETE = 0x100,        /* need a single index; for use in 
do_delete_loop */
+} assoc_kind_t;
 
 extern NODE *make_array(void);
 extern void null_array(NODE *symbol);
@@ -1376,13 +1382,14 @@ extern const char *make_aname(const NODE *symbol);
 extern const char *array_vname(const NODE *symbol);
 extern void array_init(void);
 extern int register_array_func(afunc_t *afunc);
+extern NODE **null_length(NODE *symbol, NODE *subs);
 extern NODE **null_afunc(NODE *symbol, NODE *subs);
 extern void set_SUBSEP(void);
 extern NODE *concat_exp(int nargs, int do_subsep);
 extern NODE *r_in_array(NODE *symbol, NODE *subs);
 extern NODE *assoc_copy(NODE *symbol, NODE *newsymb);
 extern void assoc_dump(NODE *symbol, NODE *p);
-extern NODE **assoc_list(NODE *symbol, const char *sort_str, SORT_CTXT 
sort_ctxt);
+extern NODE **assoc_list(NODE *symbol, const char *sort_str, sort_context_t 
sort_ctxt);
 extern void assoc_info(NODE *subs, NODE *val, NODE *p, const char *aname);
 extern void do_delete(NODE *symbol, int nsubs);
 extern void do_delete_loop(NODE *symbol, NODE **lhs);
diff --git a/awkgram.c b/awkgram.c
index 07de29e..fd38c52 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -6387,7 +6387,11 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
                                subn->lasti->assign_ctxt = Op_sub_builtin;
                                subn->lasti->field_assign = (Func_ptr) 0;
                                ip->target_assign = subn->lasti;
+                       } else if (ip->opcode == Op_subscript_lhs) {
+                               (void) list_append(subn, 
instruction(Op_subscript_assign));
+                               subn->lasti->assign_ctxt = Op_sub_builtin;
                        }
+
                        return subn;    
 
                } else {
@@ -7553,6 +7557,8 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, 
INSTRUCTION *op)
                (void) list_append(ip, instruction(Op_field_assign));
                ip->lasti->field_assign = (Func_ptr) 0;
                tp->target_assign = ip->lasti;
+       } else if (tp->opcode == Op_subscript_lhs) {
+               (void) list_append(ip, instruction(Op_subscript_assign));
        }
 
        return ip;
@@ -7762,7 +7768,11 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, 
INSTRUCTION *redir, int redirtype)
                        asgn->assign_ctxt = op->opcode;
                        asgn->field_assign = (Func_ptr) 0;   /* determined at 
run time */
                        tp->target_assign = asgn;
+               } else if (tp->opcode == Op_subscript_lhs) {
+                       asgn = instruction(Op_subscript_assign);
+                       asgn->assign_ctxt = op->opcode;
                }
+
                if (redir != NULL) {
                        ip = list_merge(redir, var);
                        (void) list_append(ip, op);
diff --git a/awkgram.y b/awkgram.y
index 73c45f6..76b40a5 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -3690,7 +3690,11 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
                                subn->lasti->assign_ctxt = Op_sub_builtin;
                                subn->lasti->field_assign = (Func_ptr) 0;
                                ip->target_assign = subn->lasti;
+                       } else if (ip->opcode == Op_subscript_lhs) {
+                               (void) list_append(subn, 
instruction(Op_subscript_assign));
+                               subn->lasti->assign_ctxt = Op_sub_builtin;
                        }
+
                        return subn;    
 
                } else {
@@ -4856,6 +4860,8 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, 
INSTRUCTION *op)
                (void) list_append(ip, instruction(Op_field_assign));
                ip->lasti->field_assign = (Func_ptr) 0;
                tp->target_assign = ip->lasti;
+       } else if (tp->opcode == Op_subscript_lhs) {
+               (void) list_append(ip, instruction(Op_subscript_assign));
        }
 
        return ip;
@@ -5065,7 +5071,11 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, 
INSTRUCTION *redir, int redirtype)
                        asgn->assign_ctxt = op->opcode;
                        asgn->field_assign = (Func_ptr) 0;   /* determined at 
run time */
                        tp->target_assign = asgn;
+               } else if (tp->opcode == Op_subscript_lhs) {
+                       asgn = instruction(Op_subscript_assign);
+                       asgn->assign_ctxt = op->opcode;
                }
+
                if (redir != NULL) {
                        ip = list_merge(redir, var);
                        (void) list_append(ip, op);
diff --git a/builtin.c b/builtin.c
index 9134e02..6ca6509 100644
--- a/builtin.c
+++ b/builtin.c
@@ -492,6 +492,7 @@ do_length(int nargs)
        tmp = POP();
        if (tmp->type == Node_var_array) {
                static short warned = FALSE;
+               unsigned long size;
 
                if (do_posix)
                        fatal(_("length: received array argument"));
@@ -499,7 +500,15 @@ do_length(int nargs)
                        warned = TRUE;
                        lintwarn(_("`length(array)' is a gawk extension"));
                }
-               return make_number((AWKNUM) tmp->table_size);
+
+               /*
+                * Support for deferred loading of array elements requires that
+                * we use the array length interface even though it isn't 
+                * necessary for the built-in array types.
+                */
+
+               size = assoc_length(tmp);
+               return make_number(size);
        }
 
        assert(tmp->type == Node_val);
@@ -2450,6 +2459,9 @@ do_match(int nargs)
                                        lhs = assoc_lookup(dest, sub);
                                        unref(*lhs);
                                        *lhs = it;
+                                       /* execute post-assignment routine if 
any */
+                                       if (dest->astore != NULL)
+                                               (*dest->astore)(dest, sub);
                                        unref(sub);
 
                                        sprintf(buff, "%d", ii);
@@ -2473,6 +2485,8 @@ do_match(int nargs)
                                        lhs = assoc_lookup(dest, sub);
                                        unref(*lhs);
                                        *lhs = it;
+                                       if (dest->astore != NULL)
+                                               (*dest->astore)(dest, sub);
                                        unref(sub);
        
                                        memcpy(buf, buff, ilen);
@@ -2486,6 +2500,8 @@ do_match(int nargs)
                                        lhs = assoc_lookup(dest, sub);
                                        unref(*lhs);
                                        *lhs = it;
+                                       if (dest->astore != NULL)
+                                               (*dest->astore)(dest, sub);
                                        unref(sub);
                                }
                        }
diff --git a/cint_array.c b/cint_array.c
index 136f9ad..9bf4987 100644
--- a/cint_array.c
+++ b/cint_array.c
@@ -59,6 +59,7 @@ static void cint_print(NODE *symbol);
 afunc_t cint_array_func[] = {
        cint_array_init,
        is_uinteger,
+       null_length,
        cint_lookup,
        cint_exists,
        cint_clear,
@@ -66,6 +67,7 @@ afunc_t cint_array_func[] = {
        cint_list,
        cint_copy,
        cint_dump,
+       (afunc_t) 0,
 };
 
 static inline int cint_hash(long k);
@@ -78,7 +80,7 @@ static NODE **tree_exists(NODE *tree, long k);
 static void tree_clear(NODE *tree);
 static int tree_remove(NODE *symbol, NODE *tree, long k);
 static void tree_copy(NODE *newsymb, NODE *tree, NODE *newtree);
-static long tree_list(NODE *tree, NODE **list, unsigned int flags);
+static long tree_list(NODE *tree, NODE **list, assoc_kind_t assoc_kind);
 static inline NODE **tree_find(NODE *tree, long k, int i);
 static void tree_info(NODE *tree, NODE *ndump, const char *aname);
 static size_t tree_kilobytes(NODE *tree);
@@ -91,7 +93,7 @@ static inline NODE **leaf_exists(NODE *array, long k);
 static void leaf_clear(NODE *array);
 static int leaf_remove(NODE *symbol, NODE *array, long k);
 static void leaf_copy(NODE *newsymb, NODE *array, NODE *newarray);
-static long leaf_list(NODE *array, NODE **list, unsigned int flags);
+static long leaf_list(NODE *array, NODE **list, assoc_kind_t assoc_kind);
 static void leaf_info(NODE *array, NODE *ndump, const char *aname);
 #ifdef ARRAYDEBUG
 static void leaf_print(NODE *array, size_t bi, int indent_level);
@@ -418,15 +420,16 @@ cint_list(NODE *symbol, NODE *t)
        unsigned long k = 0, num_elems, list_size;
        size_t j, ja, jd;
        int elem_size = 1;
+       assoc_kind_t assoc_kind;
 
        num_elems = symbol->table_size;
        if (num_elems == 0)
                return NULL;
-
-       if ((t->flags & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
+       assoc_kind = (assoc_kind_t) t->flags;
+       if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
                num_elems = 1;
 
-       if ((t->flags & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
+       if ((assoc_kind & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
                elem_size = 2;
        list_size = num_elems * elem_size;
 
@@ -434,7 +437,8 @@ cint_list(NODE *symbol, NODE *t)
                xn = symbol->xarray;
                list = xn->alist(xn, t);
                assert(list != NULL);
-               t->flags &= ~(AASC|ADESC);
+               assoc_kind &= ~(AASC|ADESC);
+               t->flags = (unsigned int) assoc_kind;
                if (num_elems == 1 || num_elems == xn->table_size)
                        return list;
                erealloc(list, NODE **, list_size * sizeof(NODE *), 
"cint_list");
@@ -442,18 +446,20 @@ cint_list(NODE *symbol, NODE *t)
        } else
                emalloc(list, NODE **, list_size * sizeof(NODE *), "cint_list");
 
-
-       if ((t->flags & AINUM) == 0)    /* not sorting by "index num" */
-               t->flags &= ~(AASC|ADESC);
+       if ((assoc_kind & AINUM) == 0) {
+               /* not sorting by "index num" */
+               assoc_kind &= ~(AASC|ADESC);
+               t->flags = (unsigned int) assoc_kind;
+       }
 
        /* populate it with index in ascending or descending order */
 
        for (ja = NHAT, jd = INT32_BIT - 1; ja < INT32_BIT && jd >= NHAT; ) {
-               j = (t->flags & ADESC) ? jd-- : ja++;
+               j = (assoc_kind & ADESC) ? jd-- : ja++;
                tn = symbol->nodes[j];
                if (tn == NULL)
                        continue;
-               k += tree_list(tn, list + k, t->flags);
+               k += tree_list(tn, list + k, assoc_kind);
                if (k >= list_size)
                        return list;
        }
@@ -875,7 +881,7 @@ tree_find(NODE *tree, long k, int i)
 /* tree_list --- return a list of items in the HAT */
 
 static long
-tree_list(NODE *tree, NODE **list, unsigned int flags)
+tree_list(NODE *tree, NODE **list, assoc_kind_t assoc_kind)
 {
        NODE *tn;
        size_t j, cj, hsize;
@@ -888,15 +894,15 @@ tree_list(NODE *tree, NODE **list, unsigned int flags)
                hsize /= 2;
 
        for (j = 0; j < hsize; j++) {
-               cj = (flags & ADESC) ? (hsize - 1 - j) : j;
+               cj = (assoc_kind & ADESC) ? (hsize - 1 - j) : j;
                tn = tree->nodes[cj];
                if (tn == NULL)
                        continue;
                if (tn->type == Node_array_tree)
-                       k += tree_list(tn, list + k, flags);
+                       k += tree_list(tn, list + k, assoc_kind);
                else
-                       k += leaf_list(tn, list + k, flags);
-               if ((flags & ADELETE) != 0 && k >= 1)
+                       k += leaf_list(tn, list + k, assoc_kind);
+               if ((assoc_kind & ADELETE) != 0 && k >= 1)
                        return k;
        }
        return k;
@@ -1141,7 +1147,7 @@ leaf_copy(NODE *newsymb, NODE *array, NODE *newarray)
 /* leaf_list --- return a list of items */
 
 static long
-leaf_list(NODE *array, NODE **list, unsigned int flags)
+leaf_list(NODE *array, NODE **list, assoc_kind_t assoc_kind)
 {
        NODE *r, *subs;
        long num, i, ci, k = 0;
@@ -1149,14 +1155,14 @@ leaf_list(NODE *array, NODE **list, unsigned int flags)
        static char buf[100];
 
        for (i = 0; i < size; i++) {
-               ci = (flags & ADESC) ? (size - 1 - i) : i;
+               ci = (assoc_kind & ADESC) ? (size - 1 - i) : i;
                r = array->nodes[ci];
                if (r == NULL)
                        continue;
 
                /* index */
                num = array->array_base + ci;
-               if (flags & AISTR) {
+               if (assoc_kind & AISTR) {
                        sprintf(buf, "%ld", num); 
                        subs = make_string(buf, strlen(buf));
                        subs->numbr = num;
@@ -1168,16 +1174,16 @@ leaf_list(NODE *array, NODE **list, unsigned int flags)
                list[k++] = subs;
 
                /* value */
-               if (flags & AVALUE) {
+               if (assoc_kind & AVALUE) {
                        if (r->type == Node_val) {
-                               if ((flags & AVNUM) != 0)
+                               if ((assoc_kind & AVNUM) != 0)
                                        (void) force_number(r);
-                               else if ((flags & AVSTR) != 0)
+                               else if ((assoc_kind & AVSTR) != 0)
                                        r = force_string(r);
                        }
                        list[k++] = r;
                }
-               if ((flags & ADELETE) != 0 && k >= 1)
+               if ((assoc_kind & ADELETE) != 0 && k >= 1)
                        return k;
        }
 
diff --git a/debug.c b/debug.c
index 30d040b..3645436 100644
--- a/debug.c
+++ b/debug.c
@@ -943,7 +943,7 @@ print_symbol(NODE *r, int isparam)
                valinfo(r->var_value, fprintf, out_fp);
                break;
        case Node_var_array:
-               fprintf(out_fp, "array, %ld elements\n", r->table_size);
+               fprintf(out_fp, "array, %ld elements\n", assoc_length(r));
                break;
        case Node_func:
                fprintf(out_fp, "`function'\n");
@@ -1064,12 +1064,12 @@ print_array(volatile NODE *arr, char *arr_name)
        volatile int ret = 0;
        volatile jmp_buf pager_quit_tag_stack;
 
-       if (array_empty(arr)) {
+       if (assoc_empty((NODE *) arr)) {
                gprintf(out_fp, _("array `%s' is empty\n"), arr_name);
                return 0;
        }
 
-       num_elems = arr->table_size;
+       num_elems = assoc_length((NODE *) arr);
 
        /* sort indices, sub_arrays are also sorted! */
        list = assoc_list((NODE *) arr, "@ind_str_asc", SORTED_IN);
@@ -1646,7 +1646,7 @@ cmp_val(struct list_item *w, NODE *old, NODE *new)
                if (new->type == Node_val)      /* 7 */
                        return TRUE;
                /* new->type == Node_var_array */       /* 8 */
-               size = new->table_size;
+               size = assoc_length(new);
                if (w->cur_size == size)
                        return FALSE;
                return TRUE;
@@ -1720,7 +1720,7 @@ watchpoint_triggered(struct list_item *w)
                        w->flags &= ~CUR_IS_ARRAY;
                        w->cur_value = dupnode(t2);
                } else
-                       w->cur_size = (t2->type == Node_var_array) ? 
t2->table_size : 0;
+                       w->cur_size = (t2->type == Node_var_array) ? 
assoc_length(t2) : 0;
        } else if (! t1) { /* 1, 2 */
                w->old_value = 0;
                /* new != NULL */
@@ -1728,7 +1728,7 @@ watchpoint_triggered(struct list_item *w)
                        w->cur_value = dupnode(t2);
                else {
                        w->flags |= CUR_IS_ARRAY;
-                       w->cur_size = (t2->type == Node_var_array) ? 
t2->table_size : 0;
+                       w->cur_size = (t2->type == Node_var_array) ? 
assoc_length(t2) : 0;
                }
        } else /* if (t1->type == Node_val) */ {        /* 4, 5, 6 */
                w->old_value = w->cur_value;
@@ -1736,7 +1736,7 @@ watchpoint_triggered(struct list_item *w)
                        w->cur_value = 0;
                else if (t2->type == Node_var_array) {
                        w->flags |= CUR_IS_ARRAY;
-                       w->cur_size = t2->table_size;
+                       w->cur_size = assoc_length(t2);
                } else
                        w->cur_value = dupnode(t2);
        }
@@ -1762,7 +1762,7 @@ initialize_watch_item(struct list_item *w)
                        w->cur_value = (NODE *) 0;
                else if (r->type == Node_var_array) { /* it's a sub-array */
                        w->flags |= CUR_IS_ARRAY;
-                       w->cur_size = r->table_size;
+                       w->cur_size = assoc_length(r);
                } else
                        w->cur_value = dupnode(r);
        } else if (IS_FIELD(w)) {
@@ -1779,7 +1779,7 @@ initialize_watch_item(struct list_item *w)
                        w->cur_value = dupnode(r);
                } else if (symbol->type == Node_var_array) {
                        w->flags |= CUR_IS_ARRAY;
-                       w->cur_size = symbol->table_size;
+                       w->cur_size = assoc_length(symbol);
                } /* else
                        can't happen */
        }
diff --git a/eval.c b/eval.c
index 2305bbb..dc49194 100644
--- a/eval.c
+++ b/eval.c
@@ -358,6 +358,7 @@ static struct optypetab {
        { "Op_var_update", NULL },
        { "Op_var_assign", NULL },
        { "Op_field_assign", NULL },
+       { "Op_subscript_assign", NULL },
        { "Op_after_beginfile", NULL },
        { "Op_after_endfile", NULL },
        { "Op_func", NULL },
diff --git a/field.c b/field.c
index 68bd699..4146eb0 100644
--- a/field.c
+++ b/field.c
@@ -939,9 +939,11 @@ set_element(long num, char *s, long len, NODE *n)
        it->flags |= MAYBE_NUM;
        sub = make_number((AWKNUM) (num));
        lhs = assoc_lookup(n, sub);
-       unref(sub);
        unref(*lhs);
        *lhs = it;
+        if (n->astore != NULL)
+                (*n->astore)(n, sub);
+       unref(sub);
 }
 
 /* do_split --- implement split(), semantics are same as for field splitting */
diff --git a/int_array.c b/int_array.c
index bc413c5..7b8b261 100644
--- a/int_array.c
+++ b/int_array.c
@@ -48,6 +48,7 @@ static void grow_int_table(NODE *symbol);
 afunc_t int_array_func[] = {
        int_array_init,
        is_integer,
+       null_length,
        int_lookup,
        int_exists,
        int_clear,
@@ -55,6 +56,7 @@ afunc_t int_array_func[] = {
        int_list,
        int_copy,
        int_dump,
+       (afunc_t) 0,
 };
 
 
@@ -458,15 +460,17 @@ int_list(NODE *symbol, NODE *t)
        int j, elem_size = 1;
        long num;
        static char buf[100];
+       assoc_kind_t assoc_kind;
 
        if (symbol->table_size == 0)
                return NULL;
 
+       assoc_kind = (assoc_kind_t) t->flags;
        num_elems = symbol->table_size;
-       if ((t->flags & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
+       if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
                num_elems = 1;
 
-       if ((t->flags & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
+       if ((assoc_kind & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
                elem_size = 2;
        list_size = elem_size * num_elems;
        
@@ -488,7 +492,7 @@ int_list(NODE *symbol, NODE *t)
                        for (j = 0; j < b->aicount; j++) {
                                /* index */
                                num = b->ainum[j];
-                               if (t->flags & AISTR) {
+                               if (assoc_kind & AISTR) {
                                        sprintf(buf, "%ld", num); 
                                        subs = make_string(buf, strlen(buf));
                                        subs->numbr = num;
@@ -500,12 +504,12 @@ int_list(NODE *symbol, NODE *t)
                                list[k++] = subs;
 
                                /* value */
-                               if (t->flags & AVALUE) {
+                               if (assoc_kind & AVALUE) {
                                        r = b->aivalue[j];
                                        if (r->type == Node_val) {
-                                               if ((t->flags & AVNUM) != 0)
+                                               if ((assoc_kind & AVNUM) != 0)
                                                        (void) force_number(r);
-                                               else if ((t->flags & AVSTR) != 
0)
+                                               else if ((assoc_kind & AVSTR) 
!= 0)
                                                        r = force_string(r);
                                        }
                                        list[k++] = r;
diff --git a/interpret.h b/interpret.h
index acb8d21..0b83001 100644
--- a/interpret.h
+++ b/interpret.h
@@ -37,6 +37,9 @@ r_interpret(INSTRUCTION *code)
        AWKNUM x, x2;
        int di;
        Regexp *rp;
+       NODE *set_array = NULL; /* array with a post-assignment routine */
+       NODE *set_idx = NULL;   /* the index of the array element */
+
 
 /* array subscript */
 #define mk_sub(n)      (n == 1 ? POP_SCALAR() : concat_exp(n, TRUE))
@@ -229,6 +232,10 @@ top:
                                *lhs = r;
                                t2 = force_string(t2);
                                r->vname = estrdup(t2->stptr, t2->stlen);       
/* the subscript in parent array */
+
+                               /* execute post-assignment routine if any */
+                               if (t1->astore != NULL)
+                                       (*t1->astore)(t1, t2);
                        } else if (r->type != Node_var_array) {
                                t2 = force_string(t2);
                                fatal(_("attempt to use scalar `%s[\"%.*s\"]' 
as an array"),
@@ -258,7 +265,15 @@ top:
                                                array_vname(t1), (int) 
t2->stlen, t2->stptr);
                        }
 
-                       DEREF(t2);
+                       assert(set_idx == NULL);
+
+                       if (t1->astore) {
+                               /* array has post-assignment routine */
+                               set_array = t1;
+                               set_idx = t2;
+                       } else
+                               DEREF(t2);
+
                        PUSH_ADDRESS(lhs);
                        break;
 
@@ -533,9 +548,14 @@ mod:
                                fatal(_("attempt to use array `%s[\"%.*s\"]' in 
a scalar context"),
                                                array_vname(t1), (int) 
t2->stlen, t2->stptr);
                        }
-                       DEREF(t2);
                        unref(*lhs);
                        *lhs = POP_SCALAR();
+
+                       /* execute post-assignment routine if any */
+                       if (t1->astore != NULL)
+                               (*t1->astore)(t1, t2);
+
+                       DEREF(t2);
                        break;
 
                case Op_store_var:
@@ -616,6 +636,30 @@ mod:
                        REPLACE(r);
                        break;
 
+               case Op_subscript_assign:
+                       /* conditionally execute post-assignment routine for an 
array element */ 
+
+                       if (set_idx != NULL) {
+                               di = TRUE;
+                               if (pc->assign_ctxt == Op_sub_builtin
+                                       && (r = TOP())
+                                       && get_number_si(r) == 0        /* no 
substitution performed */
+                               )
+                                       di = FALSE;
+                               else if ((pc->assign_ctxt == Op_K_getline
+                                               || pc->assign_ctxt == 
Op_K_getline_redir)
+                                       && (r = TOP())
+                                       && get_number_si(r) <= 0        /* EOF 
or error */
+                               )
+                                       di = FALSE;
+
+                               if (di)
+                                       (*set_array->astore)(set_array, 
set_idx);
+                               unref(set_idx);
+                               set_idx = NULL;
+                       }
+                       break;
+
                /* numeric assignments */
                case Op_assign_plus:
                case Op_assign_minus:
@@ -720,7 +764,7 @@ mod:
                        array = POP_ARRAY();
 
                        /* sanity: check if empty */
-                       if (array_empty(array))
+                       if (assoc_empty(array))
                                goto arrayfor;
 
                        num_elems = array->table_size;
diff --git a/profile.c b/profile.c
index 181395d..08ccfeb 100644
--- a/profile.c
+++ b/profile.c
@@ -477,6 +477,7 @@ cleanup:
                case Op_var_update:
                case Op_var_assign:
                case Op_field_assign:
+               case Op_subscript_assign:
                case Op_arrayfor_init:
                case Op_arrayfor_incr: 
                case Op_arrayfor_final:
diff --git a/str_array.c b/str_array.c
index a452dac..c6b33c6 100644
--- a/str_array.c
+++ b/str_array.c
@@ -58,6 +58,7 @@ static NODE **str_dump(NODE *symbol, NODE *ndump);
 afunc_t str_array_func[] = {
        str_array_init,
        (afunc_t) 0,
+       null_length,
        str_lookup,
        str_exists,
        str_clear,
@@ -65,6 +66,7 @@ afunc_t str_array_func[] = {
        str_list,
        str_copy,
        str_dump,
+       (afunc_t) 0,
 };
 
 static inline NODE **str_find(NODE *symbol, NODE *s1, size_t code1, unsigned 
long hash1);
@@ -352,16 +354,18 @@ str_list(NODE *symbol, NODE *t)
        BUCKET *b;
        unsigned long num_elems, list_size, i, k = 0;
        int elem_size = 1;
+       assoc_kind_t assoc_kind;
 
        if (symbol->table_size == 0)
                return NULL;
 
-       if ((t->flags & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
+       assoc_kind = (assoc_kind_t) t->flags;
+       if ((assoc_kind & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
                elem_size = 2;
 
        /* allocate space for array */
        num_elems = symbol->table_size;
-       if ((t->flags & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
+       if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
                num_elems = 1;
        list_size =  elem_size * num_elems;
        
@@ -373,17 +377,17 @@ str_list(NODE *symbol, NODE *t)
                for (b = symbol->buckets[i]; b != NULL; b = b->ahnext) {
                        /* index */
                        subs = b->ahname;
-                       if (t->flags & AINUM)
+                       if (assoc_kind & AINUM)
                                (void) force_number(subs);
                        list[k++] = dupnode(subs);
 
                        /* value */
-                       if (t->flags & AVALUE) {
+                       if (assoc_kind & AVALUE) {
                                val = b->ahvalue;
                                if (val->type == Node_val) {
-                                       if ((t->flags & AVNUM) != 0)
+                                       if ((assoc_kind & AVNUM) != 0)
                                                (void) force_number(val);
-                                       else if ((t->flags & AVSTR) != 0)
+                                       else if ((assoc_kind & AVSTR) != 0)
                                                val = force_string(val);
                                }
                                list[k++] = val;
diff --git a/symbol.c b/symbol.c
index ebe86c0..aed75ac 100644
--- a/symbol.c
+++ b/symbol.c
@@ -386,7 +386,7 @@ print_vars(NODE **table, int (*print_func)(FILE *, const 
char *, ...), FILE *fp)
                        continue;
                print_func(fp, "%s: ", r->vname);
                if (r->type == Node_var_array)
-                       print_func(fp, "array, %ld elements\n", r->table_size);
+                       print_func(fp, "array, %ld elements\n", 
assoc_length(r));
                else if (r->type == Node_var_new)
                        print_func(fp, "untyped variable\n");
                else if (r->type == Node_var)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog    |   42 +++++++++++++++++++++++++++++++++++
 array.c      |   69 ++++++++++++++++++++++++++++++++++-----------------------
 awk.h        |   53 +++++++++++++++++++++++++-------------------
 awkgram.c    |   10 ++++++++
 awkgram.y    |   10 ++++++++
 builtin.c    |   18 ++++++++++++++-
 cint_array.c |   52 ++++++++++++++++++++++++-------------------
 debug.c      |   18 +++++++-------
 eval.c       |    1 +
 field.c      |    4 ++-
 int_array.c  |   16 ++++++++-----
 interpret.h  |   50 +++++++++++++++++++++++++++++++++++++++--
 profile.c    |    1 +
 str_array.c  |   16 ++++++++-----
 symbol.c     |    2 +-
 15 files changed, 261 insertions(+), 101 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]