diff --git a/ase/awk/Awk.cpp b/ase/awk/Awk.cpp index 89122d8e..c1a73c0d 100644 --- a/ase/awk/Awk.cpp +++ b/ase/awk/Awk.cpp @@ -1166,7 +1166,7 @@ int Awk::open () } functionMap = ase_awk_map_open ( - this, 512, 70, freeFunctionMapValue, awk); + this, 512, 70, freeFunctionMapValue, ASE_NULL, awk); if (functionMap == ASE_NULL) { ase_awk_close (awk); diff --git a/ase/awk/awk.c b/ase/awk/awk.c index ec1e5924..61005019 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -68,7 +68,7 @@ ase_awk_t* ase_awk_open (const ase_awk_prmfns_t* prmfns, void* custom_data) return ASE_NULL; } - awk->wtab = ase_awk_map_open (awk, 512, 70, free_word, awk); + awk->wtab = ase_awk_map_open (awk, 512, 70, free_word, ASE_NULL, awk); if (awk->wtab == ASE_NULL) { ase_str_close (&awk->token.name); @@ -76,7 +76,7 @@ ase_awk_t* ase_awk_open (const ase_awk_prmfns_t* prmfns, void* custom_data) return ASE_NULL; } - awk->rwtab = ase_awk_map_open (awk, 512, 70, free_word, awk); + awk->rwtab = ase_awk_map_open (awk, 512, 70, free_word, ASE_NULL, awk); if (awk->rwtab == ASE_NULL) { ase_awk_map_close (awk->wtab); @@ -86,7 +86,7 @@ ase_awk_t* ase_awk_open (const ase_awk_prmfns_t* prmfns, void* custom_data) } /* TODO: initial map size?? */ - awk->tree.afns = ase_awk_map_open (awk, 512, 70, free_afn, awk); + awk->tree.afns = ase_awk_map_open (awk, 512, 70, free_afn, ASE_NULL, awk); if (awk->tree.afns == ASE_NULL) { ase_awk_map_close (awk->rwtab); @@ -162,7 +162,7 @@ ase_awk_t* ase_awk_open (const ase_awk_prmfns_t* prmfns, void* custom_data) awk->bfn.sys = ASE_NULL; /*awk->bfn.user = ASE_NULL;*/ - awk->bfn.user = ase_awk_map_open (awk, 512, 70, free_bfn, awk); + awk->bfn.user = ase_awk_map_open (awk, 512, 70, free_bfn, ASE_NULL, awk); if (awk->bfn.user == ASE_NULL) { ase_awk_tab_close (&awk->parse.params); diff --git a/ase/awk/map.c b/ase/awk/map.c index 94e13ce9..40805c68 100644 --- a/ase/awk/map.c +++ b/ase/awk/map.c @@ -19,7 +19,8 @@ static int rehash (ase_awk_map_t* map); ase_awk_map_t* ase_awk_map_open ( void* owner, ase_size_t capa, unsigned int factor, - void(*freeval)(void*,void*), ase_awk_t* awk) + void(*freeval)(void*,void*), void(*sameval)(void*,void*), + ase_awk_t* awk) { ase_awk_map_t* map; @@ -42,6 +43,7 @@ ase_awk_map_t* ase_awk_map_open ( map->capa = capa; map->size = 0; map->freeval = freeval; + map->sameval = sameval; while (capa > 0) map->buck[--capa] = ASE_NULL; map->factor = factor; @@ -214,15 +216,29 @@ ase_awk_pair_t* ase_awk_map_setpair ( ase_awk_map_t* map, ase_awk_pair_t* pair, void* val) { /* use this function with care */ - if (ASE_AWK_PAIR_VAL(pair) != val) + if (ASE_AWK_PAIR_VAL(pair) == val) { + /* if the old value and the new value are the same, + * it just calls the handler for this condition. + * No value replacement occurs. */ + if (map->sameval != ASE_NULL) + { + map->sameval (map->owner, val); + } + } + else + { + /* frees the old value */ if (map->freeval != ASE_NULL) { map->freeval (map->owner, ASE_AWK_PAIR_VAL(pair)); } + + /* the new value takes the place */ ASE_AWK_PAIR_VAL(pair) = val; } + return pair; } diff --git a/ase/awk/map.h b/ase/awk/map.h index ad2a8624..23c5c8e1 100644 --- a/ase/awk/map.h +++ b/ase/awk/map.h @@ -37,6 +37,7 @@ struct ase_awk_map_t ase_size_t threshold; ase_awk_pair_t** buck; void (*freeval) (void*,void*); + void (*sameval) (void*,void*); ase_awk_t* awk; }; @@ -51,7 +52,8 @@ extern "C" { ase_awk_map_t* ase_awk_map_open ( void* owner, ase_size_t capa, unsigned int factor, - void(*freeval)(void*,void*), ase_awk_t* awk); + void(*freeval)(void*,void*), void(*sameval)(void*,void*), + ase_awk_t* awk); void ase_awk_map_close (ase_awk_map_t* map); diff --git a/ase/awk/run.c b/ase/awk/run.c index dedd2dd4..f159adf6 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -718,6 +718,11 @@ static void free_namedval (void* run, void* val) ase_awk_refdownval ((ase_awk_run_t*)run, val); } +static void same_namedval (void* run, void* val) +{ + ase_awk_refdownval_nofree ((ase_awk_run_t*)run, val); +} + static int init_run ( ase_awk_run_t* run, ase_awk_t* awk, ase_awk_runios_t* runios, void* custom_data) @@ -772,7 +777,7 @@ static int init_run ( } run->named = ase_awk_map_open ( - run, 1024, 70, free_namedval, run->awk); + run, 1024, 70, free_namedval, same_namedval, run->awk); if (run->named == ASE_NULL) { ase_str_close (&run->format.fmt); @@ -2368,8 +2373,9 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) return -1; } - if (ase_awk_map_put (run->named, - var->id.name, var->id.name_len, tmp) == ASE_NULL) + pair = ase_awk_map_put (run->named, + var->id.name, var->id.name_len, tmp); + if (pair == ASE_NULL) { ase_awk_refupval (run, tmp); ase_awk_refdownval (run, tmp); @@ -2381,7 +2387,7 @@ static int run_delete (ase_awk_run_t* run, ase_awk_nde_delete_t* nde) } /* as this is the assignment, it needs to update - * the reference count of the target value */ + * the reference count of the target value. */ ase_awk_refupval (run, tmp); } else @@ -4491,11 +4497,10 @@ static ase_awk_val_t* eval_binop_ma ( ase_awk_refupval (run, rv); - res = eval_binop_match0 ( - run, lv, rv, left->line, right->line, 1); + res = eval_binop_match0 (run, lv, rv, left->line, right->line, 1); - ase_awk_refdownval (run, lv); ase_awk_refdownval (run, rv); + ase_awk_refdownval (run, lv); return res; } @@ -4525,8 +4530,8 @@ static ase_awk_val_t* eval_binop_nm ( res = eval_binop_match0 ( run, lv, rv, left->line, right->line, 0); - ase_awk_refdownval (run, lv); ase_awk_refdownval (run, rv); + ase_awk_refdownval (run, lv); return res; } diff --git a/ase/awk/val.c b/ase/awk/val.c index 676eccd8..d410b2b9 100644 --- a/ase/awk/val.c +++ b/ase/awk/val.c @@ -242,7 +242,7 @@ ase_awk_val_t* ase_awk_makerexval ( return (ase_awk_val_t*)val; } -static void free_map_val (void* run, void* v) +static void free_mapval (void* run, void* v) { #ifdef DEBUG_VAL ase_dprintf (ASE_T("refdown in map free...")); @@ -253,6 +253,16 @@ static void free_map_val (void* run, void* v) ase_awk_refdownval (run, v); } +static void same_mapval (void* run, void* v) +{ +#ifdef DEBUG_VAL + ase_dprintf (ASE_T("refdown nofree in map free...")); + ase_awk_dprintval (run, v); + ase_dprintf (ASE_T("\n")); +#endif + ase_awk_refdownval_nofree (run, v); +} + ase_awk_val_t* ase_awk_makemapval (ase_awk_run_t* run) { ase_awk_val_map_t* val; @@ -267,7 +277,8 @@ ase_awk_val_t* ase_awk_makemapval (ase_awk_run_t* run) val->type = ASE_AWK_VAL_MAP; val->ref = 0; - val->map = ase_awk_map_open (run, 256, 70, free_map_val, run->awk); + val->map = ase_awk_map_open ( + run, 256, 70, free_mapval, same_mapval, run->awk); if (val->map == ASE_NULL) { ASE_AWK_FREE (run->awk, val);