diff --git a/hawk/lib/fnc.c b/hawk/lib/fnc.c index 7c6ba4ec..dd1f8fbc 100644 --- a/hawk/lib/fnc.c +++ b/hawk/lib/fnc.c @@ -1863,16 +1863,14 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi, if (nargs >= 3) { - hawk_val_t* a2; - - a2 = hawk_rtx_getarg(rtx, 2); - if (HAWK_RTX_GETVALTYPE(rtx, a2) != HAWK_VAL_FUN) + fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 2)); + if (HAWK_UNLIKELY(!fun)) { - hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EINVAL, HAWK_T("comparator not a function")); + if (hawk_rtx_geterrnum(rtx) == HAWK_EINVAL) + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EINVAL, HAWK_T("comparator not a function")); return -1; } - fun = ((hawk_val_fun_t*)a2)->fun; if (fun->nargs < 2) { /* the comparison accepts less than 2 arguments */ diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index 44be278b..bc596e10 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -2143,9 +2143,9 @@ HAWK_EXPORT hawk_fun_t* hawk_rtx_findfunwithucstr ( ); #if defined(HAWK_OOCH_IS_BCH) -# define hawk_rtx_findfun hawk_rtx_findfunwithbcstr +# define hawk_rtx_findfunwithoocstr hawk_rtx_findfunwithbcstr #else -# define hawk_rtx_findfun hawk_rtx_findfunwithucstr +# define hawk_rtx_findfunwithoocstr hawk_rtx_findfunwithucstr #endif /** @@ -3245,13 +3245,18 @@ HAWK_EXPORT int hawk_rtx_valtoflt ( hawk_flt_t* r ); +HAWK_EXPORT hawk_fun_t* hawk_rtx_valtofun ( + hawk_rtx_t* rtx, + hawk_val_t* val +); + /** * The hawk_rtx_hashval() function hashes a simple value * to a positive integer. It returns -1 for a inhashable value. */ HAWK_EXPORT hawk_int_t hawk_rtx_hashval ( - hawk_rtx_t* rtx, - hawk_val_t* v + hawk_rtx_t* rtx, + hawk_val_t* v ); /** diff --git a/hawk/lib/val.c b/hawk/lib/val.c index 4be42301..f04fe4c9 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -2275,6 +2275,42 @@ int hawk_rtx_valtoflt (hawk_rtx_t* rtx, const hawk_val_t* v, hawk_flt_t* r) return n; } + +hawk_fun_t* hawk_rtx_valtofun (hawk_rtx_t* rtx, hawk_val_t* v) +{ + hawk_fun_t* fun; + hawk_val_type_t vtype; + + vtype = HAWK_RTX_GETVALTYPE(rtx, v); + + switch (vtype) + { + case HAWK_VAL_FUN: + fun = ((hawk_val_fun_t*)v)->fun; + break; + + case HAWK_VAL_STR: + 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: + 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); + if (!fun) return HAWK_NULL; + break; + + default: + error_inval: + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EINVAL); + return HAWK_NULL; + } + + return fun; +} + + /* ========================================================================== */ static HAWK_INLINE hawk_uint_t hash (hawk_uint8_t* ptr, hawk_oow_t len)