diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2012-07-26 11:08:02 -0400 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2012-07-26 11:08:02 -0400 |
commit | 1a69f3ec43ba9748ad63443f88b2e26b014c11d2 (patch) | |
tree | 237e9bbad6bc38c71cbfc3cbd259856757669390 | |
parent | 7e5b2a94ce3c089c50c5862168d1d917e5febcf4 (diff) | |
download | egawk-1a69f3ec43ba9748ad63443f88b2e26b014c11d2.tar.gz egawk-1a69f3ec43ba9748ad63443f88b2e26b014c11d2.tar.bz2 egawk-1a69f3ec43ba9748ad63443f88b2e26b014c11d2.zip |
Fix api_sym_update_scalar.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | gawkapi.c | 78 |
2 files changed, 53 insertions, 31 deletions
@@ -1,3 +1,9 @@ +2012-07-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawkapi.c (api_sym_update_scalar): Fix some minor bugs. Was + not updating AWK_NUMBER when valref != 1. And strings were not + freeing MPFR values. + 2012-07-25 Arnold D. Robbins <arnold@skeeve.com> Start refactoring of IOBUF handling and turn "open hooks" @@ -574,53 +574,69 @@ api_sym_update_scalar(awk_ext_id_t id, || node->type != Node_var) return false; + /* + * Optimization: if valref is 1, and the new value is a string or + * a number, we can avoid calling unref and then making a new node + * by simply installing the new value. First, we follow the same + * recipe used by node.c:r_unref to wipe the current values, and then + * we copy the logic from r_make_number or r_make_str_node to install + * the new value. + */ switch (value->val_type) { case AWK_NUMBER: + if (node->var_value->valref == 1 && ! do_mpfr) { + NODE *r = node->var_value; + + /* r_unref: */ + if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) + efree(r->stptr); + free_wstr(r); + + /* r_make_number: */ + r->numbr = value->num_value; + r->flags = MALLOC|NUMBER|NUMCUR; + r->stptr = NULL; + r->stlen = 0; + return true; + } + break; case AWK_STRING: - /* try for optimization */ if (node->var_value->valref == 1) { NODE *r = node->var_value; - if (value->val_type == AWK_NUMBER && do_mpfr) - break; /* break switch, do it the hard way */ - - /* release the old string value if any */ - if (r->flags & STRCUR) { - if (r->flags & MALLOC) - efree(r->stptr); - r->stptr = NULL; - r->stlen = 0; - } + /* r_unref: */ + if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) + efree(r->stptr); +#ifdef HAVE_MPFR + if (is_mpg_float(r)) + mpfr_clear(r->mpg_numbr); + else if (is_mpg_integer(r)) + mpz_clear(r->mpg_i); +#endif free_wstr(r); - if (value->val_type == AWK_NUMBER) { - r->flags = MALLOC|NUMBER|NUMCUR; - r->numbr = value->num_value; - } else { - r->flags &= ~(NUMBER|NUMCUR); - r->flags |= (STRING|STRCUR|MALLOC); - r->stfmt = -1; - r->stptr = value->str_value.str; - r->stlen = value->str_value.len; - } - + /* r_make_str_node(ALREADY_MALLOCED): */ + r->numbr = 0; + r->flags = (MALLOC|STRING|STRCUR); + r->stfmt = -1; + r->stptr = value->str_value.str; + r->stlen = value->str_value.len; return true; } - /* else - fall through */ + break; case AWK_UNDEFINED: case AWK_SCALAR: case AWK_VALUE_COOKIE: - unref(node->var_value); - node->var_value = awk_value_to_node(value); - - return true; - - case AWK_ARRAY: break; + + default: /* AWK_ARRAY or invalid type */ + return false; } - return false; + /* do it the hard (slow) way */ + unref(node->var_value); + node->var_value = awk_value_to_node(value); + return true; } /* |