resolved numerous bugs regarding byte-characters and byte-strings

changed the way to handle %s/%k/%K contained inside CONVFMT - treat the format specifier as if it is %g instead of returning an error.
removed HAWK_EFMTCNV for the CONVFMT formatting change
This commit is contained in:
hyung-hwan 2020-12-10 16:55:47 +00:00
parent e983d7701a
commit 0de14c4744
15 changed files with 1311 additions and 745 deletions

View File

@ -166,7 +166,6 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
HAWK_T("I/O name empty"), HAWK_T("I/O name empty"),
HAWK_T("I/O name containing '\\0'"), HAWK_T("I/O name containing '\\0'"),
HAWK_T("not sufficient arguments to formatting sequence"), HAWK_T("not sufficient arguments to formatting sequence"),
HAWK_T("recursion detected in format conversion"),
HAWK_T("invalid character in CONVFMT"), HAWK_T("invalid character in CONVFMT"),
HAWK_T("invalid character in OFMT"), HAWK_T("invalid character in OFMT"),

View File

@ -566,7 +566,10 @@ static int index_or_rindex (hawk_rtx_t* rtx, int rindex)
if (n <= -1) return -1; if (n <= -1) return -1;
} }
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str0, * str1, * ptr; hawk_bch_t* str0, * str1, * ptr;
hawk_oow_t len0, len1; hawk_oow_t len0, len1;
@ -575,7 +578,7 @@ static int index_or_rindex (hawk_rtx_t* rtx, int rindex)
len0 = ((hawk_val_mbs_t*)a0)->val.len; len0 = ((hawk_val_mbs_t*)a0)->val.len;
str1 = hawk_rtx_getvalbcstr(rtx, a1, &len1); str1 = hawk_rtx_getvalbcstr(rtx, a1, &len1);
if (!str1) return -1; if (HAWK_UNLIKELY(!str0)) return -1;
if (nargs < 3) if (nargs < 3)
{ {
@ -605,14 +608,16 @@ static int index_or_rindex (hawk_rtx_t* rtx, int rindex)
idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1); idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1);
hawk_rtx_freevalbcstr (rtx, a1, str1); hawk_rtx_freevalbcstr (rtx, a1, str1);
break;
} }
else
default:
{ {
hawk_ooch_t* str0, * str1, * ptr; hawk_ooch_t* str0, * str1, * ptr;
hawk_oow_t len0, len1; hawk_oow_t len0, len1;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (!str0) return -1; if (HAWK_UNLIKELY(!str0)) return -1;
str1 = hawk_rtx_getvaloocstr(rtx, a1, &len1); str1 = hawk_rtx_getvaloocstr(rtx, a1, &len1);
if (!str1) if (!str1)
@ -651,9 +656,11 @@ static int index_or_rindex (hawk_rtx_t* rtx, int rindex)
hawk_rtx_freevaloocstr (rtx, a1, str1); hawk_rtx_freevaloocstr (rtx, a1, str1);
hawk_rtx_freevaloocstr (rtx, a0, str0); hawk_rtx_freevaloocstr (rtx, a0, str0);
} }
break;
}
a0 = hawk_rtx_makeintval(rtx, idx); a0 = hawk_rtx_makeintval(rtx, idx);
if (a0 == HAWK_NULL) return -1; if (HAWK_UNLIKELY(!a0)) return -1;
hawk_rtx_setretval (rtx, a0); hawk_rtx_setretval (rtx, a0);
return 0; return 0;
@ -661,12 +668,12 @@ static int index_or_rindex (hawk_rtx_t* rtx, int rindex)
int hawk_fnc_index (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) int hawk_fnc_index (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
return index_or_rindex (rtx, 0); return index_or_rindex(rtx, 0);
} }
int hawk_fnc_rindex (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) int hawk_fnc_rindex (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
return index_or_rindex (rtx, 1); return index_or_rindex(rtx, 1);
} }
int hawk_fnc_length (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) int hawk_fnc_length (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
@ -701,15 +708,23 @@ int hawk_fnc_length (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
len = HAWK_ARR_TALLY(((hawk_val_arr_t*)v)->arr); len = HAWK_ARR_TALLY(((hawk_val_arr_t*)v)->arr);
break; break;
case HAWK_VAL_STR: case HAWK_VAL_BCHR:
/* string length */ len = 1;
len = ((hawk_val_str_t*)v)->val.len;
break; break;
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
len = ((hawk_val_mbs_t*)v)->val.len; len = ((hawk_val_mbs_t*)v)->val.len;
break; break;
case HAWK_VAL_CHAR:
len = 1;
break;
case HAWK_VAL_STR:
/* string length */
len = ((hawk_val_str_t*)v)->val.len;
break;
default: default:
/* convert to string and get length */ /* convert to string and get length */
str = hawk_rtx_valtooocstrdup(rtx, v, &len); str = hawk_rtx_valtooocstrdup(rtx, v, &len);
@ -753,27 +768,33 @@ int hawk_fnc_substr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
lindex = lindex - 1; lindex = lindex - 1;
if (lindex < 0) lindex = 0; if (lindex < 0) lindex = 0;
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str; hawk_bch_t* str;
hawk_oow_t len; hawk_oow_t len;
str = ((hawk_val_mbs_t*)a0)->val.ptr; str = hawk_rtx_getvalbcstr(rtx, a0, &len);
len = ((hawk_val_mbs_t*)a0)->val.len; if (HAWK_UNLIKELY(!str)) return -1;
if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len; if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len;
if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex; if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex;
r = hawk_rtx_makembsvalwithbchars(rtx, &str[lindex], (hawk_oow_t)lcount); r = hawk_rtx_makembsvalwithbchars(rtx, &str[lindex], (hawk_oow_t)lcount);
hawk_rtx_freevalbcstr (rtx, a0, str);
if (HAWK_UNLIKELY(!r)) return -1; if (HAWK_UNLIKELY(!r)) return -1;
break;
} }
else
default:
{ {
hawk_ooch_t* str; hawk_ooch_t* str;
hawk_oow_t len; hawk_oow_t len;
str = hawk_rtx_getvaloocstr(rtx, a0, &len); str = hawk_rtx_getvaloocstr(rtx, a0, &len);
if (!str) return -1; if (HAWK_UNLIKELY(!str)) return -1;
if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len; if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len;
if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex; if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex;
@ -781,6 +802,8 @@ int hawk_fnc_substr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount); r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount);
hawk_rtx_freevaloocstr (rtx, a0, str); hawk_rtx_freevaloocstr (rtx, a0, str);
if (HAWK_UNLIKELY(!r)) return -1; if (HAWK_UNLIKELY(!r)) return -1;
break;
}
} }
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
@ -836,6 +859,9 @@ static int fnc_split (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi, int use_array)
} }
else else
{ {
/* no distinction between byte-string and normal string for the lack of hawk_rtx_buildrex() with a byte string.
* TODO: distingish byte strings from normal strings once the regular expresson builder supports them */
fs.ptr = hawk_rtx_getvaloocstr(rtx, t0, &fs.len); fs.ptr = hawk_rtx_getvaloocstr(rtx, t0, &fs.len);
if (HAWK_UNLIKELY(!fs.ptr)) goto oops; if (HAWK_UNLIKELY(!fs.ptr)) goto oops;
@ -864,17 +890,20 @@ static int fnc_split (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi, int use_array)
} }
/* the first parameter - string to split */ /* the first parameter - string to split */
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
byte_str = 1; byte_str = 1;
str.ptr = do_fld? hawk_rtx_valtobcstrdup(rtx, a0, &str.len): str.ptr = do_fld? hawk_rtx_valtobcstrdup(rtx, a0, &str.len):
hawk_rtx_getvalbcstr(rtx, a0, &str.len); hawk_rtx_getvalbcstr(rtx, a0, &str.len);
} break;
else
{ default:
byte_str = 0; byte_str = 0;
str.ptr = do_fld? hawk_rtx_valtooocstrdup(rtx, a0, &str.len): str.ptr = do_fld? hawk_rtx_valtooocstrdup(rtx, a0, &str.len):
hawk_rtx_getvaloocstr(rtx, a0, &str.len); hawk_rtx_getvaloocstr(rtx, a0, &str.len);
break;
} }
if (HAWK_UNLIKELY(!str.ptr)) goto oops; if (HAWK_UNLIKELY(!str.ptr)) goto oops;
@ -1016,6 +1045,15 @@ int hawk_fnc_tolower (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
switch (HAWK_RTX_GETVALTYPE(rtx, a0)) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, a0);
tmp = hawk_to_bch_lower(tmp);
r = hawk_rtx_makebchrval(rtx, tmp);
if (HAWK_UNLIKELY(!r)) return -1;
break;
}
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
{ {
hawk_bcs_t str; hawk_bcs_t str;
@ -1033,7 +1071,7 @@ int hawk_fnc_tolower (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
tmp = hawk_to_bch_lower(tmp); tmp = hawk_to_ooch_lower(tmp);
r = hawk_rtx_makecharval(rtx, tmp); r = hawk_rtx_makecharval(rtx, tmp);
if (HAWK_UNLIKELY(!r)) return -1; if (HAWK_UNLIKELY(!r)) return -1;
break; break;
@ -1066,6 +1104,15 @@ int hawk_fnc_toupper (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
switch (HAWK_RTX_GETVALTYPE(rtx, a0)) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
tmp = hawk_to_bch_upper(tmp);
r = hawk_rtx_makebchrval(rtx, tmp);
if (HAWK_UNLIKELY(!r)) return -1;
break;
}
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
{ {
hawk_bcs_t str; hawk_bcs_t str;
@ -1083,7 +1130,7 @@ int hawk_fnc_toupper (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
tmp = hawk_to_bch_upper(tmp); tmp = hawk_to_ooch_upper(tmp);
r = hawk_rtx_makecharval(rtx, tmp); r = hawk_rtx_makecharval(rtx, tmp);
if (HAWK_UNLIKELY(!r)) return -1; if (HAWK_UNLIKELY(!r)) return -1;
break; break;
@ -1373,23 +1420,26 @@ static int __substitute (hawk_rtx_t* rtx, hawk_oow_t max_count)
{ {
r2 = hawk_rtx_getrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2)); r2 = hawk_rtx_getrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2));
if (HAWK_RTX_GETVALTYPE(rtx, r2) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, r2))
{ {
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
s2.ptr = hawk_rtx_getvalbcstr(rtx, r2, &s2.len); s2.ptr = hawk_rtx_getvalbcstr(rtx, r2, &s2.len);
s2_free = 2; s2_free = 2;
/* the second argument - substitute */ /* the second argument - substitute */
s1.ptr = hawk_rtx_getvalbcstr(rtx, a1, &s1.len); s1.ptr = hawk_rtx_getvalbcstr(rtx, a1, &s1.len);
s1_free = 2; s1_free = 2;
} break;
else
{ default:
s2.ptr = hawk_rtx_getvaloocstr(rtx, r2, &s2.len); s2.ptr = hawk_rtx_getvaloocstr(rtx, r2, &s2.len);
s2_free = 1; s2_free = 1;
/* the second argument - substitute */ /* the second argument - substitute */
s1.ptr = hawk_rtx_getvaloocstr(rtx, a1, &s1.len); s1.ptr = hawk_rtx_getvaloocstr(rtx, a1, &s1.len);
s1_free = 1; s1_free = 1;
break;
} }
} }
@ -1738,7 +1788,10 @@ int hawk_fnc_sprintf (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
HAWK_ASSERT (nargs > 0); HAWK_ASSERT (nargs > 0);
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_becs_t fbu; hawk_becs_t fbu;
int fbu_inited = 0; int fbu_inited = 0;
@ -1766,7 +1819,8 @@ int hawk_fnc_sprintf (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
if (fbu_inited) hawk_becs_fini (&fbu); if (fbu_inited) hawk_becs_fini (&fbu);
return -1; return -1;
} }
else
default:
{ {
hawk_ooecs_t fbu; hawk_ooecs_t fbu;
int fbu_inited = 0; int fbu_inited = 0;
@ -1794,6 +1848,7 @@ int hawk_fnc_sprintf (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
if (fbu_inited) hawk_ooecs_fini (&fbu); if (fbu_inited) hawk_ooecs_fini (&fbu);
return -1; return -1;
} }
}
} }
static int fnc_int (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) static int fnc_int (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)

