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:
parent
0dc6c0863e
commit
c133af0e55
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, ...)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
@ -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;
|
||||
@ -2590,7 +2582,7 @@ static struct fnctab_t fnctab[] =
|
||||
{ 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("getioattr"), { {3, 3, QSE_T("vvr")}, fnc_getioattr, QSE_AWK_RIO } }
|
||||
};
|
||||
|
||||
static int add_functions (qse_awk_t* awk)
|
||||
|
@ -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,7 +1376,14 @@ 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 (
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user