migrated rand(), srand(), system() to modules

This commit is contained in:
hyung-hwan 2014-07-11 07:42:28 +00:00
parent 82a639045f
commit fdce5fc592
9 changed files with 176 additions and 237 deletions

View File

@ -115,13 +115,6 @@ protected:
int __build_environ (Run* run, void* envptr);
// intrinsic functions
int rand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
int srand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
int system (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
qse_cmgr_t* getcmgr (const char_t* ioname);
int setioattr (Run& run, Value& ret, Value* args, size_t nargs,
@ -159,13 +152,11 @@ protected:
flt_t pow (flt_t x, flt_t y);
flt_t mod (flt_t x, flt_t y);
void* modopen (const mod_spec_t* spec);
void modclose (void* handle);
void* modsym (void* handle, const char_t* name);
void* modopen (const mod_spec_t* spec);
void modclose (void* handle);
void* modsym (void* handle, const char_t* name);
protected:
int_t seed;
uint_t prand;
qse_htb_t cmgrtab;
bool cmgrtab_inited;

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

@ -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 } }
};

View File

@ -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'. */

View File

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