View File

@ -1021,7 +1021,6 @@ enum hawk_errnum_t
HAWK_EIONMEM, /**< I/O name empty */ HAWK_EIONMEM, /**< I/O name empty */
HAWK_EIONMNL, /**< I/O name containing '\\0' */ HAWK_EIONMNL, /**< I/O name containing '\\0' */
HAWK_EFMTARG, /**< not sufficient arguments to formatting sequence */ HAWK_EFMTARG, /**< not sufficient arguments to formatting sequence */
HAWK_EFMTCNV, /**< recursion detected in format conversion */
HAWK_ECONVFMTCHR, /**< invalid character in CONVFMT */ HAWK_ECONVFMTCHR, /**< invalid character in CONVFMT */
HAWK_EOFMTCHR, /**< invalid character in OFMT */ HAWK_EOFMTCHR, /**< invalid character in OFMT */

View File

@ -381,7 +381,13 @@ struct hawk_chain_t
typedef struct hawk_ctos_b_t hawk_ctos_b_t; typedef struct hawk_ctos_b_t hawk_ctos_b_t;
struct hawk_ctos_b_t struct hawk_ctos_b_t
{ {
hawk_ooch_t c[2]; hawk_oochu_t c[2]; /* ensure the unsigned type to hold not only a character but also a free slot index */
};
typedef struct hawk_bctos_b_t hawk_bctos_b_t;
struct hawk_bctos_b_t
{
hawk_bchu_t c[2]; /* ensure the unsigned type to hold not only a byte character but also a free slot index */
}; };
struct hawk_rtx_t struct hawk_rtx_t
@ -427,6 +433,12 @@ struct hawk_rtx_t
hawk_oow_t fi; hawk_oow_t fi;
} ctos; /* char/nil to string conversion */ } ctos; /* char/nil to string conversion */
struct
{
hawk_bctos_b_t b[256];
hawk_oow_t fi;
} bctos;
struct struct
{ {
/* lists of values under gc management */ /* lists of values under gc management */

View File

@ -37,7 +37,10 @@ static int fnc_normspace (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
hawk_val_t* a0; hawk_val_t* a0;
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str0; hawk_bch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
@ -47,8 +50,10 @@ static int fnc_normspace (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
len0 = hawk_compact_bchars(str0, len0); len0 = hawk_compact_bchars(str0, len0);
retv = hawk_rtx_makembsvalwithbchars(rtx, str0, len0); retv = hawk_rtx_makembsvalwithbchars(rtx, str0, len0);
hawk_rtx_freemem (rtx, str0); hawk_rtx_freemem (rtx, str0);
break;
} }
else
default:
{ {
hawk_ooch_t* str0; hawk_ooch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
@ -59,8 +64,9 @@ static int fnc_normspace (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
retv = hawk_rtx_makestrvalwithoochars(rtx, str0, len0); retv = hawk_rtx_makestrvalwithoochars(rtx, str0, len0);
hawk_rtx_freemem (rtx, str0); hawk_rtx_freemem (rtx, str0);
} }
}
if (!retv) return -1; if (HAWK_UNLIKELY(!retv)) return -1;
hawk_rtx_setretval (rtx, retv); hawk_rtx_setretval (rtx, retv);
return 0; return 0;
@ -73,31 +79,39 @@ static int trim (hawk_rtx_t* rtx, int flags)
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bcs_t path; hawk_bcs_t path;
hawk_bch_t* npath; hawk_bch_t* npath;
path.ptr = ((hawk_val_mbs_t*)a0)->val.ptr; path.ptr = hawk_rtx_getvalbcstr(rtx, a0, &path.len);
path.len = ((hawk_val_mbs_t*)a0)->val.len; if (HAWK_UNLIKELY(!path.ptr)) return -1;
npath = hawk_trim_bchars(path.ptr, &path.len, flags); npath = hawk_trim_bchars(path.ptr, &path.len, flags);
retv = hawk_rtx_makembsvalwithbchars(rtx, npath, path.len); retv = hawk_rtx_makembsvalwithbchars(rtx, npath, path.len);
hawk_rtx_freevalbcstr (rtx, a0, path.ptr);
break;
} }
else
default:
{ {
hawk_oocs_t path; hawk_oocs_t path;
hawk_ooch_t* npath; hawk_ooch_t* npath;
path.ptr = hawk_rtx_getvaloocstr(rtx, a0, &path.len); path.ptr = hawk_rtx_getvaloocstr(rtx, a0, &path.len);
if (!path.ptr) return -1; if (HAWK_UNLIKELY(!path.ptr)) return -1;
/* because hawk_strxtrmx() returns the pointer and the length without /* because hawk_trim_oochars() returns the pointer and the length without
* affecting the string given, it's safe to pass the original value. * affecting the string given, it's safe to pass the original value.
* hawk_rtx_getvaloocstr() doesn't duplicate the value if it's of * hawk_rtx_getvaloocstr() doesn't duplicate the value if it's of
* the string type. */ * the string type. */
npath = hawk_trim_oochars(path.ptr, &path.len, flags); npath = hawk_trim_oochars(path.ptr, &path.len, flags);
retv = hawk_rtx_makestrvalwithoochars(rtx, npath, path.len); retv = hawk_rtx_makestrvalwithoochars(rtx, npath, path.len);
hawk_rtx_freevaloocstr (rtx, a0, path.ptr); hawk_rtx_freevaloocstr (rtx, a0, path.ptr);
break;
}
} }
if (!retv) return -1; if (HAWK_UNLIKELY(!retv)) return -1;
hawk_rtx_setretval (rtx, retv); hawk_rtx_setretval (rtx, retv);
return 0; return 0;
} }
@ -106,6 +120,8 @@ static int trim (hawk_rtx_t* rtx, int flags)
static int fnc_trim (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) static int fnc_trim (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
/* str::trim(" test string ");
str::trim(" test string ", str::TRIM_PAC_SPACES); */
if (hawk_rtx_getnargs(rtx) >= 2) if (hawk_rtx_getnargs(rtx) >= 2)
{ {
hawk_int_t iv; hawk_int_t iv;
@ -131,13 +147,16 @@ static int is_class (hawk_rtx_t* rtx, hawk_ooch_prop_t ctype)
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str0; hawk_bch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
str0 = ((hawk_val_mbs_t*)a0)->val.ptr; str0 = hawk_rtx_getvalbcstr(rtx, a0, &len0);
len0 = ((hawk_val_mbs_t*)a0)->val.len; if (HAWK_UNLIKELY(!str0)) return -1;
if (len0 <= 0) tmp = 0; if (len0 <= 0) tmp = 0;
else else
@ -154,14 +173,18 @@ static int is_class (hawk_rtx_t* rtx, hawk_ooch_prop_t ctype)
} }
while (len0 > 0); while (len0 > 0);
} }
hawk_rtx_freevalbcstr (rtx, a0, str0);
break;
} }
else
default:
{ {
hawk_ooch_t* str0; hawk_ooch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (!str0) return -1; if (HAWK_UNLIKELY(!str0)) return -1;
if (len0 <= 0) tmp = 0; if (len0 <= 0) tmp = 0;
else else
@ -179,10 +202,12 @@ static int is_class (hawk_rtx_t* rtx, hawk_ooch_prop_t ctype)
while (len0 > 0); while (len0 > 0);
} }
hawk_rtx_freevaloocstr (rtx, a0, str0); hawk_rtx_freevaloocstr (rtx, a0, str0);
break;
}
} }
a0 = hawk_rtx_makeintval (rtx, tmp); a0 = hawk_rtx_makeintval (rtx, tmp);
if (!a0) return -1; if (HAWK_UNLIKELY(!a0)) return -1;
hawk_rtx_setretval (rtx, a0); hawk_rtx_setretval (rtx, a0);
return 0; return 0;
@ -248,6 +273,59 @@ static int fnc_isxdigit (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
return is_class(rtx, HAWK_OOCH_PROP_XDIGIT); return is_class(rtx, HAWK_OOCH_PROP_XDIGIT);
} }
static int fnc_frombcharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
/* create a string from a series of character codes.
* create a character from a single character code.
* - str::fromcharcode(65) for 'A'
* - str::fromcharcode(65, 66, 67) for "ABC" */
/* TODO: how to support byte string? */
hawk_val_t* retv;
hawk_oow_t nargs, i;
hawk_bchu_t* ptr0; /* to guarantee the unsigned code conversion */
nargs = hawk_rtx_getnargs(rtx);
if (nargs == 1)
{
hawk_val_t* a0;
hawk_int_t cc;
a0 = hawk_rtx_getarg(rtx, 0);
if (hawk_rtx_valtoint(rtx, a0, &cc) <= -1) return -1;
retv = hawk_rtx_makecharval(rtx, (hawk_ooch_t)cc);
if (HAWK_UNLIKELY(!retv)) return -1;
}
else
{
retv = hawk_rtx_makembsvalwithbchars(rtx, HAWK_NULL, nargs);
if (HAWK_UNLIKELY(!retv)) return -1;
ptr0 = (hawk_bchu_t*)((hawk_val_mbs_t*)retv)->val.ptr;
for (i = 0; i < nargs; i++)
{
hawk_val_t* a0;
hawk_int_t cc;
a0 = hawk_rtx_getarg(rtx, i);
if (hawk_rtx_valtoint(rtx, a0, &cc) <= -1)
{
hawk_rtx_freeval (rtx, retv, 0);
return -1;
}
ptr0[i] = cc;
}
}
hawk_rtx_setretval (rtx, retv);
return 0;
}
static int fnc_fromcharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) static int fnc_fromcharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
/* create a string from a series of character codes. /* create a string from a series of character codes.
@ -255,6 +333,8 @@ static int fnc_fromcharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
* - str::fromcharcode(65) for 'A' * - str::fromcharcode(65) for 'A'
* - str::fromcharcode(65, 66, 67) for "ABC" */ * - str::fromcharcode(65, 66, 67) for "ABC" */
/* TODO: how to support byte string? */
hawk_val_t* retv; hawk_val_t* retv;
hawk_oow_t nargs, i; hawk_oow_t nargs, i;
hawk_oochu_t* ptr0; /* to guarantee the unsigned code conversion */ hawk_oochu_t* ptr0; /* to guarantee the unsigned code conversion */
@ -318,49 +398,50 @@ static int fnc_tocharcode (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
pos--; /* 1 based indexing. range check to be done before accessing below */ pos--; /* 1 based indexing. range check to be done before accessing below */
} }
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str0; hawk_bch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
str0 = ((hawk_val_mbs_t*)a0)->val.ptr; str0 = hawk_rtx_getvalbcstr(rtx, a0, &len0);
len0 = ((hawk_val_mbs_t*)a0)->val.len; if (HAWK_UNLIKELY(!str0)) return -1;
if (pos >= 0 && pos < len0) if (pos >= 0 && pos < len0)
{ {
#if defined(HAWK_OOCH_IS_BCH)
/* typecasting in case hawk_bch_t is signed */ /* typecasting in case hawk_bch_t is signed */
iv = (unsigned char)str0[pos]; iv = (hawk_bchu_t)str0[pos];
#else
iv = str0[pos];
#endif
} }
hawk_rtx_freevalbcstr(rtx, a0, str0);
break;
} }
else
default:
{ {
hawk_ooch_t* str0; hawk_ooch_t* str0;
hawk_oow_t len0; hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (!str0) return -1; if (HAWK_UNLIKELY(!str0)) return -1;
if (pos >= 0 && pos < len0) if (pos >= 0 && pos < len0)
{ {
#if defined(HAWK_OOCH_IS_BCH)
/* typecasting in case hawk_bch_t is signed */ /* typecasting in case hawk_bch_t is signed */
iv = (unsigned char)str0[pos]; iv = (hawk_oochu_t)str0[pos];
#else
iv = str0[pos];
#endif
} }
hawk_rtx_freevaloocstr(rtx, a0, str0); hawk_rtx_freevaloocstr(rtx, a0, str0);
break;
}
} }
if (iv >= 0) if (iv >= 0)
{ {
retv = hawk_rtx_makeintval(rtx, iv); retv = hawk_rtx_makeintval(rtx, iv);
if (!retv) return -1; if (HAWK_UNLIKELY(!retv)) return -1;
hawk_rtx_setretval (rtx, retv); hawk_rtx_setretval (rtx, retv);
} }
@ -498,6 +579,22 @@ static int fnc_tonum (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
switch (HAWK_RTX_GETVALTYPE(rtx, a0)) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
case HAWK_VAL_BCHR:
{
/* if the value is known to be a string, it supports the optional
* base parameter */
hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1);
hawk_int_t base;
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, a0);
if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1;
rx = hawk_bchars_to_num(
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base),
&tmp, 1, &lv, &rv
);
break;
}
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
{ {
/* if the value is known to be a byte string, it supports the optional /* if the value is known to be a byte string, it supports the optional
@ -595,22 +692,27 @@ static int fnc_subchar (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
lindex = lindex - 1; lindex = lindex - 1;
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bch_t* str; hawk_bch_t* str;
hawk_oow_t len; hawk_oow_t len;
str = ((hawk_val_mbs_t*)a0)->val.ptr; str = hawk_rtx_getvalbcstr(rtx, a0, &len);
len = ((hawk_val_mbs_t*)a0)->val.len; if (!str) return -1;
if (lindex >= 0 && lindex < (hawk_int_t)len) if (lindex >= 0 && lindex < (hawk_int_t)len)
r = hawk_rtx_makebchrval(rtx, str[lindex]); r = hawk_rtx_makebchrval(rtx, str[lindex]);
else else
r = hawk_rtx_makenilval(rtx); r = hawk_rtx_makenilval(rtx);
if (HAWK_UNLIKELY(!r)) return -1; hawk_rtx_freevalbcstr (rtx, a0, str);
break;
} }
else
default:
{ {
hawk_ooch_t* str; hawk_ooch_t* str;
hawk_oow_t len; hawk_oow_t len;
@ -624,9 +726,11 @@ static int fnc_subchar (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
r = hawk_rtx_makenilval(rtx); r = hawk_rtx_makenilval(rtx);
hawk_rtx_freevaloocstr (rtx, a0, str); hawk_rtx_freevaloocstr (rtx, a0, str);
if (HAWK_UNLIKELY(!r)) return -1; break;
}
} }
if (HAWK_UNLIKELY(!r)) return -1;
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
return 0; return 0;
} }
@ -650,6 +754,7 @@ struct inttab_t
static fnctab_t fnctab[] = static fnctab_t fnctab[] =
{ {
/* keep this table sorted for binary search in query(). */ /* keep this table sorted for binary search in query(). */
{ HAWK_T("frombcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_frombcharcode, 0 } },
{ HAWK_T("fromcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_fromcharcode, 0 } }, { HAWK_T("fromcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_fromcharcode, 0 } },
{ HAWK_T("frommbs"), { { 1, 2, HAWK_NULL }, fnc_frommbs, 0 } }, { HAWK_T("frommbs"), { { 1, 2, HAWK_NULL }, fnc_frommbs, 0 } },
{ HAWK_T("gsub"), { { 2, 3, HAWK_T("xvr")}, hawk_fnc_gsub, 0 } }, { HAWK_T("gsub"), { { 2, 3, HAWK_T("xvr")}, hawk_fnc_gsub, 0 } },

View File

@ -4666,7 +4666,7 @@ static hawk_nde_t* parse_primary_char (hawk_t* hawk, const hawk_loc_t* xloc)
{ {
hawk_nde_char_t* nde; hawk_nde_char_t* nde;
nde = (hawk_nde_char_t*)hawk_callocmem (hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_char_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde)) if (HAWK_UNLIKELY(!nde))
{ {
ADJERR_LOC (hawk, xloc); ADJERR_LOC (hawk, xloc);
@ -4691,7 +4691,7 @@ static hawk_nde_t* parse_primary_bchr (hawk_t* hawk, const hawk_loc_t* xloc)
{ {
hawk_nde_bchr_t* nde; hawk_nde_bchr_t* nde;
nde = (hawk_nde_bchr_t*)hawk_callocmem (hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_bchr_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (HAWK_UNLIKELY(!nde)) if (HAWK_UNLIKELY(!nde))
{ {
ADJERR_LOC (hawk, xloc); ADJERR_LOC (hawk, xloc);
@ -4717,7 +4717,7 @@ static hawk_nde_t* parse_primary_int (hawk_t* hawk, const hawk_loc_t* xloc)
hawk_nde_int_t* nde; hawk_nde_int_t* nde;
/* create the node for the literal */ /* create the node for the literal */
nde = (hawk_nde_int_t*)new_int_node ( nde = (hawk_nde_int_t*)new_int_node(
hawk, hawk,
hawk_oochars_to_int (HAWK_OOECS_PTR(hawk->tok.name), HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOCHARS_TO_INT_MAKE_OPTION(0, 0, 0), HAWK_NULL, HAWK_NULL), hawk_oochars_to_int (HAWK_OOECS_PTR(hawk->tok.name), HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOCHARS_TO_INT_MAKE_OPTION(0, 0, 0), HAWK_NULL, HAWK_NULL),
xloc xloc
@ -4801,7 +4801,7 @@ static hawk_nde_t* parse_primary_mbs (hawk_t* hawk, const hawk_loc_t* xloc)
hawk_nde_mbs_t* nde; hawk_nde_mbs_t* nde;
nde = (hawk_nde_mbs_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_mbs_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (nde == HAWK_NULL) if (HAWK_UNLIKELY(!nde))
{ {
ADJERR_LOC (hawk, xloc); ADJERR_LOC (hawk, xloc);
return HAWK_NULL; return HAWK_NULL;
@ -5212,7 +5212,7 @@ static hawk_nde_t* parse_primary (hawk_t* hawk, const hawk_loc_t* xloc)
hawk_loc_t ploc; hawk_loc_t ploc;
left = parse_primary_nopipe(hawk, xloc); left = parse_primary_nopipe(hawk, xloc);
if (left == HAWK_NULL) goto oops; if (!left) goto oops;
/* handle the piping part */ /* handle the piping part */
do do
@ -5288,7 +5288,7 @@ static hawk_nde_t* parse_primary (hawk_t* hawk, const hawk_loc_t* xloc)
novar: novar:
nde = (hawk_nde_getline_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde)); nde = (hawk_nde_getline_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
if (nde == HAWK_NULL) if (HAWK_UNLIKELY(!nde))
{ {
ADJERR_LOC (hawk, xloc); ADJERR_LOC (hawk, xloc);
goto oops; goto oops;
@ -7243,7 +7243,7 @@ static int deparse (hawk_t* hawk)
*/ */
} }
if (flush_out (hawk) <= -1) EXIT_DEPARSE (); if (flush_out(hawk) <= -1) EXIT_DEPARSE ();
exit_deparse: exit_deparse:
if (hawk->sio.outf(hawk, HAWK_SIO_CMD_CLOSE, &hawk->sio.arg, HAWK_NULL, 0) != 0 && n == 0) n = -1; if (hawk->sio.outf(hawk, HAWK_SIO_CMD_CLOSE, &hawk->sio.arg, HAWK_NULL, 0) != 0 && n == 0) n = -1;

View File

@ -996,9 +996,21 @@ int hawk_rtx_writeioval (hawk_rtx_t* rtx, int out_type, const hawk_ooch_t* name,
switch (vtype) switch (vtype)
{ {
case HAWK_VAL_CHAR:
{
hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v);
return hawk_rtx_writeiostr(rtx, out_type, name, &tmp, 1);
}
case HAWK_VAL_STR: case HAWK_VAL_STR:
return hawk_rtx_writeiostr(rtx, out_type, name, ((hawk_val_str_t*)v)->val.ptr, ((hawk_val_str_t*)v)->val.len); return hawk_rtx_writeiostr(rtx, out_type, name, ((hawk_val_str_t*)v)->val.ptr, ((hawk_val_str_t*)v)->val.len);
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
return hawk_rtx_writeiobytes(rtx, out_type, name, &tmp, 1);
}
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
return hawk_rtx_writeiobytes(rtx, out_type, name, ((hawk_val_mbs_t*)v)->val.ptr, ((hawk_val_mbs_t*)v)->val.len); return hawk_rtx_writeiobytes(rtx, out_type, name, ((hawk_val_mbs_t*)v)->val.ptr, ((hawk_val_mbs_t*)v)->val.len);
@ -1006,7 +1018,6 @@ int hawk_rtx_writeioval (hawk_rtx_t* rtx, int out_type, const hawk_ooch_t* name,
{ {
hawk_rtx_valtostr_out_t out; hawk_rtx_valtostr_out_t out;
int n; int n;
out.type = HAWK_RTX_VALTOSTR_CPLDUP | HAWK_RTX_VALTOSTR_PRINT; out.type = HAWK_RTX_VALTOSTR_CPLDUP | HAWK_RTX_VALTOSTR_PRINT;
if (hawk_rtx_valtostr(rtx, v, &out) <= -1) return -1; if (hawk_rtx_valtostr(rtx, v, &out) <= -1) return -1;
n = hawk_rtx_writeiostr(rtx, out_type, name, out.u.cpldup.ptr, out.u.cpldup.len); n = hawk_rtx_writeiostr(rtx, out_type, name, out.u.cpldup.ptr, out.u.cpldup.len);

View File

@ -897,6 +897,16 @@ hawk_rtx_t* hawk_rtx_open (hawk_t* hawk, hawk_oow_t xtnsize, hawk_rio_cbs_t* rio
/* rtx->ctos.b[0] is not used as the free index of 0 indicates the end of the list. /* rtx->ctos.b[0] is not used as the free index of 0 indicates the end of the list.
* see hawk_rtx_getvaloocstr(). */ * see hawk_rtx_getvaloocstr(). */
/* chain the bctos slots */
rtx->bctos.fi = HAWK_COUNTOF(rtx->bctos.b) - 1;
for (i = HAWK_COUNTOF(rtx->bctos.b); i > 1;)
{
--i;
rtx->bctos.b[i].c[0] = i - 1;
}
/* rtx->bctos.b[0] is not used as the free index of 0 indicates the end of the list.
* see hawk_rtx_getvaloocstr(). */
return rtx; return rtx;
} }
@ -5282,7 +5292,6 @@ static HAWK_INLINE int __cmp_mbs_bchr (hawk_rtx_t* rtx, hawk_val_t* left, hawk_v
return -n; return -n;
} }
static HAWK_INLINE int __cmp_mbs_int (hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right, cmp_op_t op_hint) static HAWK_INLINE int __cmp_mbs_int (hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right, cmp_op_t op_hint)
{ {
int n; int n;
@ -5612,11 +5621,19 @@ static int teq_val (hawk_rtx_t* rtx, hawk_val_t* left, hawk_val_t* right)
break; break;
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
n = (HAWK_RTX_GETCHARFROMVAL (rtx, left) == HAWK_RTX_GETCHARFROMVAL (rtx, right)); /* since a CHAR value is only reprensented in the value pointer,
* n is guaranteed to be 0 here. so the following check isn't needed */
n = (HAWK_RTX_GETCHARFROMVAL(rtx, left) == HAWK_RTX_GETCHARFROMVAL(rtx, right));
break;
case HAWK_VAL_BCHR:
/* since a BCHR value is only reprensented in the value pointer,
* n is guaranteed to be 0 here. so the following check isn't needed */
n = (HAWK_RTX_GETBCHRFROMVAL(rtx, left) == HAWK_RTX_GETBCHRFROMVAL(rtx, right));
break; break;
case HAWK_VAL_INT: case HAWK_VAL_INT:
n = (HAWK_RTX_GETINTFROMVAL (rtx, left) == HAWK_RTX_GETINTFROMVAL (rtx, right)); n = (HAWK_RTX_GETINTFROMVAL(rtx, left) == HAWK_RTX_GETINTFROMVAL(rtx, right));
break; break;
case HAWK_VAL_FLT: case HAWK_VAL_FLT:
@ -6054,7 +6071,10 @@ static hawk_val_t* eval_binop_concat (hawk_rtx_t* rtx, hawk_val_t* left, hawk_va
{ {
hawk_val_t* res; hawk_val_t* res;
if (HAWK_RTX_GETVALTYPE(rtx, left) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, left))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
{ {
hawk_bcs_t l, r; hawk_bcs_t l, r;
@ -6072,10 +6092,11 @@ static hawk_val_t* eval_binop_concat (hawk_rtx_t* rtx, hawk_val_t* left, hawk_va
hawk_rtx_freevalbcstr (rtx, right, r.ptr); hawk_rtx_freevalbcstr (rtx, right, r.ptr);
hawk_rtx_freevalbcstr (rtx, left, l.ptr); hawk_rtx_freevalbcstr (rtx, left, l.ptr);
break;
} }
else
{
default:
{
hawk_oocs_t l, r; hawk_oocs_t l, r;
l.ptr = hawk_rtx_getvaloocstr(rtx, left, &l.len); l.ptr = hawk_rtx_getvaloocstr(rtx, left, &l.len);
@ -6092,6 +6113,8 @@ static hawk_val_t* eval_binop_concat (hawk_rtx_t* rtx, hawk_val_t* left, hawk_va
hawk_rtx_freevaloocstr (rtx, right, r.ptr); hawk_rtx_freevaloocstr (rtx, right, r.ptr);
hawk_rtx_freevaloocstr (rtx, left, l.ptr); hawk_rtx_freevaloocstr (rtx, left, l.ptr);
break;
}
} }
return res; return res;
@ -8141,8 +8164,9 @@ hawk_ooch_t* hawk_rtx_format (
if (nargs_on_stack == (hawk_oow_t)-1) if (nargs_on_stack == (hawk_oow_t)-1)
{ {
/* dirty hack to support a single value argument instead of a tree node */
val = (hawk_val_t*)args; val = (hawk_val_t*)args;
nargs_on_stack = 2; nargs_on_stack = 2; /* indicate 2 arguments of a formatting specifier and the given value */
} }
else else
{ {
@ -8227,7 +8251,7 @@ wp_mod_main:
hawk_val_t* v; hawk_val_t* v;
int n; int n;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8284,7 +8308,7 @@ wp_mod_main:
FMT_STR(rtx->format.tmp.ptr, n); FMT_STR(rtx->format.tmp.ptr, n);
if (args == HAWK_NULL || val != HAWK_NULL) stack_arg_idx++; if (!args || val) stack_arg_idx++;
else args = args->next; else args = args->next;
i++; i++;
} }
@ -8334,7 +8358,7 @@ wp_mod_main:
hawk_ooch_t fmt_fill = HAWK_T('\0'); hawk_ooch_t fmt_fill = HAWK_T('\0');
const hawk_ooch_t* fmt_prefix = HAWK_NULL; const hawk_ooch_t* fmt_prefix = HAWK_NULL;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8345,7 +8369,7 @@ wp_mod_main:
} }
else else
{ {
if (val != HAWK_NULL) if (val)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8534,19 +8558,12 @@ wp_mod_main:
fmt[i] == HAWK_T('g') || fmt[i] == HAWK_T('G') || fmt[i] == HAWK_T('g') || fmt[i] == HAWK_T('G') ||
fmt[i] == HAWK_T('f')) fmt[i] == HAWK_T('f'))
{ {
hawk_val_t* v; hawk_val_t* v;
hawk_flt_t r; hawk_flt_t r;
int n; int n;
#if defined(HAWK_USE_FLTMAX) if (!args)
/*FMT_CHAR (HAWK_T('j'));*/
FMT_STR (HAWK_T("jj"), 2); /* see fmt.c for info on jj */
#else
FMT_CHAR (HAWK_T('z'));
#endif
FMT_CHAR (fmt[i]);
if (args == HAWK_NULL)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8557,7 +8574,7 @@ wp_mod_main:
} }
else else
{ {
if (val != HAWK_NULL) if (val) /* nargs_on_stack == (hawk_oow_t)-1 */
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8579,9 +8596,14 @@ wp_mod_main:
if (n <= -1) return HAWK_NULL; if (n <= -1) return HAWK_NULL;
#if defined(HAWK_USE_FLTMAX) #if defined(HAWK_USE_FLTMAX)
/*FMT_CHAR (HAWK_T('j'));*/
FMT_STR (HAWK_T("jj"), 2); /* see fmt.c for info on jj */
FMT_CHAR (fmt[i]);
/*if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/ /*if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL; if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
#else #else
FMT_CHAR (HAWK_T('z'));
FMT_CHAR (fmt[i]);
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL; if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
#endif #endif
} }
@ -8592,18 +8614,18 @@ wp_mod_main:
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype; hawk_val_type_t vtype;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EFMTARG); hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EFMTARG);
return HAWK_NULL; return HAWK_NULL;
} }
v = hawk_rtx_getarg (rtx, stack_arg_idx); v = hawk_rtx_getarg(rtx, stack_arg_idx);
} }
else else
{ {
if (val != HAWK_NULL) if (val)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8633,6 +8655,11 @@ wp_mod_main:
ch_len = 1; ch_len = 1;
break; break;
case HAWK_VAL_BCHR:
ch = (hawk_ooch_t)HAWK_RTX_GETBCHRFROMVAL(rtx, v);
ch_len = 1;
break;
case HAWK_VAL_INT: 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; ch_len = 1;
@ -8708,14 +8735,9 @@ wp_mod_main:
} }
else if (fmt[i] == HAWK_T('s') || fmt[i] == HAWK_T('k') || fmt[i] == HAWK_T('K')) else if (fmt[i] == HAWK_T('s') || fmt[i] == HAWK_T('k') || fmt[i] == HAWK_T('K'))
{ {
hawk_ooch_t* str_ptr, * str_free = HAWK_NULL;
hawk_oow_t str_len;
hawk_int_t k;
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype;
int bytetostr_flagged_radix = 16;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -8742,6 +8764,50 @@ wp_mod_main:
} }
} }
if (val)
{
/* val_flt_to_str() in val.c calls hawk_rtx_format() with nargs_on_stack of (hawk_oow_t)-1 and the actual value.
* the actual value is assigned to 'val' at the beginning of this function.
*
* the following code can drive here.
* BEGIN { CONVFMT="%s"; a=98.76 ""; }
*
* when the first attempt to convert 98.76 to a textual form invokes this function with %s and 98.76.
* it comes to this part because the format specifier is 's'. since the floating-point type is not
* specially handled, hawk_rtx_valtooocstrdup() is called below. it calls val_flt_to_str() again,
* which eventually creates recursion and stack depletion.
*
* assuming only val_flt_to_str() calls it this way, i must convert the floating point number
* to text in a rather crude way without calling hawk_rtx_valtooocstrdup().
*/
hawk_flt_t r;
int n;
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, val) == HAWK_VAL_FLT);
hawk_rtx_refupval (rtx, v);
n = hawk_rtx_valtoflt(rtx, v, &r);
hawk_rtx_refdownval (rtx, v);
if (n <= -1) return HAWK_NULL;
/* format the value as if '%g' is given */
#if defined(HAWK_USE_FLTMAX)
FMT_STR (HAWK_T("jjg"), 3); /* see fmt.c for info on jj */
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
#else
FMT_STR (HAWK_T("zg"), 2);
if (hawk_ooecs_fcat(out, HAWK_OOECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
#endif
}
else
{
hawk_ooch_t* str_ptr, * str_free = HAWK_NULL, ooch_tmp;
hawk_bch_t bch_tmp;
hawk_oow_t str_len;
hawk_int_t k;
hawk_val_type_t vtype;
int bytetostr_flagged_radix = 16;
hawk_rtx_refupval (rtx, v); hawk_rtx_refupval (rtx, v);
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_RTX_GETVALTYPE(rtx, v);
@ -8752,34 +8818,43 @@ wp_mod_main:
str_len = 0; str_len = 0;
break; break;
case HAWK_VAL_CHAR:
ooch_tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v);
str_ptr = &ooch_tmp;
str_len = 1;
break;
case HAWK_VAL_STR: case HAWK_VAL_STR:
str_ptr = ((hawk_val_str_t*)v)->val.ptr; str_ptr = ((hawk_val_str_t*)v)->val.ptr;
str_len = ((hawk_val_str_t*)v)->val.len; str_len = ((hawk_val_str_t*)v)->val.len;
break; break;
case HAWK_VAL_BCHR:
#if defined(HAWK_OOCH_IS_BCH)
ooch_tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
str_ptr = &ooch_tmp;
str_len = 1;
#else
if (fmt[i] == HAWK_T('s')) goto duplicate;
bch_tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
str_ptr = (hawk_ooch_t*)&bch_tmp;
str_len = 1;
#endif
break;
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
#if defined(HAWK_OOCH_IS_BCH) #if defined(HAWK_OOCH_IS_BCH)
str_ptr = ((hawk_val_mbs_t*)v)->val.ptr; str_ptr = ((hawk_val_mbs_t*)v)->val.ptr;
str_len = ((hawk_val_mbs_t*)v)->val.len; str_len = ((hawk_val_mbs_t*)v)->val.len;
break;
#else #else
if (fmt[i] != HAWK_T('s')) if (fmt[i] == HAWK_T('s')) goto duplicate;
{
str_ptr = (hawk_ooch_t*)((hawk_val_mbs_t*)v)->val.ptr; str_ptr = (hawk_ooch_t*)((hawk_val_mbs_t*)v)->val.ptr;
str_len = ((hawk_val_mbs_t*)v)->val.len; str_len = ((hawk_val_mbs_t*)v)->val.len;
break;
}
#endif #endif
break;
default: default:
{ duplicate:
if (v == val)
{
hawk_rtx_refdownval (rtx, v);
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EFMTCNV);
return HAWK_NULL;
}
str_ptr = hawk_rtx_valtooocstrdup(rtx, v, &str_len); str_ptr = hawk_rtx_valtooocstrdup(rtx, v, &str_len);
if (!str_ptr) if (!str_ptr)
{ {
@ -8789,7 +8864,7 @@ wp_mod_main:
str_free = str_ptr; str_free = str_ptr;
break; break;
}
} }
if (wp_idx != WP_PRECISION || wp[WP_PRECISION] <= -1 || wp[WP_PRECISION] > (hawk_int_t)str_len) if (wp_idx != WP_PRECISION || wp[WP_PRECISION] <= -1 || wp[WP_PRECISION] > (hawk_int_t)str_len)
@ -8823,7 +8898,7 @@ wp_mod_main:
#if defined(HAWK_OOCH_IS_BCH) #if defined(HAWK_OOCH_IS_BCH)
curc = str_ptr[k]; curc = str_ptr[k];
#else #else
if (vtype == HAWK_VAL_MBS && fmt[i] != HAWK_T('s')) if ((vtype == HAWK_VAL_MBS || vtype == HAWK_VAL_BCHR) && fmt[i] != HAWK_T('s'))
curc = (hawk_uint8_t)((hawk_bch_t*)str_ptr)[k]; curc = (hawk_uint8_t)((hawk_bch_t*)str_ptr)[k];
else curc = str_ptr[k]; else curc = str_ptr[k];
#endif #endif
@ -8890,6 +8965,7 @@ wp_mod_main:
hawk_rtx_refdownval (rtx, v); hawk_rtx_refdownval (rtx, v);
} }
}
else else
{ {
if (fmt[i] != HAWK_T('%')) OUT_STR (HAWK_OOECS_PTR(fbu), HAWK_OOECS_LEN(fbu)); if (fmt[i] != HAWK_T('%')) OUT_STR (HAWK_OOECS_PTR(fbu), HAWK_OOECS_LEN(fbu));
@ -8897,7 +8973,7 @@ wp_mod_main:
goto skip_taking_arg; goto skip_taking_arg;
} }
if (args == HAWK_NULL || val != HAWK_NULL) stack_arg_idx++; if (!args || val) stack_arg_idx++;
else args = args->next; else args = args->next;
skip_taking_arg: skip_taking_arg:
hawk_ooecs_clear (fbu); hawk_ooecs_clear (fbu);
@ -8937,7 +9013,7 @@ hawk_bch_t* hawk_rtx_formatmbs (
} \ } \
(buf)->len += (buf)->inc; \ (buf)->len += (buf)->inc; \
(buf)->ptr = (hawk_bch_t*)hawk_rtx_allocmem(rtx, (buf)->len * HAWK_SIZEOF(hawk_bch_t)); \ (buf)->ptr = (hawk_bch_t*)hawk_rtx_allocmem(rtx, (buf)->len * HAWK_SIZEOF(hawk_bch_t)); \
if ((buf)->ptr == HAWK_NULL) \ if (HAWK_UNLIKELY(!(buf)->ptr)) \
{ \ { \
(buf)->len = 0; \ (buf)->len = 0; \
return HAWK_NULL; \ return HAWK_NULL; \
@ -8952,7 +9028,7 @@ hawk_bch_t* hawk_rtx_formatmbs (
} \ } \
(buf)->len += ((incv) > (buf)->inc)? (incv): (buf)->inc; \ (buf)->len += ((incv) > (buf)->inc)? (incv): (buf)->inc; \
(buf)->ptr = (hawk_bch_t*)hawk_rtx_allocmem(rtx, (buf)->len * HAWK_SIZEOF(hawk_bch_t)); \ (buf)->ptr = (hawk_bch_t*)hawk_rtx_allocmem(rtx, (buf)->len * HAWK_SIZEOF(hawk_bch_t)); \
if ((buf)->ptr == HAWK_NULL) \ if (HAWK_UNLIKELY(!(buf)->ptr)) \
{ \ { \
(buf)->len = 0; \ (buf)->len = 0; \
return HAWK_NULL; \ return HAWK_NULL; \
@ -8964,6 +9040,7 @@ hawk_bch_t* hawk_rtx_formatmbs (
if (nargs_on_stack == (hawk_oow_t)-1) if (nargs_on_stack == (hawk_oow_t)-1)
{ {
/* dirty hack to support a single value argument instead of a tree node */
val = (hawk_val_t*)args; val = (hawk_val_t*)args;
nargs_on_stack = 2; nargs_on_stack = 2;
} }
@ -9050,7 +9127,7 @@ wp_mod_main:
hawk_val_t* v; hawk_val_t* v;
int n; int n;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9107,7 +9184,7 @@ wp_mod_main:
FMT_MBS(rtx->formatmbs.tmp.ptr, n); FMT_MBS(rtx->formatmbs.tmp.ptr, n);
if (args == HAWK_NULL || val != HAWK_NULL) stack_arg_idx++; if (!args || val) stack_arg_idx++;
else args = args->next; else args = args->next;
i++; i++;
} }
@ -9158,7 +9235,7 @@ wp_mod_main:
hawk_bch_t fmt_fill = HAWK_BT('\0'); hawk_bch_t fmt_fill = HAWK_BT('\0');
const hawk_bch_t* fmt_prefix = HAWK_NULL; const hawk_bch_t* fmt_prefix = HAWK_NULL;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9169,7 +9246,7 @@ wp_mod_main:
} }
else else
{ {
if (val != HAWK_NULL) if (val)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9360,15 +9437,7 @@ wp_mod_main:
hawk_flt_t r; hawk_flt_t r;
int n; int n;
#if defined(HAWK_USE_FLTMAX) if (!args)
/*FMT_MCHAR (HAWK_BT('j'));*/
FMT_MBS (HAWK_BT("jj"), 2); /* see fmt.c for info on jj */
#else
FMT_MCHAR (HAWK_BT('z'));
#endif
FMT_MCHAR (fmt[i]);
if (args == HAWK_NULL)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9379,7 +9448,7 @@ wp_mod_main:
} }
else else
{ {
if (val != HAWK_NULL) if (val)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9401,9 +9470,14 @@ wp_mod_main:
if (n <= -1) return HAWK_NULL; if (n <= -1) return HAWK_NULL;
#if defined(HAWK_USE_FLTMAX) #if defined(HAWK_USE_FLTMAX)
/*FMT_MCHAR (HAWK_BT('j'));*/
FMT_MBS (HAWK_BT("jj"), 2); /* see fmt.c for info on jj */
FMT_MCHAR (fmt[i]);
/*if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/ /*if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;*/
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL; if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
#else #else
FMT_MCHAR (HAWK_BT('z'));
FMT_MCHAR (fmt[i]);
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL; if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
#endif #endif
} }
@ -9414,7 +9488,7 @@ wp_mod_main:
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype; hawk_val_type_t vtype;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9425,7 +9499,7 @@ wp_mod_main:
} }
else else
{ {
if (val != HAWK_NULL) if (val)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9455,6 +9529,11 @@ wp_mod_main:
ch_len = 1; ch_len = 1;
break; break;
case HAWK_VAL_BCHR:
ch = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
ch_len = 1;
break;
case HAWK_VAL_INT: case HAWK_VAL_INT:
ch = (hawk_bch_t)HAWK_RTX_GETINTFROMVAL(rtx, v); ch = (hawk_bch_t)HAWK_RTX_GETINTFROMVAL(rtx, v);
ch_len = 1; ch_len = 1;
@ -9527,7 +9606,7 @@ wp_mod_main:
/* left align */ /* left align */
while (wp[WP_WIDTH] > wp[WP_PRECISION]) while (wp[WP_WIDTH] > wp[WP_PRECISION])
{ {
if (hawk_becs_ccat (out, HAWK_BT(' ')) == (hawk_oow_t)-1) if (hawk_becs_ccat(out, HAWK_BT(' ')) == (hawk_oow_t)-1)
{ {
hawk_rtx_refdownval (rtx, v); hawk_rtx_refdownval (rtx, v);
return HAWK_NULL; return HAWK_NULL;
@ -9540,14 +9619,9 @@ wp_mod_main:
} }
else if (fmt[i] == HAWK_BT('s') || fmt[i] == HAWK_BT('k') || fmt[i] == HAWK_BT('K')) else if (fmt[i] == HAWK_BT('s') || fmt[i] == HAWK_BT('k') || fmt[i] == HAWK_BT('K'))
{ {
hawk_bch_t* str_ptr, * str_free = HAWK_NULL;
hawk_oow_t str_len;
hawk_int_t k;
hawk_val_t* v; hawk_val_t* v;
hawk_val_type_t vtype;
int bytetombs_flagged_radix = 16;
if (args == HAWK_NULL) if (!args)
{ {
if (stack_arg_idx >= nargs_on_stack) if (stack_arg_idx >= nargs_on_stack)
{ {
@ -9574,6 +9648,50 @@ wp_mod_main:
} }
} }
if (val)
{
/* val_flt_to_str() in val.c calls hawk_rtx_format() with nargs_on_stack of (hawk_oow_t)-1 and the actual value.
* the actual value is assigned to 'val' at the beginning of this function.
*
* the following code can drive here.
* BEGIN { CONVFMT="%s"; a=98.76 ""; }
*
* when the first attempt to convert 98.76 to a textual form invokes this function with %s and 98.76.
* it comes to this part because the format specifier is 's'. since the floating-point type is not
* specially handled, hawk_rtx_valtooocstrdup() is called below. it calls val_flt_to_str() again,
* which eventually creates recursion and stack depletion.
*
* assuming only val_flt_to_str() calls it this way, i must convert the floating point number
* to text in a rather crude way without calling hawk_rtx_valtooocstrdup().
*/
hawk_flt_t r;
int n;
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, val) == HAWK_VAL_FLT);
hawk_rtx_refupval (rtx, v);
n = hawk_rtx_valtoflt(rtx, v, &r);
hawk_rtx_refdownval (rtx, v);
if (n <= -1) return HAWK_NULL;
/* format the value as if '%g' is given */
#if defined(HAWK_USE_FLTMAX)
FMT_MBS (HAWK_BT("jjg"), 3); /* see fmt.c for info on jj */
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), &r) == (hawk_oow_t)-1) return HAWK_NULL;
#else
FMT_MBS (HAWK_BT("zg"), 2);
if (hawk_becs_fcat(out, HAWK_BECS_PTR(fbu), r) == (hawk_oow_t)-1) return HAWK_NULL;
#endif
}
else
{
hawk_bch_t* str_ptr, * str_free = HAWK_NULL, bchr_tmp;
hawk_ooch_t ooch_tmp;
hawk_oow_t str_len;
hawk_int_t k;
hawk_val_type_t vtype;
int bytetombs_flagged_radix = 16;
hawk_rtx_refupval (rtx, v); hawk_rtx_refupval (rtx, v);
vtype = HAWK_RTX_GETVALTYPE(rtx, v); vtype = HAWK_RTX_GETVALTYPE(rtx, v);
@ -9584,36 +9702,44 @@ wp_mod_main:
str_len = 0; str_len = 0;
break; break;
case HAWK_VAL_BCHR:
bchr_tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
str_ptr = &bchr_tmp;
str_len = 1;
break;
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
str_ptr = ((hawk_val_mbs_t*)v)->val.ptr; str_ptr = ((hawk_val_mbs_t*)v)->val.ptr;
str_len = ((hawk_val_mbs_t*)v)->val.len; str_len = ((hawk_val_mbs_t*)v)->val.len;
break; break;
case HAWK_VAL_CHAR:
#if defined(HAWK_OOCH_IS_BCH)
bchr_tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
str_ptr = &bchr_tmp;
str_len = 1;
#else
if (fmt[i] == HAWK_BT('s')) goto duplicate;
ooch_tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v);
str_ptr = (hawk_bch_t*)&ooch_tmp;
str_len = 1 * (HAWK_SIZEOF_OOCH_T / HAWK_SIZEOF_BCH_T);
#endif
break;
case HAWK_VAL_STR: case HAWK_VAL_STR:
#if defined(HAWK_OOCH_IS_BCH) #if defined(HAWK_OOCH_IS_BCH)
str_ptr = ((hawk_val_str_t*)v)->val.ptr; str_ptr = ((hawk_val_str_t*)v)->val.ptr;
str_len = ((hawk_val_str_t*)v)->val.len; str_len = ((hawk_val_str_t*)v)->val.len;
break;
#else #else
if (fmt[i] != HAWK_BT('s')) if (fmt[i] == HAWK_BT('s')) goto duplicate;
{
/* arrange to print the wide character string byte by byte regardless of byte order */ /* arrange to print the wide character string byte by byte regardless of byte order */
str_ptr = (hawk_bch_t*)((hawk_val_str_t*)v)->val.ptr; str_ptr = (hawk_bch_t*)((hawk_val_str_t*)v)->val.ptr;
str_len = ((hawk_val_str_t*)v)->val.len * (HAWK_SIZEOF_OOCH_T / HAWK_SIZEOF_BCH_T); str_len = ((hawk_val_str_t*)v)->val.len * (HAWK_SIZEOF_OOCH_T / HAWK_SIZEOF_BCH_T);
break;
}
/* fall thru */
#endif #endif
break;
default: default:
{ duplicate:
if (v == val)
{
hawk_rtx_refdownval (rtx, v);
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EFMTCNV);
return HAWK_NULL;
}
str_ptr = hawk_rtx_valtobcstrdup(rtx, v, &str_len); str_ptr = hawk_rtx_valtobcstrdup(rtx, v, &str_len);
if (!str_ptr) if (!str_ptr)
{ {
@ -9624,7 +9750,6 @@ wp_mod_main:
str_free = str_ptr; str_free = str_ptr;
break; break;
} }
}
if (wp_idx != WP_PRECISION || wp[WP_PRECISION] <= -1 || wp[WP_PRECISION] > (hawk_int_t)str_len) if (wp_idx != WP_PRECISION || wp[WP_PRECISION] <= -1 || wp[WP_PRECISION] > (hawk_int_t)str_len)
{ {
@ -9718,6 +9843,7 @@ wp_mod_main:
hawk_rtx_refdownval (rtx, v); hawk_rtx_refdownval (rtx, v);
} }
}
else else
{ {
if (fmt[i] != HAWK_BT('%')) OUT_MBS (HAWK_BECS_PTR(fbu), HAWK_BECS_LEN(fbu)); if (fmt[i] != HAWK_BT('%')) OUT_MBS (HAWK_BECS_PTR(fbu), HAWK_BECS_LEN(fbu));
@ -9725,7 +9851,7 @@ wp_mod_main:
goto skip_taking_arg; goto skip_taking_arg;
} }
if (args == HAWK_NULL || val != HAWK_NULL) stack_arg_idx++; if (!args || val) stack_arg_idx++;
else args = args->next; else args = args->next;
skip_taking_arg: skip_taking_arg:
hawk_becs_clear (fbu); hawk_becs_clear (fbu);

View File

@ -318,18 +318,18 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
#if defined(HAWK_OOCH_IS_UCH) #if defined(HAWK_OOCH_IS_UCH)
else if (tmp <= 0xFFFF) else if (tmp <= 0xFFFF)
{ {
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\u%04x"), tmp); hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\u%04x"), (hawk_oochu_t)tmp);
PUT_SRCSTR (hawk, buf); PUT_SRCSTR (hawk, buf);
} }
else else
{ {
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\U%08x"), tmp); hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\U%08x"), (hawk_oochu_t)tmp);
PUT_SRCSTR (hawk, buf); PUT_SRCSTR (hawk, buf);
} }
#else #else
else else
{ {
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\x%02x"), tmp); hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\x%02x"), (hawk_oochu_t)tmp);
PUT_SRCSTR (hawk, buf); PUT_SRCSTR (hawk, buf);
} }
#endif #endif
@ -349,10 +349,13 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
else if (tmp == '\'') else if (tmp == '\'')
PUT_SRCSTR (hawk, HAWK_T("\\'")); PUT_SRCSTR (hawk, HAWK_T("\\'"));
else if (hawk_is_bch_print(tmp)) else if (hawk_is_bch_print(tmp))
PUT_SRCSTRN (hawk, &tmp, 1); {
hawk_ooch_t oc = (hawk_bchu_t)tmp;
PUT_SRCSTRN (hawk, &oc, 1);
}
else else
{ {
hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\x%02x"), tmp); hawk_fmttooocstr (hawk, buf, HAWK_COUNTOF(buf), HAWK_T("\\x%02x"), (hawk_bchu_t)tmp);
PUT_SRCSTR (hawk, buf); PUT_SRCSTR (hawk, buf);
} }
@ -364,9 +367,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
{ {
if (((hawk_nde_int_t*)nde)->str) if (((hawk_nde_int_t*)nde)->str)
{ {
PUT_SRCSTRN (hawk, PUT_SRCSTRN (hawk, ((hawk_nde_int_t*)nde)->str, ((hawk_nde_int_t*)nde)->len);
((hawk_nde_int_t*)nde)->str,
((hawk_nde_int_t*)nde)->len);
} }
else else
{ {
@ -399,9 +400,7 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
{ {
if (((hawk_nde_flt_t*)nde)->str) if (((hawk_nde_flt_t*)nde)->str)
{ {
PUT_SRCSTRN (hawk, PUT_SRCSTRN (hawk, ((hawk_nde_flt_t*)nde)->str, ((hawk_nde_flt_t*)nde)->len);
((hawk_nde_flt_t*)nde)->str,
((hawk_nde_flt_t*)nde)->len);
} }
else else
{ {
@ -519,18 +518,18 @@ static int print_expr (hawk_t* hawk, hawk_nde_t* nde)
#if defined(HAWK_OOCH_IS_BCH) #if defined(HAWK_OOCH_IS_BCH)
PUT_SRCSTRN (hawk, &ptr[i], 1); PUT_SRCSTRN (hawk, &ptr[i], 1);
#else #else
hawk_ooch_t wc = ptr[i]; hawk_ooch_t oc = (hawk_bchu_t)ptr[i];
if (HAWK_BYTE_PRINTABLE(wc)) if (HAWK_BYTE_PRINTABLE(oc))
{ {
PUT_SRCSTRN (hawk, &wc, 1); PUT_SRCSTRN (hawk, &oc, 1);
} }
else else
{ {
hawk_bch_t xbuf[3]; hawk_bch_t xbuf[3];
hawk_byte_to_bcstr (wc, xbuf, HAWK_COUNTOF(xbuf), 16, '0'); hawk_byte_to_bcstr (oc, xbuf, HAWK_COUNTOF(xbuf), 16, '0');
PUT_SRCSTR (hawk, HAWK_T("\\x")); PUT_SRCSTR (hawk, HAWK_T("\\x"));
wc = xbuf[0]; PUT_SRCSTRN (hawk, &wc, 1); oc = (hawk_bchu_t)xbuf[0]; PUT_SRCSTRN (hawk, &oc, 1);
wc = xbuf[1]; PUT_SRCSTRN (hawk, &wc, 1); oc = (hawk_bchu_t)xbuf[1]; PUT_SRCSTRN (hawk, &oc, 1);
} }
#endif #endif
break; break;

View File

@ -81,7 +81,7 @@ static HAWK_INLINE __utf8_t* get_utf8_slot (hawk_uch_t uc)
hawk_oow_t hawk_uc_to_utf8 (hawk_uch_t uc, hawk_bch_t* utf8, hawk_oow_t size) hawk_oow_t hawk_uc_to_utf8 (hawk_uch_t uc, hawk_bch_t* utf8, hawk_oow_t size)
{ {
__utf8_t* cur = get_utf8_slot (uc); __utf8_t* cur = get_utf8_slot(uc);
if (cur == HAWK_NULL) return 0; /* illegal character */ if (cur == HAWK_NULL) return 0; /* illegal character */

View File

@ -3495,9 +3495,7 @@ int hawk_conv_bcstr_to_ucstr_with_cmgr (
return n; return n;
} }
int hawk_conv_uchars_to_bchars_with_cmgr ( int hawk_conv_uchars_to_bchars_with_cmgr (const hawk_uch_t* ucs, hawk_oow_t* ucslen, hawk_bch_t* bcs, hawk_oow_t* bcslen, hawk_cmgr_t* cmgr)
const hawk_uch_t* ucs, hawk_oow_t* ucslen,
hawk_bch_t* bcs, hawk_oow_t* bcslen, hawk_cmgr_t* cmgr)
{ {
const hawk_uch_t* p = ucs; const hawk_uch_t* p = ucs;
const hawk_uch_t* end = ucs + *ucslen; const hawk_uch_t* end = ucs + *ucslen;

View File

@ -66,7 +66,7 @@ struct hawk_val_rchunk_t
* add a field to indicate if a value is static. * add a field to indicate if a value is static.
* *
#define HAWK_IS_STATICVAL(val) ((val) == HAWK_NULL || (val) == hawk_val_nil || (val) == hawk_val_zls || (val) == hawk_val_zlm) #define HAWK_IS_STATICVAL(val) ((val) == HAWK_NULL || (val) == hawk_val_nil || (val) == hawk_val_zls || (val) == hawk_val_zlbs)
*/ */
#define HAWK_IS_STATICVAL(val) ((val)->v_static) #define HAWK_IS_STATICVAL(val) ((val)->v_static)
@ -169,6 +169,9 @@ extern hawk_val_t* hawk_val_nil;
/* represents an empty string */ /* represents an empty string */
extern hawk_val_t* hawk_val_zls; extern hawk_val_t* hawk_val_zls;
/* represents an empty byte string */
extern hawk_val_t* hawk_val_zlbs;
void hawk_rtx_freeval ( void hawk_rtx_freeval (
hawk_rtx_t* rtx, hawk_rtx_t* rtx,

View File

@ -30,11 +30,11 @@
static hawk_val_nil_t hawk_nil = { HAWK_VAL_NIL, 0, 1, 0, 0 }; static hawk_val_nil_t hawk_nil = { HAWK_VAL_NIL, 0, 1, 0, 0 };
static hawk_val_str_t hawk_zls = { HAWK_VAL_STR, 0, 1, 0, 0, { HAWK_T(""), 0 } }; static hawk_val_str_t hawk_zls = { HAWK_VAL_STR, 0, 1, 0, 0, { HAWK_T(""), 0 } };
static hawk_val_mbs_t hawk_zlm = { HAWK_VAL_MBS, 0, 1, 0, 0, { HAWK_BT(""), 0 } }; static hawk_val_mbs_t hawk_zlbs = { HAWK_VAL_MBS, 0, 1, 0, 0, { HAWK_BT(""), 0 } };
hawk_val_t* hawk_val_nil = (hawk_val_t*)&hawk_nil; hawk_val_t* hawk_val_nil = (hawk_val_t*)&hawk_nil;
hawk_val_t* hawk_val_zls = (hawk_val_t*)&hawk_zls; hawk_val_t* hawk_val_zls = (hawk_val_t*)&hawk_zls;
hawk_val_t* hawk_val_zlm = (hawk_val_t*)&hawk_zlm; hawk_val_t* hawk_val_zlbs = (hawk_val_t*)&hawk_zlbs;
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -734,7 +734,7 @@ hawk_val_t* hawk_rtx_makenumorstrvalwithuchars (hawk_rtx_t* rtx, const hawk_uch_
hawk_int_t l; hawk_int_t l;
hawk_flt_t r; hawk_flt_t r;
if (ptr[0] == '.' && len == 1) goto make_str; if (len == 1 && ptr[0] == '.') goto make_str;
x = hawk_uchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r); x = hawk_uchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r);
if (x == 0) return hawk_rtx_makeintval(rtx, l); if (x == 0) return hawk_rtx_makeintval(rtx, l);
@ -750,7 +750,7 @@ hawk_val_t* hawk_rtx_makenumorstrvalwithbchars (hawk_rtx_t* rtx, const hawk_bch_
hawk_int_t l; hawk_int_t l;
hawk_flt_t r; hawk_flt_t r;
if (ptr[0] == '.' && len == 1) goto make_str; if (len == 1 && ptr[0] == '.') goto make_str;
x = hawk_bchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r); x = hawk_bchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r);
if (x == 0) return hawk_rtx_makeintval(rtx, l); if (x == 0) return hawk_rtx_makeintval(rtx, l);
@ -838,7 +838,7 @@ static HAWK_INLINE hawk_val_t* make_mbs_val (hawk_rtx_t* rtx, const hawk_bch_t*
hawk_oow_t i; hawk_oow_t i;
#endif #endif
if (HAWK_UNLIKELY(len1 <= 0 && len2 <= 0)) return hawk_val_zls; if (HAWK_UNLIKELY(len1 <= 0 && len2 <= 0)) return hawk_val_zlbs;
aligned_len = HAWK_ALIGN_POW2((len1 + len2 + 1), HAWK_MBS_CACHE_BLOCK_UNIT); aligned_len = HAWK_ALIGN_POW2((len1 + len2 + 1), HAWK_MBS_CACHE_BLOCK_UNIT);
#if defined(HAWK_ENABLE_MBS_CACHE) #if defined(HAWK_ENABLE_MBS_CACHE)
@ -887,7 +887,7 @@ hawk_val_t* hawk_rtx_makembsvalwithuchars (hawk_rtx_t* rtx, const hawk_uch_t* uc
hawk_bch_t* bcs; hawk_bch_t* bcs;
hawk_oow_t bcslen; hawk_oow_t bcslen;
if (HAWK_UNLIKELY(len <= 0)) return hawk_val_zlm; if (HAWK_UNLIKELY(len <= 0)) return hawk_val_zlbs;
bcs = hawk_rtx_duputobchars(rtx, ucs, len, &bcslen); bcs = hawk_rtx_duputobchars(rtx, ucs, len, &bcslen);
if (HAWK_UNLIKELY(!bcs)) return HAWK_NULL; if (HAWK_UNLIKELY(!bcs)) return HAWK_NULL;
@ -954,10 +954,13 @@ hawk_val_t* hawk_rtx_makenumormbsvalwithuchars (hawk_rtx_t* rtx, const hawk_uch_
hawk_int_t l; hawk_int_t l;
hawk_flt_t r; hawk_flt_t r;
if (len == 1 && ptr[0] == '.') goto make_str;
x = hawk_uchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r); x = hawk_uchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r);
if (x == 0) return hawk_rtx_makeintval(rtx, l); if (x == 0) return hawk_rtx_makeintval(rtx, l);
else if (x >= 1) return hawk_rtx_makefltval(rtx, r); else if (x >= 1) return hawk_rtx_makefltval(rtx, r);
make_str:
return hawk_rtx_makembsvalwithuchars(rtx, ptr, len); return hawk_rtx_makembsvalwithuchars(rtx, ptr, len);
} }
@ -967,10 +970,13 @@ hawk_val_t* hawk_rtx_makenumormbsvalwithbchars (hawk_rtx_t* rtx, const hawk_bch_
hawk_int_t l; hawk_int_t l;
hawk_flt_t r; hawk_flt_t r;
if (len == 1 && ptr[0] == '.') goto make_str;
x = hawk_bchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r); x = hawk_bchars_to_num(HAWK_OOCHARS_TO_NUM_MAKE_OPTION(1, 1, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0), ptr, len, &l, &r);
if (x == 0) return hawk_rtx_makeintval(rtx, l); if (x == 0) return hawk_rtx_makeintval(rtx, l);
else if (x >= 1) return hawk_rtx_makefltval(rtx, r); else if (x >= 1) return hawk_rtx_makefltval(rtx, r);
make_str:
return hawk_rtx_makembsvalwithbchars(rtx, ptr, len); return hawk_rtx_makembsvalwithbchars(rtx, ptr, len);
} }
@ -1465,6 +1471,7 @@ void hawk_rtx_freeval (hawk_rtx_t* rtx, hawk_val_t* val, int flags)
break; break;
} }
case HAWK_VAL_BCHR:
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
/* this never happens */ /* this never happens */
@ -1713,9 +1720,12 @@ int hawk_rtx_valtobool (hawk_rtx_t* rtx, const hawk_val_t* val)
{ {
case HAWK_VAL_NIL: case HAWK_VAL_NIL:
return 0; return 0;
case HAWK_VAL_BCHR:
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
/* return always true - treat it like a 1-letter string */ /* return always true - treat it like a 1-letter string */
return 1; return 1;
case HAWK_VAL_INT: case HAWK_VAL_INT:
return HAWK_RTX_GETINTFROMVAL(rtx, val) != 0; return HAWK_RTX_GETINTFROMVAL(rtx, val) != 0;
case HAWK_VAL_FLT: case HAWK_VAL_FLT:
@ -2134,6 +2144,16 @@ int hawk_rtx_valtostr (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_rtx_valtostr_o
case HAWK_VAL_NIL: case HAWK_VAL_NIL:
return str_to_str(rtx, HAWK_T(""), 0, out); return str_to_str(rtx, HAWK_T(""), 0, out);
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
#if defined(HAWK_OOCH_IS_BCH)
return str_to_str(rtx, &tmp, 1, out);
#else
return mbs_to_str(rtx, &tmp, 1, out);
#endif
}
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v);
@ -2416,8 +2436,33 @@ void hawk_rtx_freevaloocstr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_ooch_t* str)
hawk_bch_t* hawk_rtx_getvalbcstrwithcmgr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_oow_t* len, hawk_cmgr_t* cmgr) hawk_bch_t* hawk_rtx_getvalbcstrwithcmgr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_oow_t* len, hawk_cmgr_t* cmgr)
{ {
hawk_bch_t c;
hawk_oow_t l;
switch (HAWK_RTX_GETVALTYPE(rtx, v)) switch (HAWK_RTX_GETVALTYPE(rtx, v))
{ {
case HAWK_VAL_NIL:
c = '\0';
l = 0;
goto bctos;
case HAWK_VAL_BCHR:
c = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
l = 1;
bctos:
if (rtx->bctos.fi) /* free slot available */
{
/* use a bctos slot to avoid duplication */
hawk_oow_t fi;
fi = rtx->bctos.fi;
rtx->bctos.fi = rtx->bctos.b[rtx->bctos.fi].c[0];
rtx->bctos.b[fi].c[0] = c;
rtx->bctos.b[fi].c[1] = '\0';
if (len) *len = l;
HAWK_ASSERT ((void*)&rtx->bctos.b[fi] == (void*)rtx->bctos.b[fi].c);
return rtx->bctos.b[fi].c;
}
goto duplicate;
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
#if 0 #if 0
plain_mbs: plain_mbs:
@ -2436,19 +2481,8 @@ hawk_bch_t* hawk_rtx_getvalbcstrwithcmgr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_o
/* fall through */ /* fall through */
#endif #endif
#if 0
case HAWK_VAL_CHAR:
i can treat a character value between 0 and 255 as a byte.
but doing so can cause inconsitency between the two ranges:
* 128 - 255 (kept as a single byte)
* 255 - max character value (encoded to multiple bytes)
it looks more consistent that 255 becomes \xc3\xbf (assuming utf8).
so no special handling for HAWK_VAL_CHAR here.
#endif
default: default:
duplicate:
return hawk_rtx_valtobcstrdupwithcmgr(rtx, v, len, cmgr); return hawk_rtx_valtobcstrdupwithcmgr(rtx, v, len, cmgr);
} }
} }
@ -2457,6 +2491,22 @@ void hawk_rtx_freevalbcstr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_bch_t* str)
{ {
switch (HAWK_RTX_GETVALTYPE(rtx, v)) switch (HAWK_RTX_GETVALTYPE(rtx, v))
{ {
case HAWK_VAL_NIL:
case HAWK_VAL_BCHR:
{
hawk_bctos_b_t* b = (hawk_bctos_b_t*)str;
if (b >= &rtx->bctos.b[0] && b < &rtx->bctos.b[HAWK_COUNTOF(rtx->bctos.b)])
{
hawk_oow_t fi;
fi = b - &rtx->bctos.b[0];
rtx->bctos.b[fi].c[0] = rtx->bctos.fi;
rtx->bctos.fi = fi;
break;
}
goto freemem;
}
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
#if 0 #if 0
plain_mbs: plain_mbs:
@ -2472,6 +2522,7 @@ void hawk_rtx_freevalbcstr (hawk_rtx_t* rtx, hawk_val_t* v, hawk_bch_t* str)
#endif #endif
default: default:
freemem:
hawk_rtx_freemem (rtx, str); hawk_rtx_freemem (rtx, str);
break; break;
} }
@ -2542,6 +2593,15 @@ int hawk_rtx_valtonum (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_int_t* l, hawk
*l = 0; *l = 0;
return 0; return 0;
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
return hawk_bchars_to_num(
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), 0),
&tmp, 1, l, r
);
}
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
/* treat it as if it is a 1-letter string */ /* treat it as if it is a 1-letter string */
@ -2651,17 +2711,39 @@ hawk_fun_t* hawk_rtx_valtofun (hawk_rtx_t* rtx, hawk_val_t* v)
fun = ((hawk_val_fun_t*)v)->fun; fun = ((hawk_val_fun_t*)v)->fun;
break; break;
case HAWK_VAL_STR: case HAWK_VAL_BCHR:
if (hawk_count_oocstr(((hawk_val_str_t*)v)->val.ptr) != ((hawk_val_str_t*)v)->val.len) goto error_inval;
fun = hawk_rtx_findfunwithoocstr(rtx, ((hawk_val_str_t*)v)->val.ptr);
if (!fun) return HAWK_NULL;
break;
case HAWK_VAL_MBS: case HAWK_VAL_MBS:
if (hawk_count_bcstr(((hawk_val_mbs_t*)v)->val.ptr) != ((hawk_val_mbs_t*)v)->val.len) goto error_inval; {
fun = hawk_rtx_findfunwithbcstr(rtx, ((hawk_val_mbs_t*)v)->val.ptr); hawk_bcs_t x;
x.ptr = hawk_rtx_getvalbcstr(rtx, v, &x.len);
if (HAWK_UNLIKELY(!x.ptr)) return HAWK_NULL;
if (hawk_count_bcstr(x.ptr) != x.len)
{
hawk_rtx_freevalbcstr (rtx, v, x.ptr);
goto error_inval;
}
fun = hawk_rtx_findfunwithbcstr(rtx, x.ptr);
hawk_rtx_freevalbcstr (rtx, v, x.ptr);
if (!fun) return HAWK_NULL; if (!fun) return HAWK_NULL;
break; break;
}
case HAWK_VAL_CHAR:
case HAWK_VAL_STR:
{
hawk_oocs_t x;
x.ptr = hawk_rtx_getvaloocstr(rtx, v, &x.len);
if (HAWK_UNLIKELY(!x.ptr)) return HAWK_NULL;
if (hawk_count_oocstr(x.ptr) != x.len)
{
hawk_rtx_freevaloocstr (rtx, v, x.ptr);
goto error_inval;
}
fun = hawk_rtx_findfunwithoocstr(rtx, x.ptr);
hawk_rtx_freevaloocstr (rtx, v, x.ptr);
if (!fun) return HAWK_NULL;
break;
}
default: default:
error_inval: error_inval:
@ -2693,6 +2775,13 @@ hawk_int_t hawk_rtx_hashval (hawk_rtx_t* rtx, hawk_val_t* v)
hv = 0; hv = 0;
break; break;
case HAWK_VAL_BCHR:
{
hawk_bch_t tmp = HAWK_RTX_GETBCHRFROMVAL(rtx, v);
hv = (hawk_int_t)hash((hawk_uint8_t*)&tmp, HAWK_SIZEOF(tmp));
break;
}
case HAWK_VAL_CHAR: case HAWK_VAL_CHAR:
{ {
hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, v);
@ -3008,8 +3097,16 @@ void hawk_dprintval (hawk_rtx_t* run, hawk_val_t* val)
break; break;
} }
case HAWK_VAL_BCHR:
hawk_errputstrf (HAWK_T("%hc"), HAWK_GETBCHRFROMVAL(val));
break;
case HAWK_VAL_CHAR:
hawk_errputstrf (HAWK_T("%jc"), HAWK_GETCHARFROMVAL(val));
break;
case HAWK_VAL_INT: case HAWK_VAL_INT:
hawk_errputstrf (HAWK_T("%jd"), (hawk_intmax_t)((hawk_val_int_t*)val)->val); hawk_errputstrf (HAWK_T("%jd"), (hawk_intmax_t)HAWK_GETINTFROMVAL(val));
break; break;
case HAWK_VAL_FLT: case HAWK_VAL_FLT:

View File

@ -3,6 +3,11 @@
@include "ensure.inc"; @include "ensure.inc";
function f(a, b, c)
{
return a + b + c;
}
function call_by_ref_1(&a, b, &c) function call_by_ref_1(&a, b, &c)
{ {
c = "hello, world"; c = "hello, world";
@ -23,8 +28,17 @@ function call_by_ref_3(&x)
function main() function main()
{ {
{ {
ensure (@b"" !== "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b"" === "", 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b"" != "", 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b"" == "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b' ' !== ' ', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b' ' === ' ', 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b' ' != ' ', 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (@b' ' == ' ', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@nil == 'A'), 0, @SCRIPTNAME, @SCRIPTLINE); ensure ((@nil == 'A'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@nil != 'A'), 1, @SCRIPTNAME, @SCRIPTLINE); ensure ((@nil != 'A'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@nil > 'A'), 0, @SCRIPTNAME, @SCRIPTLINE); ensure ((@nil > 'A'), 0, @SCRIPTNAME, @SCRIPTLINE);
@ -41,6 +55,14 @@ function main()
ensure (('A' == @b'A'), 1, @SCRIPTNAME, @SCRIPTLINE); ensure (('A' == @b'A'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (('\u00FF' == @b'\xFF'), 1, @SCRIPTNAME, @SCRIPTLINE); ensure (('\u00FF' == @b'\xFF'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (('A' < @b'\xFF'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b'A' < @b'\xFF'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (('A' > @b'\xFF'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b'A' > @b'\xFF'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (('A' < @b'B'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b'A' < @b'B'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (('A' > @b'B'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b'A' > @b'B'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (("10" == 10), 1, @SCRIPTNAME, @SCRIPTLINE); ensure (("10" == 10), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (("10" == 10.00), 1, @SCRIPTNAME, @SCRIPTLINE); ensure (("10" == 10.00), 1, @SCRIPTNAME, @SCRIPTLINE);
@ -146,6 +168,11 @@ function main()
ensure (length(b), 2, @SCRIPTNAME, @SCRIPTLINE); ensure (length(b), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (b[1], 99, @SCRIPTNAME, @SCRIPTLINE); ensure (b[1], 99, @SCRIPTNAME, @SCRIPTLINE);
ensure (b[2], "perfect", @SCRIPTNAME, @SCRIPTLINE); ensure (b[2], "perfect", @SCRIPTNAME, @SCRIPTLINE);
ensure (hawk::call('f', 1, 2, 3), 6, @SCRIPTNAME, @SCRIPTLINE);
ensure (hawk::call("f", 1, 2, 3), 6, @SCRIPTNAME, @SCRIPTLINE);
ensure (hawk::call(@b'f', 1, 2, 3), 6, @SCRIPTNAME, @SCRIPTLINE);
ensure (hawk::call(@b"f", 1, 2, 3), 6, @SCRIPTNAME, @SCRIPTLINE);
} }
@ -262,6 +289,8 @@ function main()
ensure ((@b"hawk" str::fromcharcode(0x26be)) === @b"hawk\xe2\x9a\xbe", 1, @SCRIPTNAME, @SCRIPTLINE); ensure ((@b"hawk" str::fromcharcode(0x26be)) === @b"hawk\xe2\x9a\xbe", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (("hawk" str::fromcharcode(0x26be)) === "hawk⚾", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (("hawk" str::fromcharcode(0x26be)) === "hawk⚾", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b"hawk" @b'\xFF') === @b"hawk\xFF", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((str::subchar(@b"\xFF\xFE", 1) str::subchar(@b"\xFF\xFE", 2)) === @b"\xFF\xFE", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure ((@b"hawk" %% 10) === @b"hawk10", 1, @SCRIPTNAME, @SCRIPTLINE); ensure ((@b"hawk" %% 10) === @b"hawk10", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (("hawk" %% 10) === "hawk10", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (("hawk" %% 10) === "hawk10", 1, @SCRIPTNAME, @SCRIPTLINE);

View File

@ -44,6 +44,54 @@ function main()
gsub("\\\\", "A", y); gsub("\\\\", "A", y);
ensure (x, "xAy", @SCRIPTNAME, @SCRIPTLINE); ensure (x, "xAy", @SCRIPTNAME, @SCRIPTLINE);
ensure (y, "xAAy", @SCRIPTNAME, @SCRIPTLINE); ensure (y, "xAAy", @SCRIPTNAME, @SCRIPTLINE);
x = y = @b"x\\\\y";
gsub(/\\\\/, "A", x);
gsub("\\\\", "A", y);
ensure (x === @b"xAy", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === @b"xAAy", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = @b"x\\\\y";
gsub(/\\\\/, 'A', x);
gsub("\\\\", 'A', y);
ensure (x === @b"xAy", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === @b"xAAy", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = "x\\\\y";
gsub(/\\\\/, @b'A', x);
gsub("\\\\", @b'A', y);
ensure (x === "xAy", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === "xAAy", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = "x\\\\y";
gsub(/\\\\/, @b"A", x);
gsub("\\\\", @b"A", y);
ensure (x === "xAy", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === "xAAy", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = '\\';
gsub(/\\/, @b"A", x);
gsub("\\\\", @b"A", y);
ensure (x === "A", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === "A", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = '\\';
gsub(/\\/, @b'A', x);
gsub("\\\\", @b'A', y);
ensure (x === "A", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = @b'\\';
gsub(/\\/, @b"A", x);
gsub("\\\\", @b"A", y);
ensure (x === @b"A", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === @b"A", 1, @SCRIPTNAME, @SCRIPTLINE);
x = y = @b'\\';
gsub(/\\/, @b'A', x);
gsub("\\\\", @b'A', y);
ensure (x === @b"A", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (y === @b"A", 1, @SCRIPTNAME, @SCRIPTLINE);
} }
## gsub - POSIX rule for &, \&, \\&, \\\& ## gsub - POSIX rule for &, \&, \\&, \\\&
@ -248,6 +296,10 @@ function main()
ensure (sprintf("%+d %d", 3, 4), "+3 4", @SCRIPTNAME, @SCRIPTLINE); ensure (sprintf("%+d %d", 3, 4), "+3 4", @SCRIPTNAME, @SCRIPTLINE);
ensure (sprintf(@b"%+d %d", 3, 4), @b"+3 4", @SCRIPTNAME, @SCRIPTLINE); ensure (sprintf(@b"%+d %d", 3, 4), @b"+3 4", @SCRIPTNAME, @SCRIPTLINE);
ensure (sprintf(@b'A') === @b"A", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (sprintf('A') === "A", 1, @SCRIPTNAME, @SCRIPTLINE);
} }
{ {
@ -282,29 +334,74 @@ function main()
ensure (substr(1000+10000, 2) === "1000", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (substr(1000+10000, 2) === "1000", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 1) === 'a', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 2) === 'b', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 3) === 'c', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 1) === 'a', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", 1) === '☕', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 2) === 'b', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", 2) === '⛄', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 3) === 'c', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", 3) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar("☕⛄", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", 1) === '☕', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", 1) === @b'a', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", 2) === '⛄', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", 2) === @b'b', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", 3) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", 3) === @b'c', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("☕⛄", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b"abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b"abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar('a', 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b"abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar('a', 1) === 'a', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b"abc", 1) === @b'a', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar('a', 2) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b"abc", 2) === @b'b', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 3) === @b'c', 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b'a', 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b"abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME); ensure (str::subchar(@b'a', 1) === @b'a', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(@b'a', 2) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(123, 0) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(123, 1) === '1', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(123, 2) === '2', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(123, 3) === '3', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar(123, 4) === @nil, 1, @SCRIPTNAME, @SCRIPTLINE);
} }
{
ensure (str::substr("☕Q⛄", 0) === "☕Q⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 1) === "☕Q⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 2) === "Q⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 3) === "⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 4) === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 1, 2) === "☕Q", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr("☕Q⛄", 1, 4) === "☕Q⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
###ensure (str::substr("☕Q⛄", -1, 1) === "⛄", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr('☕', 1, 4) === "☕", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr(@b"\xAD\xAA\xBB\CC", 2, 2) === @b"\xAA\xBB", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::substr(@b'\xAD', 1, 1) === @b"\xAD", 1, @SCRIPTNAME, @SCRIPTLINE);
}
{
ensure (str::index("☕Q⛄X⛄Z", '⛄'), 3, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::index("☕Q⛄X⛄Z", "⛄"), 3, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::index("☕Q⛄X⛄Z", "Q⛄"), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex("☕Q⛄X⛄Z", '⛄'), 5, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex("☕Q⛄X⛄Z", "⛄"), 5, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex("☕Q⛄X⛄Z", "Q⛄"), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex("☕Q⛄X⛄Z", "Q⛄Q"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::index(@b"\xFFQ\xABX\xABZ", @b'\xAB'), 3, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::index(@b"\xFFQ\xABX\xABZ", @b"\xAB"), 3, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::index(@b"\xFFQ\xABX\xABZ", @b"Q\xAB"), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex(@b"\xFFQ\xABX\xABZ", @b'\xAB'), 5, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex(@b"\xFFQ\xABX\xABZ", @b"\xAB"), 5, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex(@b"\xFFQ\xABX\xABZ", @b"Q\xAB"), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::rindex(@b"\xFFQ\xABX\xABZ", @b"Q\xABQ"), 0, @SCRIPTNAME, @SCRIPTLINE);
}
{ {
# split, str::split, str::splita # split, str::split, str::splita
@ -365,6 +462,26 @@ function main()
ensure (a[3], "", @SCRIPTNAME, @SCRIPTLINE); ensure (a[3], "", @SCRIPTNAME, @SCRIPTLINE);
ensure (a[4], "b\t\tc", @SCRIPTNAME, @SCRIPTLINE); ensure (a[4], "b\t\tc", @SCRIPTNAME, @SCRIPTLINE);
ensure (a[5], "d", @SCRIPTNAME, @SCRIPTLINE); ensure (a[5], "d", @SCRIPTNAME, @SCRIPTLINE);
ensure (str::split('a', a, /a/), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[1] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[2] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::split('a', a, 'a'), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[1] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[2] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::split('a', a, @b'a'), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[1] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[2] === "", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::split(@b'a', a, /a/), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[1] === @b"", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[2] === @b"", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::split(@b'a', a, @b'a'), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[1] === @b"", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (a[2] === @b"", 1, @SCRIPTNAME, @SCRIPTLINE);
} }
@ -413,10 +530,26 @@ function main()
ensure (str::tolower(@b"ABC") === @b"abc", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (str::tolower(@b"ABC") === @b"abc", 1, @SCRIPTNAME, @SCRIPTLINE);
} }
{ {
ensure (str::tocharcode(str::fromcharcode('2')), 2, @SCRIPTNAME, @SCRIPTNAME); ensure (str::tocharcode(@b'\xFF'), 0xFF, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tonum('a', 16), 10, @SCRIPTNAME, @SCRIPTNAME); ensure (str::tocharcode('\u3321'), 0x3321, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode(@b'\xFF', 0), @nil, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode('\u3321', 0), @nil, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode(@b'\xFF', 1), 0xFF, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode('\u3321', 1), 0x3321, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode(@b'\xFF', 2), @nil, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode('\u3321', 2), @nil, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tocharcode(str::fromcharcode('2')), 2, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tonum('a', 16), 10, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::fromcharcode(65, 66, 67) === "ABC", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::frombcharcode(65, 66, 67) === @b"ABC", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::trim(" hello world ") === "hello world", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::trim(" hello world ", str::TRIM_PAC_SPACES) === "hello world", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::trim(@b" hello world ") === @b"hello world", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::trim(@b" hello world ", str::TRIM_PAC_SPACES) === @b"hello world", 1, @SCRIPTNAME, @SCRIPTLINE);
} }
print "SUCCESS"; print "SUCCESS";