migrated rand(), srand(), system() to modules
This commit is contained in:
		| @ -1623,7 +1623,7 @@ int Awk::addFunction ( | ||||
| 	spec.arg.min = minArgs; | ||||
| 	spec.arg.max = maxArgs; | ||||
| 	spec.arg.spec = argSpec; | ||||
| 	spec.impl = functionHandler; | ||||
| 	spec.impl = this->functionHandler; | ||||
| 	spec.trait = validOpts; | ||||
|  | ||||
| 	qse_awk_fnc_t* fnc = qse_awk_addfnc (awk, name, &spec); | ||||
|  | ||||
| @ -26,7 +26,6 @@ | ||||
| #include <qse/cmn/sio.h> | ||||
| #include <qse/cmn/nwio.h> | ||||
| #include <qse/cmn/path.h> | ||||
| #include <qse/cmn/alg.h> | ||||
| #include "awk.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
| @ -128,11 +127,11 @@ int StdAwk::open () | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (addFunction (QSE_T("rand"),       0, 0, QSE_NULL,     (FunctionHandler)&StdAwk::rand,      0) <= -1 || | ||||
| 	    addFunction (QSE_T("srand"),      0, 1, QSE_NULL,     (FunctionHandler)&StdAwk::srand,     0) <= -1 || | ||||
| 	    addFunction (QSE_T("system"),     1, 1, QSE_NULL,     (FunctionHandler)&StdAwk::system,    0) <= -1 || | ||||
| 	    addFunction (QSE_T("setioattr"),  3, 3, QSE_NULL,     (FunctionHandler)&StdAwk::setioattr, QSE_AWK_RIO) <= -1 || | ||||
| 	    addFunction (QSE_T("getioattr"),  3, 3, QSE_T("vvr"), (FunctionHandler)&StdAwk::getioattr, QSE_AWK_RIO) <= -1) | ||||
| 	if (addFunction (QSE_T("rand"),       1, 0, QSE_T("math"),   QSE_NULL,                            0) <= -1 || | ||||
| 	    addFunction (QSE_T("srand"),      1, 0, QSE_T("math"),   QSE_NULL,                            0) <= -1 || | ||||
| 	    addFunction (QSE_T("system"),     1, 0, QSE_T("sys"),    QSE_NULL,                            0) <= -1 || | ||||
| 	    addFunction (QSE_T("setioattr"),  3, 3, QSE_NULL,        (FunctionHandler)&StdAwk::setioattr, QSE_AWK_RIO) <= -1 || | ||||
| 	    addFunction (QSE_T("getioattr"),  3, 3, QSE_T("vvr"),    (FunctionHandler)&StdAwk::getioattr, QSE_AWK_RIO) <= -1) | ||||
| 	{ | ||||
| 		goto oops; | ||||
| 	} | ||||
| @ -145,15 +144,6 @@ int StdAwk::open () | ||||
| 	if (lt_dlinit() != 0) goto oops; | ||||
| #endif | ||||
|  | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	this->seed = (qse_gettime(&now) <= -1)? 0u: ((int_t)now.sec + (int_t)now.nsec); | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	this->prand = (uint_t)(this->seed * this->seed * this->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (this->prand == 0) this->prand++; | ||||
|  | ||||
| 	this->cmgrtab_inited = false; | ||||
| 	return 0; | ||||
|  | ||||
| @ -336,69 +326,6 @@ int StdAwk::make_additional_globals (Run* run) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int StdAwk::rand (Run& run, Value& ret, Value* args, size_t nargs, | ||||
| 	const char_t* name, size_t len) | ||||
| { | ||||
| #define RANDV_MAX QSE_TYPE_MAX(int_t) | ||||
|  | ||||
| #if defined(QSE_USE_AWK_INTMAX) | ||||
| 	this->prand = qse_randxsuintmax (this->prand); | ||||
| #else | ||||
| 	this->prand = qse_randxsulong (this->prand); | ||||
| #endif | ||||
|  | ||||
|      int_t randv = this->prand % RANDV_MAX; | ||||
| 	return ret.setFlt ((flt_t)randv / RANDV_MAX); | ||||
| #undef RANDV_MAX  | ||||
| } | ||||
|  | ||||
| int StdAwk::srand (Run& run, Value& ret, Value* args, size_t nargs, | ||||
| 	const char_t* name, size_t len) | ||||
| { | ||||
| 	int_t prevSeed = (int_t)this->seed; | ||||
|  | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	if (nargs <= 0) | ||||
| 	{ | ||||
| 		this->seed = (qse_gettime (&now) <= -1)? | ||||
| 			(this->seed * this->seed): ((int_t)now.sec + (int_t)now.nsec); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		this->seed = args[0].toInt(); | ||||
| 	} | ||||
|  | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	this->prand = (uint_t)(this->seed * this->seed * this->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (this->prand == 0) this->prand++; | ||||
|  | ||||
| 	return ret.setInt ((int_t)prevSeed); | ||||
| } | ||||
|  | ||||
| int StdAwk::system (Run& run, Value& ret, Value* args, size_t nargs, | ||||
| 	const char_t* name, size_t len) | ||||
| { | ||||
| 	size_t l; | ||||
| 	const char_t* ptr = args[0].toStr(&l); | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| 	return ret.setInt ((int_t)::_tsystem(ptr)); | ||||
| #elif defined(QSE_CHAR_IS_MCHAR) | ||||
| 	return ret.setInt ((int_t)::system(ptr)); | ||||
| #else | ||||
|  | ||||
| 	qse_mchar_t* mbs; | ||||
| 	mbs = qse_wcstombsdup (ptr, QSE_NULL, ((Awk*)run)->getMmgr()); | ||||
| 	if (mbs == QSE_NULL) return -1; | ||||
| 	int n = ret.setInt ((int_t)::system(mbs)); | ||||
| 	QSE_MMGR_FREE (((Awk*)run)->getMmgr(), mbs); | ||||
| 	return n; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| qse_cmgr_t* StdAwk::getcmgr (const char_t* ioname) | ||||
| { | ||||
| 	QSE_ASSERT (this->cmgrtab_inited == true); | ||||
|  | ||||
| @ -21,6 +21,8 @@ | ||||
| #include "mod-str.h" | ||||
| #include <qse/cmn/str.h> | ||||
| #include <qse/cmn/chr.h> | ||||
| #include <qse/cmn/alg.h> | ||||
| #include <qse/cmn/time.h> | ||||
| #include "../cmn/mem.h" | ||||
| #include "fnc.h" | ||||
|  | ||||
| @ -53,6 +55,12 @@ | ||||
| #	endif | ||||
| #endif | ||||
|  | ||||
| typedef struct modctx_t | ||||
| { | ||||
| 	qse_awk_int_t seed;	 | ||||
| 	qse_awk_uint_t prand; /* last random value returned */ | ||||
| } modctx_t; | ||||
|  | ||||
| static int fnc_math_1 ( | ||||
| 	qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi, qse_awk_math1_t f) | ||||
| { | ||||
| @ -454,6 +462,73 @@ static int fnc_sqrt (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| 	return fnc_math_1 (rtx, fi, math_sqrt); | ||||
| } | ||||
|  | ||||
| /* ----------------------------------------------------------------------- */ | ||||
|  | ||||
| static int fnc_rand (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| #define RANDV_MAX QSE_TYPE_MAX(qse_awk_int_t) | ||||
| 	qse_awk_val_t* r; | ||||
| 	qse_awk_int_t randv; | ||||
| 	modctx_t* modctx; | ||||
|  | ||||
| 	modctx = (modctx_t*)fi->mod->ctx; | ||||
|  | ||||
| #if defined(QSE_USE_AWK_INTMAX) | ||||
| 	modctx->prand = qse_randxsuintmax (modctx->prand); | ||||
| #else | ||||
| 	modctx->prand = qse_randxsulong (modctx->prand); | ||||
| #endif | ||||
| 	randv = modctx->prand % RANDV_MAX; | ||||
|  | ||||
| 	r = qse_awk_rtx_makefltval (rtx, (qse_awk_flt_t)randv / RANDV_MAX); | ||||
| 	if (r == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, r); | ||||
| 	return 0; | ||||
| #undef RANDV_MAX | ||||
| } | ||||
|  | ||||
| static int fnc_srand (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| 	qse_size_t nargs; | ||||
| 	qse_awk_val_t* a0; | ||||
| 	qse_awk_int_t lv; | ||||
| 	qse_awk_val_t* r; | ||||
| 	int n; | ||||
| 	qse_awk_int_t prev; | ||||
| 	qse_ntime_t now; | ||||
| 	modctx_t* modctx; | ||||
|  | ||||
| 	modctx = (modctx_t*)fi->mod->ctx; | ||||
| 	nargs = qse_awk_rtx_getnargs (rtx); | ||||
| 	QSE_ASSERT (nargs == 0 || nargs == 1); | ||||
|  | ||||
| 	prev = modctx->seed; | ||||
|  | ||||
| 	if (nargs <= 0) | ||||
| 	{ | ||||
| 		modctx->seed = (qse_gettime (&now) <= -1)?  | ||||
| 			(modctx->seed * modctx->seed): ((qse_awk_int_t)now.sec + (qse_awk_int_t)now.nsec); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		a0 = qse_awk_rtx_getarg (rtx, 0); | ||||
| 		n = qse_awk_rtx_valtoint (rtx, a0, &lv); | ||||
| 		if (n <= -1) return -1; | ||||
| 		modctx->seed = lv; | ||||
| 	} | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	modctx->prand = (qse_awk_uint_t)(modctx->seed * modctx->seed * modctx->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (modctx->prand == 0) modctx->prand++; | ||||
|  | ||||
| 	r = qse_awk_rtx_makeintval (rtx, prev); | ||||
| 	if (r == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, r); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* ----------------------------------------------------------------------- */ | ||||
|  | ||||
| @ -478,10 +553,12 @@ static fnctab_t fnctab[] = | ||||
| 	{ QSE_T("floor"),   { { 1, 1, QSE_NULL },     fnc_floor,      0 } }, | ||||
| 	{ QSE_T("log"),     { { 1, 1, QSE_NULL },     fnc_log,        0 } }, | ||||
| 	{ QSE_T("log10"),   { { 1, 1, QSE_NULL },     fnc_log10,      0 } }, | ||||
| 	{ QSE_T("rand"),    { { 0, 0, QSE_NULL },     fnc_rand,       0 } }, | ||||
| 	{ QSE_T("round"),   { { 1, 1, QSE_NULL },     fnc_round,      0 } }, | ||||
| 	{ QSE_T("sin"),     { { 1, 1, QSE_NULL },     fnc_sin,        0 } }, | ||||
| 	{ QSE_T("sinh"),    { { 1, 1, QSE_NULL },     fnc_sinh,       0 } }, | ||||
| 	{ QSE_T("sqrt"),    { { 1, 1, QSE_NULL },     fnc_sqrt,       0 } }, | ||||
| 	{ QSE_T("srand"),   { { 0, 1, QSE_NULL },     fnc_srand,      0 } }, | ||||
| 	{ QSE_T("tan"),     { { 1, 1, QSE_NULL },     fnc_tan,        0 } }, | ||||
| 	{ QSE_T("tanh"),    { { 1, 1, QSE_NULL },     fnc_tanh,       0 } } | ||||
| }; | ||||
| @ -541,27 +618,44 @@ static int init (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx) | ||||
|  | ||||
| static void fini (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx) | ||||
| { | ||||
| 	/* TODO:  | ||||
| 	for (each pid for rtx) kill (pid, SIGKILL); | ||||
| 	for (each pid for rtx) waitpid (pid, QSE_NULL, 0); | ||||
| 	*/ | ||||
| 	/* TODO: anything */ | ||||
| } | ||||
|  | ||||
| static void unload (qse_awk_mod_t* mod, qse_awk_t* awk) | ||||
| { | ||||
| 	/* TODO: anything */ | ||||
| 	modctx_t* modctx; | ||||
|  | ||||
| 	modctx = (modctx_t*)mod->ctx; | ||||
| 	qse_awk_freemem (awk, modctx); | ||||
| } | ||||
|  | ||||
| int qse_awk_mod_math (qse_awk_mod_t* mod, qse_awk_t* awk) | ||||
| { | ||||
| 	modctx_t* modctx; | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	modctx = qse_awk_allocmem (awk, QSE_SIZEOF(*modctx)); | ||||
| 	if (modctx == QSE_NULL)  | ||||
| 	{ | ||||
| 		qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	QSE_MEMSET (modctx, 0, QSE_SIZEOF(*modctx)); | ||||
|  | ||||
| 	modctx->seed = (qse_gettime (&now) <= -1)? 0u: ((qse_awk_int_t)now.sec + (qse_awk_int_t)now.nsec); | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	modctx->prand = (qse_awk_uint_t)(modctx->seed * modctx->seed * modctx->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (modctx->prand == 0) modctx->prand++; | ||||
|  | ||||
| 	mod->query = query; | ||||
| 	mod->unload = unload; | ||||
|  | ||||
| 	mod->init = init; | ||||
| 	mod->fini = fini; | ||||
| 	/* | ||||
| 	mod->ctx... | ||||
| 	 */ | ||||
| 	mod->ctx = modctx; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -301,10 +301,7 @@ static int init (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx) | ||||
|  | ||||
| static void fini (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx) | ||||
| { | ||||
| 	/* TODO:  | ||||
| 	for (each pid for rtx) kill (pid, SIGKILL); | ||||
| 	for (each pid for rtx) waitpid (pid, QSE_NULL, 0); | ||||
| 	*/ | ||||
| 	/* TODO: anything */ | ||||
| } | ||||
|  | ||||
| static void unload (qse_awk_mod_t* mod, qse_awk_t* awk) | ||||
|  | ||||
| @ -23,11 +23,13 @@ | ||||
| #include <qse/cmn/time.h> | ||||
| #include <qse/cmn/nwif.h> | ||||
| #include <qse/cmn/nwad.h> | ||||
| #include <qse/cmn/mbwc.h> | ||||
| #include "../cmn/mem.h" | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #	include <windows.h> | ||||
| #	include <process.h> | ||||
| #	include <tchar.h> | ||||
| #elif defined(__OS2__) | ||||
| #	define INCL_DOSPROCESS | ||||
| #	define INCL_DOSEXCEPTIONS | ||||
| @ -42,7 +44,7 @@ | ||||
| #	endif | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> /* getenv */ | ||||
| #include <stdlib.h> /* getenv, system */ | ||||
|  | ||||
| static int fnc_fork (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| @ -597,6 +599,56 @@ static int fnc_getnwifcfg (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int fnc_system (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| 	qse_awk_val_t* v, * a0; | ||||
| 	qse_char_t* str; | ||||
| 	qse_size_t len; | ||||
| 	int n = 0; | ||||
|  | ||||
| 	a0 = qse_awk_rtx_getarg (rtx, 0); | ||||
| 	str = qse_awk_rtx_getvalstr (rtx, a0, &len); | ||||
| 	if (str == QSE_NULL) return -1; | ||||
|  | ||||
| 	/* the target name contains a null character. | ||||
| 	 * make system return -1 */ | ||||
| 	if (qse_strxchr (str, len, QSE_T('\0'))) | ||||
| 	{ | ||||
| 		n = -1; | ||||
| 		goto skip_system; | ||||
| 	} | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| 	n = _tsystem (str); | ||||
| #elif defined(QSE_CHAR_IS_MCHAR) | ||||
| 	n = system (str); | ||||
| #else | ||||
|  | ||||
| 	{ | ||||
| 		qse_mchar_t* mbs; | ||||
| 		mbs = qse_wcstombsdup (str, QSE_NULL, qse_awk_rtx_getmmgr(rtx)); | ||||
| 		if (mbs == QSE_NULL)  | ||||
| 		{ | ||||
| 			n = -1; | ||||
| 			goto skip_system; | ||||
| 		} | ||||
| 		n = system (mbs); | ||||
| 		qse_awk_rtx_freemem (rtx, mbs); | ||||
| 	} | ||||
|  | ||||
| #endif | ||||
|  | ||||
| skip_system: | ||||
| 	qse_awk_rtx_freevalstr (rtx, a0, str); | ||||
|  | ||||
| 	v = qse_awk_rtx_makeintval (rtx, (qse_awk_int_t)n); | ||||
| 	if (v == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, v); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| typedef struct fnctab_t fnctab_t; | ||||
| struct fnctab_t | ||||
| { | ||||
| @ -630,6 +682,7 @@ static fnctab_t fnctab[] = | ||||
| 	{ QSE_T("kill"),       { { 2, 2, QSE_NULL     }, fnc_kill,       0  } }, | ||||
| 	{ QSE_T("settime"),    { { 1, 1, QSE_NULL     }, fnc_settime,    0  } }, | ||||
| 	{ QSE_T("sleep"),      { { 1, 1, QSE_NULL     }, fnc_sleep,      0  } }, | ||||
| 	{ QSE_T("system"),     { { 1, 1, QSE_NULL     }, fnc_system,     0  } }, | ||||
| 	{ QSE_T("wait"),       { { 1, 1, QSE_NULL     }, fnc_wait,       0  } } | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -2089,7 +2089,7 @@ static qse_awk_nde_t* parse_if (qse_awk_t* awk, const qse_awk_loc_t* xloc) | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| /* TODO: optimization. if you know 'tese' evaluates to true or false, | ||||
| /* TODO: optimization. if you know 'test' evaluates to true or false, | ||||
|  *       you can drop the 'if' statement and take either the 'then_part' | ||||
|  *       or 'else_part'. */ | ||||
|  | ||||
|  | ||||
| @ -29,7 +29,6 @@ | ||||
| #include <qse/cmn/path.h> | ||||
| #include <qse/cmn/htb.h> | ||||
| #include <qse/cmn/env.h> | ||||
| #include <qse/cmn/alg.h> | ||||
| #include "../cmn/mem.h" | ||||
|  | ||||
| #include <stdarg.h> | ||||
| @ -113,9 +112,6 @@ typedef struct xtn_t | ||||
|  | ||||
| typedef struct rxtn_t | ||||
| { | ||||
| 	qse_awk_int_t seed;	 | ||||
| 	qse_awk_uint_t prand; /* last random value returned */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		struct { | ||||
| @ -1903,7 +1899,6 @@ qse_awk_rtx_t* qse_awk_rtx_openstd ( | ||||
| 	qse_awk_rio_t rio; | ||||
| 	rxtn_t* rxtn; | ||||
| 	xtn_t* xtn; | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	xtn = (xtn_t*)QSE_XTN (awk); | ||||
|  | ||||
| @ -1938,13 +1933,6 @@ qse_awk_rtx_t* qse_awk_rtx_openstd ( | ||||
| 	rxtn->ecb.close = fini_rxtn; | ||||
| 	qse_awk_rtx_pushecb (rtx, &rxtn->ecb); | ||||
|  | ||||
| 	rxtn->seed = (qse_gettime (&now) <= -1)? 0u: ((qse_awk_int_t)now.sec + (qse_awk_int_t)now.nsec); | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	rxtn->prand = (qse_awk_uint_t)(rxtn->seed * rxtn->seed * rxtn->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (rxtn->prand == 0) rxtn->prand++; | ||||
|  | ||||
| 	rxtn->c.in.files = icf; | ||||
| 	rxtn->c.in.index = 0; | ||||
| 	rxtn->c.in.count = 0; | ||||
| @ -1990,120 +1978,6 @@ void* qse_awk_rtx_getxtnstd (qse_awk_rtx_t* rtx) | ||||
| 	return (void*)((rxtn_t*)QSE_XTN(rtx) + 1); | ||||
| } | ||||
|  | ||||
| static int fnc_rand (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| #define RANDV_MAX QSE_TYPE_MAX(qse_awk_int_t) | ||||
| 	qse_awk_val_t* r; | ||||
| 	qse_awk_int_t randv; | ||||
| 	rxtn_t* rxtn; | ||||
|  | ||||
| 	rxtn = (rxtn_t*) QSE_XTN (rtx); | ||||
|  | ||||
| #if defined(QSE_USE_AWK_INTMAX) | ||||
| 	rxtn->prand = qse_randxsuintmax (rxtn->prand); | ||||
| #else | ||||
| 	rxtn->prand = qse_randxsulong (rxtn->prand); | ||||
| #endif | ||||
| 	randv = rxtn->prand % RANDV_MAX; | ||||
|  | ||||
| 	r = qse_awk_rtx_makefltval (rtx, (qse_awk_flt_t)randv / RANDV_MAX); | ||||
| 	if (r == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, r); | ||||
| 	return 0; | ||||
| #undef RANDV_MAX | ||||
| } | ||||
|  | ||||
| static int fnc_srand (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| 	qse_size_t nargs; | ||||
| 	qse_awk_val_t* a0; | ||||
| 	qse_awk_int_t lv; | ||||
| 	qse_awk_val_t* r; | ||||
| 	int n; | ||||
| 	qse_awk_int_t prev; | ||||
| 	qse_ntime_t now; | ||||
| 	rxtn_t* rxtn; | ||||
|  | ||||
| 	rxtn = (rxtn_t*) QSE_XTN (rtx); | ||||
| 	nargs = qse_awk_rtx_getnargs (rtx); | ||||
| 	QSE_ASSERT (nargs == 0 || nargs == 1); | ||||
|  | ||||
| 	prev = rxtn->seed; | ||||
|  | ||||
| 	if (nargs <= 0) | ||||
| 	{ | ||||
| 		rxtn->seed = (qse_gettime (&now) <= -1)?  | ||||
| 			(rxtn->seed * rxtn->seed): ((qse_awk_int_t)now.sec + (qse_awk_int_t)now.nsec); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		a0 = qse_awk_rtx_getarg (rtx, 0); | ||||
| 		n = qse_awk_rtx_valtoint (rtx, a0, &lv); | ||||
| 		if (n <= -1) return -1; | ||||
| 		rxtn->seed = lv; | ||||
| 	} | ||||
| 	/* i don't care if the seed becomes negative or overflows. | ||||
| 	 * i just convert the signed value to the unsigned one. */ | ||||
| 	rxtn->prand = (qse_awk_uint_t)(rxtn->seed * rxtn->seed * rxtn->seed); | ||||
| 	/* make sure that the actual seeding is not 0 */ | ||||
| 	if (rxtn->prand == 0) rxtn->prand++; | ||||
|  | ||||
| 	r = qse_awk_rtx_makeintval (rtx, prev); | ||||
| 	if (r == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, r); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int fnc_system (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| { | ||||
| 	qse_awk_val_t* v, * a0; | ||||
| 	qse_char_t* str; | ||||
| 	qse_size_t len; | ||||
| 	int n = 0; | ||||
|  | ||||
| 	a0 = qse_awk_rtx_getarg (rtx, 0); | ||||
| 	str = qse_awk_rtx_getvalstr (rtx, a0, &len); | ||||
| 	if (str == QSE_NULL) return -1; | ||||
|  | ||||
| 	/* the target name contains a null character. | ||||
| 	 * make system return -1 */ | ||||
| 	if (qse_strxchr (str, len, QSE_T('\0'))) | ||||
| 	{ | ||||
| 		n = -1; | ||||
| 		goto skip_system; | ||||
| 	} | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| 	n = _tsystem (str); | ||||
| #elif defined(QSE_CHAR_IS_MCHAR) | ||||
| 	n = system (str); | ||||
| #else | ||||
|  | ||||
| 	{ | ||||
| 		qse_mchar_t* mbs; | ||||
| 		mbs = qse_wcstombsdup (str, QSE_NULL, rtx->awk->mmgr); | ||||
| 		if (mbs == QSE_NULL)  | ||||
| 		{ | ||||
| 			n = -1; | ||||
| 			goto skip_system; | ||||
| 		} | ||||
| 		n = system (mbs); | ||||
| 		QSE_AWK_FREE (rtx->awk, mbs); | ||||
| 	} | ||||
|  | ||||
| #endif | ||||
|  | ||||
| skip_system: | ||||
| 	qse_awk_rtx_freevalstr (rtx, a0, str); | ||||
|  | ||||
| 	v = qse_awk_rtx_makeintval (rtx, (qse_awk_int_t)n); | ||||
| 	if (v == QSE_NULL) return -1; | ||||
|  | ||||
| 	qse_awk_rtx_setretval (rtx, v); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int timeout_code (const qse_char_t* name) | ||||
| { | ||||
| @ -2407,11 +2281,14 @@ struct fnctab_t | ||||
|  | ||||
| static struct fnctab_t fnctab[] = | ||||
| { | ||||
| 	{ QSE_T("rand"),      { {0, 0, QSE_NULL},     fnc_rand,      0           } }, | ||||
| 	{ QSE_T("srand"),     { {0, 1, QSE_NULL},     fnc_srand,     0           } }, | ||||
| 	{ QSE_T("system"),    { {1, 1, QSE_NULL},     fnc_system ,   0           } }, | ||||
| 	{ QSE_T("setioattr"), { {3, 3, QSE_NULL},     fnc_setioattr, QSE_AWK_RIO } }, | ||||
| 	{ QSE_T("getioattr"), { {3, 3, QSE_T("vvr")}, fnc_getioattr, QSE_AWK_RIO } } | ||||
| 	/* additional aliases to module functions */ | ||||
| 	{ QSE_T("rand"),      { {1, 0, QSE_T("math")},  QSE_NULL,      0           } }, | ||||
| 	{ QSE_T("srand"),     { {1, 0, QSE_T("math")},  QSE_NULL,      0           } }, | ||||
| 	{ QSE_T("system"),    { {1, 0, QSE_T("sys")},   QSE_NULL ,     0           } },  | ||||
|  | ||||
| 	/* additional functions */ | ||||
| 	{ QSE_T("setioattr"), { {3, 3, QSE_NULL},       fnc_setioattr, QSE_AWK_RIO } }, | ||||
| 	{ QSE_T("getioattr"), { {3, 3, QSE_T("vvr")},   fnc_getioattr, QSE_AWK_RIO } } | ||||
| }; | ||||
|  | ||||
| static int add_functions (qse_awk_t* awk) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user