diff --git a/hawk/lib/hawk.c b/hawk/lib/hawk.c index 8e5bc0b0..2f7d2845 100644 --- a/hawk/lib/hawk.c +++ b/hawk/lib/hawk.c @@ -627,6 +627,7 @@ int hawk_findmodsymfnc_noseterr (hawk_t* hawk, hawk_mod_fnc_tab_t* fnctab, hawk_ if (n == 0) { sym->type = HAWK_MOD_FNC; + sym->name = fnctab[mid].name; sym->u.fnc_ = fnctab[mid].info; return 0; } @@ -651,6 +652,7 @@ int hawk_findmodsymint_noseterr (hawk_t* hawk, hawk_mod_int_tab_t* inttab, hawk_ if (n == 0) { sym->type = HAWK_MOD_INT; + sym->name = inttab[mid].name; sym->u.int_ = inttab[mid].info; return 0; } @@ -674,6 +676,7 @@ int hawk_findmodsymflt_noseterr (hawk_t* hawk, hawk_mod_flt_tab_t* flttab, hawk_ if (n == 0) { sym->type = HAWK_MOD_FLT; + sym->name = flttab[mid].name; sym->u.flt_ = flttab[mid].info; return 0; } diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index da2d5fa0..0dd42fe3 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -1041,6 +1041,7 @@ struct hawk_mod_sym_flt_t struct hawk_mod_sym_t { hawk_mod_sym_type_t type; + const hawk_ooch_t* name; union { hawk_mod_sym_fnc_t fnc_; @@ -1807,7 +1808,7 @@ HAWK_EXPORT int hawk_findgblwithucstr ( */ HAWK_EXPORT hawk_fnc_t* hawk_addfncwithbcstr ( hawk_t* hawk, - const hawk_bch_t* name, + const hawk_bch_t* name, const hawk_fnc_mspec_t* spec ); @@ -1816,7 +1817,7 @@ HAWK_EXPORT hawk_fnc_t* hawk_addfncwithbcstr ( */ HAWK_EXPORT hawk_fnc_t* hawk_addfncwithucstr ( hawk_t* hawk, - const hawk_uch_t* name, + const hawk_uch_t* name, const hawk_fnc_wspec_t* spec ); @@ -1825,7 +1826,7 @@ HAWK_EXPORT hawk_fnc_t* hawk_addfncwithucstr ( * \return 0 on success, -1 on failure */ HAWK_EXPORT int hawk_delfncwithbcstr ( - hawk_t* hawk, /**< hawk */ + hawk_t* hawk, /**< hawk */ const hawk_bch_t* name /**< function name */ ); @@ -1834,7 +1835,7 @@ HAWK_EXPORT int hawk_delfncwithbcstr ( * \return 0 on success, -1 on failure */ HAWK_EXPORT int hawk_delfncwithucstr ( - hawk_t* hawk, /**< hawk */ + hawk_t* hawk, /**< hawk */ const hawk_uch_t* name /**< function name */ ); @@ -3381,10 +3382,19 @@ HAWK_EXPORT hawk_fun_t* hawk_rtx_valtofun ( hawk_val_t* val ); -HAWK_EXPORT hawk_mod_t* hawk_rtx_valtomodfnc ( - hawk_rtx_t* rtx, - hawk_val_t* val, - hawk_fnc_spec_t* spec +/** + * The hawk_rtx_valtofnc() function finds an intrinsic function by the name + * pointed to by \a val. Unlike hawk_findfncwithoocstr() and the like, + * it accepts a function name prefixed with a module name and find an intrinsic + * function located in a module. In principle, it combines hawk_findfncwithoocstr() + * and hawk_querymodulewithname(). + * + * \return \a fnc on success, #HAWK_NULL on failure + */ +HAWK_EXPORT hawk_fnc_t* hawk_rtx_valtofnc ( + hawk_rtx_t* rtx, + hawk_val_t* val, + hawk_fnc_t* fnc /**< buffer to hold the function information */ ); /** diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index d0e524e0..eb0163ea 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -104,7 +104,7 @@ static hawk_oow_t push_args_from_stack (hawk_rtx_t* rtx, hawk_nde_fncall_t* call static int fnc_call (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { hawk_fun_t* fun; - hawk_oow_t nargs; + hawk_oow_t nargs, f_nargs; hawk_nde_fncall_t call; struct pafs_t pafs; hawk_val_t* v; @@ -112,11 +112,12 @@ static int fnc_call (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) /* this function is similar to hawk_rtx_callfun() but it is more simplified */ HAWK_MEMSET (&call, 0, HAWK_SIZEOF(call)); nargs = hawk_rtx_getnargs(rtx); + f_nargs = nargs - 1; fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 0)); if (fun) { - if (nargs - 1 > fun->nargs) + if (f_nargs > fun->nargs) { hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EARGTM); return -1; /* hard failure */ @@ -133,30 +134,40 @@ static int fnc_call (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) else { /* find the name in the modules */ - hawk_mod_t* m; + hawk_fnc_t fnc, * fncp; mod_data_t* md; -// TODO: find normal fnc too. md = (mod_data_t*)fi->mod->ctx; - /* hawk_querymodulewithname() may update some shared data under - * the hawk object. use a mutex for shared data safety */ - hawk_mtx_lock (&md->mq_mtx, HAWK_NULL); - m = hawk_rtx_valtomodfnc(rtx, hawk_rtx_getarg(rtx, 0), &call.u.fnc.spec); - hawk_mtx_unlock (&md->mq_mtx); - if (!m) return -1; /* hard failure */ + /* hawk_querymodulewithname() called by hawk_rtx_valtofnc() + * may update some shared data under the hawk object. + * use a mutex for shared data safety */ + /* TODO: this mutex protection is wrong in that if a call to hawk_querymodulewithname() + * is made outside this hawk module, the call is not protected under + * the same mutex. FIX THIS */ + hawk_mtx_lock (&md->mq_mtx, HAWK_NULL); + fncp = hawk_rtx_valtofnc(rtx, hawk_rtx_getarg(rtx, 0), &fnc); + hawk_mtx_unlock (&md->mq_mtx); + if (!fncp) return -1; /* hard failure */ + + if (f_nargs < fnc.spec.arg.min || f_nargs > fnc.spec.arg.max) + { + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EARGTM); + return -1; + } call.type = HAWK_NDE_FNCALL_FNC; - // QQQ0 - // call.u.fnc.info.name = name; - call.u.fnc.info.mod = m; + call.u.fnc.info.name.ptr = fnc.name.ptr; + call.u.fnc.info.name.len = fnc.name.len; + call.u.fnc.info.mod = fnc.mod; + call.u.fnc.spec = fnc.spec; pafs.is_fun = 0; pafs.argspec_ptr = call.u.fnc.spec.arg.spec; pafs.argspec_len = call.u.fnc.spec.arg.spec? hawk_count_oocstr(call.u.fnc.spec.arg.spec): 0; } - call.nargs = nargs - 1; + call.nargs = f_nargs; /* keep HAWK_NULL in call.args so that hawk_rtx_evalcall() knows it's a fake call structure */ call.arg_base = rtx->stack_base + 5; /* 5 = 4(stack frame prologue) + 1(the first argument to hawk::call()) */ diff --git a/hawk/lib/val.c b/hawk/lib/val.c index 7ddd2149..917be65e 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -2821,11 +2821,15 @@ hawk_fun_t* hawk_rtx_valtofun (hawk_rtx_t* rtx, hawk_val_t* v) return fun; } -hawk_mod_t* hawk_rtx_valtomodfnc (hawk_rtx_t* rtx, hawk_val_t* v, hawk_fnc_spec_t* spec) +hawk_fnc_t* hawk_rtx_valtofnc (hawk_rtx_t* rtx, hawk_val_t* v, hawk_fnc_t* rfnc) { + /* this function looks for intrinsic functions as well as module functions. + * it combines the functionality of the following two functions. + * hawk_findfncwithoocs() - finds an intrisic function + * hawk_querymodulewithname() - finds a function defined in a module + */ + hawk_t* hawk = hawk_rtx_gethawk(rtx); - hawk_mod_t* mod; - hawk_mod_sym_t sym; hawk_val_type_t vtype; vtype = HAWK_RTX_GETVALTYPE(rtx, v); @@ -2838,6 +2842,8 @@ hawk_mod_t* hawk_rtx_valtomodfnc (hawk_rtx_t* rtx, hawk_val_t* v, hawk_fnc_spec_ case HAWK_VAL_STR: { hawk_oocs_t x; + hawk_fnc_t* fnc; + 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) @@ -2845,9 +2851,36 @@ hawk_mod_t* hawk_rtx_valtomodfnc (hawk_rtx_t* rtx, hawk_val_t* v, hawk_fnc_spec_ hawk_rtx_freevaloocstr (rtx, v, x.ptr); goto error_inval; } - mod = hawk_querymodulewithname(hawk, &x, &sym); - hawk_rtx_freevaloocstr (rtx, v, x.ptr); - if (!mod) return HAWK_NULL; + + fnc = hawk_findfncwithoocs(hawk, &x); + if (fnc) + { + hawk_rtx_freevaloocstr (rtx, v, x.ptr); + *rfnc = *fnc; + } + else + { + hawk_mod_t* mod; + hawk_mod_sym_t sym; + + mod = hawk_querymodulewithname(hawk, &x, &sym); + hawk_rtx_freevaloocstr (rtx, v, x.ptr); + if (!mod) return HAWK_NULL; + + if (sym.type != HAWK_MOD_FNC || (hawk->opt.trait & sym.u.fnc_.trait) != sym.u.fnc_.trait) + { + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOENT); + return HAWK_NULL; + } + + HAWK_MEMSET (rfnc, 0, HAWK_SIZEOF(*rfnc)); + rfnc->name.ptr = sym.name; + rfnc->name.len = hawk_count_oocstr(sym.name); + rfnc->spec = sym.u.fnc_; + /* TODO: FIX THIS - set the owner name */ + /*rfnc->owner = name of the module?*/ + rfnc->mod = mod; + } break; } @@ -2857,14 +2890,7 @@ hawk_mod_t* hawk_rtx_valtomodfnc (hawk_rtx_t* rtx, hawk_val_t* v, hawk_fnc_spec_ return HAWK_NULL; } - if (sym.type != HAWK_MOD_FNC || (hawk->opt.trait & sym.u.fnc_.trait) != sym.u.fnc_.trait) - { - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOENT); - return HAWK_NULL; - } - - *spec = sym.u.fnc_; - return mod; + return rfnc; } /* ========================================================================== */ diff --git a/hawk/t/h-009.hawk b/hawk/t/h-009.hawk index 244ae4e0..85cb3e37 100644 --- a/hawk/t/h-009.hawk +++ b/hawk/t/h-009.hawk @@ -7,9 +7,16 @@ function run_test_001 () { @local tmp, out; + tap_ensure (hawk::function_exists(111), 0, @SCRIPTNAME, @SCRIPTLINE); + tap_ensure (hawk::function_exists(1.69), 0, @SCRIPTNAME, @SCRIPTLINE); + tap_ensure (hawk::function_exists("111"), 0, @SCRIPTNAME, @SCRIPTLINE); + tap_ensure (hawk::function_exists(@b"111"), 0, @SCRIPTNAME, @SCRIPTLINE); + + tap_ensure (hawk::call(@b"length", "hawk"), 4, @SCRIPTNAME, @SCRIPTLINE); + tap_ensure (hawk::call("length", @b"hawk"), 4, @SCRIPTNAME, @SCRIPTLINE); + if (hawk::function_exists("sed::str_to_str")) { - ##tmp = sed::str_to_str("s/a/j/g", "aaabbbaaacccaaaddd", out); tmp = hawk::call("sed::str_to_str", "s/a/j/g", "aaabbbaaacccaaaddd", out); tap_ensure (out === "jjjbbbjjjcccjjjddd", 1, @SCRIPTNAME, @SCRIPTLINE); }