added qse_awk_rtx_setrefval()

enhanced qse_awk_rtx_valtobool(), qse_awk_rtx_valtonum()< qse_awk_rtx_valtostr() to handle reference values
This commit is contained in:
2012-12-22 14:01:41 +00:00
parent 0dc6c0863e
commit c133af0e55
7 changed files with 243 additions and 32 deletions

View File

@ -5887,7 +5887,7 @@ static qse_size_t push_arg_from_nde (
(fnc_arg_spec != QSE_NULL &&
qse_strlen(fnc_arg_spec) > nargs));
if (fnc_arg_spec != QSE_NULL &&
if (fnc_arg_spec &&
(fnc_arg_spec[nargs] == QSE_T('r') ||
fnc_arg_spec[0] == QSE_T('R')))
{
@ -5904,7 +5904,7 @@ static qse_size_t push_arg_from_nde (
v = qse_awk_rtx_makerefval (
rtx, p->type-QSE_AWK_NDE_NAMED, ref);
}
else if (fnc_arg_spec != QSE_NULL &&
else if (fnc_arg_spec &&
fnc_arg_spec[nargs] == QSE_T('x'))
{
/* a regular expression is passed to

View File

@ -2208,15 +2208,11 @@ static int fnc_srand (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
static int fnc_system (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
qse_size_t nargs;
qse_awk_val_t* v;
qse_char_t* str;
qse_size_t len;
int n = 0;
nargs = qse_awk_rtx_getnargs (rtx);
QSE_ASSERT (nargs == 1);
v = qse_awk_rtx_getarg (rtx, 0);
if (v->type == QSE_AWK_VAL_STR)
{
@ -2324,7 +2320,6 @@ static ioattr_t* find_or_make_ioattr (
static int fnc_setioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
rxtn_t* rxtn;
qse_size_t nargs;
qse_awk_val_t* v[3];
qse_char_t* ptr[3];
qse_size_t len[3];
@ -2334,9 +2329,6 @@ static int fnc_setioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
rxtn = (rxtn_t*) QSE_XTN (rtx);
QSE_ASSERT (rxtn->cmgrtab_inited == 1);
nargs = qse_awk_rtx_getnargs (rtx);
QSE_ASSERT (nargs == 3);
for (i = 0; i < 3; i++)
{
v[i] = qse_awk_rtx_getarg (rtx, i);
@ -2454,7 +2446,6 @@ done:
static int fnc_getioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
rxtn_t* rxtn;
qse_size_t nargs;
qse_awk_val_t* v[2];
qse_char_t* ptr[2];
qse_size_t len[2];
@ -2468,9 +2459,6 @@ static int fnc_getioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
rxtn = (rxtn_t*) QSE_XTN (rtx);
QSE_ASSERT (rxtn->cmgrtab_inited == 1);
nargs = qse_awk_rtx_getnargs (rtx);
QSE_ASSERT (nargs == 2);
for (i = 0; i < 2; i++)
{
v[i] = qse_awk_rtx_getarg (rtx, i);
@ -2492,7 +2480,7 @@ static int fnc_getioattr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
if (qse_strxchr (ptr[i], len[i], QSE_T('\0'))) goto done;
}
ioattr = get_ioattr (&rxtn->cmgrtab, ptr[0], len[0]);
ioattr = get_ioattr (&rxtn->cmgrtab, ptr[0], len[0]);
if (ioattr == QSE_NULL)
{
init_ioattr (&ioattr_buf);
@ -2538,11 +2526,15 @@ done:
if (ret >= 0)
{
/* the return value of -1 for an error may be confusing since
* a literal value of -1 can be returned for some attribute
* names */
if (rv == QSE_NULL) rv = qse_awk_val_negone;
qse_awk_rtx_setretval (rtx, rv);
if (rv)
{
qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv);
qse_awk_rtx_setretval (rtx, qse_awk_val_zero);
}
else
{
qse_awk_rtx_setretval (rtx, qse_awk_val_negone);
}
}
return ret;
@ -2586,11 +2578,11 @@ 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"), { {2, 2, QSE_NULL}, fnc_getioattr, QSE_AWK_RIO } }
{ 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 } }
};
static int add_functions (qse_awk_t* awk)

View File

