enhanced qse_awk_rtx_setrefval() to handle references properly

enhanced qse_awk_rtx_valtostr() and qse_awk_rtx_valtonum() to handle references more correctly.
changed some awk error codes.
This commit is contained in:
hyung-hwan 2013-04-16 10:09:24 +00:00
parent d5cca9d524
commit 23d316a659
11 changed files with 550 additions and 468 deletions

View File

@ -250,7 +250,7 @@ static qse_htb_walk_t print_awk_value (
str = qse_awk_rtx_valtostrdup (rtx, QSE_HTB_VPTR(pair), &len);
if (str == QSE_NULL)
{
if (qse_awk_rtx_geterrnum(rtx) == QSE_AWK_EVALTYPE)
if (qse_awk_rtx_geterrnum(rtx) == QSE_AWK_EVALTOSTR)
{
dprint (QSE_T("%.*s = [not printable]\n"),
(int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair));

View File

@ -949,7 +949,9 @@ typedef void (*qse_awk_rtx_ecb_stmt_t) (
/**
* The qse_awk_rtx_ecb_gblset_t type defines the callback function
* executed when a global variable is set with a value.
* executed when a global variable is set with a value. It is not
* called when a global variable is changed implicitly. For example,
* it is not called when FNR is updated for each record read.
*/
typedef void (*qse_awk_rtx_ecb_gblset_t) (
qse_awk_rtx_t* rtx, /**< runtime context */
@ -1239,9 +1241,12 @@ enum qse_awk_errnum_t
QSE_AWK_EMAPNA, /**< map cannot be assigned to variable */
QSE_AWK_EMAPNRA, /**< map '${0}' cannot be reassigned */
QSE_AWK_EMAPUR, /**< map unreturnable */
QSE_AWK_EMAPPH, /**< map prohibited */
QSE_AWK_EMAPTOSCALAR, /**< cannot change a map to a scalar value */
QSE_AWK_ESCALARTOMAP, /**< cannot change a scalar value to a map */
QSE_AWK_EVALTYPE, /**< invalid value type */
QSE_AWK_EVALTOSTR, /**< invalid value to convert to a string */
QSE_AWK_EVALTONUM, /**< invalid value to convert to a number */
QSE_AWK_EVALTOCHR, /**< invalid value to convert to a character */
QSE_AWK_EHASHVAL, /**< invalid value to hash */
QSE_AWK_ERNEXTBEG, /**< 'next' called from BEGIN block */
QSE_AWK_ERNEXTEND, /**< 'next' called from END block */
QSE_AWK_ERNEXTFBEG, /**< 'nextfile' called from BEGIN block */

View File

@ -241,6 +241,14 @@ struct qse_awk_chain_t
qse_awk_chain_t* next;
};
#define RTX_STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)])
#define RTX_STACK_NARGS(rtx) (RTX_STACK_AT(rtx,3))
#define RTX_STACK_ARG(rtx,n) RTX_STACK_AT(rtx,3+1+(n))
#define RTX_STACK_LCL(rtx,n) RTX_STACK_AT(rtx,3+(qse_size_t)RTX_STACK_NARGS(rtx)+1+(n))
#define RTX_STACK_RETVAL(rtx) RTX_STACK_AT(rtx,2)
#define RTX_STACK_GBL(rtx,n) ((rtx)->stack[(n)])
#define RTX_STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->awk->tree.ngbls+2])
struct qse_awk_rtx_t
{
int id;

View File

@ -118,14 +118,17 @@ const qse_char_t* qse_awk_dflerrstr (const qse_awk_t* awk, qse_awk_errnum_t errn
QSE_T("right-hand side of the 'in' operator not a map"),
QSE_T("right-hand side of the 'in' operator not a map nor nil"),
QSE_T("value not referenceable"),
QSE_T("indexed value cannot be a map"),
QSE_T("positional value cannot be a map"),
QSE_T("indexed variable cannot be assigned a map"),
QSE_T("positional cannot be assigned a map"),
QSE_T("map cannot be assigned to variable"),
QSE_T("map '${0}' cannot be reassigned"),
QSE_T("map cannot be returned"),
QSE_T("map prohibited"),
QSE_T("cannot change a map to a scalar value"),
QSE_T("cannot change a scalar value to a map"),
QSE_T("invalid value type"),
QSE_T("invalid value to convert to a string"),
QSE_T("invalid value to convert to a number"),
QSE_T("invalid value to a character"),
QSE_T("invalid value for hashing"),
QSE_T("'next' called from BEGIN block"),
QSE_T("'next' called from END block"),
QSE_T("'nextfile' called from BEGIN block"),

View File

@ -627,7 +627,7 @@ static int fnc_substr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi)
{
qse_size_t nargs;
qse_awk_val_t* a0, * a1, * a2, * t1, * t2, ** a1_ref;
qse_awk_val_t* a0, * a1, * a2, * t1, * t2;
qse_cstr_t str, fs;
qse_char_t* str_free = QSE_NULL, * fs_free = QSE_NULL;
@ -640,6 +640,7 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi)
qse_long_t nflds;
qse_awk_errnum_t errnum;
int x;
nargs = qse_awk_rtx_getnargs (run);
QSE_ASSERT (nargs >= 2 && nargs <= 3);
@ -650,33 +651,6 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi)
QSE_ASSERT (a1->type == QSE_AWK_VAL_REF);
if (((qse_awk_val_ref_t*)a1)->id >= QSE_AWK_VAL_REF_NAMEDIDX &&
((qse_awk_val_ref_t*)a1)->id <= QSE_AWK_VAL_REF_ARGIDX)
{
/* an indexed value should not be assigned another map */
qse_awk_rtx_seterrnum (run, QSE_AWK_EIDXVALMAP, QSE_NULL);
return -1;
}
if (((qse_awk_val_ref_t*)a1)->id == QSE_AWK_VAL_REF_POS)
{
/* a positional should not be assigned a map */
qse_awk_rtx_seterrnum (run, QSE_AWK_EPOSVALMAP, QSE_NULL);
return -1;
}
a1_ref = (qse_awk_val_t**)((qse_awk_val_ref_t*)a1)->adr;
if ((*a1_ref)->type != QSE_AWK_VAL_NIL &&
(*a1_ref)->type != QSE_AWK_VAL_MAP)
{
if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP))
{
/* cannot change a scalar value to a map */
qse_awk_rtx_seterrnum (run, QSE_AWK_ESCALARTOMAP, QSE_NULL);
return -1;
}
}
if (a0->type == QSE_AWK_VAL_STR)
{
str.ptr = ((qse_awk_val_str_t*)a0)->val.ptr;
@ -752,14 +726,12 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi)
t1 = qse_awk_rtx_makemapval (run);
if (t1 == QSE_NULL) goto oops;
/* use the following 3 lines intead of
* qse_awk_rtx_setrefval (run, a1, t1);
* just for less overhead.
*/
qse_awk_rtx_refdownval (run, *a1_ref);
*a1_ref = t1;
qse_awk_rtx_refupval (run, *a1_ref);
qse_awk_rtx_refupval (run, t1);
x = qse_awk_rtx_setrefval (run, a1, t1);
qse_awk_rtx_refdownval (run, t1);
if (x <= -1) goto oops;
/* fill the map with actual values */
p = str.ptr; str_left = str.len; org_len = str.len;
nflds = 0;
@ -907,6 +879,7 @@ static int fnc_toupper (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi)
return 0;
}
static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count)
{
qse_size_t nargs;
@ -972,54 +945,11 @@ static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count)
s2.ptr = QSE_STR_PTR(&run->inrec.line);
s2.len = QSE_STR_LEN(&run->inrec.line);
}
else if (((qse_awk_val_ref_t*)a2)->id == QSE_AWK_VAL_REF_POS)
{
qse_size_t idx;
idx = (qse_size_t)((qse_awk_val_ref_t*)a2)->adr;
if (idx == 0)
{
s2.ptr = QSE_STR_PTR(&run->inrec.line);
s2.len = QSE_STR_LEN(&run->inrec.line);
}
else if (idx <= run->inrec.nflds)
{
s2.ptr = run->inrec.flds[idx-1].ptr;
s2.len = run->inrec.flds[idx-1].len;
}
else
{
s2.ptr = QSE_T("");
s2.len = 0;
}
}
else
{
a2_ref = (qse_awk_val_t**)((qse_awk_val_ref_t*)a2)->adr;
if ((*a2_ref)->type == QSE_AWK_VAL_MAP)
{
/* a map is not allowed as the third parameter.
* this is a prohibited condition regardless of QSE_AWK_FLEXMAP.
* i don't accept this.
*
* TODO: can i extend to replace something in a map???
*/
qse_awk_rtx_seterrnum (run, QSE_AWK_EMAPPH, QSE_NULL);
goto oops;
}
if ((*a2_ref)->type == QSE_AWK_VAL_STR)
{
s2.ptr = ((qse_awk_val_str_t*)(*a2_ref))->val.ptr;
s2.len = ((qse_awk_val_str_t*)(*a2_ref))->val.len;
}
else
{
s2.ptr = qse_awk_rtx_valtostrdup (run, *a2_ref, &s2.len);
if (s2.ptr == QSE_NULL) goto oops;
s2_free = (qse_char_t*)s2.ptr;
}
s2.ptr = qse_awk_rtx_valtostrdup (run, a2, &s2.len);
if (s2.ptr == QSE_NULL) goto oops;
s2_free = (qse_char_t*)s2.ptr;
}
if (qse_str_init (&new, run->awk->mmgr, s2.len) <= -1)
@ -1165,24 +1095,16 @@ static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count)
n = qse_awk_rtx_setrec (run, 0, QSE_STR_CSTR(&new));
if (n <= -1) goto oops;
}
else if (((qse_awk_val_ref_t*)a2)->id == QSE_AWK_VAL_REF_POS)
else
{
int n;
n = qse_awk_rtx_setrec (
run, (qse_size_t)((qse_awk_val_ref_t*)a2)->adr,
QSE_STR_CSTR(&new));
if (n <= -1) goto oops;
}
else
{
v = qse_awk_rtx_makestrvalwithcstr (run, QSE_STR_CSTR(&new));
if (v == QSE_NULL) goto oops;
qse_awk_rtx_refdownval (run, *a2_ref);
*a2_ref = v;
qse_awk_rtx_refupval (run, *a2_ref);
qse_awk_rtx_refupval (run, v);
n = qse_awk_rtx_setrefval (run, a2, v);
qse_awk_rtx_refdownval (run, v);
if (n <= -1) goto oops;
}
}

