diff --git a/hawk/lib/hawk-prv.h b/hawk/lib/hawk-prv.h index b1b9dd76..d6e4f6e4 100644 --- a/hawk/lib/hawk-prv.h +++ b/hawk/lib/hawk-prv.h @@ -378,6 +378,12 @@ struct hawk_chain_t hawk_chain_t* next; }; +typedef struct hawk_ctos_b_t hawk_ctos_b_t; +struct hawk_ctos_b_t +{ + hawk_ooch_t c[2]; +}; + struct hawk_rtx_t { HAWK_RTX_HDR; @@ -411,6 +417,16 @@ struct hawk_rtx_t hawk_val_chunk_t* rchunk; } vmgr; + struct + { +#if defined(HAWK_OOCH_IS_UCH) + hawk_ctos_b_t b[512]; +#else + hawk_ctos_b_t b[256]; /* it must not be larger than 256 */ +#endif + hawk_oow_t fi; + } ctos; /* char/nil to string conversion */ + struct { /* lists of values under gc management */ diff --git a/hawk/lib/mod-str.c b/hawk/lib/mod-str.c index 0496a98f..03b27832 100644 --- a/hawk/lib/mod-str.c +++ b/hawk/lib/mod-str.c @@ -43,7 +43,7 @@ static int fnc_normspace (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) hawk_oow_t len0; str0 = hawk_rtx_valtobcstrdup(rtx, a0, &len0); - if (!str0) return -1; + if (HAWK_UNLIKELY(!str0)) return -1; len0 = hawk_compact_bchars(str0, len0); retv = hawk_rtx_makembsvalwithbchars(rtx, str0, len0); hawk_rtx_freemem (rtx, str0); @@ -54,7 +54,7 @@ static int fnc_normspace (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) hawk_oow_t len0; str0 = hawk_rtx_valtooocstrdup(rtx, a0, &len0); - if (!str0) return -1; + if (HAWK_UNLIKELY(!str0)) return -1; len0 = hawk_compact_oochars(str0, len0); retv = hawk_rtx_makestrvalwithoochars(rtx, str0, len0); hawk_rtx_freemem (rtx, str0); diff --git a/hawk/lib/rec.c b/hawk/lib/rec.c index c4781d57..4cd496d2 100644 --- a/hawk/lib/rec.c +++ b/hawk/lib/rec.c @@ -489,7 +489,7 @@ static int recomp_record_fields (hawk_rtx_t* rtx, hawk_oow_t lv, const hawk_oocs int hawk_rtx_truncrec (hawk_rtx_t* rtx, hawk_oow_t nflds) { - hawk_val_t* v; + hawk_val_t* v = HAWK_NULL, * w; hawk_ooch_t* ofs_free = HAWK_NULL, * ofs_ptr; hawk_oow_t ofs_len, i; hawk_ooecs_t tmp; @@ -509,62 +509,47 @@ int hawk_rtx_truncrec (hawk_rtx_t* rtx, hawk_oow_t nflds) ofs_ptr = HAWK_T(" "); ofs_len = 1; } - else if (vtype == HAWK_VAL_STR) - { - ofs_ptr = ((hawk_val_str_t*)v)->val.ptr; - ofs_len = ((hawk_val_str_t*)v)->val.len; - } else { - hawk_rtx_valtostr_out_t out; - - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, v, &out) <= -1) return -1; - - ofs_ptr = out.u.cpldup.ptr; - ofs_len = out.u.cpldup.len; + ofs_ptr = hawk_rtx_getvaloocstr(rtx, v, &ofs_len); + if (HAWK_UNLIKELY(!ofs_ptr)) goto oops; ofs_free = ofs_ptr; } } - if (hawk_ooecs_init(&tmp, hawk_rtx_getgem(rtx), HAWK_OOECS_LEN(&rtx->inrec.line)) <= -1) - { - if (ofs_free) hawk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) hawk_rtx_refdownval (rtx, v); - return -1; - } + if (hawk_ooecs_init(&tmp, hawk_rtx_getgem(rtx), HAWK_OOECS_LEN(&rtx->inrec.line)) <= -1) goto oops; for (i = 0; i < nflds; i++) { if (i > 0 && hawk_ooecs_ncat(&tmp,ofs_ptr,ofs_len) == (hawk_oow_t)-1) { hawk_ooecs_fini (&tmp); - if (ofs_free) hawk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) hawk_rtx_refdownval (rtx, v); - return -1; + goto oops; } if (hawk_ooecs_ncat(&tmp, rtx->inrec.flds[i].ptr, rtx->inrec.flds[i].len) == (hawk_oow_t)-1) { hawk_ooecs_fini (&tmp); - if (ofs_free) hawk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) hawk_rtx_refdownval (rtx, v); - return -1; + goto oops; } } - if (ofs_free) hawk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) hawk_rtx_refdownval (rtx, v); + if (v) + { + if (ofs_free) hawk_rtx_freevaloocstr (rtx, v, ofs_free); + hawk_rtx_refdownval(rtx, v); + v = HAWK_NULL; + } - v = (hawk_val_t*)hawk_rtx_makestrvalwithoocs(rtx, HAWK_OOECS_OOCS(&tmp)); - if (!v) + w = (hawk_val_t*)hawk_rtx_makestrvalwithoocs(rtx, HAWK_OOECS_OOCS(&tmp)); + if (!w) { hawk_ooecs_fini (&tmp); return -1; } if (HAWK_RTX_GETVALTYPE(rtx, rtx->inrec.d0) != HAWK_VAL_NIL) hawk_rtx_refdownval (rtx, rtx->inrec.d0); - rtx->inrec.d0 = v; + rtx->inrec.d0 = w; hawk_rtx_refupval (rtx, rtx->inrec.d0); hawk_ooecs_swap (&tmp, &rtx->inrec.line); @@ -577,4 +562,12 @@ int hawk_rtx_truncrec (hawk_rtx_t* rtx, hawk_oow_t nflds) rtx->inrec.nflds = nflds; return 0; + +oops: + if (v) + { + if (ofs_free) hawk_rtx_freevaloocstr (rtx, v, ofs_free); + hawk_rtx_refdownval(rtx, v); + } + return -1; } diff --git a/hawk/lib/run.c b/hawk/lib/run.c index c099e82d..2e0d7d42 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -325,26 +325,25 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t case HAWK_GBL_CONVFMT: { hawk_oow_t i; - hawk_rtx_valtostr_out_t out; + hawk_oocs_t str; - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr (rtx, val, &out) <= -1) - return -1; + str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) return -1; - for (i = 0; i < out.u.cpldup.len; i++) + for (i = 0; i < str.len; i++) { - if (out.u.cpldup.ptr[i] == HAWK_T('\0')) + if (str.ptr[i] == '\0') { /* '\0' is included in the value */ - hawk_rtx_freemem (rtx, out.u.cpldup.ptr); + hawk_rtx_freemem (rtx, str.ptr); hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ECONVFMTCHR); return -1; } } if (rtx->gbl.convfmt.ptr) hawk_rtx_freemem (rtx, rtx->gbl.convfmt.ptr); - rtx->gbl.convfmt.ptr = out.u.cpldup.ptr; - rtx->gbl.convfmt.len = out.u.cpldup.len; + rtx->gbl.convfmt.ptr = str.ptr; + rtx->gbl.convfmt.len = str.len; break; } @@ -365,24 +364,12 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t hawk_ooch_t* fs_ptr; hawk_oow_t fs_len; - if (vtype == HAWK_VAL_STR) - { - fs_ptr = ((hawk_val_str_t*)val)->val.ptr; - fs_len = ((hawk_val_str_t*)val)->val.len; - } - else - { - hawk_rtx_valtostr_out_t out; + /* due to the expression evaluation rule, the + * regular expression can not be an assigned value */ + HAWK_ASSERT (vtype != HAWK_VAL_REX); - /* due to the expression evaluation rule, the - * regular expression can not be an assigned value */ - HAWK_ASSERT (vtype != HAWK_VAL_REX); - - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, val, &out) <= -1) return -1; - fs_ptr = out.u.cpldup.ptr; - fs_len = out.u.cpldup.len; - } + fs_ptr = hawk_rtx_getvaloocstr(rtx, val, &fs_len); + if (HAWK_UNLIKELY(!fs_ptr)) return -1; if (fs_len > 1 && !(fs_len == 5 && fs_ptr[0] == '?')) { @@ -393,7 +380,7 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t if (hawk_rtx_buildrex(rtx, fs_ptr, fs_len, &rex, &irex) <= -1) { - if (vtype != HAWK_VAL_STR) hawk_rtx_freemem (rtx, fs_ptr); + hawk_rtx_freevaloocstr (rtx, val, fs_ptr); return -1; } @@ -403,7 +390,7 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t rtx->gbl.fs[1] = irex; } - if (vtype != HAWK_VAL_STR) hawk_rtx_freemem (rtx, fs_ptr); + hawk_rtx_freevaloocstr (rtx, val, fs_ptr); break; } @@ -487,50 +474,51 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t case HAWK_GBL_OFMT: { hawk_oow_t i; - hawk_rtx_valtostr_out_t out; + hawk_oocs_t str; - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, val, &out) <= -1) return -1; + str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) return -1; - for (i = 0; i < out.u.cpldup.len; i++) + for (i = 0; i < str.len; i++) { - if (out.u.cpldup.ptr[i] == HAWK_T('\0')) + if (str.ptr[i] == '\0') { - hawk_rtx_freemem (rtx, out.u.cpldup.ptr); - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EOFMTCHR); + /* '\0' is included in the value */ + hawk_rtx_freemem (rtx, str.ptr); + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ECONVFMTCHR); return -1; } } if (rtx->gbl.ofmt.ptr) hawk_rtx_freemem (rtx, rtx->gbl.ofmt.ptr); - rtx->gbl.ofmt.ptr = out.u.cpldup.ptr; - rtx->gbl.ofmt.len = out.u.cpldup.len; - - break; + rtx->gbl.ofmt.ptr = str.ptr; + rtx->gbl.ofmt.len = str.len; } case HAWK_GBL_OFS: { - hawk_rtx_valtostr_out_t out; + hawk_oocs_t str; + + str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) return -1; - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, val, &out) <= -1) return -1; if (rtx->gbl.ofs.ptr) hawk_rtx_freemem (rtx, rtx->gbl.ofs.ptr); - rtx->gbl.ofs.ptr = out.u.cpldup.ptr; - rtx->gbl.ofs.len = out.u.cpldup.len; + rtx->gbl.ofs.ptr = str.ptr; + rtx->gbl.ofs.len = str.len; break; } case HAWK_GBL_ORS: { - hawk_rtx_valtostr_out_t out; + hawk_oocs_t str; + + str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) return -1; - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, val, &out) <= -1) return -1; if (rtx->gbl.ors.ptr) hawk_rtx_freemem (rtx, rtx->gbl.ors.ptr); - rtx->gbl.ors.ptr = out.u.cpldup.ptr; - rtx->gbl.ors.len = out.u.cpldup.len; + rtx->gbl.ors.ptr = str.ptr; + rtx->gbl.ors.len = str.len; break; } @@ -607,14 +595,14 @@ static int set_global (hawk_rtx_t* rtx, int idx, hawk_nde_var_t* var, hawk_val_t case HAWK_GBL_SUBSEP: { - hawk_rtx_valtostr_out_t out; + hawk_oocs_t str; - out.type = HAWK_RTX_VALTOSTR_CPLDUP; - if (hawk_rtx_valtostr(rtx, val, &out) <= -1) return -1; + str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) return -1; if (rtx->gbl.subsep.ptr) hawk_rtx_freemem (rtx, rtx->gbl.subsep.ptr); - rtx->gbl.subsep.ptr = out.u.cpldup.ptr; - rtx->gbl.subsep.len = out.u.cpldup.len; + rtx->gbl.subsep.ptr = str.ptr; + rtx->gbl.subsep.len = str.len; break; } @@ -835,6 +823,7 @@ hawk_rtx_t* hawk_rtx_open (hawk_t* hawk, hawk_oow_t xtnsize, hawk_rio_cbs_t* rio { hawk_rtx_t* rtx; struct module_init_ctx_t mic; + hawk_oow_t i; /* clear the hawk error code */ hawk_seterrnum (hawk, HAWK_NULL, HAWK_ENOERR); @@ -897,6 +886,16 @@ hawk_rtx_t* hawk_rtx_open (hawk_t* hawk, hawk_oow_t xtnsize, hawk_rio_cbs_t* rio return HAWK_NULL; } + /* chain the ctos slots */ + rtx->ctos.fi = HAWK_COUNTOF(rtx->ctos.b) - 1; + for (i = HAWK_COUNTOF(rtx->ctos.b); i > 1;) + { + --i; + rtx->ctos.b[i].c[0] = i - 1; + } + /* rtx->ctos.b[0] is not used as the free index of 0 indicates the end of the list. + * see hawk_rtx_getvaloocstr(). */ + return rtx; } @@ -8335,12 +8334,12 @@ wp_mod_main: break; case HAWK_VAL_CHAR: - ch = (hawk_ooch_t)HAWK_RTX_GETCHARFROMVAL (rtx, v); + ch = (hawk_ooch_t)HAWK_RTX_GETCHARFROMVAL(rtx, v); ch_len = 1; break; case HAWK_VAL_INT: - ch = (hawk_ooch_t)HAWK_RTX_GETINTFROMVAL (rtx, v); + ch = (hawk_ooch_t)HAWK_RTX_GETINTFROMVAL(rtx, v); ch_len = 1; break; diff --git a/hawk/lib/std.c b/hawk/lib/std.c index f2d81eed..f864d81b 100644 --- a/hawk/lib/std.c +++ b/hawk/lib/std.c @@ -3246,7 +3246,7 @@ done: if (rv) { hawk_rtx_refupval (rtx, rv); - ret = hawk_rtx_setrefval (rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2), rv); + ret = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2), rv); hawk_rtx_refdownval (rtx, rv); if (ret >= 0) hawk_rtx_setretval (rtx, HAWK_VAL_ZERO); } diff --git a/hawk/lib/val-prv.h b/hawk/lib/val-prv.h index d55fe734..db416112 100644 --- a/hawk/lib/val-prv.h +++ b/hawk/lib/val-prv.h @@ -107,7 +107,7 @@ struct hawk_val_rchunk_t #define HAWK_QUICKINT_TO_VTR(i) \ ((hawk_val_t*)(((i) < 0)? HAWK_QUICKINT_TO_VTR_NEGATIVE(i): HAWK_QUICKINT_TO_VTR_POSITIVE(i))) -#define HAWK_QUICKCHAR_TO_VTR(i) (((hawk_uintptr_t)(i) << HAWK_VTR_NUM_TYPE_BITS) | HAWK_VTR_TYPE_BITS_QUICKCHAR) +#define HAWK_QUICKCHAR_TO_VTR(i) ((hawk_val_t*)(((hawk_uintptr_t)(i) << HAWK_VTR_NUM_TYPE_BITS) | HAWK_VTR_TYPE_BITS_QUICKCHAR)) #define HAWK_VTR_ZERO ((hawk_val_t*)HAWK_QUICKINT_TO_VTR_POSITIVE(0)) #define HAWK_VTR_ONE ((hawk_val_t*)HAWK_QUICKINT_TO_VTR_POSITIVE(1)) diff --git a/hawk/lib/val.c b/hawk/lib/val.c index ddb41962..45b64ddd 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -1663,7 +1663,8 @@ int hawk_rtx_valtobool (hawk_rtx_t* rtx, const hawk_val_t* val) case HAWK_VAL_NIL: return 0; case HAWK_VAL_CHAR: - return HAWK_RTX_GETCHARFROMVAL(rtx, val) != 0; + /* return always true - treat it like a 1-letter string */ + return 1; case HAWK_VAL_INT: return HAWK_RTX_GETINTFROMVAL(rtx, val) != 0; case HAWK_VAL_FLT: @@ -1949,7 +1950,7 @@ static int val_flt_to_str (hawk_rtx_t* rtx, const hawk_val_flt_t* v, hawk_rtx_va fbu_inited = 1; tmp = hawk_rtx_format(rtx, &buf, &fbu, tmp, tmp_len, (hawk_oow_t)-1, (hawk_nde_t*)v, &tmp_len); - if (tmp == HAWK_NULL) goto oops; + if (HAWK_UNLIKELY(!tmp)) goto oops; switch (type) { @@ -2270,8 +2271,32 @@ hawk_uch_t* hawk_rtx_valtoucstrdupwithcmgr (hawk_rtx_t* rtx, const hawk_val_t* v hawk_ooch_t* hawk_rtx_getvaloocstrwithcmgr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_oow_t* len, hawk_cmgr_t* cmgr) { + hawk_ooch_t c; + hawk_oow_t l; + switch (HAWK_RTX_GETVALTYPE(rtx, v)) { + case HAWK_VAL_NIL: + c = '\0'; + l = 0; + goto ctos; + case HAWK_VAL_CHAR: + c = HAWK_RTX_GETCHARFROMVAL(rtx, v); + l = 1; + ctos: + if (rtx->ctos.fi) /* free slot available */ + { + /* use a ctos slot to avoid duplication */ + hawk_oow_t fi; + fi = rtx->ctos.fi; + rtx->ctos.fi = rtx->ctos.b[rtx->ctos.fi].c[0]; + rtx->ctos.b[fi].c[0] = c; + rtx->ctos.b[fi].c[1] = '\0'; + if (len) *len = l; + return &rtx->ctos.b[fi]; + } + goto duplicate; + case HAWK_VAL_STR: #if 0 plain_str: @@ -2291,6 +2316,7 @@ hawk_ooch_t* hawk_rtx_getvaloocstrwithcmgr (hawk_rtx_t* rtx, hawk_val_t* v, hawk #endif default: + duplicate: return hawk_rtx_valtooocstrdupwithcmgr(rtx, v, len, cmgr); } } @@ -2299,6 +2325,22 @@ void hawk_rtx_freevaloocstr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_ooch_t* str) { switch (HAWK_RTX_GETVALTYPE(rtx, v)) { + case HAWK_VAL_NIL: + case HAWK_VAL_CHAR: + { + hawk_ctos_b_t* b = (hawk_ctos_b_t*)str; + if (b >= &rtx->ctos.b[0] && b < &rtx->ctos.b[HAWK_COUNTOF(rtx->ctos.b)]) + { + hawk_oow_t fi; + fi = b - &rtx->ctos.b[0]; + rtx->ctos.b[fi].c[0] = rtx->ctos.fi; + rtx->ctos.fi = fi; + break; + } + + goto freemem; + } + case HAWK_VAL_STR: #if 0 plain_str: @@ -2314,6 +2356,7 @@ void hawk_rtx_freevaloocstr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_ooch_t* str) #endif default: + freemem: hawk_rtx_freemem (rtx, str); break; } @@ -2436,8 +2479,14 @@ int hawk_rtx_valtonum (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_int_t* l, hawk return 0; case HAWK_VAL_CHAR: - *l = HAWK_RTX_GETCHARFROMVAL(rtx, v); - return 0; /* long */ + { + /* treat it as if it is a 1-letter string */ + hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v); + return hawk_oochars_to_num( + HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), + &tmp, 1, l, r + ); + } case HAWK_VAL_INT: *l = HAWK_RTX_GETINTFROMVAL(rtx, v); @@ -2748,41 +2797,21 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENONSCATOPOS); return -1; - case HAWK_VAL_STR: - { - int x; - /* handle this separately from the default case - * for no duplication. jumping to the default case - * and callinghawk_rtx_valtooocstrdup() would also work, anyway. */ - hawk_rtx_refupval (rtx, val); - x = hawk_rtx_setrec(rtx, (hawk_oow_t)ref->adr, &((hawk_val_str_t*)val)->val, 0); - hawk_rtx_refdownval (rtx, val); - return x; - } - - case HAWK_VAL_MBS: - #if defined(HAWK_OOCH_IS_BCH) - { - /* same as str in the mchar mode */ - int x; - hawk_rtx_refupval (rtx, val); - x = hawk_rtx_setrec(rtx, (hawk_oow_t)ref->adr, &((hawk_val_mbs_t*)val)->val, 0); - hawk_rtx_refdownval (rtx, val); - return x; - } - #endif - /* fall thru otherwise */ - default: { hawk_oocs_t str; int x; - str.ptr = hawk_rtx_valtooocstrdup(rtx, val, &str.len); hawk_rtx_refupval (rtx, val); + str.ptr = hawk_rtx_getvaloocstr(rtx, val, &str.len); + if (HAWK_UNLIKELY(!str.ptr)) + { + hawk_rtx_refdownval (rtx, val); + return -1; + } x = hawk_rtx_setrec(rtx, (hawk_oow_t)ref->adr, &str, 0); + hawk_rtx_freevaloocstr (rtx, val, str.ptr); hawk_rtx_refdownval (rtx, val); - hawk_rtx_freemem (rtx, str.ptr); return x; } }