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,94 +566,101 @@ 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))
{ {
hawk_bch_t* str0, * str1, * ptr; case HAWK_VAL_BCHR:
hawk_oow_t len0, len1; case HAWK_VAL_MBS:
str0 = ((hawk_val_mbs_t*)a0)->val.ptr;
len0 = ((hawk_val_mbs_t*)a0)->val.len;
str1 = hawk_rtx_getvalbcstr(rtx, a1, &len1);
if (!str1) return -1;
if (nargs < 3)
{ {
boundary = rindex? len0: 1; hawk_bch_t* str0, * str1, * ptr;
} hawk_oow_t len0, len1;
else
{ str0 = ((hawk_val_mbs_t*)a0)->val.ptr;
if (boundary == 0) boundary = 1; len0 = ((hawk_val_mbs_t*)a0)->val.len;
else if (boundary < 0) boundary = len0 + boundary + 1;
str1 = hawk_rtx_getvalbcstr(rtx, a1, &len1);
if (HAWK_UNLIKELY(!str0)) return -1;
if (nargs < 3)
{
boundary = rindex? len0: 1;
}
else
{
if (boundary == 0) boundary = 1;
else if (boundary < 0) boundary = len0 + boundary + 1;
}
if (boundary > len0 || boundary <= 0)
{
ptr = HAWK_NULL;
}
else if (rindex)
{
/* 'boundary' acts as an end position */
ptr = hawk_rfind_bchars_in_bchars(&str0[0], boundary, str1, len1, rtx->gbl.ignorecase);
}
else
{
/* 'boundary' acts as an start position */
ptr = hawk_find_bchars_in_bchars(&str0[boundary-1], len0 - boundary + 1, str1, len1, rtx->gbl.ignorecase);
}
idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1);
hawk_rtx_freevalbcstr (rtx, a1, str1);
break;
} }
if (boundary > len0 || boundary <= 0) default:
{ {
ptr = HAWK_NULL; hawk_ooch_t* str0, * str1, * ptr;
} hawk_oow_t len0, len1;
else if (rindex)
{
/* 'boundary' acts as an end position */
ptr = hawk_rfind_bchars_in_bchars(&str0[0], boundary, str1, len1, rtx->gbl.ignorecase);
}
else
{
/* 'boundary' acts as an start position */
ptr = hawk_find_bchars_in_bchars(&str0[boundary-1], len0 - boundary + 1, str1, len1, rtx->gbl.ignorecase);
}
idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1); str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1;
hawk_rtx_freevalbcstr (rtx, a1, str1); str1 = hawk_rtx_getvaloocstr(rtx, a1, &len1);
} if (!str1)
else {
{ hawk_rtx_freevaloocstr (rtx, a0, str0);
hawk_ooch_t* str0, * str1, * ptr; return -1;
hawk_oow_t len0, len1; }
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); if (nargs < 3)
if (!str0) return -1; {
boundary = rindex? len0: 1;
}
else
{
if (boundary == 0) boundary = 1;
else if (boundary < 0) boundary = len0 + boundary + 1;
}
str1 = hawk_rtx_getvaloocstr(rtx, a1, &len1); if (boundary > len0 || boundary <= 0)
if (!str1) {
{ ptr = HAWK_NULL;
}
else if (rindex)
{
/* 'boundary' acts as an end position */
ptr = hawk_rfind_oochars_in_oochars(&str0[0], boundary, str1, len1, rtx->gbl.ignorecase);
}
else
{
/* 'boundary' acts as an start position */
ptr = hawk_find_oochars_in_oochars(&str0[boundary-1], len0 - boundary + 1, str1, len1, rtx->gbl.ignorecase);
}
idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1);
hawk_rtx_freevaloocstr (rtx, a1, str1);
hawk_rtx_freevaloocstr (rtx, a0, str0); hawk_rtx_freevaloocstr (rtx, a0, str0);
return -1;
} }
break;
if (nargs < 3)
{
boundary = rindex? len0: 1;
}
else
{
if (boundary == 0) boundary = 1;
else if (boundary < 0) boundary = len0 + boundary + 1;
}
if (boundary > len0 || boundary <= 0)
{
ptr = HAWK_NULL;
}
else if (rindex)
{
/* 'boundary' acts as an end position */
ptr = hawk_rfind_oochars_in_oochars(&str0[0], boundary, str1, len1, rtx->gbl.ignorecase);
}
else
{
/* 'boundary' acts as an start position */
ptr = hawk_find_oochars_in_oochars(&str0[boundary-1], len0 - boundary + 1, str1, len1, rtx->gbl.ignorecase);
}
idx = (ptr == HAWK_NULL)? 0: ((hawk_int_t)(ptr - str0) + 1);
hawk_rtx_freevaloocstr (rtx, a1, str1);
hawk_rtx_freevaloocstr (rtx, a0, str0);
} }
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,34 +768,42 @@ 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))
{ {
hawk_bch_t* str; case HAWK_VAL_BCHR:
hawk_oow_t len; case HAWK_VAL_MBS:
{
hawk_bch_t* str;
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);
if (HAWK_UNLIKELY(!r)) return -1; hawk_rtx_freevalbcstr (rtx, a0, str);
} if (HAWK_UNLIKELY(!r)) return -1;
else break;
{ }
hawk_ooch_t* str;
hawk_oow_t len;
str = hawk_rtx_getvaloocstr(rtx, a0, &len); default:
if (!str) return -1; {
hawk_ooch_t* str;
hawk_oow_t len;
if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len; str = hawk_rtx_getvaloocstr(rtx, a0, &len);
if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex; if (HAWK_UNLIKELY(!str)) return -1;
r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount); if (lindex >= (hawk_int_t)len) lindex = (hawk_int_t)len;
hawk_rtx_freevaloocstr (rtx, a0, str); if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex;
if (HAWK_UNLIKELY(!r)) return -1;
r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount);
hawk_rtx_freevaloocstr (rtx, a0, str);
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))
{ {
byte_str = 1; case HAWK_VAL_BCHR:
str.ptr = do_fld? hawk_rtx_valtobcstrdup(rtx, a0, &str.len): case HAWK_VAL_MBS:
hawk_rtx_getvalbcstr(rtx, a0, &str.len); byte_str = 1;
} str.ptr = do_fld? hawk_rtx_valtobcstrdup(rtx, a0, &str.len):
else hawk_rtx_getvalbcstr(rtx, a0, &str.len);
{ break;
byte_str = 0;
str.ptr = do_fld? hawk_rtx_valtooocstrdup(rtx, a0, &str.len): default:
hawk_rtx_getvaloocstr(rtx, a0, &str.len); byte_str = 0;
str.ptr = do_fld? hawk_rtx_valtooocstrdup(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))
{ {
s2.ptr = hawk_rtx_getvalbcstr(rtx, r2, &s2.len); case HAWK_VAL_BCHR:
s2_free = 2; case HAWK_VAL_MBS:
s2.ptr = hawk_rtx_getvalbcstr(rtx, r2, &s2.len);
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
{
s2.ptr = hawk_rtx_getvaloocstr(rtx, r2, &s2.len);
s2_free = 1;
/* the second argument - substitute */ default:
s1.ptr = hawk_rtx_getvaloocstr(rtx, a1, &s1.len); s2.ptr = hawk_rtx_getvaloocstr(rtx, r2, &s2.len);
s1_free = 1; s2_free = 1;
/* the second argument - substitute */
s1.ptr = hawk_rtx_getvaloocstr(rtx, a1, &s1.len);
s1_free = 1;
break;
} }
} }
@ -1738,61 +1788,66 @@ 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))
{ {
hawk_becs_t fbu; case HAWK_VAL_BCHR:
int fbu_inited = 0; case HAWK_VAL_MBS:
hawk_bcs_t cs0; {
hawk_bcs_t x; hawk_becs_t fbu;
int fbu_inited = 0;
hawk_bcs_t cs0;
hawk_bcs_t x;
if (hawk_becs_init(&fbu, hawk_rtx_getgem(rtx), 256) <= -1) goto oops_mbs; if (hawk_becs_init(&fbu, hawk_rtx_getgem(rtx), 256) <= -1) goto oops_mbs;
fbu_inited = 1; fbu_inited = 1;
cs0.ptr = hawk_rtx_getvalbcstr(rtx, a0, &cs0.len); cs0.ptr = hawk_rtx_getvalbcstr(rtx, a0, &cs0.len);
if (HAWK_UNLIKELY(!cs0.ptr)) goto oops_mbs; if (HAWK_UNLIKELY(!cs0.ptr)) goto oops_mbs;
x.ptr = hawk_rtx_formatmbs(rtx, &rtx->fnc.bout, &fbu, cs0.ptr, cs0.len, nargs, HAWK_NULL, &x.len); x.ptr = hawk_rtx_formatmbs(rtx, &rtx->fnc.bout, &fbu, cs0.ptr, cs0.len, nargs, HAWK_NULL, &x.len);
hawk_rtx_freevalbcstr (rtx, a0, cs0.ptr); hawk_rtx_freevalbcstr (rtx, a0, cs0.ptr);
if (HAWK_UNLIKELY(!x.ptr)) goto oops_mbs; if (HAWK_UNLIKELY(!x.ptr)) goto oops_mbs;
a0 = hawk_rtx_makembsvalwithbcs(rtx, &x); a0 = hawk_rtx_makembsvalwithbcs(rtx, &x);
if (HAWK_UNLIKELY(!a0)) goto oops_mbs; if (HAWK_UNLIKELY(!a0)) goto oops_mbs;
hawk_becs_fini (&fbu); hawk_becs_fini (&fbu);
hawk_rtx_setretval (rtx, a0); hawk_rtx_setretval (rtx, a0);
return 0; return 0;
oops_mbs: oops_mbs:
if (fbu_inited) hawk_becs_fini (&fbu); if (fbu_inited) hawk_becs_fini (&fbu);
return -1; return -1;
} }
else
{
hawk_ooecs_t fbu;
int fbu_inited = 0;
hawk_oocs_t cs0;
hawk_oocs_t x;
if (hawk_ooecs_init(&fbu, hawk_rtx_getgem(rtx), 256) <= -1) goto oops; default:
fbu_inited = 1; {
hawk_ooecs_t fbu;
int fbu_inited = 0;
hawk_oocs_t cs0;
hawk_oocs_t x;
cs0.ptr = hawk_rtx_getvaloocstr(rtx, a0, &cs0.len); if (hawk_ooecs_init(&fbu, hawk_rtx_getgem(rtx), 256) <= -1) goto oops;
if (HAWK_UNLIKELY(!cs0.ptr)) goto oops; fbu_inited = 1;
x.ptr = hawk_rtx_format(rtx, &rtx->fnc.oout, &fbu, cs0.ptr, cs0.len, nargs, HAWK_NULL, &x.len); cs0.ptr = hawk_rtx_getvaloocstr(rtx, a0, &cs0.len);
hawk_rtx_freevaloocstr (rtx, a0, cs0.ptr); if (HAWK_UNLIKELY(!cs0.ptr)) goto oops;
if (HAWK_UNLIKELY(!x.ptr)) goto oops;
a0 = hawk_rtx_makestrvalwithoocs(rtx, &x); x.ptr = hawk_rtx_format(rtx, &rtx->fnc.oout, &fbu, cs0.ptr, cs0.len, nargs, HAWK_NULL, &x.len);
if (HAWK_UNLIKELY(!a0)) goto oops; hawk_rtx_freevaloocstr (rtx, a0, cs0.ptr);
if (HAWK_UNLIKELY(!x.ptr)) goto oops;
hawk_ooecs_fini (&fbu); a0 = hawk_rtx_makestrvalwithoocs(rtx, &x);
hawk_rtx_setretval (rtx, a0); if (HAWK_UNLIKELY(!a0)) goto oops;
return 0;
oops: hawk_ooecs_fini (&fbu);
if (fbu_inited) hawk_ooecs_fini (&fbu); hawk_rtx_setretval (rtx, a0);
return -1; return 0;
oops:
if (fbu_inited) hawk_ooecs_fini (&fbu);
return -1;
}
} }
} }

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,30 +37,36 @@ 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))
{ {
hawk_bch_t* str0; case HAWK_VAL_BCHR:
hawk_oow_t len0; case HAWK_VAL_MBS:
{
hawk_bch_t* str0;
hawk_oow_t len0;
str0 = hawk_rtx_valtobcstrdup(rtx, a0, &len0); str0 = hawk_rtx_valtobcstrdup(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1; if (HAWK_UNLIKELY(!str0)) return -1;
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 }
{
hawk_ooch_t* str0;
hawk_oow_t len0;
str0 = hawk_rtx_valtooocstrdup(rtx, a0, &len0); default:
if (HAWK_UNLIKELY(!str0)) return -1; {
len0 = hawk_compact_oochars(str0, len0); hawk_ooch_t* str0;
retv = hawk_rtx_makestrvalwithoochars(rtx, str0, len0); hawk_oow_t len0;
hawk_rtx_freemem (rtx, str0);
str0 = hawk_rtx_valtooocstrdup(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1;
len0 = hawk_compact_oochars(str0, len0);
retv = hawk_rtx_makestrvalwithoochars(rtx, str0, len0);
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))
{ {
hawk_bcs_t path; case HAWK_VAL_BCHR:
hawk_bch_t* npath; case HAWK_VAL_MBS:
path.ptr = ((hawk_val_mbs_t*)a0)->val.ptr; {
path.len = ((hawk_val_mbs_t*)a0)->val.len; hawk_bcs_t path;
npath = hawk_trim_bchars(path.ptr, &path.len, flags); hawk_bch_t* npath;
retv = hawk_rtx_makembsvalwithbchars(rtx, npath, path.len); path.ptr = hawk_rtx_getvalbcstr(rtx, a0, &path.len);
} if (HAWK_UNLIKELY(!path.ptr)) return -1;
else npath = hawk_trim_bchars(path.ptr, &path.len, flags);
{ retv = hawk_rtx_makembsvalwithbchars(rtx, npath, path.len);
hawk_oocs_t path; hawk_rtx_freevalbcstr (rtx, a0, path.ptr);
hawk_ooch_t* npath; break;
path.ptr = hawk_rtx_getvaloocstr(rtx, a0, &path.len); }
if (!path.ptr) return -1;
/* because hawk_strxtrmx() returns the pointer and the length without default:
* 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_oocs_t path;
* the string type. */ hawk_ooch_t* npath;
npath = hawk_trim_oochars(path.ptr, &path.len, flags); path.ptr = hawk_rtx_getvaloocstr(rtx, a0, &path.len);
retv = hawk_rtx_makestrvalwithoochars(rtx, npath, path.len); if (HAWK_UNLIKELY(!path.ptr)) return -1;
hawk_rtx_freevaloocstr (rtx, a0, path.ptr); /* because hawk_trim_oochars() returns the pointer and the length without
* affecting the string given, it's safe to pass the original value.
* hawk_rtx_getvaloocstr() doesn't duplicate the value if it's of
* the string type. */
npath = hawk_trim_oochars(path.ptr, &path.len, flags);
retv = hawk_rtx_makestrvalwithoochars(rtx, npath, path.len);
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,58 +147,67 @@ 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))
{ {
hawk_bch_t* str0; case HAWK_VAL_BCHR:
hawk_oow_t len0; case HAWK_VAL_MBS:
str0 = ((hawk_val_mbs_t*)a0)->val.ptr;
len0 = ((hawk_val_mbs_t*)a0)->val.len;
if (len0 <= 0) tmp = 0;
else
{ {
tmp = 1; hawk_bch_t* str0;
do hawk_oow_t len0;
str0 = hawk_rtx_getvalbcstr(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1;
if (len0 <= 0) tmp = 0;
else
{ {
len0--; tmp = 1;
if (!hawk_is_bch_type(str0[len0], ctype)) do
{ {
tmp = 0; len0--;
break; if (!hawk_is_bch_type(str0[len0], ctype))
{
tmp = 0;
break;
}
} }
while (len0 > 0);
} }
while (len0 > 0);
hawk_rtx_freevalbcstr (rtx, a0, str0);
break;
} }
}
else
{
hawk_ooch_t* str0;
hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); default:
if (!str0) return -1;
if (len0 <= 0) tmp = 0;
else
{ {
tmp = 1; hawk_ooch_t* str0;
do hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1;
if (len0 <= 0) tmp = 0;
else
{ {
len0--; tmp = 1;
if (!hawk_is_ooch_type(str0[len0], ctype)) do
{ {
tmp = 0; len0--;
break; if (!hawk_is_ooch_type(str0[len0], ctype))
{
tmp = 0;
break;
}
} }
while (len0 > 0);
} }
while (len0 > 0); hawk_rtx_freevaloocstr (rtx, a0, str0);
break;
} }
hawk_rtx_freevaloocstr (rtx, a0, str0);
} }
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))
{ {
hawk_bch_t* str0; case HAWK_VAL_BCHR:
hawk_oow_t len0; case HAWK_VAL_MBS:
str0 = ((hawk_val_mbs_t*)a0)->val.ptr;
len0 = ((hawk_val_mbs_t*)a0)->val.len;
if (pos >= 0 && pos < len0)
{ {
#if defined(HAWK_OOCH_IS_BCH) hawk_bch_t* str0;
/* typecasting in case hawk_bch_t is signed */ hawk_oow_t len0;
iv = (unsigned char)str0[pos];
#else
iv = str0[pos];
#endif
}
}
else
{
hawk_ooch_t* str0;
hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0); str0 = hawk_rtx_getvalbcstr(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 = (hawk_bchu_t)str0[pos];
iv = (unsigned char)str0[pos]; }
#else
iv = str0[pos]; hawk_rtx_freevalbcstr(rtx, a0, str0);
#endif break;
} }
hawk_rtx_freevaloocstr(rtx, a0, str0); default:
{
hawk_ooch_t* str0;
hawk_oow_t len0;
str0 = hawk_rtx_getvaloocstr(rtx, a0, &len0);
if (HAWK_UNLIKELY(!str0)) return -1;
if (pos >= 0 && pos < len0)
{
/* typecasting in case hawk_bch_t is signed */
iv = (hawk_oochu_t)str0[pos];
}
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,38 +692,45 @@ 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))
{ {
hawk_bch_t* str; case HAWK_VAL_BCHR:
hawk_oow_t len; case HAWK_VAL_MBS:
{
hawk_bch_t* str;
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 }
{
hawk_ooch_t* str;
hawk_oow_t len;
str = hawk_rtx_getvaloocstr(rtx, a0, &len); default:
if (!str) return -1; {
hawk_ooch_t* str;
hawk_oow_t len;
if (lindex >= 0 && lindex < (hawk_int_t)len) str = hawk_rtx_getvaloocstr(rtx, a0, &len);
r = hawk_rtx_makecharval(rtx, str[lindex]); if (!str) return -1;
else
r = hawk_rtx_makenilval(rtx);
hawk_rtx_freevaloocstr (rtx, a0, str); if (lindex >= 0 && lindex < (hawk_int_t)len)
if (HAWK_UNLIKELY(!r)) return -1; r = hawk_rtx_makecharval(rtx, str[lindex]);
else
r = hawk_rtx_makenilval(rtx);
hawk_rtx_freevaloocstr (rtx, a0, str);
break;
}
} }
if (HAWK_UNLIKELY(!r)) return -1;
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
return 0; return 0;
} }
@ -650,40 +754,41 @@ 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("fromcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_fromcharcode, 0 } }, { HAWK_T("frombcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_frombcharcode, 0 } },
{ HAWK_T("frommbs"), { { 1, 2, HAWK_NULL }, fnc_frommbs, 0 } }, { HAWK_T("fromcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_fromcharcode, 0 } },
{ HAWK_T("gsub"), { { 2, 3, HAWK_T("xvr")}, hawk_fnc_gsub, 0 } }, { HAWK_T("frommbs"), { { 1, 2, HAWK_NULL }, fnc_frommbs, 0 } },
{ HAWK_T("index"), { { 2, 3, HAWK_NULL }, hawk_fnc_index, 0 } }, { HAWK_T("gsub"), { { 2, 3, HAWK_T("xvr")}, hawk_fnc_gsub, 0 } },
{ HAWK_T("isalnum"), { { 1, 1, HAWK_NULL }, fnc_isalnum, 0 } }, { HAWK_T("index"), { { 2, 3, HAWK_NULL }, hawk_fnc_index, 0 } },
{ HAWK_T("isalpha"), { { 1, 1, HAWK_NULL }, fnc_isalpha, 0 } }, { HAWK_T("isalnum"), { { 1, 1, HAWK_NULL }, fnc_isalnum, 0 } },
{ HAWK_T("isblank"), { { 1, 1, HAWK_NULL }, fnc_isblank, 0 } }, { HAWK_T("isalpha"), { { 1, 1, HAWK_NULL }, fnc_isalpha, 0 } },
{ HAWK_T("iscntrl"), { { 1, 1, HAWK_NULL }, fnc_iscntrl, 0 } }, { HAWK_T("isblank"), { { 1, 1, HAWK_NULL }, fnc_isblank, 0 } },
{ HAWK_T("isdigit"), { { 1, 1, HAWK_NULL }, fnc_isdigit, 0 } }, { HAWK_T("iscntrl"), { { 1, 1, HAWK_NULL }, fnc_iscntrl, 0 } },
{ HAWK_T("isgraph"), { { 1, 1, HAWK_NULL }, fnc_isgraph, 0 } }, { HAWK_T("isdigit"), { { 1, 1, HAWK_NULL }, fnc_isdigit, 0 } },
{ HAWK_T("islower"), { { 1, 1, HAWK_NULL }, fnc_islower, 0 } }, { HAWK_T("isgraph"), { { 1, 1, HAWK_NULL }, fnc_isgraph, 0 } },
{ HAWK_T("isprint"), { { 1, 1, HAWK_NULL }, fnc_isprint, 0 } }, { HAWK_T("islower"), { { 1, 1, HAWK_NULL }, fnc_islower, 0 } },
{ HAWK_T("ispunct"), { { 1, 1, HAWK_NULL }, fnc_ispunct, 0 } }, { HAWK_T("isprint"), { { 1, 1, HAWK_NULL }, fnc_isprint, 0 } },
{ HAWK_T("isspace"), { { 1, 1, HAWK_NULL }, fnc_isspace, 0 } }, { HAWK_T("ispunct"), { { 1, 1, HAWK_NULL }, fnc_ispunct, 0 } },
{ HAWK_T("isupper"), { { 1, 1, HAWK_NULL }, fnc_isupper, 0 } }, { HAWK_T("isspace"), { { 1, 1, HAWK_NULL }, fnc_isspace, 0 } },
{ HAWK_T("isxdigit"), { { 1, 1, HAWK_NULL }, fnc_isxdigit, 0 } }, { HAWK_T("isupper"), { { 1, 1, HAWK_NULL }, fnc_isupper, 0 } },
{ HAWK_T("length"), { { 1, 1, HAWK_NULL }, hawk_fnc_length, 0 } }, { HAWK_T("isxdigit"), { { 1, 1, HAWK_NULL }, fnc_isxdigit, 0 } },
{ HAWK_T("ltrim"), { { 1, 1, HAWK_NULL }, fnc_ltrim, 0 } }, { HAWK_T("length"), { { 1, 1, HAWK_NULL }, hawk_fnc_length, 0 } },
{ HAWK_T("match"), { { 2, 4, HAWK_T("vxvr") }, hawk_fnc_match, 0 } }, { HAWK_T("ltrim"), { { 1, 1, HAWK_NULL }, fnc_ltrim, 0 } },
{ HAWK_T("normspace"), { { 1, 1, HAWK_NULL }, fnc_normspace, 0 } }, /* deprecated, use trim("xxx", str::TRIM_PAC_SPACES) */ { HAWK_T("match"), { { 2, 4, HAWK_T("vxvr") }, hawk_fnc_match, 0 } },
{ HAWK_T("printf"), { { 1, A_MAX, HAWK_NULL }, hawk_fnc_sprintf, 0 } }, { HAWK_T("normspace"), { { 1, 1, HAWK_NULL }, fnc_normspace, 0 } }, /* deprecated, use trim("xxx", str::TRIM_PAC_SPACES) */
{ HAWK_T("rindex"), { { 2, 3, HAWK_NULL }, hawk_fnc_rindex, 0 } }, { HAWK_T("printf"), { { 1, A_MAX, HAWK_NULL }, hawk_fnc_sprintf, 0 } },
{ HAWK_T("rtrim"), { { 1, 1, HAWK_NULL }, fnc_rtrim, 0 } }, { HAWK_T("rindex"), { { 2, 3, HAWK_NULL }, hawk_fnc_rindex, 0 } },
{ HAWK_T("split"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_split, 0 } }, { HAWK_T("rtrim"), { { 1, 1, HAWK_NULL }, fnc_rtrim, 0 } },
{ HAWK_T("splita"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_splita, 0 } }, /* split to array. asplit is not a good name for this */ { HAWK_T("split"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_split, 0 } },
{ HAWK_T("sub"), { { 2, 3, HAWK_T("xvr") }, hawk_fnc_sub, 0 } }, { HAWK_T("splita"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_splita, 0 } }, /* split to array. asplit is not a good name for this */
{ HAWK_T("subchar"), { { 2, 2, HAWK_NULL }, fnc_subchar, 0 } }, { HAWK_T("sub"), { { 2, 3, HAWK_T("xvr") }, hawk_fnc_sub, 0 } },
{ HAWK_T("substr"), { { 2, 3, HAWK_NULL }, hawk_fnc_substr, 0 } }, { HAWK_T("subchar"), { { 2, 2, HAWK_NULL }, fnc_subchar, 0 } },
{ HAWK_T("tocharcode"), { { 1, 2, HAWK_NULL }, fnc_tocharcode, 0 } }, { HAWK_T("substr"), { { 2, 3, HAWK_NULL }, hawk_fnc_substr, 0 } },
{ HAWK_T("tolower"), { { 1, 1, HAWK_NULL }, hawk_fnc_tolower, 0 } }, { HAWK_T("tocharcode"), { { 1, 2, HAWK_NULL }, fnc_tocharcode, 0 } },
{ HAWK_T("tombs"), { { 1, 2, HAWK_NULL }, fnc_tombs, 0 } }, { HAWK_T("tolower"), { { 1, 1, HAWK_NULL }, hawk_fnc_tolower, 0 } },
{ HAWK_T("tonum"), { { 1, 2, HAWK_NULL }, fnc_tonum, 0 } }, { HAWK_T("tombs"), { { 1, 2, HAWK_NULL }, fnc_tombs, 0 } },
{ HAWK_T("toupper"), { { 1, 1, HAWK_NULL }, hawk_fnc_toupper, 0 } }, { HAWK_T("tonum"), { { 1, 2, HAWK_NULL }, fnc_tonum, 0 } },
{ HAWK_T("trim"), { { 1, 2, HAWK_NULL }, fnc_trim, 0 } } { HAWK_T("toupper"), { { 1, 1, HAWK_NULL }, hawk_fnc_toupper, 0 } },
{ HAWK_T("trim"), { { 1, 2, HAWK_NULL }, fnc_trim, 0 } }
}; };
static inttab_t inttab[] = static inttab_t inttab[] =

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);

File diff suppressed because it is too large Load Diff

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,11 +169,14 @@ 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,
hawk_val_t* val, hawk_val_t* val,
int flags int flags
); );
void hawk_rtx_freevalchunk ( void hawk_rtx_freevalchunk (

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";