diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index d37fd71d..150fcd7c 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -1827,12 +1827,12 @@ static hawk_nde_t* parse_block (hawk_t* awk, const hawk_loc_t* xloc, int istop) nde = parse_statement (awk, &sloc); } - if (nde == HAWK_NULL) + if (HAWK_UNLIKELY(!nde)) { hawk_arr_delete ( awk->parse.lcls, nlcls, HAWK_ARR_SIZE(awk->parse.lcls)-nlcls); - if (head != HAWK_NULL) hawk_clrpt (awk, head); + if (head) hawk_clrpt (awk, head); return HAWK_NULL; } @@ -1857,7 +1857,7 @@ static hawk_nde_t* parse_block (hawk_t* awk, const hawk_loc_t* xloc, int istop) } block = (hawk_nde_blk_t*)hawk_callocmem(awk, HAWK_SIZEOF(*block)); - if (block == HAWK_NULL) + if (HAWK_UNLIKELY(!block)) { hawk_arr_delete (awk->parse.lcls, nlcls, HAWK_ARR_SIZE(awk->parse.lcls) - nlcls); hawk_clrpt (awk, head); @@ -5687,33 +5687,38 @@ static hawk_nde_t* parse_hashidx (hawk_t* awk, const hawk_oocs_t* name, const ha idx = HAWK_NULL; last = HAWK_NULL; +#if defined(HAWK_ENABLE_GC) +more_idx: +#endif do { if (get_token(awk) <= -1) { - if (idx != HAWK_NULL) hawk_clrpt (awk, idx); + if (idx) hawk_clrpt (awk, idx); return HAWK_NULL; } { hawk_loc_t eloc; - eloc = awk->tok.loc; tmp = parse_expr_withdc(awk, &eloc); } - if (tmp == HAWK_NULL) + if (HAWK_UNLIKELY(!tmp)) { - if (idx != HAWK_NULL) hawk_clrpt (awk, idx); + if (idx) hawk_clrpt (awk, idx); return HAWK_NULL; } - if (idx == HAWK_NULL) + if (!idx) { + /* this is the first item */ HAWK_ASSERT (last == HAWK_NULL); - idx = tmp; last = tmp; + idx = tmp; + last = tmp; } else { + /* not the first item. append it */ last->next = tmp; last = tmp; } @@ -5735,8 +5740,31 @@ static hawk_nde_t* parse_hashidx (hawk_t* awk, const hawk_oocs_t* name, const ha return HAWK_NULL; } +#if defined(HAWK_ENABLE_GC) + if (MATCH(awk,TOK_LBRACK)) + { + /* additional index - a[10][20] ... + * use the NULL node as a splitter */ + tmp = (hawk_nde_t*)hawk_callocmem(awk, HAWK_SIZEOF(*tmp)); + if (HAWK_UNLIKELY(!tmp)) + { + hawk_clrpt (awk, idx); + ADJERR_LOC (awk, xloc); + return HAWK_NULL; + } + tmp->type = HAWK_NDE_NULL; + + HAWK_ASSERT (idx != HAWK_NULL); + HAWK_ASSERT (last != HAWK_NULL); + + last->next = tmp; + last = tmp; + goto more_idx; + } +#endif + nde = (hawk_nde_var_t*)hawk_callocmem(awk, HAWK_SIZEOF(*nde)); - if (nde == HAWK_NULL) + if (HAWK_UNLIKELY(!nde)) { hawk_clrpt (awk, idx); ADJERR_LOC (awk, xloc); diff --git a/hawk/lib/run.c b/hawk/lib/run.c index 95433e84..a2369e0a 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -208,7 +208,7 @@ static hawk_val_t* eval_printf (hawk_rtx_t* rtx, hawk_nde_t* nde); static int read_record (hawk_rtx_t* rtx); -static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t* buf, hawk_oow_t* len); +static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t* buf, hawk_oow_t* len, hawk_nde_t** remidx); typedef hawk_val_t* (*binop_func_t) (hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right); typedef hawk_val_t* (*eval_expr_t) (hawk_rtx_t* rtx, hawk_nde_t* nde); @@ -2867,13 +2867,14 @@ static int delete_indexed (hawk_rtx_t* rtx, hawk_map_t* map, hawk_nde_var_t* var hawk_ooch_t* iptr; hawk_oow_t ilen; hawk_ooch_t idxbuf[IDXBUFSIZE]; + hawk_nde_t* remidx; HAWK_ASSERT (var->idx != HAWK_NULL); /* delete x["abc"]; * delete x[20,"abc"]; */ ilen = HAWK_COUNTOF(idxbuf); - iptr = idxnde_to_str(rtx, var->idx, idxbuf, &ilen); + iptr = idxnde_to_str(rtx, var->idx, idxbuf, &ilen, &remidx); if (HAWK_UNLIKELY(!iptr)) return -1; hawk_map_delete (map, iptr, ilen); @@ -2960,7 +2961,7 @@ static int run_delete_unnamed (hawk_rtx_t* rtx, hawk_nde_var_t* var) case HAWK_NDE_GBLIDX: val = HAWK_RTX_STACK_GBL(rtx,var->id.idxa); break; - + case HAWK_NDE_LCL: case HAWK_NDE_LCLIDX: val = HAWK_RTX_STACK_LCL(rtx,var->id.idxa); @@ -3001,7 +3002,7 @@ static int run_delete_unnamed (hawk_rtx_t* rtx, hawk_nde_var_t* var) x = hawk_rtx_setgbl(rtx, (int)var->id.idxa, tmp); hawk_rtx_refdownval (rtx, tmp); - if (x <= -1) + if (HAWK_UNLIKELY(x <= -1)) { ADJERR_LOC (rtx, &var->loc); return -1; @@ -3908,6 +3909,7 @@ static hawk_val_t* do_assignment_idx (hawk_rtx_t* rtx, hawk_nde_var_t* var, hawk hawk_ooch_t* str; hawk_oow_t len; hawk_ooch_t idxbuf[IDXBUFSIZE]; + hawk_nde_t* remidx; HAWK_ASSERT ( (var->type == HAWK_NDE_NAMEDIDX || @@ -3949,7 +3951,7 @@ retry: /* the map is not initialized yet */ tmp = hawk_rtx_makemapval(rtx); - if (tmp == HAWK_NULL) + if (HAWK_UNLIKELY(!tmp)) { ADJERR_LOC (rtx, &var->loc); return HAWK_NULL; @@ -4031,8 +4033,8 @@ retry: } len = HAWK_COUNTOF(idxbuf); - str = idxnde_to_str(rtx, var->idx, idxbuf, &len); - if (str == HAWK_NULL) return HAWK_NULL; + str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx); + if (HAWK_UNLIKELY(!str)) return HAWK_NULL; #if defined(DEBUG_RUN) @@ -4321,6 +4323,7 @@ static hawk_val_t* eval_binop_in (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* hawk_ooch_t* str; hawk_oow_t len; hawk_ooch_t idxbuf[IDXBUFSIZE]; + hawk_nde_t* remidx; if (right->type != HAWK_NDE_GBL && right->type != HAWK_NDE_LCL && @@ -4336,8 +4339,8 @@ static hawk_val_t* eval_binop_in (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* /* evaluate the left-hand side of the operator */ len = HAWK_COUNTOF(idxbuf); str = (left->type == HAWK_NDE_GRP)? - idxnde_to_str(rtx, ((hawk_nde_grp_t*)left)->body, idxbuf, &len): - idxnde_to_str(rtx, left, idxbuf, &len); + idxnde_to_str(rtx, ((hawk_nde_grp_t*)left)->body, idxbuf, &len, &remidx): + idxnde_to_str(rtx, left, idxbuf, &len, &remidx); if (HAWK_UNLIKELY(!str)) return HAWK_NULL; /* evaluate the right-hand side of the operator */ @@ -6674,6 +6677,7 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, hawk_oow_t len; hawk_ooch_t idxbuf[IDXBUFSIZE]; hawk_val_type_t vtype; + hawk_nde_t* remidx; HAWK_ASSERT (val != HAWK_NULL); @@ -6702,7 +6706,7 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, HAWK_ASSERT (nde->idx != HAWK_NULL); len = HAWK_COUNTOF(idxbuf); - str = idxnde_to_str(rtx, nde->idx, idxbuf, &len); + str = idxnde_to_str(rtx, nde->idx, idxbuf, &len, &remidx); if (HAWK_UNLIKELY(!str)) return HAWK_NULL; pair = hawk_map_search((*(hawk_val_map_t**)val)->map, str, len); @@ -6821,46 +6825,95 @@ static hawk_val_t* eval_arg (hawk_rtx_t* rtx, hawk_nde_t* nde) static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, hawk_val_t** val) { + hawk_map_t* map; /* containing map */ hawk_map_pair_t* pair; - hawk_ooch_t* str; + hawk_ooch_t* str = HAWK_NULL; hawk_oow_t len; hawk_ooch_t idxbuf[IDXBUFSIZE]; + hawk_val_t* v; hawk_val_type_t vtype; + hawk_nde_t* remidx; HAWK_ASSERT (val != HAWK_NULL); vtype = HAWK_RTX_GETVALTYPE(rtx, *val); - if (vtype == HAWK_VAL_NIL) + switch (vtype) { - hawk_val_t* tmp; + case HAWK_VAL_NIL: + v = hawk_rtx_makemapval(rtx); + if (HAWK_UNLIKELY(!v)) goto oops; - tmp = hawk_rtx_makemapval(rtx); - if (tmp == HAWK_NULL) - { - ADJERR_LOC (rtx, &nde->loc); - return HAWK_NULL; - } + hawk_rtx_refdownval (rtx, *val); + *val = v; + hawk_rtx_refupval (rtx, (hawk_val_t*)*val); + break; - hawk_rtx_refdownval (rtx, *val); - *val = tmp; - hawk_rtx_refupval (rtx, (hawk_val_t*)*val); - } - else if (vtype != HAWK_VAL_MAP) - { - hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENOTMAP); - return HAWK_NULL; + case HAWK_VAL_MAP: + v = *val; + break; + + default: + hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENOTMAP); + goto oops; } HAWK_ASSERT (nde->idx != HAWK_NULL); len = HAWK_COUNTOF(idxbuf); - str = idxnde_to_str(rtx, nde->idx, idxbuf, &len); - if (str == HAWK_NULL) return HAWK_NULL; + str = idxnde_to_str(rtx, nde->idx, idxbuf, &len, &remidx); + if (HAWK_UNLIKELY(!str)) goto oops; + + map = ((hawk_val_map_t*)v)->map; + pair = hawk_map_search(map, str, len); + +#if defined(HAWK_ENABLE_GC) + while (remidx) + { + v = pair? (hawk_val_t*)HAWK_HTB_VPTR(pair): hawk_val_nil; + vtype = HAWK_RTX_GETVALTYPE(rtx, v); + + switch (vtype) + { + case HAWK_VAL_NIL: + v = hawk_rtx_makemapval(rtx); + if (HAWK_UNLIKELY(!v)) goto oops; + + hawk_rtx_refupval (rtx, v); + pair = hawk_map_upsert(map, str, len, v, 0); + if (HAWK_UNLIKELY(!pair)) + { + hawk_rtx_refdownval (rtx, v); + goto oops; + } + + map = ((hawk_val_map_t*)v)->map; + break; + + case HAWK_VAL_MAP: + map = ((hawk_val_map_t*)v)->map; + break; + + default: + hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENOTMAP); + goto oops; + } + + if (str != idxbuf) hawk_rtx_freemem (rtx, str); + len = HAWK_COUNTOF(idxbuf); + str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx); + if (HAWK_UNLIKELY(!str)) goto oops; + + pair = hawk_map_search(map, str, len); + } +#endif - pair = hawk_map_search((*(hawk_val_map_t**)val)->map, str, len); if (str != idxbuf) hawk_rtx_freemem (rtx, str); + return pair? (hawk_val_t*)HAWK_HTB_VPTR(pair): hawk_val_nil; - return (pair == HAWK_NULL)? hawk_val_nil: (hawk_val_t*)HAWK_HTB_VPTR(pair); +oops: + if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); + ADJERR_LOC (rtx, &nde->loc); + return HAWK_NULL; } static hawk_val_t* eval_namedidx (hawk_rtx_t* rtx, hawk_nde_t* nde) @@ -6872,7 +6925,7 @@ static hawk_val_t* eval_namedidx (hawk_rtx_t* rtx, hawk_nde_t* nde) if (pair == HAWK_NULL) { pair = hawk_htb_upsert(rtx->named, tgt->id.name.ptr, tgt->id.name.len, hawk_val_nil, 0); - if (pair == HAWK_NULL) + if (HAWK_UNLIKELY(!pair)) { ADJERR_LOC (rtx, &nde->loc); return HAWK_NULL; @@ -7209,7 +7262,7 @@ read_again: return 1; } -static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t* buf, hawk_oow_t* len) +static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t* buf, hawk_oow_t* len, hawk_nde_t** remidx) { hawk_ooch_t* str; hawk_val_t* idx; @@ -7260,6 +7313,7 @@ static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t } hawk_rtx_refdownval (rtx, idx); + *remidx = HAWK_NULL; } else { @@ -7279,7 +7333,11 @@ static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t } xnde = nde; +#if defined(HAWK_ENABLE_GC) + while (nde && nde->type != HAWK_NDE_NULL) +#else while (nde) +#endif { idx = eval_expression(rtx, nde); if (HAWK_UNLIKELY(!idx)) @@ -7314,6 +7372,9 @@ static hawk_ooch_t* idxnde_to_str (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_ooch_t *len = tmp.len; hawk_ooecs_fini (&idxstr); + + /* if nde is not HAWK_NULL, it should be of the HAWK_NDE_NULL type */ + *remidx = nde? nde->next: nde; } return str; diff --git a/hawk/lib/tree.c b/hawk/lib/tree.c index c1572d2c..74d49935 100644 --- a/hawk/lib/tree.c +++ b/hawk/lib/tree.c @@ -136,6 +136,10 @@ static const hawk_ooch_t* print_outop_str[] = if (print_expr_list(awk,nde) == -1) return -1; \ } while(0) +#define PRINT_EXPR_LIST_FOR_IDX(awk,nde) do { \ + if (print_expr_list_for_idx(awk,nde) == -1) return -1; \ +} while(0) + #define PRINT_STMTS(awk,nde,depth) do { \ if (print_stmts(awk,nde,depth) == -1) return -1; \ } while(0) @@ -143,6 +147,7 @@ static const hawk_ooch_t* print_outop_str[] = static int print_tabs (hawk_t* awk, int depth); static int print_expr (hawk_t* awk, hawk_nde_t* nde); static int print_expr_list (hawk_t* awk, hawk_nde_t* tree); +static int print_expr_list_for_idx (hawk_t* awk, hawk_nde_t* tree); static int print_stmts (hawk_t* awk, hawk_nde_t* tree, int depth); static int print_tabs (hawk_t* awk, int depth) @@ -527,9 +532,7 @@ static int print_expr (hawk_t* awk, hawk_nde_t* nde) PUT_SRCSTR (awk, HAWK_T("__p")); n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, awk->tmp.fmt, HAWK_COUNTOF(awk->tmp.fmt)); PUT_SRCSTRN (awk, awk->tmp.fmt, n); - PUT_SRCSTR (awk, HAWK_T("[")); - PRINT_EXPR_LIST (awk, px->idx); - PUT_SRCSTR (awk, HAWK_T("]")); + PRINT_EXPR_LIST_FOR_IDX (awk, px->idx); break; } @@ -550,9 +553,7 @@ static int print_expr (hawk_t* awk, hawk_nde_t* nde) HAWK_ASSERT (px->idx != HAWK_NULL); PUT_SRCSTRN (awk, px->id.name.ptr, px->id.name.len); - PUT_SRCSTR (awk, HAWK_T("[")); - PRINT_EXPR_LIST (awk, px->idx); - PUT_SRCSTR (awk, HAWK_T("]")); + PRINT_EXPR_LIST_FOR_IDX (awk, px->idx); break; } @@ -621,16 +622,13 @@ static int print_expr (hawk_t* awk, hawk_nde_t* nde) n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, tmp, HAWK_COUNTOF(tmp)); PUT_SRCSTRN (awk, tmp, n); } - PUT_SRCSTR (awk, HAWK_T("[")); } else { PUT_SRCSTRN (awk, px->id.name.ptr, px->id.name.len); - PUT_SRCSTR (awk, HAWK_T("[")); } HAWK_ASSERT (px->idx != HAWK_NULL); - PRINT_EXPR_LIST (awk, px->idx); - PUT_SRCSTR (awk, HAWK_T("]")); + PRINT_EXPR_LIST_FOR_IDX (awk, px->idx); break; } @@ -663,16 +661,13 @@ static int print_expr (hawk_t* awk, hawk_nde_t* nde) PUT_SRCSTR (awk, HAWK_T("__l")); n = hawk_int_to_oocstr(px->id.idxa, 10, HAWK_NULL, awk->tmp.fmt, HAWK_COUNTOF(awk->tmp.fmt)); PUT_SRCSTRN (awk, awk->tmp.fmt, n); - PUT_SRCSTR (awk, HAWK_T("[")); } else { PUT_SRCSTRN (awk, px->id.name.ptr, px->id.name.len); - PUT_SRCSTR (awk, HAWK_T("[")); } HAWK_ASSERT (px->idx != HAWK_NULL); - PRINT_EXPR_LIST (awk, px->idx); - PUT_SRCSTR (awk, HAWK_T("]")); + PRINT_EXPR_LIST_FOR_IDX (awk, px->idx); break; } @@ -774,16 +769,44 @@ static int print_expr_list (hawk_t* awk, hawk_nde_t* tree) { hawk_nde_t* p = tree; - while (p != HAWK_NULL) + while (p) { PRINT_EXPR (awk, p); p = p->next; - if (p != HAWK_NULL) PUT_SRCSTR (awk, HAWK_T(",")); + if (p) PUT_SRCSTR (awk, HAWK_T(",")); } return 0; } +static int print_expr_list_for_idx (hawk_t* awk, hawk_nde_t* tree) +{ + hawk_nde_t* p = tree; + + PUT_SRCSTR (awk, HAWK_T("[")); + while (p) + { + PRINT_EXPR (awk, p); + p = p->next; + if (p) + { + if (p->type == HAWK_NDE_NULL) + { + /* the parser injects a HAWK_NDE_NULL node between the true multi-dimensional indices + * if the true multi-dimensional indices are enabled(i.e. HAWK_ENABLE_GC is defined) + * e.g. a[x][y][z] + * let me print this regardless of */ + PUT_SRCSTR (awk, HAWK_T("][")); + p = p->next; + } + else PUT_SRCSTR (awk, HAWK_T(",")); + } + } + PUT_SRCSTR (awk, HAWK_T("]")); + + return 0; +} + static int print_stmt (hawk_t* awk, hawk_nde_t* p, int depth) { hawk_oow_t i; @@ -877,7 +900,7 @@ static int print_stmt (hawk_t* awk, hawk_nde_t* p, int depth) PRINT_TABS (awk, depth); hawk_getkwname (awk, HAWK_KWID_WHILE, &kw); PUT_SRCSTRN (awk, kw.ptr, kw.len); - PUT_SRCSTR (awk, HAWK_T(" (")); + PUT_SRCSTR (awk, HAWK_T(" (")); PRINT_EXPR (awk, px->test); PUT_SRCSTR (awk, HAWK_T(")")); PUT_NL (awk); @@ -912,7 +935,7 @@ static int print_stmt (hawk_t* awk, hawk_nde_t* p, int depth) PRINT_TABS (awk, depth); hawk_getkwname (awk, HAWK_KWID_WHILE, &kw); PUT_SRCSTRN (awk, kw.ptr, kw.len); - PUT_SRCSTR (awk, HAWK_T(" (")); + PUT_SRCSTR (awk, HAWK_T(" (")); PRINT_EXPR (awk, px->test); PUT_SRCSTR (awk, HAWK_T(");")); PUT_NL (awk); diff --git a/hawk/lib/val.c b/hawk/lib/val.c index a31b2f8c..7253d1a4 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -1078,7 +1078,7 @@ hawk_val_t* hawk_rtx_setmapvalfld (hawk_rtx_t* rtx, hawk_val_t* map, const hawk_ { HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, map) == HAWK_VAL_MAP); - if (hawk_map_upsert (((hawk_val_map_t*)map)->map, (hawk_ooch_t*)kptr, klen, v, 0) == HAWK_NULL) return HAWK_NULL; + if (hawk_map_upsert(((hawk_val_map_t*)map)->map, (hawk_ooch_t*)kptr, klen, v, 0) == HAWK_NULL) return HAWK_NULL; /* the value is passed in by an external party. we can't refup() * and refdown() the value if htb_upsert() fails. that way, the value