diff --git a/hawk/lib/Hawk.cpp b/hawk/lib/Hawk.cpp index 6a3c0dc6..2868f5e2 100644 --- a/hawk/lib/Hawk.cpp +++ b/hawk/lib/Hawk.cpp @@ -2182,18 +2182,18 @@ int Hawk::deleteGlobal (const hawk_uch_t* name) } -int Hawk::findGlobal (const hawk_bch_t* name) +int Hawk::findGlobal (const hawk_bch_t* name, bool inc_builtins) { HAWK_ASSERT (awk != HAWK_NULL); - int n = hawk_findgblwithbcstr(this->hawk, name); + int n = hawk_findgblwithbcstr(this->hawk, name, inc_builtins); if (n <= -1) this->retrieveError (); return n; } -int Hawk::findGlobal (const hawk_uch_t* name) +int Hawk::findGlobal (const hawk_uch_t* name, bool inc_builtins) { HAWK_ASSERT (awk != HAWK_NULL); - int n = hawk_findgblwithucstr(this->hawk, name); + int n = hawk_findgblwithucstr(this->hawk, name, inc_builtins); if (n <= -1) this->retrieveError (); return n; } diff --git a/hawk/lib/Hawk.hpp b/hawk/lib/Hawk.hpp index 67113ccd..2a98f926 100644 --- a/hawk/lib/Hawk.hpp +++ b/hawk/lib/Hawk.hpp @@ -1520,10 +1520,12 @@ public: /// \return integer >= 0 on success, -1 on failure. /// int findGlobal ( - const hawk_bch_t* name ///> variable name + const hawk_bch_t* name, ///> variable name + bool inc_builtins = false ); int findGlobal ( - const hawk_uch_t* name ///> variable name + const hawk_uch_t* name, ///> variable name + bool inc_builtins = false ); /// diff --git a/hawk/lib/HawkStd.cpp b/hawk/lib/HawkStd.cpp index f4c5347b..ae5c4734 100644 --- a/hawk/lib/HawkStd.cpp +++ b/hawk/lib/HawkStd.cpp @@ -912,7 +912,14 @@ int HawkStd::open_console_in (Console& io) */ argv = hawk_rtx_getgbl (rtx, this->gbl_argv); HAWK_ASSERT (argv != HAWK_NULL); - HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, argv) == HAWK_VAL_MAP); + if (HAWK_RTX_GETVALTYPE(rtx, argv) != HAWK_VAL_MAP) + { + /* with flexmap on, you can change ARGV to a scalar. + * BEGIN { ARGV="xxx"; } + * you must not do this. */ + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EINVAL, HAWK_T("phony value in ARGV")); + return -1; + } map = ((hawk_val_map_t*)argv)->map; HAWK_ASSERT (map != HAWK_NULL); diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index bfe64c5c..0a7fa40e 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -1685,7 +1685,7 @@ HAWK_EXPORT void hawk_pushecb ( * \return the ID of the global variable added on success, -1 on failure. */ HAWK_EXPORT int hawk_addgblwithbcstr ( - hawk_t* awk, /**< awk */ + hawk_t* hawk, /**< hawk */ const hawk_bch_t* name /**< variable name */ ); @@ -1694,7 +1694,7 @@ HAWK_EXPORT int hawk_addgblwithbcstr ( * \return the ID of the global variable added on success, -1 on failure. */ HAWK_EXPORT int hawk_addgblwithucstr ( - hawk_t* awk, /**< awk */ + hawk_t* hawk, /**< hawk */ const hawk_uch_t* name /**< variable name */ ); @@ -1703,7 +1703,7 @@ HAWK_EXPORT int hawk_addgblwithucstr ( * \return 0 on success, -1 on failure */ HAWK_EXPORT int hawk_delgblwithbcstr ( - hawk_t* awk, /**< awk */ + hawk_t* hawk, /**< hawk */ const hawk_bch_t* name /**< variable name */ ); @@ -1712,28 +1712,28 @@ HAWK_EXPORT int hawk_delgblwithbcstr ( * \return 0 on success, -1 on failure */ HAWK_EXPORT int hawk_delgblwithucstr ( - hawk_t* awk, /**< awk */ + hawk_t* hawk, /**< hawk */ const hawk_uch_t* name /**< variable name */ ); /** - * The hawk_findgblwithbcstr() function returns the numeric ID of an intrinsic global - * variable. + * The hawk_findgblwithbcstr() function returns the numeric ID of a global variable. * \return number >= 0 on success, -1 on failure */ HAWK_EXPORT int hawk_findgblwithbcstr ( - hawk_t* awk, /**< awk */ - const hawk_bch_t* name /**< variable name */ + hawk_t* hawk, /**< hawk */ + const hawk_bch_t* name, /**< variable name */ + int inc_builtins /**< include builtin global variables like FS */ ); /** - * The hawk_findgblwithucstr() function returns the numeric ID of an intrinsic global - * variable. + * The hawk_findgblwithucstr() function returns the numeric ID of a global variable. * \return number >= 0 on success, -1 on failure */ HAWK_EXPORT int hawk_findgblwithucstr ( - hawk_t* awk, /**< awk */ - const hawk_uch_t* name /**< variable name */ + hawk_t* hawk, /**< hawk */ + const hawk_uch_t* name, /**< variable name */ + int inc_builtins /**< include builtin globals variables like FS */ ); #if defined(HAWK_OOCH_IS_BCH) @@ -1843,6 +1843,12 @@ HAWK_EXPORT int hawk_parse ( hawk_sio_cbs_t* sio /**< source script I/O handler */ ); + +HAWK_EXPORT int hawk_isvalidident ( + hawk_t* hawk, + const hawk_ooch_t* str +); + #if defined(HAWK_HAVE_INLINE) static HAWK_INLINE void* hawk_allocmem (hawk_t* hawk, hawk_oow_t size) { return hawk_gem_allocmem(hawk_getgem(hawk), size); } static HAWK_INLINE void* hawk_reallocmem (hawk_t* hawk, void* ptr, hawk_oow_t size) { return hawk_gem_reallocmem(hawk_getgem(hawk), ptr, size); } @@ -2350,6 +2356,12 @@ HAWK_EXPORT int hawk_rtx_setgbl ( hawk_val_t* val ); +HAWK_EXPORT int hawk_rtx_setgblbyname ( + hawk_rtx_t* rtx, + const hawk_ooch_t* name, + const hawk_ooch_t* val +); + /** * The hawk_rtx_setretval() sets the return value of a function * when called from within a function handler. The caller doesn't @@ -3037,15 +3049,15 @@ HAWK_EXPORT int hawk_rtx_valtostr ( HAWK_EXPORT hawk_bch_t* hawk_rtx_valtobcstrdupwithcmgr ( hawk_rtx_t* rtx, /**< runtime context */ const hawk_val_t* val, /**< value to convert */ - hawk_oow_t* len, /**< result length */ - hawk_cmgr_t* cmgr + hawk_oow_t* len, /**< result length */ + hawk_cmgr_t* cmgr ); HAWK_EXPORT hawk_uch_t* hawk_rtx_valtoucstrdupwithcmgr ( hawk_rtx_t* rtx, /**< runtime context */ const hawk_val_t* val, /**< value to convert */ - hawk_oow_t* len, /**< result length */ - hawk_cmgr_t* cmgr + hawk_oow_t* len, /**< result length */ + hawk_cmgr_t* cmgr ); diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index b9b3282b..af5bffda 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -2177,7 +2177,7 @@ int hawk_delgblwithucstr (hawk_t* hawk, const hawk_uch_t* name) return 0; } -int hawk_findgblwithbcstr (hawk_t* hawk, const hawk_bch_t* name) +int hawk_findgblwithbcstr (hawk_t* hawk, const hawk_bch_t* name, int inc_builtins) { hawk_oow_t n; hawk_bcs_t ncs; @@ -2187,7 +2187,7 @@ int hawk_findgblwithbcstr (hawk_t* hawk, const hawk_bch_t* name) ncs.len = hawk_count_bcstr(name); #if defined(HAWK_OOCH_IS_BCH) - n = hawk_arr_search(hawk->parse.gbls, HAWK_NUM_STATIC_GBLS, ncs.ptr, ncs.len); + n = hawk_arr_search(hawk->parse.gbls, (inc_builtins? 0: HAWK_NUM_STATIC_GBLS), ncs.ptr, ncs.len); if (n == HAWK_ARR_NIL) { hawk_seterrfmt (hawk, HAWK_NULL, HAWK_ENOENT, FMT_ENOENT_GBL_HS, ncs.len, ncs.ptr); @@ -2196,7 +2196,7 @@ int hawk_findgblwithbcstr (hawk_t* hawk, const hawk_bch_t* name) #else wcs.ptr = hawk_dupbtoucstr(hawk, ncs.ptr, &wcs.len, 0); if (!wcs.ptr) return -1; - n = hawk_arr_search(hawk->parse.gbls, HAWK_NUM_STATIC_GBLS, wcs.ptr, wcs.len); + n = hawk_arr_search(hawk->parse.gbls, (inc_builtins? 0: HAWK_NUM_STATIC_GBLS), wcs.ptr, wcs.len); if (n == HAWK_ARR_NIL) { hawk_seterrfmt (hawk, HAWK_NULL, HAWK_ENOENT, FMT_ENOENT_GBL_LS, wcs.len, wcs.ptr); @@ -2209,7 +2209,7 @@ int hawk_findgblwithbcstr (hawk_t* hawk, const hawk_bch_t* name) return (int)n; } -int hawk_findgblwithucstr (hawk_t* hawk, const hawk_uch_t* name) +int hawk_findgblwithucstr (hawk_t* hawk, const hawk_uch_t* name, int inc_builtins) { hawk_oow_t n; hawk_ucs_t ncs; @@ -2221,7 +2221,7 @@ int hawk_findgblwithucstr (hawk_t* hawk, const hawk_uch_t* name) #if defined(HAWK_OOCH_IS_BCH) mbs.ptr = hawk_duputobcstr(hawk, ncs.ptr, &mbs.len); if (!mbs.ptr) return -1; - n = hawk_arr_search(hawk->parse.gbls, HAWK_NUM_STATIC_GBLS, mbs.ptr, mbs.len); + n = hawk_arr_search(hawk->parse.gbls, (inc_builtins? 0: HAWK_NUM_STATIC_GBLS), mbs.ptr, mbs.len); if (n == HAWK_ARR_NIL) { hawk_seterrfmt (hawk, HAWK_NULL, HAWK_ENOENT, FMT_ENOENT_GBL_HS, mbs.len, mbs.ptr); @@ -2230,7 +2230,7 @@ int hawk_findgblwithucstr (hawk_t* hawk, const hawk_uch_t* name) } hawk_freemem (hawk, mbs.ptr); #else - n = hawk_arr_search(hawk->parse.gbls, HAWK_NUM_STATIC_GBLS, ncs.ptr, ncs.len); + n = hawk_arr_search(hawk->parse.gbls, (inc_builtins? 0: HAWK_NUM_STATIC_GBLS), ncs.ptr, ncs.len); if (n == HAWK_ARR_NIL) { hawk_seterrfmt (hawk, HAWK_NULL, HAWK_ENOENT, FMT_ENOENT_GBL_LS, ncs.len, ncs.ptr); @@ -6772,6 +6772,29 @@ static int classify_ident (hawk_t* awk, const hawk_oocs_t* name) return TOK_IDENT; } +int hawk_isvalidident (hawk_t* hawk, const hawk_ooch_t* name) +{ + hawk_ooch_t c; + hawk_oocs_t cs; + + cs.ptr = (hawk_ooch_t*)name; + + if ((c = *name) == '_' || hawk_is_ooch_alpha(c)) + { + do + { + c = *++name; + } + while (c == '_' || hawk_is_ooch_alpha(c) || hawk_is_ooch_digit(c)); + if (c != '\0') return 0; + + cs.len = name - cs.ptr; + return classify_ident(hawk, &cs) == TOK_IDENT; + } + + return 0; +} + struct deparse_func_t { hawk_t* awk; diff --git a/hawk/lib/run.c b/hawk/lib/run.c index bc213b50..ead6ddfb 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -634,6 +634,42 @@ HAWK_INLINE int hawk_rtx_setgbl (hawk_rtx_t* rtx, int id, hawk_val_t* val) return set_global(rtx, id, HAWK_NULL, val, 0); } +int hawk_rtx_setgblbyname (hawk_rtx_t* rtx, const hawk_ooch_t* name, const hawk_ooch_t* val) +{ + int id, n; + hawk_val_t* v; + + HAWK_ASSERT (hawk_isvalidident(hawk_rtx_gethawk(rtx), name)); + + id = hawk_findgblwithoocstr(hawk_rtx_gethawk(rtx), name, 1); + v = hawk_rtx_makestrvalwithoocstr(rtx, val); + if (!v) return -1; + + hawk_rtx_refupval (rtx, v); + if (id <= -1) + { + /* not found. it's not a builtin/declared global variable */ + hawk_nde_var_t var; + + /* make a fake variable node for assignment and use it */ + HAWK_MEMSET (&var, 0, HAWK_SIZEOF(var)); + var.type = HAWK_NDE_NAMED; + var.id.name.ptr = (hawk_ooch_t*)name; + var.id.name.len = hawk_count_oocstr(name); + var.id.idxa = (hawk_oow_t)-1; + var.idx = HAWK_NULL; + + n = do_assignment_nonidx(rtx, &var, v)? 0: -1; + } + else + { + n = set_global(rtx, id, HAWK_NULL, v, 1); + } + hawk_rtx_refdownval (rtx, v); + + return n; +} + int hawk_rtx_setscriptnamewithuchars (hawk_rtx_t* rtx, const hawk_uch_t* name, hawk_oow_t len) { hawk_val_t* tmp; @@ -643,7 +679,7 @@ int hawk_rtx_setscriptnamewithuchars (hawk_rtx_t* rtx, const hawk_uch_t* name, h if (tmp == HAWK_NULL) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_SCRIPTNAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_SCRIPTNAME, tmp); hawk_rtx_refdownval (rtx, tmp); return n; @@ -658,7 +694,7 @@ int hawk_rtx_setscriptnamewithbchars (hawk_rtx_t* rtx, const hawk_bch_t* name, h if (tmp == HAWK_NULL) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_SCRIPTNAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_SCRIPTNAME, tmp); hawk_rtx_refdownval (rtx, tmp); return n; @@ -673,7 +709,7 @@ int hawk_rtx_setfilenamewithuchars (hawk_rtx_t* rtx, const hawk_uch_t* name, haw if (HAWK_UNLIKELY(!tmp)) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_FILENAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_FILENAME, tmp); hawk_rtx_refdownval (rtx, tmp); return n; @@ -688,7 +724,7 @@ int hawk_rtx_setfilenamewithbchars (hawk_rtx_t* rtx, const hawk_bch_t* name, haw if (HAWK_UNLIKELY(!tmp)) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_FILENAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_FILENAME, tmp); hawk_rtx_refdownval (rtx, tmp); return n; @@ -706,7 +742,7 @@ int hawk_rtx_setofilenamewithuchars (hawk_rtx_t* rtx, const hawk_uch_t* name, ha if (HAWK_UNLIKELY(!tmp)) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_OFILENAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_OFILENAME, tmp); hawk_rtx_refdownval (rtx, tmp); } else n = 0; @@ -725,7 +761,7 @@ int hawk_rtx_setofilenamewithbchars (hawk_rtx_t* rtx, const hawk_bch_t* name, ha if (HAWK_UNLIKELY(!tmp)) return -1; hawk_rtx_refupval (rtx, tmp); - n = hawk_rtx_setgbl (rtx, HAWK_GBL_OFILENAME, tmp); + n = hawk_rtx_setgbl(rtx, HAWK_GBL_OFILENAME, tmp); hawk_rtx_refdownval (rtx, tmp); } else n = 0; @@ -1183,6 +1219,7 @@ static void fini_rtx (hawk_rtx_t* rtx, int fini_globals) static int update_fnr (hawk_rtx_t* rtx, hawk_int_t fnr, hawk_int_t nr) { hawk_val_t* tmp1, * tmp2; + int n; tmp1 = hawk_rtx_makeintval(rtx, fnr); if (!tmp1) return -1; @@ -1193,32 +1230,18 @@ static int update_fnr (hawk_rtx_t* rtx, hawk_int_t fnr, hawk_int_t nr) else { tmp2 = hawk_rtx_makeintval(rtx, nr); - if (!tmp2) - { - hawk_rtx_refdownval (rtx, tmp1); - return -1; - } - + if (!tmp2) { n = -1; goto oops; } hawk_rtx_refupval (rtx, tmp2); } - if (hawk_rtx_setgbl (rtx, HAWK_GBL_FNR, tmp1) == -1) - { - if (nr != fnr) hawk_rtx_refdownval (rtx, tmp2); - hawk_rtx_refdownval (rtx, tmp1); - return -1; - } + n = (hawk_rtx_setgbl(rtx, HAWK_GBL_FNR, tmp1) <= -1 || + hawk_rtx_setgbl(rtx, HAWK_GBL_NR, tmp2) <= -1)? -1: 0; - if (hawk_rtx_setgbl (rtx, HAWK_GBL_NR, tmp2) == -1) - { - if (nr != fnr) hawk_rtx_refdownval (rtx, tmp2); - hawk_rtx_refdownval (rtx, tmp1); - return -1; - } + if (tmp2 != tmp1) hawk_rtx_refdownval (rtx, tmp2); - if (nr != fnr) hawk_rtx_refdownval (rtx, tmp2); +oops: hawk_rtx_refdownval (rtx, tmp1); - return 0; + return n; } /* @@ -1271,7 +1294,7 @@ static int defaultify_globals (hawk_rtx_t* rtx) int idx; const hawk_ooch_t* str[2]; }; - static struct gtab_t gtab[8] = + static struct gtab_t gtab[9] = { { HAWK_GBL_CONVFMT, { DEFAULT_CONVFMT, DEFAULT_CONVFMT } }, { HAWK_GBL_FILENAME, { HAWK_NULL, HAWK_NULL } }, @@ -6806,7 +6829,7 @@ static hawk_val_t* __eval_getbline (hawk_rtx_t* rtx, hawk_nde_t* nde) hawk_val_t* v = HAWK_NULL, * tmp; hawk_oocs_t dst; hawk_becs_t* buf; - int n, x; + int n; p = (hawk_nde_getline_t*)nde; diff --git a/hawk/lib/std.c b/hawk/lib/std.c index 86277de6..5698f1af 100644 --- a/hawk/lib/std.c +++ b/hawk/lib/std.c @@ -1671,6 +1671,23 @@ int hawk_parsestd (hawk_t* awk, hawk_parsestd_t in[], hawk_parsestd_t* out) return n; } +static int check_var_assign (hawk_rtx_t* rtx, hawk_ooch_t* str) +{ + hawk_ooch_t* eq, * var; + int n; + + eq = hawk_find_oochar_in_oocstr(str, '='); + if (!eq || eq <= str) return 0; /* not assignment */ + + var = hawk_rtx_dupoochars(rtx, str, eq - str); + if (HAWK_UNLIKELY(!var)) return -1; + + n = hawk_isvalidident(hawk_rtx_gethawk(rtx), var)? + ((hawk_rtx_setgblbyname(rtx, var, eq + 1) <= -1)? -1: 1): 0; + hawk_rtx_freemem (rtx, var); + return n; +} + /*** RTX_OPENSTD ***/ static ioattr_t* get_ioattr (hawk_htb_t* tab, const hawk_ooch_t* ptr, hawk_oow_t len); @@ -2032,6 +2049,7 @@ static int open_rio_console (hawk_rtx_t* rtx, hawk_rio_arg_t* riod) hawk_oow_t ibuflen; hawk_val_t* v; hawk_oocs_t as; + int x; nextfile: file = rxtn->c.in.files[rxtn->c.in.index]; @@ -2071,7 +2089,14 @@ static int open_rio_console (hawk_rtx_t* rtx, hawk_rio_arg_t* riod) */ argv = hawk_rtx_getgbl(rtx, xtn->gbl_argv); HAWK_ASSERT (argv != HAWK_NULL); - HAWK_ASSERT (HAWK_RTX_GETVALTYPE (rtx, argv) == HAWK_VAL_MAP); + if (HAWK_RTX_GETVALTYPE(rtx, argv) != HAWK_VAL_MAP) + { + /* with flexmap on, you can change ARGV to a scalar. + * BEGIN { ARGV="xxx"; } + * you must not do this. */ + hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_EINVAL, HAWK_T("phony value in ARGV")); + return -1; + } map = ((hawk_val_map_t*)argv)->map; HAWK_ASSERT (map != HAWK_NULL); @@ -2105,9 +2130,23 @@ static int open_rio_console (hawk_rtx_t* rtx, hawk_rio_arg_t* riod) file = as.ptr; - -/* TODO: special awk quarkyness - check if the file name is var=val format. - * if so, do variable assignment */ + /* + * this is different from the -v option. + * if an argument has a special form of var=val, it is treated specially + * + * on the command-line + * hawk -f a.awk a=20 /etc/passwd + * or via ARGV + * hawk 'BEGIN { ARGV[1] = "a=20"; } + * { print a $1; }' dummy /etc/hosts + */ + if ((x = check_var_assign(rtx, file)) != 0) + { + hawk_rtx_freevaloocstr (rtx, v, as.ptr); + if (HAWK_UNLIKELY(x <= -1)) return -1; + rxtn->c.in.index++; + goto nextfile; + } sio = (file[0] == HAWK_T('-') && file[1] == HAWK_T('\0'))? open_sio_std_rtx(rtx, HAWK_SIO_STDIN, HAWK_SIO_READ | HAWK_SIO_IGNOREECERR): diff --git a/hawk/lib/tree-prv.h b/hawk/lib/tree-prv.h index 6ac64a9e..f42e72a1 100644 --- a/hawk/lib/tree-prv.h +++ b/hawk/lib/tree-prv.h @@ -129,7 +129,7 @@ struct hawk_nde_cnd_t struct hawk_nde_pos_t { HAWK_NDE_HDR; - hawk_nde_t* val; + hawk_nde_t* val; }; /* HAWK_NDE_INT */