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:
hyung-hwan 2012-12-22 14:01:41 +00:00
parent 0dc6c0863e
commit c133af0e55
7 changed files with 243 additions and 32 deletions

View File

@ -1,7 +1,10 @@
AUTOMAKE_OPTION = foreign
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = LICENSE
EXTRA_DIST = LICENSE \
bld/qse.bkl bld/readme.txt bld/os2.bkgen bld/win32.bkgen \
bld/os2-watcom/makefile bld/win32-watcom/makefile \
bld/win32-msvc/makefile bld/win32-borland/makefile
SUBDIRS = libltdl include lib cmd mod
DIST_SUBDIRS = $(SUBDIRS) regress samples doc tools

View File

@ -282,7 +282,11 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTION = foreign
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = LICENSE
EXTRA_DIST = LICENSE \
bld/qse.bkl bld/readme.txt bld/os2.bkgen bld/win32.bkgen \
bld/os2-watcom/makefile bld/win32-watcom/makefile \
bld/win32-msvc/makefile bld/win32-borland/makefile
SUBDIRS = libltdl include lib cmd mod
DIST_SUBDIRS = $(SUBDIRS) regress samples doc tools
all: all-recursive

View File

@ -355,7 +355,7 @@ static void on_statement (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
static void print_version (void)
{
qse_printf (QSE_T("QSEAWK version %hs\n"), QSE_PACKAGE_VERSION);
qse_fprintf (QSE_STDOUT, QSE_T("QSEAWK version %hs\n"), QSE_PACKAGE_VERSION);
}
static void print_error (const qse_char_t* fmt, ...)

View File

@ -2005,7 +2005,8 @@ QSE_EXPORT qse_size_t qse_awk_rtx_getnargs (
);
/**
* The qse_awk_rtx_getarg() function gets an argument passed to qse_awk_run().
* The qse_awk_rtx_getarg() function gets an argument passed to an intrinsic
* function. it doesn't touch the reference count of the value.
*/
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getarg (
qse_awk_rtx_t* rtx,
@ -2642,7 +2643,7 @@ QSE_EXPORT int qse_awk_rtx_strtonum (
);
/**
* The qse_awk_rtx_hashval() functions hashes a simple value
* The qse_awk_rtx_hashval() function hashes a simple value
* to a positive integer. It returns -1 for a inhashable value.
*/
QSE_EXPORT qse_long_t qse_awk_rtx_hashval (
@ -2650,6 +2651,16 @@ QSE_EXPORT qse_long_t qse_awk_rtx_hashval (
qse_awk_val_t* v
);
/**
* The qse_awk_rtx_setrefval() function changes the value
* of a variable referenced in @a ref.
* @return 0 on success, -1 on failure.
*/
QSE_EXPORT int qse_awk_rtx_setrefval (
qse_awk_rtx_t* rtx,
qse_awk_val_ref_t* ref,
qse_awk_val_t* val
);
QSE_EXPORT void qse_awk_rtx_setnrflt (
qse_awk_rtx_t* rtx,

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