View File

@ -275,21 +275,28 @@ static int read_byid (qse_awk_rtx_t* rtx, dir_list_t* list, qse_long_t id, qse_a
return -1;
}
if (y == 0) return 0;
if (y == 0) return 0; /* no more entry */
tmp = qse_awk_rtx_makestrvalwithstr (rtx, ent.name);
if (!tmp || qse_awk_rtx_setrefval (rtx, ref, tmp) <= -1)
if (!tmp)
{
list->errnum = awk_err_to_errnum (qse_awk_rtx_geterrnum (rtx));
if (tmp)
{
qse_awk_rtx_refupval (rtx, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
}
return -1;
}
else
{
int n;
qse_awk_rtx_refupval (rtx, tmp);
n = qse_awk_rtx_setrefval (rtx, ref, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
if (n <= -1)
{
list->errnum = awk_err_to_errnum (qse_awk_rtx_geterrnum (rtx));
return -1;
}
}
return 0;
return 1; /* has entry */
}
else
{

View File

@ -567,12 +567,11 @@ static int fnc_getnwifcfg (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
tmp = qse_awk_rtx_makemapvalwithdata (rtx, md);
if (tmp)
{
if (qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), tmp) <= -1)
{
qse_awk_rtx_refupval (rtx, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
}
else ret = 0;
int x;
qse_awk_rtx_refupval (rtx, tmp);
x = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), tmp);
qse_awk_rtx_refdownval (rtx, tmp);
if (x >= 0) ret = 0;
}
}
}

View File

