moved ARGC and ARGV to base to std for simplication of the base implementation.

note C++ wrappers need the same changes
This commit is contained in:
hyung-hwan 2012-08-05 08:56:42 +00:00
parent d03a4f4a33
commit 785c95b1e6
4 changed files with 149 additions and 181 deletions

View File

@ -71,11 +71,10 @@
* qse_awk_rtx_t* rtx; * qse_awk_rtx_t* rtx;
* qse_awk_sio_t sio; // need to initialize it with callback functions * qse_awk_sio_t sio; // need to initialize it with callback functions
* qse_awk_rio_t rio; // need to initialize it with callback functions * qse_awk_rio_t rio; // need to initialize it with callback functions
* qse_cstr_t args[5]; // need to initialize it with strings
* *
* awk = qse_awk_open (mmgr, 0, prm); // create an interpreter * awk = qse_awk_open (mmgr, 0, prm); // create an interpreter
* qse_awk_parse (awk, &sio); // parse a script * qse_awk_parse (awk, &sio); // parse a script
* rtx = qse_awk_rtx_open (awk, 0, &rio, args); // create a runtime context * rtx = qse_awk_rtx_open (awk, 0, &rio); // create a runtime context
* retv = qse_awk_rtx_loop (rtx); // run a standard AWK loop * retv = qse_awk_rtx_loop (rtx); // run a standard AWK loop
* if (retv != QSE_NULL) * if (retv != QSE_NULL)
* qse_awk_rtx_refdownval (rtx, retv); // free return value * qse_awk_rtx_refdownval (rtx, retv); // free return value
@ -1029,10 +1028,15 @@ enum qse_awk_gbl_id_t
{ {
/* this table should match gtab in parse.c. /* this table should match gtab in parse.c.
* in addition, qse_awk_rtx_setgbl also counts * in addition, qse_awk_rtx_setgbl also counts
* on the order of these values */ * on the order of these values.
*
* note that set_global() in run.c contains code
* preventing these global variables from being assigned
* with a map value. if you happen to add one that can
* be a map, don't forget to change code in set_global().
* but is this check really necessary???
*/
QSE_AWK_GBL_ARGC,
QSE_AWK_GBL_ARGV,
QSE_AWK_GBL_CONVFMT, QSE_AWK_GBL_CONVFMT,
QSE_AWK_GBL_FILENAME, QSE_AWK_GBL_FILENAME,
QSE_AWK_GBL_FNR, QSE_AWK_GBL_FNR,
@ -1052,7 +1056,7 @@ enum qse_awk_gbl_id_t
/* these are not not the actual IDs and are used internally only /* these are not not the actual IDs and are used internally only
* Make sure you update these values properly if you add more * Make sure you update these values properly if you add more
* ID definitions, however */ * ID definitions, however */
QSE_AWK_MIN_GBL_ID = QSE_AWK_GBL_ARGC, QSE_AWK_MIN_GBL_ID = QSE_AWK_GBL_CONVFMT,
QSE_AWK_MAX_GBL_ID = QSE_AWK_GBL_SUBSEP QSE_AWK_MAX_GBL_ID = QSE_AWK_GBL_SUBSEP
}; };
typedef enum qse_awk_gbl_id_t qse_awk_gbl_id_t; typedef enum qse_awk_gbl_id_t qse_awk_gbl_id_t;
@ -1559,17 +1563,14 @@ qse_size_t qse_awk_longtostr (
* It also allocates an extra memory block as large as the @a xtn bytes. * It also allocates an extra memory block as large as the @a xtn bytes.
* You can get the pointer to the beginning of the block with * You can get the pointer to the beginning of the block with
* qse_awk_rtx_getxtn(). The block is destroyed when the runtime context is * qse_awk_rtx_getxtn(). The block is destroyed when the runtime context is
* destroyed. The argument array @a arg, if not #QSE_NULL, is used to set * destroyed.
* @b ARGV. The @b ptr field and the @b len field of the last member of
* this array must be set to #QSE_NULL and 0 respectively.
* *
* @return new runtime context on success, #QSE_NULL on failure * @return new runtime context on success, #QSE_NULL on failure
*/ */
qse_awk_rtx_t* qse_awk_rtx_open ( qse_awk_rtx_t* qse_awk_rtx_open (
qse_awk_t* awk, /**< awk */ qse_awk_t* awk, /**< awk */
qse_size_t xtn, /**< size of extension in bytes */ qse_size_t xtn, /**< size of extension in bytes */
qse_awk_rio_t* rio, /**< runtime IO handlers */ qse_awk_rio_t* rio /**< runtime IO handlers */
const qse_cstr_t* arg /**< argument array to set ARGV */
); );
/** /**

View File

@ -284,9 +284,6 @@ struct global_t
static global_t gtab[] = static global_t gtab[] =
{ {
{ QSE_T("ARGC"), 4, 0 },
{ QSE_T("ARGV"), 4, 0 },
/* output real-to-str conversion format for other cases than 'print' */ /* output real-to-str conversion format for other cases than 'print' */
{ QSE_T("CONVFMT"), 7, 0 }, { QSE_T("CONVFMT"), 7, 0 },

View File

@ -101,7 +101,7 @@ static qse_size_t push_arg_from_vals (
static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio); static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio);
static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals); static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals);
static int init_globals (qse_awk_rtx_t* rtx, const qse_cstr_t* arg); static int init_globals (qse_awk_rtx_t* rtx);
static void refdown_globals (qse_awk_rtx_t* run, int pop); static void refdown_globals (qse_awk_rtx_t* run, int pop);
static int run_pblocks (qse_awk_rtx_t* rtx); static int run_pblocks (qse_awk_rtx_t* rtx);
@ -326,10 +326,12 @@ static int set_global (
return -1; return -1;
} }
/* builtin variables except ARGV cannot be assigned a map */ /* all the basic builtin variables cannot be assigned a map.
if (val->type == QSE_AWK_VAL_MAP && * if you happen to add one and if that's allowed to be a map,
(idx >= QSE_AWK_GBL_ARGC && idx <= QSE_AWK_GBL_SUBSEP) && * you may have to change the condition here.
idx != QSE_AWK_GBL_ARGV) * but is this check really necessary??? */
if (val->type == QSE_AWK_VAL_MAP &&
idx >= QSE_AWK_MIN_GBL_ID && idx <= QSE_AWK_MAX_GBL_ID)
{ {
/* TODO: better error code */ /* TODO: better error code */
SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP); SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP);
@ -686,8 +688,7 @@ qse_htb_t* qse_awk_rtx_getnvmap (qse_awk_rtx_t* rtx)
} }
qse_awk_rtx_t* qse_awk_rtx_open ( qse_awk_rtx_t* qse_awk_rtx_open (
qse_awk_t* awk, qse_size_t xtn, qse_awk_t* awk, qse_size_t xtn, qse_awk_rio_t* rio)
qse_awk_rio_t* rio, const qse_cstr_t* arg)
{ {
qse_awk_rtx_t* rtx; qse_awk_rtx_t* rtx;
@ -726,7 +727,7 @@ qse_awk_rtx_t* qse_awk_rtx_open (
return QSE_NULL; return QSE_NULL;
} }
if (init_globals (rtx, arg) <= -1) if (init_globals (rtx) <= -1)
{ {
awk->errinf = rtx->errinf; /* transfer error info */ awk->errinf = rtx->errinf; /* transfer error info */
fini_rtx (rtx, 0); fini_rtx (rtx, 0);
@ -1078,101 +1079,6 @@ static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals)
rtx->vmgr.rchunk = QSE_NULL; rtx->vmgr.rchunk = QSE_NULL;
} }
static int build_runarg (
qse_awk_rtx_t* rtx, const qse_cstr_t* runarg, qse_size_t* nargs)
{
const qse_cstr_t* p;
qse_size_t argc;
qse_awk_val_t* v_argc;
qse_awk_val_t* v_argv;
qse_awk_val_t* v_tmp;
qse_char_t key[QSE_SIZEOF(qse_long_t)*8+2];
qse_size_t key_len;
v_argv = qse_awk_rtx_makemapval (rtx);
if (v_argv == QSE_NULL) return -1;
qse_awk_rtx_refupval (rtx, v_argv);
if (runarg)
{
for (argc = 0, p = runarg; p->ptr != QSE_NULL; argc++, p++)
{
v_tmp = qse_awk_rtx_makestrval (rtx, p->ptr, p->len);
if (v_tmp == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
key_len = qse_awk_longtostr (
rtx->awk, argc, 10,
QSE_NULL, key, QSE_COUNTOF(key));
QSE_ASSERT (key_len != (qse_size_t)-1);
/* increment reference count of v_tmp in advance as if
* it has successfully been assigned into ARGV. */
qse_awk_rtx_refupval (rtx, v_tmp);
if (qse_htb_upsert (
((qse_awk_val_map_t*)v_argv)->map,
key, key_len, v_tmp, 0) == QSE_NULL)
{
/* if the assignment operation fails, decrements
* the reference of v_tmp to free it */
qse_awk_rtx_refdownval (rtx, v_tmp);
/* the values previously assigned into the
* map will be freeed when v_argv is freed */
qse_awk_rtx_refdownval (rtx, v_argv);
SETERR_COD (rtx, QSE_AWK_ENOMEM);
return -1;
}
}
}
else argc = 0;
v_argc = qse_awk_rtx_makeintval (rtx, (qse_long_t)argc);
if (v_argc == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
qse_awk_rtx_refupval (rtx, v_argc);
QSE_ASSERT (
STACK_GBL(rtx,QSE_AWK_GBL_ARGC) == qse_awk_val_nil);
if (qse_awk_rtx_setgbl (rtx, QSE_AWK_GBL_ARGC, v_argc) == -1)
{
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
if (qse_awk_rtx_setgbl (rtx, QSE_AWK_GBL_ARGV, v_argv) == -1)
{
/* ARGC is assigned nil when ARGV assignment has failed.
* However, this requires preconditions, as follows:
* 1. build_runarg should be called in a proper place
* as it is not a generic-purpose routine.
* 2. ARGC should be nil before build_runarg is called
* If the restoration fails, nothing can salvage it. */
qse_awk_rtx_setgbl (rtx, QSE_AWK_GBL_ARGC, qse_awk_val_nil);
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
*nargs = argc;
return 0;
}
static int update_fnr (qse_awk_rtx_t* rtx, qse_long_t fnr, qse_long_t nr) static int update_fnr (qse_awk_rtx_t* rtx, qse_long_t fnr, qse_long_t nr)
{ {
qse_awk_val_t* tmp1, * tmp2; qse_awk_val_t* tmp1, * tmp2;
@ -1217,13 +1123,11 @@ static int update_fnr (qse_awk_rtx_t* rtx, qse_long_t fnr, qse_long_t nr)
/* /*
* create global variables into the runtime stack * create global variables into the runtime stack
* each variable is initialized to nil or zero. * each variable is initialized to nil or zero.
* ARGC and ARGV are built in this function
*/ */
static int prepare_globals (qse_awk_rtx_t* rtx, const qse_cstr_t* runarg) static int prepare_globals (qse_awk_rtx_t* rtx)
{ {
qse_size_t saved_stack_top; qse_size_t saved_stack_top;
qse_size_t ngbls; qse_size_t ngbls;
qse_size_t nrunargs;
saved_stack_top = rtx->stack_top; saved_stack_top = rtx->stack_top;
ngbls = rtx->awk->tree.ngbls; ngbls = rtx->awk->tree.ngbls;
@ -1243,9 +1147,6 @@ static int prepare_globals (qse_awk_rtx_t* rtx, const qse_cstr_t* runarg)
if (qse_awk_rtx_setgbl ( if (qse_awk_rtx_setgbl (
rtx, QSE_AWK_GBL_NF, qse_awk_val_zero) <= -1) goto oops; rtx, QSE_AWK_GBL_NF, qse_awk_val_zero) <= -1) goto oops;
/* override ARGC and ARGV if necessary */
if (runarg && build_runarg (rtx, runarg, &nrunargs) <= -1) goto oops;
/* return success */ /* return success */
return 0; return 0;
@ -1337,13 +1238,13 @@ static void refdown_globals (qse_awk_rtx_t* run, int pop)
} }
} }
static int init_globals (qse_awk_rtx_t* rtx, const qse_cstr_t* arg) static int init_globals (qse_awk_rtx_t* rtx)
{ {
/* the stack must be clean when this function is invoked */ /* the stack must be clean when this function is invoked */
QSE_ASSERTX (rtx->stack_base == 0, "stack not clean"); QSE_ASSERTX (rtx->stack_base == 0, "stack not clean");
QSE_ASSERTX (rtx->stack_top == 0, "stack not clean"); QSE_ASSERTX (rtx->stack_top == 0, "stack not clean");
if (prepare_globals (rtx, arg) == -1) return -1; if (prepare_globals (rtx) == -1) return -1;
if (update_fnr (rtx, 0, 0) == -1) goto oops; if (update_fnr (rtx, 0, 0) == -1) goto oops;
if (defaultify_globals (rtx) == -1) goto oops; if (defaultify_globals (rtx) == -1) goto oops;
return 0; return 0;

View File

@ -104,6 +104,8 @@ typedef struct xtn_t
} out; } out;
} s; /* script/source handling */ } s; /* script/source handling */
int gbl_argc;
int gbl_argv;
int gbl_environ; int gbl_environ;
int gbl_procinfo; int gbl_procinfo;
} xtn_t; } xtn_t;
@ -1179,6 +1181,8 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
if (riod->mode == QSE_AWK_RIO_CONSOLE_READ) if (riod->mode == QSE_AWK_RIO_CONSOLE_READ)
{ {
xtn_t* xtn = (xtn_t*)QSE_XTN (rtx->awk);
if (rxtn->c.in.files == QSE_NULL) if (rxtn->c.in.files == QSE_NULL)
{ {
/* if no input files is specified, /* if no input files is specified,
@ -1254,7 +1258,7 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
* 'BEGIN { ARGV[1]="file3"; } * 'BEGIN { ARGV[1]="file3"; }
* { print $0; }' file1 file2 * { print $0; }' file1 file2
*/ */
argv = qse_awk_rtx_getgbl (rtx, QSE_AWK_GBL_ARGV); argv = qse_awk_rtx_getgbl (rtx, xtn->gbl_argv);
QSE_ASSERT (argv != QSE_NULL); QSE_ASSERT (argv != QSE_NULL);
QSE_ASSERT (argv->type == QSE_AWK_VAL_MAP); QSE_ASSERT (argv->type == QSE_AWK_VAL_MAP);
@ -1482,6 +1486,112 @@ static void fini_rxtn (qse_awk_rtx_t* rtx, void* ctx)
} }
} }
static int build_argcv (
qse_awk_rtx_t* rtx, int argc_id, int argv_id,
const qse_char_t* id, const qse_char_t*const icf[])
{
const qse_char_t*const* p;
qse_size_t argc;
qse_awk_val_t* v_argc;
qse_awk_val_t* v_argv;
qse_awk_val_t* v_tmp;
qse_char_t key[QSE_SIZEOF(qse_long_t)*8+2];
qse_size_t key_len;
v_argv = qse_awk_rtx_makemapval (rtx);
if (v_argv == QSE_NULL) return -1;
qse_awk_rtx_refupval (rtx, v_argv);
/* make ARGV[0] */
v_tmp = qse_awk_rtx_makestrval0 (rtx, id);
if (v_tmp == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
/* increment reference count of v_tmp in advance as if
* it has successfully been assigned into ARGV. */
qse_awk_rtx_refupval (rtx, v_tmp);
key_len = qse_strxcpy (key, QSE_COUNTOF(key), QSE_T("0"));
if (qse_htb_upsert (
((qse_awk_val_map_t*)v_argv)->map,
key, key_len, v_tmp, 0) == QSE_NULL)
{
/* if the assignment operation fails, decrements
* the reference of v_tmp to free it */
qse_awk_rtx_refdownval (rtx, v_tmp);
/* the values previously assigned into the
* map will be freeed when v_argv is freed */
qse_awk_rtx_refdownval (rtx, v_argv);
qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL);
return -1;
}
if (icf)
{
for (argc = 1, p = icf; *p; p++, argc++)
{
v_tmp = qse_awk_rtx_makestrval0 (rtx, *p);
if (v_tmp == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
key_len = qse_awk_longtostr (
rtx->awk, argc, 10,
QSE_NULL, key, QSE_COUNTOF(key));
QSE_ASSERT (key_len != (qse_size_t)-1);
qse_awk_rtx_refupval (rtx, v_tmp);
if (qse_htb_upsert (
((qse_awk_val_map_t*)v_argv)->map,
key, key_len, v_tmp, 0) == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_tmp);
qse_awk_rtx_refdownval (rtx, v_argv);
qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL);
return -1;
}
}
}
else argc = 1;
v_argc = qse_awk_rtx_makeintval (rtx, (qse_long_t)argc);
if (v_argc == QSE_NULL)
{
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
qse_awk_rtx_refupval (rtx, v_argc);
if (qse_awk_rtx_setgbl (rtx, argc_id, v_argc) <= -1)
{
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
if (qse_awk_rtx_setgbl (rtx, argv_id, v_argv) <= -1)
{
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
return -1;
}
qse_awk_rtx_refdownval (rtx, v_argc);
qse_awk_rtx_refdownval (rtx, v_argv);
return 0;
}
static int __build_environ ( static int __build_environ (
qse_awk_rtx_t* rtx, int gbl_id, qse_env_char_t* envarr[]) qse_awk_rtx_t* rtx, int gbl_id, qse_env_char_t* envarr[])
{ {
@ -1744,10 +1854,14 @@ static int build_procinfo (qse_awk_rtx_t* rtx, int gbl_id)
return 0; return 0;
} }
static int make_additional_globals (qse_awk_rtx_t* rtx, xtn_t* xtn) static int make_additional_globals (
qse_awk_rtx_t* rtx, xtn_t* xtn,
const qse_char_t* id, const qse_char_t*const icf[])
{ {
if (build_environ (rtx, xtn->gbl_environ) <= -1) return -1; if (build_argcv (rtx, xtn->gbl_argc, xtn->gbl_argv, id, icf) <= -1 ||
if (build_procinfo (rtx, xtn->gbl_procinfo) <= -1) return -1; build_environ (rtx, xtn->gbl_environ) <= -1 ||
build_procinfo (rtx, xtn->gbl_procinfo) <= -1) return -1;
return 0; return 0;
} }
@ -1772,65 +1886,18 @@ qse_awk_rtx_t* qse_awk_rtx_openstd (
xtn_t* xtn; xtn_t* xtn;
qse_ntime_t now; qse_ntime_t now;
const qse_char_t*const* p;
qse_cstr_t* p2;
qse_size_t argc = 0;
qse_cstr_t argv[16];
qse_cstr_t* argvp = QSE_NULL;
xtn = (xtn_t*)QSE_XTN (awk); xtn = (xtn_t*)QSE_XTN (awk);
rio.pipe = awk_rio_pipe; rio.pipe = awk_rio_pipe;
rio.file = awk_rio_file; rio.file = awk_rio_file;
rio.console = awk_rio_console; rio.console = awk_rio_console;
if (icf)
{
for (p = icf; *p != QSE_NULL; p++);
argc = p - icf;
}
argc++; /* for id */
if (argc < QSE_COUNTOF(argv)) argvp = argv;
else
{
argvp = QSE_AWK_ALLOC (
awk, QSE_SIZEOF(*argvp) * (argc + 1));
if (argvp == QSE_NULL)
{
qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return QSE_NULL;
}
}
p2 = argvp;
p2->ptr = id;
p2->len = qse_strlen(id);
p2++;
if (icf)
{
for (p = icf; *p; p++, p2++)
{
p2->ptr = *p;
p2->len = qse_strlen(*p);
}
}
p2->ptr = QSE_NULL;
p2->len = 0;
rtx = qse_awk_rtx_open ( rtx = qse_awk_rtx_open (
awk, awk,
QSE_SIZEOF(rxtn_t) + xtnsize, QSE_SIZEOF(rxtn_t) + xtnsize,
&rio, &rio
argvp
); );
if (argvp && argvp != argv) QSE_AWK_FREE (awk, argvp);
if (rtx == QSE_NULL) return QSE_NULL; if (rtx == QSE_NULL) return QSE_NULL;
rxtn = (rxtn_t*) QSE_XTN (rtx); rxtn = (rxtn_t*) QSE_XTN (rtx);
@ -1887,7 +1954,7 @@ qse_awk_rtx_t* qse_awk_rtx_openstd (
} }
} }
if (make_additional_globals (rtx, xtn) <= -1) if (make_additional_globals (rtx, xtn, id, icf) <= -1)
{ {
awk->errinf = rtx->errinf; /* transfer error info */ awk->errinf = rtx->errinf; /* transfer error info */
qse_awk_rtx_close (rtx); qse_awk_rtx_close (rtx);
@ -2338,11 +2405,13 @@ static int add_globals (qse_awk_t* awk)
xtn = (xtn_t*) QSE_XTN (awk); xtn = (xtn_t*) QSE_XTN (awk);
xtn->gbl_argc = qse_awk_addgbl (awk, QSE_T("ARGC"), 4);
xtn->gbl_argv = qse_awk_addgbl (awk, QSE_T("ARGV"), 4);
xtn->gbl_environ = qse_awk_addgbl (awk, QSE_T("ENVIRON"), 7); xtn->gbl_environ = qse_awk_addgbl (awk, QSE_T("ENVIRON"), 7);
if (xtn->gbl_environ <= -1) return -1;
xtn->gbl_procinfo = qse_awk_addgbl (awk, QSE_T("PROCINFO"), 8); xtn->gbl_procinfo = qse_awk_addgbl (awk, QSE_T("PROCINFO"), 8);
if (xtn->gbl_procinfo <= -1) return -1;
if (xtn->gbl_argc <= -1 || xtn->gbl_argv <= -1 ||
xtn->gbl_environ <= -1 || xtn->gbl_procinfo <= -1) return -1;
return 0; return 0;
} }