diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 28eac025..b71828b5 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -2892,12 +2892,15 @@ QSE_EXPORT void qse_awk_rtx_freevalstr ( ); -QSE_EXPORT qse_mchar_t* qse_awk_rtx_getvalmbs ( +QSE_EXPORT qse_mchar_t* qse_awk_rtx_getvalmbswithcmgr ( qse_awk_rtx_t* rtx, /**< runtime context */ const qse_awk_val_t* val, /**< value to convert */ - qse_size_t* len /**< result length */ + qse_size_t* len, /**< result length */ + qse_cmgr_t* cmgr ); +#define qse_awk_rtx_getvalmbs(rtx,val,len) qse_awk_rtx_getvalmbswithcmgr(rtx, val, len, qse_awk_rtx_getcmgr(rtx)) + QSE_EXPORT void qse_awk_rtx_freevalmbs ( qse_awk_rtx_t* rtx, /**< runtime context */ const qse_awk_val_t* val, /**< value to convert */ diff --git a/qse/lib/awk/mod-str.c b/qse/lib/awk/mod-str.c index b82328d6..7599bf9d 100644 --- a/qse/lib/awk/mod-str.c +++ b/qse/lib/awk/mod-str.c @@ -27,6 +27,7 @@ #include "mod-str.h" #include #include +#include #include "../cmn/mem-prv.h" #include "fnc.h" #include "val.h" @@ -357,13 +358,32 @@ static int fnc_tocharcode (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) static int fnc_frommbs (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) { - /* str::frommbs(B"byte-string") */ + /* str::frommbs(B"byte-string" [, "encoding-name"]) */ qse_awk_val_t* a0, * r; + qse_cmgr_t* cmgr = qse_awk_rtx_getcmgr(rtx); + + if (qse_awk_rtx_getnargs(rtx) >= 2) + { + qse_awk_val_t* a1; + qse_cstr_t enc; + + a1 = qse_awk_rtx_getarg(rtx, 1); + enc.ptr = qse_awk_rtx_getvalstr(rtx, a1, &enc.len); + if (!enc.ptr) return -1; + cmgr = (enc.len == qse_strlen(enc.ptr))? qse_findcmgr(enc.ptr): QSE_NULL; + qse_awk_rtx_freevalstr (rtx, a1, enc.ptr); + + if (!cmgr) + { + /* if the encoding name is not known, return a zero-length string */ + r = qse_awk_rtx_makestrval(rtx, QSE_NULL, 0); /* this never fails for length 0 */ + goto done; + } + } a0 = qse_awk_rtx_getarg(rtx, 0); switch (QSE_AWK_RTX_GETVALTYPE(rtx, a0)) { - case QSE_AWK_VAL_STR: r = a0; break; @@ -380,14 +400,34 @@ static int fnc_frommbs (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) } } +done: qse_awk_rtx_setretval (rtx, r); return 0; } static int fnc_tombs (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) { - /* str::tombs("string") */ + /* str::tombs("string", [, "encoding-name"]) */ qse_awk_val_t* a0, * r; + qse_cmgr_t* cmgr = qse_awk_rtx_getcmgr(rtx); + + if (qse_awk_rtx_getnargs(rtx) >= 2) + { + qse_awk_val_t* a1; + qse_cstr_t enc; + a1 = qse_awk_rtx_getarg(rtx, 1); + enc.ptr = qse_awk_rtx_getvalstr(rtx, a1, &enc.len); + if (!enc.ptr) return -1; + cmgr = (enc.len == qse_strlen(enc.ptr))? qse_findcmgr(enc.ptr): QSE_NULL; + qse_awk_rtx_freevalstr (rtx, a1, enc.ptr); + + if (!cmgr) + { + /* if the encoding name is not known, return a zero-length string */ + r = qse_awk_rtx_makembsval(rtx, QSE_NULL, 0); /* this never fails for length 0 */ + goto done; + } + } a0 = qse_awk_rtx_getarg(rtx, 0); switch (QSE_AWK_RTX_GETVALTYPE(rtx, a0)) @@ -399,7 +439,7 @@ static int fnc_tombs (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) default: { qse_mcstr_t str; - str.ptr = qse_awk_rtx_getvalmbs(rtx, a0, &str.len); + str.ptr = qse_awk_rtx_getvalmbswithcmgr(rtx, a0, &str.len, cmgr); if (!str.ptr) return -1; r = qse_awk_rtx_makembsvalwithmxstr(rtx, &str); qse_awk_rtx_freevalmbs (rtx, a0, str.ptr); @@ -408,6 +448,7 @@ static int fnc_tombs (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) } } +done: qse_awk_rtx_setretval (rtx, r); return 0; } @@ -501,7 +542,7 @@ static fnctab_t fnctab[] = { /* keep this table sorted for binary search in query(). */ { QSE_T("fromcharcode"), { { 0, A_MAX, QSE_NULL }, fnc_fromcharcode, 0 } }, - { QSE_T("frommbs"), { { 1, 1, QSE_NULL }, fnc_frommbs, 0 } }, + { QSE_T("frommbs"), { { 1, 2, QSE_NULL }, fnc_frommbs, 0 } }, { QSE_T("gsub"), { { 2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 } }, { QSE_T("index"), { { 2, 3, QSE_NULL }, qse_awk_fnc_index, 0 } }, { QSE_T("isalnum"), { { 1, 1, QSE_NULL }, fnc_isalnum, 0 } }, @@ -528,7 +569,7 @@ static fnctab_t fnctab[] = { QSE_T("substr"), { { 2, 3, QSE_NULL }, qse_awk_fnc_substr, 0 } }, { QSE_T("tocharcode"), { { 1, 2, QSE_NULL }, fnc_tocharcode, 0 } }, { QSE_T("tolower"), { { 1, 1, QSE_NULL }, qse_awk_fnc_tolower, 0 } }, - { QSE_T("tombs"), { { 1, 1, QSE_NULL }, fnc_tombs, 0 } }, + { QSE_T("tombs"), { { 1, 2, QSE_NULL }, fnc_tombs, 0 } }, { QSE_T("tonum"), { { 1, 2, QSE_NULL }, fnc_tonum, 0 } }, { QSE_T("toupper"), { { 1, 1, QSE_NULL }, qse_awk_fnc_toupper, 0 } }, { QSE_T("trim"), { { 1, 2, QSE_NULL }, fnc_trim, 0 } } diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index 024aab52..3af99376 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -36,9 +36,11 @@ static qse_awk_val_nil_t awk_nil = { QSE_AWK_VAL_NIL, 0, 1, 0, 0 }; static qse_awk_val_str_t awk_zls = { QSE_AWK_VAL_STR, 0, 1, 0, 0, { QSE_T(""), 0 } }; +static qse_awk_val_mbs_t awk_zlm = { QSE_AWK_VAL_MBS, 0, 1, 0, 0, { QSE_MT(""), 0 } }; qse_awk_val_t* qse_awk_val_nil = (qse_awk_val_t*)&awk_nil; qse_awk_val_t* qse_awk_val_zls = (qse_awk_val_t*)&awk_zls; +qse_awk_val_t* qse_awk_val_zlm = (qse_awk_val_t*)&awk_zlm; qse_awk_val_t* qse_getawknilval (void) { @@ -167,10 +169,13 @@ qse_awk_val_t* qse_awk_rtx_makestrvalwithxstr (qse_awk_rtx_t* rtx, const qse_cst { qse_awk_val_str_t* val = QSE_NULL; qse_size_t rlen = str->len; - #ifdef ENABLE_FEATURE_SCACHE qse_size_t i; +#endif + if (rlen <= 0) return qse_awk_val_zls; + +#ifdef ENABLE_FEATURE_SCACHE i = rlen / FEATURE_SCACHE_BLOCK_UNIT; if (i < QSE_COUNTOF(rtx->scache_count)) { @@ -381,7 +386,11 @@ qse_awk_val_t* qse_awk_rtx_makenstrvalwithxstr (qse_awk_rtx_t* rtx, const qse_cs qse_awk_val_t* qse_awk_rtx_makembsval (qse_awk_rtx_t* rtx, const qse_mchar_t* ptr, qse_size_t len) { qse_awk_val_mbs_t* val = QSE_NULL; - qse_size_t xsz = len * QSE_SIZEOF(*ptr); + qse_size_t xsz; + + if (len <= 0) return qse_awk_val_zlm; + + xsz = len * QSE_SIZEOF(*ptr); val = (qse_awk_val_mbs_t*)qse_awk_rtx_callocmem(rtx, QSE_SIZEOF(qse_awk_val_mbs_t) + xsz + QSE_SIZEOF(*ptr)); if (!val) return QSE_NULL; @@ -1635,6 +1644,7 @@ void qse_awk_rtx_freevalstr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_cha } +#if 0 qse_mchar_t* qse_awk_rtx_getvalmbs (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len) { if (QSE_AWK_RTX_GETVALTYPE(rtx, v) == QSE_AWK_VAL_MBS) @@ -1647,6 +1657,20 @@ qse_mchar_t* qse_awk_rtx_getvalmbs (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, return qse_awk_rtx_valtombsdup(rtx, v, len); } } +#endif + +qse_mchar_t* qse_awk_rtx_getvalmbswithcmgr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_size_t* len, qse_cmgr_t* cmgr) +{ + if (QSE_AWK_RTX_GETVALTYPE(rtx, v) == QSE_AWK_VAL_MBS) + { + if (len) *len = ((qse_awk_val_mbs_t*)v)->val.len; + return ((qse_awk_val_mbs_t*)v)->val.ptr; + } + else + { + return qse_awk_rtx_valtombsdup(rtx, v, len); /* TODO: */ + } +} void qse_awk_rtx_freevalmbs (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_mchar_t* str) { diff --git a/qse/lib/awk/val.h b/qse/lib/awk/val.h index 0ef2afc6..49a8f0dc 100644 --- a/qse/lib/awk/val.h +++ b/qse/lib/awk/val.h @@ -66,7 +66,7 @@ struct qse_awk_val_rchunk_t * add a field to indicate if a value is static. * -#define IS_STATICVAL(val) ((val) == QSE_NULL || (val) == qse_awk_val_nil || (val) == qse_awk_val_zls) +#define IS_STATICVAL(val) ((val) == QSE_NULL || (val) == qse_awk_val_nil || (val) == qse_awk_val_zls || (val) == qse_awk_val_zlm) */ #define IS_STATICVAL(val) ((val)->stat)