@ -471,12 +471,11 @@ static int getsection_byid (
tmp = qse_awk_rtx_makemapvalwithdata (rtx, md);
if (tmp)
{
if (qse_awk_rtx_setrefval (rtx, ref, tmp) <= -1)
{
qse_awk_rtx_refupval (rtx, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
x = UCI_ERR_MEM;
}
int n;
qse_awk_rtx_refupval (rtx, tmp);
n = qse_awk_rtx_setrefval (rtx, ref, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
if (n <= -1) x = UCI_ERR_MEM; /* this is not a correct error code. who cares? */
}
else x = UCI_ERR_MEM;
}
@ -534,10 +533,12 @@ static int getoption_byid (
map = qse_awk_rtx_makemapvalwithdata (rtx, md);
if (map)
{
if (qse_awk_rtx_setrefval (rtx, ref, map) <= -1)
int n;
qse_awk_rtx_refupval (rtx, map);
n = qse_awk_rtx_setrefval (rtx, ref, map);
qse_awk_rtx_refdownval (rtx, map);
if (n <= -1)
{
qse_awk_rtx_refupval (rtx, map);
qse_awk_rtx_refdownval (rtx, map);
map = QSE_NULL;
x = UCI_ERR_MEM;
}

View File

@ -29,20 +29,12 @@
#define CMP_ERROR -99
#define DEF_BUF_CAPA 256
#define STACK_INCREMENT 512
#define RTX_STACK_INCREMENT 512
#define IDXBUFSIZE 64
#define MMGR(rtx) ((rtx)->awk->mmgr)
#define STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)])
#define STACK_NARGS(rtx) (STACK_AT(rtx,3))
#define STACK_ARG(rtx,n) STACK_AT(rtx,3+1+(n))
#define STACK_LCL(rtx,n) STACK_AT(rtx,3+(qse_size_t)STACK_NARGS(rtx)+1+(n))
#define STACK_RETVAL(rtx) STACK_AT(rtx,2)
#define STACK_GBL(rtx,n) ((rtx)->stack[(n)])
#define STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->awk->tree.ngbls+2])
enum exit_level_t
{
EXIT_NONE,
@ -285,18 +277,18 @@ static QSE_INLINE qse_cstr_t* xstr_to_cstr (qse_xstr_t* xstr)
QSE_INLINE qse_size_t qse_awk_rtx_getnargs (qse_awk_rtx_t* run)
{
return (qse_size_t) STACK_NARGS (run);
return (qse_size_t) RTX_STACK_NARGS (run);
}
QSE_INLINE qse_awk_val_t* qse_awk_rtx_getarg (qse_awk_rtx_t* run, qse_size_t idx)
{
return STACK_ARG (run, idx);
return RTX_STACK_ARG (run, idx);
}
QSE_INLINE qse_awk_val_t* qse_awk_rtx_getgbl (qse_awk_rtx_t* run, int id)
{
QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(run->awk->parse.gbls));
return STACK_GBL (run, id);
return RTX_STACK_GBL (run, id);
}
const qse_xstr_t* qse_awk_rtx_getsubsep (qse_awk_rtx_t* run)
@ -308,49 +300,70 @@ const qse_xstr_t* qse_awk_rtx_getsubsep (qse_awk_rtx_t* run)
* this function can handle a few special global variables that
* require special treatment. */
static int set_global (
qse_awk_rtx_t* rtx, qse_size_t idx,
qse_awk_rtx_t* rtx, int idx,
qse_awk_nde_var_t* var, qse_awk_val_t* val)
{
qse_awk_val_t* old;
qse_awk_rtx_ecb_t* ecb;
old = STACK_GBL (rtx, idx);
if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP)
{
/* once a variable becomes a map,
* it cannot be assigned with another value.
* you can only add a member using indexing. */
if (var)
old = RTX_STACK_GBL (rtx, idx);
if (old == val) return 0; /* the old value is the same as the new value. nothing to do */
if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP))
{
qse_awk_errnum_t errnum = QSE_AWK_ENOERR;
if (old->type == QSE_AWK_VAL_MAP && val->type != QSE_AWK_VAL_MAP)
errnum = QSE_AWK_EMAPNRA;
if (val->type == QSE_AWK_VAL_MAP)
{
/* global variable */
SETERR_ARGX_LOC (
rtx,
QSE_AWK_EMAPNRA,
xstr_to_cstr(&var->id.name),
&var->loc
);
if (old->type != QSE_AWK_VAL_NIL)
errnum = QSE_AWK_EMAPNA;
}
else
{
/* qse_awk_rtx_setgbl() has been called */
qse_cstr_t ea;
ea.ptr = qse_awk_getgblname (rtx->awk, idx, &ea.len);
SETERR_ARGX (rtx, QSE_AWK_EMAPNRA, &ea);
if (old->type == QSE_AWK_VAL_MAP) errnum = QSE_AWK_EMAPNRA;
}
if (errnum != QSE_AWK_ENOERR)
{
/* once a variable becomes a map, it cannot be assigned
* others value than another map. you can only add a member
* using indexing. */
if (var)
{
/* global variable */
SETERR_ARGX_LOC (
rtx,
errnum,
xstr_to_cstr(&var->id.name),
&var->loc
);
}
else
{
/* qse_awk_rtx_setgbl() has been called */
qse_cstr_t ea;
ea.ptr = qse_awk_getgblname (rtx->awk, idx, &ea.len);
SETERR_ARGX (rtx, errnum, &ea);
}
return -1;
return -1;
}
}
/* all the basic builtin variables cannot be assigned a map.
* if you happen to add one and if that's allowed to be a map,
* you may have to change the condition here.
* 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)
if (val->type == QSE_AWK_VAL_MAP)
{
/* TODO: better error code */
SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP);
return -1;
if (idx >= QSE_AWK_MIN_GBL_ID && idx <= QSE_AWK_MAX_GBL_ID)
{
/* short-circuit check block to prevent the basic built-in variables
* from being assigned a map. if you happen to add one and if that's
* allowed to be a map, you may have to change the condition here. */
/* TODO: use global variable attribute. can it be a map? can it be a scalar? is it read-only???? */
SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP);
return -1;
}
}
switch (idx)
@ -469,7 +482,7 @@ static int set_global (
if (shorten_record (rtx, (qse_size_t)lv) == -1)
{
/* adjust the error line */
if (var) ADJERR_LOC (rtx, &var->loc);
/*if (var) ADJERR_LOC (rtx, &var->loc);*/
return -1;
}
}
@ -614,11 +627,10 @@ static int set_global (
break;
}
}
qse_awk_rtx_refdownval (rtx, old);
STACK_GBL(rtx,idx) = val;
RTX_STACK_GBL(rtx,idx) = val;
qse_awk_rtx_refupval (rtx, val);
for (ecb = (rtx)->ecb; ecb; ecb = ecb->next)
@ -630,8 +642,8 @@ static int set_global (
QSE_INLINE void qse_awk_rtx_setretval (
qse_awk_rtx_t* rtx, qse_awk_val_t* val)
{
qse_awk_rtx_refdownval (rtx, STACK_RETVAL(rtx));
STACK_RETVAL(rtx) = val;
qse_awk_rtx_refdownval (rtx, RTX_STACK_RETVAL(rtx));
RTX_STACK_RETVAL(rtx) = val;
/* should use the same trick as run_return */
qse_awk_rtx_refupval (rtx, val);
}
@ -640,7 +652,7 @@ QSE_INLINE int qse_awk_rtx_setgbl (
qse_awk_rtx_t* rtx, int id, qse_awk_val_t* val)
{
QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(rtx->awk->parse.gbls));
return set_global (rtx, (qse_size_t)id, QSE_NULL, val);
return set_global (rtx, id, QSE_NULL, val);
}
int qse_awk_rtx_setfilename (
@ -1251,7 +1263,7 @@ static int defaultify_globals (qse_awk_rtx_t* rtx)
qse_awk_rtx_refupval (rtx, tmp);
QSE_ASSERT (STACK_GBL(rtx,gtab[i].idx) == qse_awk_val_nil);
QSE_ASSERT (RTX_STACK_GBL(rtx,gtab[i].idx) == qse_awk_val_nil);
if (qse_awk_rtx_setgbl (rtx, gtab[i].idx, tmp) == -1)
{
@ -1279,9 +1291,9 @@ static void refdown_globals (qse_awk_rtx_t* run, int pop)
while (ngbls > 0)
{
--ngbls;
qse_awk_rtx_refdownval (run, STACK_GBL(run,ngbls));
qse_awk_rtx_refdownval (run, RTX_STACK_GBL(run,ngbls));
if (pop) __raw_pop (run);
else STACK_GBL(run,ngbls) = qse_awk_val_nil;
else RTX_STACK_GBL(run,ngbls) = qse_awk_val_nil;
}
}
@ -1312,7 +1324,7 @@ static void capture_retval_on_exit (void* arg)
struct capture_retval_data_t* data;
data = (struct capture_retval_data_t*)arg;
data->val = STACK_RETVAL(data->rtx);
data->val = RTX_STACK_RETVAL(data->rtx);
qse_awk_rtx_refupval (data->rtx, data->val);
}
@ -1332,7 +1344,7 @@ static int enter_stack_frame (qse_awk_rtx_t* rtx)
/* secure space for a return value */
if (__raw_push(rtx,qse_awk_val_nil) == -1) goto oops;
/* secure space for STACK_NARGS */
/* secure space for RTX_STACK_NARGS */
if (__raw_push(rtx,qse_awk_val_nil) == -1) goto oops;
/* let the stack top remembered be the base of a new stack frame */
@ -1367,7 +1379,7 @@ static qse_awk_val_t* run_bpae_loop (qse_awk_rtx_t* rtx)
/* set nargs to zero */
nargs = 0;
STACK_NARGS(rtx) = (void*)nargs;
RTX_STACK_NARGS(rtx) = (void*)nargs;
/* execute the BEGIN block */
for (nde = rtx->awk->tree.begin;
@ -1448,13 +1460,13 @@ static qse_awk_val_t* run_bpae_loop (qse_awk_rtx_t* rtx)
/* derefrence all arguments. however, there should be no arguments
* pushed to the stack as asserted below. we didn't push any arguments
* for BEGIN/pattern action/END block execution.*/
nargs = (qse_size_t)STACK_NARGS(rtx);
nargs = (qse_size_t)RTX_STACK_NARGS(rtx);
QSE_ASSERT (nargs == 0);
for (i = 0; i < nargs; i++)
qse_awk_rtx_refdownval (rtx, STACK_ARG(rtx,i));
qse_awk_rtx_refdownval (rtx, RTX_STACK_ARG(rtx,i));
/* get the return value in the current stack frame */
retv = STACK_RETVAL(rtx);
retv = RTX_STACK_RETVAL(rtx);
if (ret <= -1)
{
@ -1888,7 +1900,7 @@ static int run_block0 (qse_awk_rtx_t* rtx, qse_awk_nde_blk_t* nde)
while (nlcls > 0)
{
--nlcls;
qse_awk_rtx_refdownval (rtx, STACK_LCL(rtx,nlcls));
qse_awk_rtx_refdownval (rtx, RTX_STACK_LCL(rtx,nlcls));
__raw_pop (rtx);
}
@ -2330,8 +2342,8 @@ static int run_return (qse_awk_rtx_t* run, qse_awk_nde_return_t* nde)
}
}
qse_awk_rtx_refdownval (run, STACK_RETVAL(run));
STACK_RETVAL(run) = val;
qse_awk_rtx_refdownval (run, RTX_STACK_RETVAL(run));
RTX_STACK_RETVAL(run) = val;
/* NOTE: see eval_call() for the trick */
qse_awk_rtx_refupval (run, val);
@ -2354,8 +2366,8 @@ static int run_exit (qse_awk_rtx_t* run, qse_awk_nde_exit_t* nde)
val = eval_expression (run, nde->val);
if (val == QSE_NULL) return -1;
qse_awk_rtx_refdownval (run, STACK_RETVAL_GBL(run));
STACK_RETVAL_GBL(run) = val; /* global return value */
qse_awk_rtx_refdownval (run, RTX_STACK_RETVAL_GBL(run));
RTX_STACK_RETVAL_GBL(run) = val; /* global return value */
qse_awk_rtx_refupval (run, val);
}
@ -2599,13 +2611,22 @@ static int run_delete_unnamed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var)
{
qse_awk_val_t* val;
if (var->type == QSE_AWK_NDE_GBL ||
var->type == QSE_AWK_NDE_GBLIDX)
val = STACK_GBL (rtx,var->id.idxa);
else if (var->type == QSE_AWK_NDE_LCL ||
var->type == QSE_AWK_NDE_LCLIDX)
val = STACK_LCL (rtx,var->id.idxa);
else val = STACK_ARG (rtx,var->id.idxa);
switch (var->type)
{
case QSE_AWK_NDE_GBL:
case QSE_AWK_NDE_GBLIDX:
val = RTX_STACK_GBL (rtx,var->id.idxa);
break;
case QSE_AWK_NDE_LCL:
case QSE_AWK_NDE_LCLIDX:
val = RTX_STACK_LCL (rtx,var->id.idxa);
break;
default:
val = RTX_STACK_ARG (rtx,var->id.idxa);
break;
}
QSE_ASSERT (val != QSE_NULL);
@ -2625,28 +2646,35 @@ static int run_delete_unnamed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var)
/* no need to reduce the reference count of
* the previous value because it was nil. */
if (var->type == QSE_AWK_NDE_GBL ||
var->type == QSE_AWK_NDE_GBLIDX)
switch (var->type)
{
if (qse_awk_rtx_setgbl (
rtx, (int)var->id.idxa, tmp) == -1)
case QSE_AWK_NDE_GBL:
case QSE_AWK_NDE_GBLIDX:
{
int x;
qse_awk_rtx_refupval (rtx, tmp);
x = qse_awk_rtx_setgbl (rtx, (int)var->id.idxa, tmp);
qse_awk_rtx_refdownval (rtx, tmp);
ADJERR_LOC (rtx, &var->loc);
return -1;
if (x <= -1)
{
ADJERR_LOC (rtx, &var->loc);
return -1;
}
break;
}
}
else if (var->type == QSE_AWK_NDE_LCL ||
var->type == QSE_AWK_NDE_LCLIDX)
{
STACK_LCL(rtx,var->id.idxa) = tmp;
qse_awk_rtx_refupval (rtx, tmp);
}
else
{
STACK_ARG(rtx,var->id.idxa) = tmp;
qse_awk_rtx_refupval (rtx, tmp);
case QSE_AWK_NDE_LCL:
case QSE_AWK_NDE_LCLIDX:
RTX_STACK_LCL(rtx,var->id.idxa) = tmp;
qse_awk_rtx_refupval (rtx, tmp);
break;
default:
RTX_STACK_ARG(rtx,var->id.idxa) = tmp;
qse_awk_rtx_refupval (rtx, tmp);
break;
}
}
else
@ -2717,52 +2745,69 @@ static int run_reset (qse_awk_rtx_t* rtx, qse_awk_nde_reset_t* nde)
var = (qse_awk_nde_var_t*) nde->var;
if (var->type == QSE_AWK_NDE_NAMED)
switch (var->type)
{
QSE_ASSERTX (
var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL,
"if a named variable has an index part, something is definitely wrong");
case QSE_AWK_NDE_NAMED:
QSE_ASSERTX (
var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL,
"if a named variable has an index part, something is definitely wrong");
/* a named variable can be reset if removed from a internal map
to manage it */
qse_htb_delete (rtx->named, var->id.name.ptr, var->id.name.len);
}
else if (var->type == QSE_AWK_NDE_GBL ||
var->type == QSE_AWK_NDE_LCL ||
var->type == QSE_AWK_NDE_ARG)
{
qse_awk_val_t* val;
/* a named variable can be reset if removed from a internal map
to manage it */
qse_htb_delete (rtx->named, var->id.name.ptr, var->id.name.len);
return 0;
if (var->type == QSE_AWK_NDE_GBL)
val = STACK_GBL(rtx,var->id.idxa);
else if (var->type == QSE_AWK_NDE_LCL)
val = STACK_LCL(rtx,var->id.idxa);
else val = STACK_ARG(rtx,var->id.idxa);
QSE_ASSERT (val != QSE_NULL);
if (val->type != QSE_AWK_VAL_NIL)
case QSE_AWK_NDE_GBL:
case QSE_AWK_NDE_LCL:
case QSE_AWK_NDE_ARG:
{
qse_awk_rtx_refdownval (rtx, val);
if (var->type == QSE_AWK_NDE_GBL)
STACK_GBL(rtx,var->id.idxa) = qse_awk_val_nil;
else if (var->type == QSE_AWK_NDE_LCL)
STACK_LCL(rtx,var->id.idxa) = qse_awk_val_nil;
else
STACK_ARG(rtx,var->id.idxa) = qse_awk_val_nil;
qse_awk_val_t* val;
switch (var->type)
{
case QSE_AWK_NDE_GBL:
val = RTX_STACK_GBL(rtx,var->id.idxa);
break;
case QSE_AWK_NDE_LCL:
val = RTX_STACK_LCL(rtx,var->id.idxa);
break;
case QSE_AWK_NDE_ARG:
val = RTX_STACK_ARG(rtx,var->id.idxa);
break;
}
QSE_ASSERT (val != QSE_NULL);
if (val->type != QSE_AWK_VAL_NIL)
{
qse_awk_rtx_refdownval (rtx, val);
switch (var->type)
{
case QSE_AWK_NDE_GBL:
RTX_STACK_GBL(rtx,var->id.idxa) = qse_awk_val_nil;
break;
case QSE_AWK_NDE_LCL:
RTX_STACK_LCL(rtx,var->id.idxa) = qse_awk_val_nil;
break;
case QSE_AWK_NDE_ARG:
RTX_STACK_ARG(rtx,var->id.idxa) = qse_awk_val_nil;
break;
}
}
return 0;
}
}
else
{
QSE_ASSERTX (
!"should never happen - wrong target for reset",
"the reset statement can only be called with plain variables");
SETERR_LOC (rtx, QSE_AWK_EBADARG, &var->loc);
return -1;
default:
QSE_ASSERTX (
!"should never happen - wrong target for reset",
"the reset statement can only be called with plain variables");
SETERR_LOC (rtx, QSE_AWK_EBADARG, &var->loc);
return -1;
}
return 0;
}
static int run_print (qse_awk_rtx_t* rtx, qse_awk_nde_print_t* nde)
@ -3494,7 +3539,7 @@ static qse_awk_val_t* do_assignment_scalar (
case QSE_AWK_NDE_LCL:
{
qse_awk_val_t* old = STACK_LCL(run,var->id.idxa);
qse_awk_val_t* old = RTX_STACK_LCL(run,var->id.idxa);
if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP)
{
/* once the variable becomes a map,
@ -3506,14 +3551,14 @@ static qse_awk_val_t* do_assignment_scalar (
}
qse_awk_rtx_refdownval (run, old);
STACK_LCL(run,var->id.idxa) = val;
RTX_STACK_LCL(run,var->id.idxa) = val;
qse_awk_rtx_refupval (run, val);
break;
}
case QSE_AWK_NDE_ARG:
{
qse_awk_val_t* old = STACK_ARG(run,var->id.idxa);
qse_awk_val_t* old = RTX_STACK_ARG(run,var->id.idxa);
if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP)
{
/* once the variable becomes a map,
@ -3525,7 +3570,7 @@ static qse_awk_val_t* do_assignment_scalar (
}
qse_awk_rtx_refdownval (run, old);
STACK_ARG(run,var->id.idxa) = val;
RTX_STACK_ARG(run,var->id.idxa) = val;
qse_awk_rtx_refupval (run, val);
break;
}
@ -3562,10 +3607,10 @@ static qse_awk_val_t* do_assignment_map (
else
{
map = (var->type == QSE_AWK_NDE_GBLIDX)?
(qse_awk_val_map_t*)STACK_GBL(run,var->id.idxa):
(qse_awk_val_map_t*)RTX_STACK_GBL(run,var->id.idxa):
(var->type == QSE_AWK_NDE_LCLIDX)?
(qse_awk_val_map_t*)STACK_LCL(run,var->id.idxa):
(qse_awk_val_map_t*)STACK_ARG(run,var->id.idxa);
(qse_awk_val_map_t*)RTX_STACK_LCL(run,var->id.idxa):
(qse_awk_val_map_t*)RTX_STACK_ARG(run,var->id.idxa);
}
if (map->type == QSE_AWK_VAL_NIL)
@ -3580,49 +3625,50 @@ static qse_awk_val_t* do_assignment_map (
return QSE_NULL;
}
if (var->type == QSE_AWK_NDE_NAMEDIDX)
switch (var->type)
{
/* doesn't have to decrease the reference count
* of the previous value here as it is done by
* qse_htb_upsert */
if (qse_htb_upsert (
run->named,
var->id.name.ptr,
var->id.name.len,
tmp,
0) == QSE_NULL)
case QSE_AWK_NDE_NAMEDIDX:
{
/* doesn't have to decrease the reference count
* of the previous value here as it is done by
* qse_htb_upsert */
qse_awk_rtx_refupval (run, tmp);
qse_awk_rtx_refdownval (run, tmp);
if (qse_htb_upsert (run->named, var->id.name.ptr, var->id.name.len, tmp, 0) == QSE_NULL)
{
qse_awk_rtx_refdownval (run, tmp);
SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc);
return QSE_NULL;
}
SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc);
return QSE_NULL;
break;
}
qse_awk_rtx_refupval (run, tmp);
}
else if (var->type == QSE_AWK_NDE_GBLIDX)
{
qse_awk_rtx_refupval (run, tmp);
if (qse_awk_rtx_setgbl (run, (int)var->id.idxa, tmp) == -1)
case QSE_AWK_NDE_GBLIDX:
{
int x;
qse_awk_rtx_refupval (run, tmp);
x = qse_awk_rtx_setgbl (run, (int)var->id.idxa, tmp);
qse_awk_rtx_refdownval (run, tmp);
ADJERR_LOC (run, &var->loc);
return QSE_NULL;
if (x <= -1)
{
ADJERR_LOC (run, &var->loc);
return QSE_NULL;
}
break;
}
qse_awk_rtx_refdownval (run, tmp);
}
else if (var->type == QSE_AWK_NDE_LCLIDX)
{
qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map);
STACK_LCL(run,var->id.idxa) = tmp;
qse_awk_rtx_refupval (run, tmp);
}
else /* if (var->type == QSE_AWK_NDE_ARGIDX) */
{
qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map);
STACK_ARG(run,var->id.idxa) = tmp;
qse_awk_rtx_refupval (run, tmp);
case QSE_AWK_NDE_LCLIDX:
qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map);
RTX_STACK_LCL(run,var->id.idxa) = tmp;
qse_awk_rtx_refupval (run, tmp);
break;
default: /* QSE_AWK_NDE_ARGIDX */
qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map);
RTX_STACK_ARG(run,var->id.idxa) = tmp;
qse_awk_rtx_refupval (run, tmp);
break;
}
map = (qse_awk_val_map_t*) tmp;
@ -5565,9 +5611,9 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
}
/* run->stack_base has not been set for this
* stack frame. so the STACK_ARG macro cannot be used as in
* qse_awk_rtx_refdownval (run, STACK_ARG(run,nargs));*/
#define UNWIND_RTX_STACK_ARG(rtx,nargs) \
* stack frame. so the RTX_STACK_ARG macro cannot be used as in
* qse_awk_rtx_refdownval (run, RTX_STACK_ARG(run,nargs));*/
#define UNWIND_RTX_RTX_STACK_ARG(rtx,nargs) \
do { \
while ((nargs) > 0) \
{ \
@ -5577,7 +5623,7 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
} \
} while (0)
#define UNWIND_RTX_STACK_BASE(rtx) \
#define UNWIND_RTX_RTX_STACK_BASE(rtx) \
do { \
__raw_pop (rtx); /* nargs */ \
__raw_pop (rtx); /* return */ \
@ -5587,8 +5633,8 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
#define UNWIND_RTX_STACK(rtx,nargs) \
do { \
UNWIND_RTX_STACK_ARG(rtx,nargs); \
UNWIND_RTX_STACK_BASE(rtx); \
UNWIND_RTX_RTX_STACK_ARG(rtx,nargs); \
UNWIND_RTX_RTX_STACK_BASE(rtx); \
} while (0)
static qse_awk_val_t* __eval_call (
@ -5692,7 +5738,7 @@ static qse_awk_val_t* __eval_call (
nargs = argpusher (run, call, apdata);
if (nargs == (qse_size_t)-1)
{
UNWIND_RTX_STACK_BASE (run);
UNWIND_RTX_RTX_STACK_BASE (run);
return QSE_NULL;
}
@ -5717,7 +5763,7 @@ static qse_awk_val_t* __eval_call (
}
run->stack_base = saved_stack_top;
STACK_NARGS(run) = (void*)nargs;
RTX_STACK_NARGS(run) = (void*)nargs;
#ifdef DEBUG_RUN
qse_dprintf (QSE_T("running function body\n"));
@ -5768,21 +5814,21 @@ static qse_awk_val_t* __eval_call (
}
/* refdown args in the run.stack */
nargs = (qse_size_t)STACK_NARGS(run);
nargs = (qse_size_t)RTX_STACK_NARGS(run);
#ifdef DEBUG_RUN
qse_dprintf (QSE_T("block run complete nargs = %d\n"), (int)nargs);
#endif
for (i = 0; i < nargs; i++)
{
qse_awk_rtx_refdownval (run, STACK_ARG(run,i));
qse_awk_rtx_refdownval (run, RTX_STACK_ARG(run,i));
}
#ifdef DEBUG_RUN
qse_dprintf (QSE_T("got return value\n"));
#endif
v = STACK_RETVAL(run);
v = RTX_STACK_RETVAL(run);
if (n == -1)
{
if (run->errinf.num == QSE_AWK_ENOERR && errhandler != QSE_NULL)
@ -5791,19 +5837,19 @@ static qse_awk_val_t* __eval_call (
* invoked from qse_awk_rtx_call(). Under this
* circumstance, this stack frame is the first
* activated and the stack base is the first element
* after the global variables. so STACK_RETVAL(run)
* effectively becomes STACK_RETVAL_GBL(run).
* after the global variables. so RTX_STACK_RETVAL(run)
* effectively becomes RTX_STACK_RETVAL_GBL(run).
* As __eval_call() returns QSE_NULL on error and
* the reference count of STACK_RETVAL(run) should be
* the reference count of RTX_STACK_RETVAL(run) should be
* decremented, it can't get the return value
* if it turns out to be terminated by exit().
* The return value could be destroyed by then.
* Unlikely, run_bpae_loop() just checks if run->errinf.num
* is QSE_AWK_ENOERR and gets STACK_RETVAL_GBL(run)
* is QSE_AWK_ENOERR and gets RTX_STACK_RETVAL_GBL(run)
* to determine if it is terminated by exit().
*
* The handler capture_retval_on_exit()
* increments the reference of STACK_RETVAL(run)
* increments the reference of RTX_STACK_RETVAL(run)
* and stores the pointer into accompanying space.
* This way, the return value is preserved upon
* termination by exit() out to the caller.
@ -5815,7 +5861,7 @@ static qse_awk_val_t* __eval_call (
* has to return a error, the return value is just
* destroyed and replaced by nil */
qse_awk_rtx_refdownval (run, v);
STACK_RETVAL(run) = qse_awk_val_nil;
RTX_STACK_RETVAL(run) = qse_awk_val_nil;
}
else
{
@ -5858,7 +5904,7 @@ static qse_size_t push_arg_from_vals (
qse_awk_rtx_refupval (rtx, pafv->args[nargs]);
qse_awk_rtx_refdownval (rtx, pafv->args[nargs]);
UNWIND_RTX_STACK_ARG (rtx, nargs);
UNWIND_RTX_RTX_STACK_ARG (rtx, nargs);
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &call->loc);
return (qse_size_t)-1;
}
@ -5892,7 +5938,7 @@ static qse_size_t push_arg_from_nde (
if (get_reference (rtx, p, &ref) == -1)
{
UNWIND_RTX_STACK_ARG (rtx, nargs);
UNWIND_RTX_RTX_STACK_ARG (rtx, nargs);
return (qse_size_t)-1;
}
@ -5915,7 +5961,7 @@ static qse_size_t push_arg_from_nde (
if (v == QSE_NULL)
{
UNWIND_RTX_STACK_ARG (rtx, nargs);
UNWIND_RTX_RTX_STACK_ARG (rtx, nargs);
return (qse_size_t)-1;
}
@ -5929,7 +5975,7 @@ static qse_size_t push_arg_from_nde (
qse_awk_rtx_refupval (rtx, v);
qse_awk_rtx_refdownval (rtx, v);
UNWIND_RTX_STACK_ARG (rtx, nargs);
UNWIND_RTX_RTX_STACK_ARG (rtx, nargs);
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &call->loc);
return (qse_size_t)-1;
}
@ -5987,15 +6033,16 @@ static int get_reference (
}
case QSE_AWK_NDE_GBL:
*ref = (qse_awk_val_t**)&STACK_GBL(run,tgt->id.idxa);
/* *ref = (qse_awk_val_t**)&RTX_STACK_GBL(run,tgt->id.idxa); */
*ref = (qse_awk_val_t**)((qse_size_t)tgt->id.idxa);
return 0;
case QSE_AWK_NDE_LCL:
*ref = (qse_awk_val_t**)&STACK_LCL(run,tgt->id.idxa);
*ref = (qse_awk_val_t**)&RTX_STACK_LCL(run,tgt->id.idxa);
return 0;
case QSE_AWK_NDE_ARG:
*ref = (qse_awk_val_t**)&STACK_ARG(run,tgt->id.idxa);
*ref = (qse_awk_val_t**)&RTX_STACK_ARG(run,tgt->id.idxa);
return 0;
case QSE_AWK_NDE_NAMEDIDX:
@ -6025,21 +6072,21 @@ static int get_reference (
case QSE_AWK_NDE_GBLIDX:
tmp = get_reference_indexed (run, tgt,
(qse_awk_val_t**)&STACK_GBL(run,tgt->id.idxa));
(qse_awk_val_t**)&RTX_STACK_GBL(run,tgt->id.idxa));
if (tmp == QSE_NULL) return -1;
*ref = tmp;
return 0;
case QSE_AWK_NDE_LCLIDX:
tmp = get_reference_indexed (run, tgt,
(qse_awk_val_t**)&STACK_LCL(run,tgt->id.idxa));
(qse_awk_val_t**)&RTX_STACK_LCL(run,tgt->id.idxa));
if (tmp == QSE_NULL) return -1;
*ref = tmp;
return 0;
case QSE_AWK_NDE_ARGIDX:
tmp = get_reference_indexed (run, tgt,
(qse_awk_val_t**)&STACK_ARG(run,tgt->id.idxa));
(qse_awk_val_t**)&RTX_STACK_ARG(run,tgt->id.idxa));
if (tmp == QSE_NULL) return -1;
*ref = tmp;
return 0;
@ -6199,17 +6246,17 @@ static qse_awk_val_t* eval_named (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
static qse_awk_val_t* eval_gbl (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa);
return RTX_STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa);
}
static qse_awk_val_t* eval_lcl (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa);
return RTX_STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa);
}
static qse_awk_val_t* eval_arg (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa);
return RTX_STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa);
}
static qse_awk_val_t* eval_indexed (
@ -6281,19 +6328,19 @@ static qse_awk_val_t* eval_namedidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
static qse_awk_val_t* eval_gblidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return eval_indexed (run, (qse_awk_nde_var_t*)nde,
(qse_awk_val_t**)&STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa));
(qse_awk_val_t**)&RTX_STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa));
}
static qse_awk_val_t* eval_lclidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return eval_indexed (run, (qse_awk_nde_var_t*)nde,
(qse_awk_val_t**)&STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa));
(qse_awk_val_t**)&RTX_STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa));
}
static qse_awk_val_t* eval_argidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
{
return eval_indexed (run, (qse_awk_nde_var_t*)nde,
(qse_awk_val_t**)&STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa));
(qse_awk_val_t**)&RTX_STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa));
}
static qse_awk_val_t* eval_pos (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
@ -6495,7 +6542,7 @@ static int __raw_push (qse_awk_rtx_t* run, void* val)
void** tmp;
qse_size_t n;
n = run->stack_limit + STACK_INCREMENT;
n = run->stack_limit + RTX_STACK_INCREMENT;
tmp = (void**) QSE_AWK_REALLOC (
run->awk, run->stack, n * QSE_SIZEOF(void*));
@ -6561,7 +6608,7 @@ static int shorten_record (qse_awk_rtx_t* run, qse_size_t nflds)
if (nflds > 1)
{
v = STACK_GBL(run, QSE_AWK_GBL_OFS);
v = RTX_STACK_GBL(run, QSE_AWK_GBL_OFS);
qse_awk_rtx_refupval (run, v);
if (v->type == QSE_AWK_VAL_NIL)
@ -7328,36 +7375,37 @@ wp_mod_main:
}
qse_awk_rtx_refupval (rtx, v);
if (v->type == QSE_AWK_VAL_NIL)
switch (v->type)
{
ch = QSE_T('\0');
ch_len = 0;
}
else if (v->type == QSE_AWK_VAL_INT)
{
ch = (qse_char_t)((qse_awk_val_int_t*)v)->val;
ch_len = 1;
}
else if (v->type == QSE_AWK_VAL_FLT)
{
ch = (qse_char_t)((qse_awk_val_flt_t*)v)->val;
ch_len = 1;
}
else if (v->type == QSE_AWK_VAL_STR)
{
ch_len = ((qse_awk_val_str_t*)v)->val.len;
if (ch_len > 0)
{
ch = ((qse_awk_val_str_t*)v)->val.ptr[0];
case QSE_AWK_VAL_NIL:
ch = QSE_T('\0');
ch_len = 0;
break;
case QSE_AWK_VAL_INT:
ch = (qse_char_t)((qse_awk_val_int_t*)v)->val;
ch_len = 1;
}
else ch = QSE_T('\0');
}
else
{
qse_awk_rtx_refdownval (rtx, v);
SETERR_COD (rtx, QSE_AWK_EVALTYPE);
return QSE_NULL;
break;
case QSE_AWK_VAL_FLT:
ch = (qse_char_t)((qse_awk_val_flt_t*)v)->val;
ch_len = 1;
break;
case QSE_AWK_VAL_STR:
ch_len = ((qse_awk_val_str_t*)v)->val.len;
if (ch_len > 0)
{
ch = ((qse_awk_val_str_t*)v)->val.ptr[0];
ch_len = 1;
}
else ch = QSE_T('\0');
break;
default:
qse_awk_rtx_refdownval (rtx, v);
SETERR_COD (rtx, QSE_AWK_EVALTOCHR);
return QSE_NULL;
}
if (wp[WP_PRECISION] == -1 || wp[WP_PRECISION] == 0 || wp[WP_PRECISION] > (qse_long_t)ch_len)

View File

@ -2536,14 +2536,20 @@ done:
if (ret >= 0)
{
if (rv && qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv) >= 0)
qse_awk_val_t* retv;
if (rv)
{
qse_awk_rtx_setretval (rtx, qse_awk_val_zero);
}
else
{
qse_awk_rtx_setretval (rtx, qse_awk_val_negone);
int x;
qse_awk_rtx_refupval (rtx, rv);
x = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv);
qse_awk_rtx_refdownval (rtx, rv);
if (x <= -1) retv = qse_awk_val_negone;
else retv = qse_awk_val_zero;
}
else retv = qse_awk_val_negone;
qse_awk_rtx_setretval (rtx, qse_awk_val_zero);
}
return ret;