@ -910,7 +910,45 @@ void qse_awk_rtx_freevalchunk (qse_awk_rtx_t* rtx, qse_awk_val_chunk_t* chunk)
}
}
int qse_awk_rtx_valtobool (qse_awk_rtx_t* run, const qse_awk_val_t* val)
static int val_ref_to_bool (
qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref)
{
if (ref->id == QSE_AWK_VAL_REF_POS)
{
qse_size_t idx;
idx = (qse_size_t)ref->adr;
if (idx == 0)
{
return QSE_STR_LEN(&rtx->inrec.line) > 0;
}
else if (idx <= rtx->inrec.nflds)
{
return rtx->inrec.flds[idx-1].len > 0;
}
else
{
/* the index is greater than the number of records.
* it's an empty string. so false */
return 0;
}
}
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);
/* make a recursive call back to the caller */
return qse_awk_rtx_valtobool (rtx, *xref);
}
}
int qse_awk_rtx_valtobool (qse_awk_rtx_t* rtx, const qse_awk_val_t* val)
{
if (val == QSE_NULL) return 0;
@ -929,7 +967,8 @@ int qse_awk_rtx_valtobool (qse_awk_rtx_t* run, const qse_awk_val_t* val)
case QSE_AWK_VAL_MAP:
return 0; /* TODO: is this correct? */
case QSE_AWK_VAL_REF:
return 0; /* TODO: is this correct? */
return val_ref_to_bool (rtx, (qse_awk_val_ref_t*)val);
}
QSE_ASSERTX (
@ -1253,6 +1292,55 @@ oops:
return -1;
}
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)
{
qse_size_t idx;
/* 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
);
}
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);
/* make a recursive call back to the caller */
return qse_awk_rtx_valtostr (rtx, *xref, out);
}
}
int qse_awk_rtx_valtostr (
qse_awk_rtx_t* rtx, const qse_awk_val_t* v,
qse_awk_rtx_valtostr_out_t* out)
@ -1288,8 +1376,15 @@ int qse_awk_rtx_valtostr (
return str_to_str (rtx, QSE_T("#MAP"), 4, out);
break;
}
case QSE_AWK_VAL_REF:
{
return val_ref_to_str (
rtx, (qse_awk_val_ref_t*)v, out);
}
}
#ifdef DEBUG_VAL
qse_dprintf (
QSE_T(">>WRONG VALUE TYPE [%d] in qse_awk_rtx_valtostr\n"),
@ -1360,6 +1455,54 @@ qse_wchar_t* qse_awk_rtx_valtowcsdup (
#endif
}
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)
{
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
);
}
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);
/* make a recursive call back to the caller */
return qse_awk_rtx_valtonum (rtx, *xref, l, r);
}
}
int qse_awk_rtx_valtonum (
qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_long_t* l, qse_flt_t* r)
{
@ -1392,6 +1535,11 @@ int qse_awk_rtx_valtonum (
l, r
);
}
case QSE_AWK_VAL_REF:
{
return val_ref_to_num (rtx, (qse_awk_val_str_t*)v, l, r);
}
}
#ifdef DEBUG_VAL
@ -1509,6 +1657,59 @@ qse_long_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
return hv & ~(((qse_ulong_t)1) << ((QSE_SIZEOF(qse_ulong_t) * 8) - 1));
}
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
{
if (val->type == QSE_AWK_VAL_REX)
{
/* though it is possible that an intrinsic function handler
* can accept a regular expression withtout evaluation when 'x'
* is specified for the parameter, this function doesn't allow
* regular expression to be set to a reference variable to
* avoid potential chaos. the nature of performing '/rex/ ~ $0'
* for a regular expression without the match operator
* makes it difficult to be implemented. */
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
return -1;
}
if (ref->id == QSE_AWK_VAL_REF_POS)
{
if (val->type == QSE_AWK_VAL_STR)
{
return qse_awk_rtx_setrec (
rtx, (qse_size_t)ref->adr,
&((qse_awk_val_str_t*)val)->val
);
}
else
{
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;
}
}
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;
qse_awk_rtx_refdownval (rtx, *rref);
*rref = val;
qse_awk_rtx_refupval (rtx, *rref);
return 0;
}
}
#if 0
#define DPRINTF run->awk->prmfns->dprintf