View File

@ -1296,48 +1296,58 @@ static int val_ref_to_str (
qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref,
qse_awk_rtx_valtostr_out_t* out)
{
if (ref->id == QSE_AWK_VAL_REF_POS)
switch (ref->id)
{
qse_size_t idx;
case QSE_AWK_VAL_REF_POS:
{
qse_size_t idx;
/* special case when the reference value is
* pointing to the positional */
/* special case when the reference value is
* pointing to the positional */
idx = (qse_size_t)ref->adr;
if (idx == 0)
{
return str_to_str (
rtx,
QSE_STR_PTR(&rtx->inrec.line),
QSE_STR_LEN(&rtx->inrec.line),
out
);
idx = (qse_size_t)ref->adr;
if (idx == 0)
{
return str_to_str (
rtx,
QSE_STR_PTR(&rtx->inrec.line),
QSE_STR_LEN(&rtx->inrec.line),
out
);
}
else if (idx <= rtx->inrec.nflds)
{
return str_to_str (
rtx,
rtx->inrec.flds[idx-1].ptr,
rtx->inrec.flds[idx-1].len,
out
);
}
else
{
return str_to_str (rtx, QSE_T(""), 0, out);
}
}
else if (idx <= rtx->inrec.nflds)
{
return str_to_str (
rtx,
rtx->inrec.flds[idx-1].ptr,
rtx->inrec.flds[idx-1].len,
out
);
}
else
{
return str_to_str (rtx, QSE_T(""), 0, out);
}
}
else
{
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
/* A reference value is not able to point to another
* refernce value for the way values are represented
* in QSEAWK */
QSE_ASSERT ((*xref)->type != QSE_AWK_VAL_REF);
case QSE_AWK_VAL_REF_GBL:
{
qse_size_t idx = (qse_size_t)ref->adr;
return qse_awk_rtx_valtostr (rtx, RTX_STACK_GBL (rtx, idx), out);
}
/* make a recursive call back to the caller */
return qse_awk_rtx_valtostr (rtx, *xref, out);
default:
{
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
/* A reference value is not able to point to another
* refernce value for the way values are represented
* in QSEAWK */
QSE_ASSERT ((*xref)->type != QSE_AWK_VAL_REF);
/* make a recursive call back to the caller */
return qse_awk_rtx_valtostr (rtx, *xref, out);
}
}
}
@ -1373,7 +1383,9 @@ int qse_awk_rtx_valtostr (
case QSE_AWK_VAL_MAP:
{
if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP)
{
return str_to_str (rtx, QSE_T("#MAP"), 4, out);
}
break;
}
@ -1391,7 +1403,7 @@ int qse_awk_rtx_valtostr (
v->type
);
#endif
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL);
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTOSTR, QSE_NULL);
return -1;
}
@ -1458,47 +1470,57 @@ qse_wchar_t* qse_awk_rtx_valtowcsdup (
static int val_ref_to_num (
qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse_long_t* l, qse_flt_t* r)
{
if (ref->id == QSE_AWK_VAL_REF_POS)
switch (ref->id)
{
qse_size_t idx;
case QSE_AWK_VAL_REF_POS:
{
qse_size_t idx;
idx = (qse_size_t)ref->adr;
if (idx == 0)
{
return qse_awk_rtx_strtonum (
rtx, 0,
QSE_STR_PTR(&rtx->inrec.line),
QSE_STR_LEN(&rtx->inrec.line),
l, r
);
idx = (qse_size_t)ref->adr;
if (idx == 0)
{
return qse_awk_rtx_strtonum (
rtx, 0,
QSE_STR_PTR(&rtx->inrec.line),
QSE_STR_LEN(&rtx->inrec.line),
l, r
);
}
else if (idx <= rtx->inrec.nflds)
{
return qse_awk_rtx_strtonum (
rtx, 0,
rtx->inrec.flds[idx-1].ptr,
rtx->inrec.flds[idx-1].len,
l, r
);
}
else
{
return qse_awk_rtx_strtonum (
rtx, 0, QSE_T(""), 0, l, r
);
}
}
else if (idx <= rtx->inrec.nflds)
{
return qse_awk_rtx_strtonum (
rtx, 0,
rtx->inrec.flds[idx-1].ptr,
rtx->inrec.flds[idx-1].len,
l, r
);
}
else
{
return qse_awk_rtx_strtonum (
rtx, 0, QSE_T(""), 0, l, r
);
}
}
else
{
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
/* A reference value is not able to point to another
* refernce value for the way values are represented
* in QSEAWK */
QSE_ASSERT ((*xref)->type != QSE_AWK_VAL_REF);
case QSE_AWK_VAL_REF_GBL:
{
qse_size_t idx = (qse_size_t)ref->adr;
return qse_awk_rtx_valtonum (rtx, RTX_STACK_GBL (rtx, idx), l, r);
}
/* make a recursive call back to the caller */
return qse_awk_rtx_valtonum (rtx, *xref, l, r);
default:
{
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
/* A reference value is not able to point to another
* refernce value for the way values are represented
* in QSEAWK */
QSE_ASSERT ((*xref)->type != QSE_AWK_VAL_REF);
/* make a recursive call back to the caller */
return qse_awk_rtx_valtonum (rtx, *xref, l, r);
}
}
}
@ -1549,7 +1571,7 @@ int qse_awk_rtx_valtonum (
);
#endif
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL);
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTONUM, QSE_NULL);
return -1; /* error */
}
@ -1648,8 +1670,7 @@ qse_long_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
v->type
);
#endif
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL);
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EHASHVAL, QSE_NULL);
return -1;
}
@ -1672,45 +1693,107 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
return -1;
}
if (ref->id == QSE_AWK_VAL_REF_POS)
switch (ref->id)
{
if (val->type == QSE_AWK_VAL_STR)
case QSE_AWK_VAL_REF_POS:
{
return qse_awk_rtx_setrec (
rtx, (qse_size_t)ref->adr,
&((qse_awk_val_str_t*)val)->val
);
switch (val->type)
{
case QSE_AWK_VAL_MAP:
/* a map is assigned to a positional. this is disallowed. */
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EPOSVALMAP, QSE_NULL);
return -1;
case QSE_AWK_VAL_STR:
{
int x;
/* handle this separately from the default case
* for no duplication. jumping to the default case
* and callingqse_awk_rtx_valtostrdup() would also work, anyway. */
qse_awk_rtx_refupval (rtx, val);
x = qse_awk_rtx_setrec (
rtx, (qse_size_t)ref->adr,
&((qse_awk_val_str_t*)val)->val
);
qse_awk_rtx_refdownval (rtx, val);
return x;
}
default:
{
qse_xstr_t str;
int x;
str.ptr = qse_awk_rtx_valtostrdup (rtx, val, &str.len);
qse_awk_rtx_refupval (rtx, val);
x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &str);
qse_awk_rtx_refdownval (rtx, val);
QSE_AWK_FREE (rtx->awk, str.ptr);
return x;
}
}
}
else
case QSE_AWK_VAL_REF_GBL:
return qse_awk_rtx_setgbl (rtx, (int)ref->adr, val);
case QSE_AWK_VAL_REF_NAMEDIDX:
case QSE_AWK_VAL_REF_GBLIDX:
case QSE_AWK_VAL_REF_LCLIDX:
case QSE_AWK_VAL_REF_ARGIDX:
if (val->type == QSE_AWK_VAL_MAP)
{
/* an indexed variable cannot be assigned a map.
* in other cases, it falls down to the default case. */
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EIDXVALMAP, QSE_NULL);
return -1;
}
/* fall through */
default:
{
qse_xstr_t str;
int x;
str.ptr = qse_awk_rtx_valtostrdup (rtx, val, &str.len);
x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &str);
QSE_AWK_FREE (rtx->awk, str.ptr);
return x;
qse_awk_val_t** rref;
rref = (qse_awk_val_t**)ref->adr;
if (val->type == QSE_AWK_VAL_MAP)
{
/* new value: map, old value: nil or map => ok */
if ((*rref)->type != QSE_AWK_VAL_NIL &&
(*rref)->type != QSE_AWK_VAL_MAP)
{
if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP))
{
/* cannot change a scalar value to a map */
qse_awk_rtx_seterrnum (rtx, QSE_AWK_ESCALARTOMAP, QSE_NULL);
return -1;
}
}
}
else
{
/* new value: scalar, old value: nil or scalar => ok */
if ((*rref)->type == QSE_AWK_VAL_MAP)
{
if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP))
{
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EMAPTOSCALAR, QSE_NULL);
return -1;
}
}
}
if (*rref != val)
{
/* if the new value is not the same as the old value */
qse_awk_rtx_refdownval (rtx, *rref);
*rref = val;
qse_awk_rtx_refupval (rtx, *rref);
}
return 0;
}
}
else
{
qse_awk_val_t** rref;
/* TODO: handle QSE_AWK_FLEXMAP...
if FLEXMAP is not set.. check if rref is nil or map if value is map.
also check if rref is nil... scalar if valeu is scalar..
but is this really necessary? i feel all these awk quarkiness is nasty..
*/
rref = (qse_awk_val_t**)ref->adr;
if (*rref != val)
{
qse_awk_rtx_refdownval (rtx, *rref);
*rref = val;
qse_awk_rtx_refupval (rtx, *rref);
}
return 0;
}
}
#if 0