redefined qse_awk_mmgr(), qse_awk_getcmgr(), qse_setcmgr() by exposing the mmgr/cmgr fields via qse_awk_alt_t.

implemented comparison operations for the fun value.
changed behavior of some comparison operations that would otherwise result in a runtime error
This commit is contained in:
hyung-hwan 2019-04-30 07:23:34 +00:00
parent 3368c91834
commit b3d63c259b
10 changed files with 424 additions and 205 deletions

View File

@ -219,14 +219,13 @@ static qse_htb_walk_t print_awk_value (
return QSE_HTB_WALK_FORWARD; return QSE_HTB_WALK_FORWARD;
} }
static qse_htb_walk_t set_global ( static qse_htb_walk_t set_global (qse_htb_t* map, qse_htb_pair_t* pair, void* arg)
qse_htb_t* map, qse_htb_pair_t* pair, void* arg)
{ {
qse_awk_val_t* v; qse_awk_val_t* v;
qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg; qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg;
struct gvmv_t* gvmv = (struct gvmv_t*)QSE_HTB_VPTR(pair); struct gvmv_t* gvmv = (struct gvmv_t*)QSE_HTB_VPTR(pair);
v = qse_awk_rtx_makenstrvalwithxstr (rtx, &gvmv->str); v = qse_awk_rtx_makenstrvalwithxstr(rtx, &gvmv->str);
if (v == QSE_NULL) return QSE_HTB_WALK_STOP; if (v == QSE_NULL) return QSE_HTB_WALK_STOP;
qse_awk_rtx_refupval (rtx, v); qse_awk_rtx_refupval (rtx, v);

View File

@ -91,6 +91,17 @@ typedef qse_flt_t qse_awk_flt_t;
*/ */
typedef struct qse_awk_t qse_awk_t; typedef struct qse_awk_t qse_awk_t;
#define QSE_AWK_HDR \
qse_mmgr_t* mmgr; \
qse_cmgr_t* cmgr
typedef struct qse_awk_alt_t qse_awk_alt_t;
struct qse_awk_alt_t
{
/* ensure that qse_awk_alt_t matches the beginning part of qse_awk_t */
QSE_AWK_HDR;
};
/** \struct qse_awk_rtx_t /** \struct qse_awk_rtx_t
* The #qse_awk_rtx_t type defines a runtime context. A runtime context * The #qse_awk_rtx_t type defines a runtime context. A runtime context
* maintains runtime state for a running script. You can create multiple * maintains runtime state for a running script. You can create multiple
@ -1401,7 +1412,7 @@ typedef enum qse_awk_gbl_id_t qse_awk_gbl_id_t;
*/ */
enum qse_awk_val_type_t enum qse_awk_val_type_t
{ {
/* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_MAP inclusive /* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_FUN inclusive
* must be synchronized with an internal table of the __cmp_val * must be synchronized with an internal table of the __cmp_val
* function in run.c and the __val_type_name in val.c */ * function in run.c and the __val_type_name in val.c */
QSE_AWK_VAL_NIL = 0, /**< nil */ QSE_AWK_VAL_NIL = 0, /**< nil */
@ -1409,11 +1420,11 @@ enum qse_awk_val_type_t
QSE_AWK_VAL_FLT = 2, /**< floating-pointer number */ QSE_AWK_VAL_FLT = 2, /**< floating-pointer number */
QSE_AWK_VAL_STR = 3, /**< string */ QSE_AWK_VAL_STR = 3, /**< string */
QSE_AWK_VAL_MBS = 4, /**< byte array */ QSE_AWK_VAL_MBS = 4, /**< byte array */
QSE_AWK_VAL_MAP = 5, /**< map */ QSE_AWK_VAL_FUN = 5, /**< function pointer */
QSE_AWK_VAL_MAP = 6, /**< map */
QSE_AWK_VAL_REX = 6, /**< regular expression */ QSE_AWK_VAL_REX = 7, /**< regular expression */
QSE_AWK_VAL_REF = 7, /**< reference to other types */ QSE_AWK_VAL_REF = 8 /**< reference to other types */
QSE_AWK_VAL_FUN = 8
}; };
typedef enum qse_awk_val_type_t qse_awk_val_type_t; typedef enum qse_awk_val_type_t qse_awk_val_type_t;
@ -1525,9 +1536,15 @@ QSE_EXPORT void qse_awk_close (
* The qse_awk_getmmgr() function gets the memory manager used in * The qse_awk_getmmgr() function gets the memory manager used in
* qse_awk_open(). * qse_awk_open().
*/ */
QSE_EXPORT qse_mmgr_t* qse_awk_getmmgr ( #if defined(MOO_HAVE_INLINE)
qse_awk_t* awk static MOO_INLINE qse_mmgr_t* qse_awk_getmmgr (qse_awk_t* awk) { return awk->mmgr; }
); static MOO_INLINE qse_cmgr_t* qse_awk_getcmgr (qse_awk_t* awk) { return awk->cmgr; }
static MOO_INLINE void qse_setcmgr (qse_awk_t* awk, qse_awk_cmgr_t* cmgr) { awk->cmgr = cmgr; }
#else
# define qse_awk_getmmgr(awk) (((qse_awk_alt_t*)(awk))->mmgr)
# define qse_awk_getcmgr(awk) (((qse_awk_alt_t*)(awk))->cmgr)
# define qse_awk_setcmgr(awk,mgr) (((qse_awk_alt_t*)(awk))->cmgr = (mgr))
#endif
/** /**
* The qse_awk_getxtn() function gets the poniter to the beginning * The qse_awk_getxtn() function gets the poniter to the beginning

View File

@ -166,8 +166,8 @@ struct qse_awk_tok_t
struct qse_awk_t struct qse_awk_t
{ {
qse_mmgr_t* mmgr; /* exposed fields via qse_awk_alt_t */
qse_cmgr_t* cmgr; QSE_AWK_HDR;
/* primitive functions */ /* primitive functions */
qse_awk_prm_t prm; qse_awk_prm_t prm;

View File

@ -350,7 +350,7 @@ void qse_awk_clear (qse_awk_t* awk)
/* clear parse trees */ /* clear parse trees */
/*awk->tree.ngbls_base = 0; /*awk->tree.ngbls_base = 0;
awk->tree.ngbls = 0; */ awk->tree.ngbls = 0; */
awk->tree.ngbls = awk->tree.ngbls_base; awk->tree.ngbls = awk->tree.ngbls_base;
awk->tree.cur_fun.ptr = QSE_NULL; awk->tree.cur_fun.ptr = QSE_NULL;
@ -395,11 +395,6 @@ void qse_awk_clear (qse_awk_t* awk)
*/ */
} }
qse_mmgr_t* qse_awk_getmmgr (qse_awk_t* awk)
{
return awk->mmgr;
}
void* qse_awk_getxtn (qse_awk_t* awk) void* qse_awk_getxtn (qse_awk_t* awk)
{ {
return QSE_XTN (awk); return QSE_XTN (awk);
@ -419,13 +414,13 @@ static int dup_str_opt (qse_awk_t* awk, const void* value, qse_cstr_t* tmp)
{ {
if (value) if (value)
{ {
tmp->ptr = qse_strdup (value, awk->mmgr); tmp->ptr = qse_strdup(value, awk->mmgr);
if (tmp->ptr == QSE_NULL) if (!tmp->ptr)
{ {
qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return -1; return -1;
} }
tmp->len = qse_strlen (tmp->ptr); tmp->len = qse_strlen(tmp->ptr);
} }
else else
{ {

View File

@ -594,7 +594,7 @@ int qse_awk_fnc_length (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
default: default:
/* convert to string and get length */ /* convert to string and get length */
str = qse_awk_rtx_valtostrdup (rtx, v, &len); str = qse_awk_rtx_valtostrdup(rtx, v, &len);
if (str == QSE_NULL) return -1; if (str == QSE_NULL) return -1;
QSE_AWK_FREE (rtx->awk, str); QSE_AWK_FREE (rtx->awk, str);
} }
@ -1517,7 +1517,6 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{ {
qse_size_t nargs; qse_size_t nargs;
qse_awk_val_t* a0; qse_awk_val_t* a0;
qse_awk_int_t lv;
qse_awk_val_t* r; qse_awk_val_t* r;
int n; int n;
@ -1527,12 +1526,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
a0 = qse_awk_rtx_getarg(rtx, 0); a0 = qse_awk_rtx_getarg(rtx, 0);
n = qse_awk_rtx_valtoint(rtx, a0, &lv); r = qse_awk_rtx_makeintval(rtx, QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_NIL);
if (n <= -1) return -1;
r = qse_awk_rtx_makeintval(rtx, lv);
if (r == QSE_NULL) return -1;
qse_awk_rtx_setretval (rtx, r); qse_awk_rtx_setretval (rtx, r);
return 0; return 0;
} }

View File

@ -36,14 +36,14 @@
void* qse_awk_allocmem (qse_awk_t* awk, qse_size_t size) void* qse_awk_allocmem (qse_awk_t* awk, qse_size_t size)
{ {
void* ptr = QSE_AWK_ALLOC (awk, size); void* ptr = QSE_AWK_ALLOC(awk, size);
if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return ptr; return ptr;
} }
void* qse_awk_callocmem (qse_awk_t* awk, qse_size_t size) void* qse_awk_callocmem (qse_awk_t* awk, qse_size_t size)
{ {
void* ptr = QSE_AWK_ALLOC (awk, size); void* ptr = QSE_AWK_ALLOC(awk, size);
if (ptr) QSE_MEMSET (ptr, 0, size); if (ptr) QSE_MEMSET (ptr, 0, size);
else qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); else qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return ptr; return ptr;
@ -51,8 +51,8 @@ void* qse_awk_callocmem (qse_awk_t* awk, qse_size_t size)
void* qse_awk_reallocmem (qse_awk_t* awk, void* ptr, qse_size_t size) void* qse_awk_reallocmem (qse_awk_t* awk, void* ptr, qse_size_t size)
{ {
void* nptr = QSE_AWK_REALLOC (awk, ptr, size); void* nptr = QSE_AWK_REALLOC(awk, ptr, size);
if (nptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); if (!nptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return nptr; return nptr;
} }
@ -63,22 +63,22 @@ void qse_awk_freemem (qse_awk_t* awk, void* ptr)
qse_char_t* qse_awk_strdup (qse_awk_t* awk, const qse_char_t* s) qse_char_t* qse_awk_strdup (qse_awk_t* awk, const qse_char_t* s)
{ {
qse_char_t* ptr = QSE_AWK_STRDUP (awk, s); qse_char_t* ptr = QSE_AWK_STRDUP(awk, s);
if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return ptr; return ptr;
} }
qse_char_t* qse_awk_strxdup (qse_awk_t* awk, const qse_char_t* s, qse_size_t l) qse_char_t* qse_awk_strxdup (qse_awk_t* awk, const qse_char_t* s, qse_size_t l)
{ {
qse_char_t* ptr = QSE_AWK_STRXDUP (awk, s, l); qse_char_t* ptr = QSE_AWK_STRXDUP(awk, s, l);
if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return ptr; return ptr;
} }
qse_char_t* qse_awk_cstrdup (qse_awk_t* awk, const qse_cstr_t* s) qse_char_t* qse_awk_cstrdup (qse_awk_t* awk, const qse_cstr_t* s)
{ {
qse_char_t* ptr = qse_cstrdup (s, awk->mmgr); qse_char_t* ptr = qse_cstrdup(s, awk->mmgr);
if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL);
return ptr; return ptr;
} }

View File

@ -4252,8 +4252,10 @@ static qse_awk_nde_t* parse_increment (qse_awk_t* awk, const qse_awk_loc_t* xloc
#define FNTYPE_FNC 1 #define FNTYPE_FNC 1
#define FNTYPE_FUN 2 #define FNTYPE_FUN 2
static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name) static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name, qse_awk_fun_t** fun)
{ {
qse_htb_pair_t* pair;
/* check if it is an awk function being processed currently */ /* check if it is an awk function being processed currently */
if (awk->tree.cur_fun.ptr) if (awk->tree.cur_fun.ptr)
{ {
@ -4265,14 +4267,20 @@ static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name)
} }
/* check the funtion name in the function table */ /* check the funtion name in the function table */
if (qse_htb_search(awk->tree.funs, name->ptr, name->len) != QSE_NULL) pair = qse_htb_search(awk->tree.funs, name->ptr, name->len);
if (pair)
{ {
/* one of the functions defined previously */ /* one of the functions defined previously */
if (fun)
{
*fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair);
QSE_ASSERT (*fun != QSE_NULL);
}
return FNTYPE_FUN; return FNTYPE_FUN;
} }
/* check if it is a function not resolved so far */ /* check if it is a function not resolved so far */
if (qse_htb_search(awk->parse.funs, name->ptr, name->len) != QSE_NULL) if (qse_htb_search(awk->parse.funs, name->ptr, name->len))
{ {
/* one of the function calls not resolved so far. */ /* one of the function calls not resolved so far. */
return FNTYPE_FUN; return FNTYPE_FUN;
@ -4289,7 +4297,7 @@ static QSE_INLINE int isfnname (qse_awk_t* awk, const qse_cstr_t* name)
return FNTYPE_FNC; return FNTYPE_FNC;
} }
return isfunname(awk, name); return isfunname(awk, name, QSE_NULL);
} }
static qse_awk_nde_t* parse_primary_int (qse_awk_t* awk, const qse_awk_loc_t* xloc) static qse_awk_nde_t* parse_primary_int (qse_awk_t* awk, const qse_awk_loc_t* xloc)
@ -4981,7 +4989,7 @@ oops:
} }
#if defined(ENABLE_FEATURE_FUN_AS_VALUE) #if defined(ENABLE_FEATURE_FUN_AS_VALUE)
static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc) static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc, qse_awk_fun_t* funptr)
{ {
qse_awk_nde_fun_t* nde; qse_awk_nde_fun_t* nde;
@ -4997,6 +5005,7 @@ static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* nam
nde->loc = *xloc; nde->loc = *xloc;
nde->name.ptr = name->ptr; nde->name.ptr = name->ptr;
nde->name.len = name->len; nde->name.len = name->len;
nde->funptr = funptr;
return (qse_awk_nde_t*)nde; return (qse_awk_nde_t*)nde;
@ -5067,8 +5076,9 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l
else else
{ {
int fntype; int fntype;
qse_awk_fun_t* funptr = QSE_NULL;
fntype = isfunname(awk, name); fntype = isfunname(awk, name, &funptr);
if (fntype) if (fntype)
{ {
@ -5084,7 +5094,7 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l
{ {
/* function name appeared without () */ /* function name appeared without () */
#if defined(ENABLE_FEATURE_FUN_AS_VALUE) #if defined(ENABLE_FEATURE_FUN_AS_VALUE)
nde = parse_fun_as_value(awk, name, xloc); nde = parse_fun_as_value(awk, name, xloc, funptr);
#else #else
SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name->ptr, name->len, xloc); SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name->ptr, name->len, xloc);
#endif #endif

View File

@ -4188,46 +4188,106 @@ static qse_awk_val_t* eval_binop_band (
return qse_awk_rtx_makeintval (rtx, l1 & l2); return qse_awk_rtx_makeintval (rtx, l1 & l2);
} }
static QSE_INLINE int __cmp_nil_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) /* -------------------------------------------------------------------- */
enum cmp_op_t
{
CMP_OP_EQ = 0,
CMP_OP_NE = 1,
CMP_OP_GT = 2,
CMP_OP_GE = 3,
CMP_OP_LT = 4,
CMP_OP_LE = 5
};
typedef enum cmp_op_t cmp_op_t;
static QSE_INLINE cmp_op_t inverse_cmp_op (cmp_op_t op)
{
static cmp_op_t inverse_cmp_op_tab[] =
{
CMP_OP_NE,
CMP_OP_EQ,
CMP_OP_LT,
CMP_OP_LE,
CMP_OP_GT,
CMP_OP_GE
};
return inverse_cmp_op_tab[op];
}
static QSE_INLINE int __cmp_ensure_not_equal (cmp_op_t op_hint)
{
/* checking equality is mostly obvious. however, it is not possible
* to test if one is less/greater than the other for some operands.
* this function return a number that ensures to make NE to true and
* all other operations false */
switch (op_hint)
{
case CMP_OP_EQ:
case CMP_OP_NE:
return 1; /* not equal */
case CMP_OP_GT:
case CMP_OP_LT:
return 0; /* make GT or LT to be false by claiming equal */
case CMP_OP_GE:
return -1; /* make GE false by claiming less */
case CMP_OP_LE:
return 1; /* make LE false by claiming greater */
}
}
/* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_nil_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return 0; return 0;
} }
static QSE_INLINE int __cmp_nil_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_nil_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL (rtx, right); qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL (rtx, right);
return (v < 0)? 1: ((v > 0)? -1: 0); return (v < 0)? 1: ((v > 0)? -1: 0);
} }
static QSE_INLINE int __cmp_nil_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_nil_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
if (((qse_awk_val_flt_t*)right)->val < 0) return 1; if (((qse_awk_val_flt_t*)right)->val < 0) return 1;
if (((qse_awk_val_flt_t*)right)->val > 0) return -1; if (((qse_awk_val_flt_t*)right)->val > 0) return -1;
return 0; return 0;
} }
static QSE_INLINE int __cmp_nil_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_nil_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return (((qse_awk_val_str_t*)right)->val.len == 0)? 0: -1; return (((qse_awk_val_str_t*)right)->val.len == 0)? 0: -1;
} }
static QSE_INLINE int __cmp_nil_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_nil_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return (((qse_awk_val_mbs_t*)right)->val.len == 0)? 0: -1; return (((qse_awk_val_mbs_t*)right)->val.len == 0)? 0: -1;
} }
static QSE_INLINE int __cmp_nil_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_nil_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
/* != -> true, all others -> false */
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_nil_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return (QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map) == 0)? 0: -1; return (QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map) == 0)? 0: -1;
} }
static QSE_INLINE int __cmp_int_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) /* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_int_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL(rtx, left);
return (v > 0)? 1: ((v < 0)? -1: 0); return (v > 0)? 1: ((v < 0)? -1: 0);
} }
static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left);
@ -4236,7 +4296,7 @@ static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
} }
static QSE_INLINE int __cmp_int_flt ( static QSE_INLINE int __cmp_int_flt (
qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL (rtx, left); qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL (rtx, left);
if (v1 > ((qse_awk_val_flt_t*)right)->val) return 1; if (v1 > ((qse_awk_val_flt_t*)right)->val) return 1;
@ -4244,9 +4304,10 @@ static QSE_INLINE int __cmp_int_flt (
return 0; return 0;
} }
static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_rtx_valtostr_out_t out; qse_char_t* str0;
qse_size_t len0;
int n; int n;
/* SCO CC doesn't seem to handle right->nstr > 0 properly */ /* SCO CC doesn't seem to handle right->nstr > 0 properly */
@ -4263,7 +4324,7 @@ static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
&ll, &rr &ll, &rr
); );
v1 = QSE_AWK_RTX_GETINTFROMVAL (rtx, left); v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left);
if (n == 0) if (n == 0)
{ {
/* a numeric integral string */ /* a numeric integral string */
@ -4276,40 +4337,76 @@ static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
} }
} }
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; str0 = qse_awk_rtx_valtostrdup(rtx, left, &len0);
if (qse_awk_rtx_valtostr(rtx, left, &out) <= -1) return CMP_ERROR; if (!str0) return CMP_ERROR;
if (rtx->gbl.ignorecase) if (rtx->gbl.ignorecase)
{ {
n = qse_strxncasecmp( n = qse_strxncasecmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len);
out.u.cpldup.ptr,
out.u.cpldup.len,
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len
);
} }
else else
{ {
n = qse_strxncmp( n = qse_strxncmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len);
out.u.cpldup.ptr,
out.u.cpldup.len,
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len
);
} }
QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr); qse_awk_rtx_freemem (rtx, str0);
return n; return n;
} }
static QSE_INLINE int __cmp_int_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_int_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare an integer with a byte array */ qse_mchar_t* str0;
SETERR_COD (rtx, QSE_AWK_EOPERAND); qse_size_t len0;
return CMP_ERROR; int n;
if (rtx->awk->opt.trait & QSE_AWK_NCMPONSTR || right->nstr /*> 0*/)
{
qse_awk_int_t ll, v1;
qse_awk_flt_t rr;
n = qse_awk_rtx_mbstonum (
rtx,
QSE_AWK_RTX_STRTONUM_MAKE_OPTION(1, 0),
((qse_awk_val_mbs_t*)right)->val.ptr,
((qse_awk_val_mbs_t*)right)->val.len,
&ll, &rr
);
v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left);
if (n == 0)
{
/* a numeric integral string */
return (v1 > ll)? 1: ((v1 < ll)? -1: 0);
}
else if (n > 0)
{
/* a numeric floating-point string */
return (v1 > rr)? 1: ((v1 < rr)? -1: 0);
}
}
str0 = qse_awk_rtx_valtombsdup(rtx, left, &len0);
if (!str0) return QSE_NULL;
if (rtx->gbl.ignorecase)
{
n = qse_mbsxncasecmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len);
}
else
{
n = qse_mbsxncmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len);
}
qse_awk_rtx_freemem (rtx, str0);
return n;
} }
static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_int_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* compare an integer and the size of a map */ /* compare an integer and the size of a map */
qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left);
@ -4319,14 +4416,16 @@ static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
return 0; return 0;
} }
static QSE_INLINE int __cmp_flt_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) /* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_flt_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
if (((qse_awk_val_flt_t*)left)->val > 0) return 1; if (((qse_awk_val_flt_t*)left)->val > 0) return 1;
if (((qse_awk_val_flt_t*)left)->val < 0) return -1; if (((qse_awk_val_flt_t*)left)->val < 0) return -1;
return 0; return 0;
} }
static int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_int_t v2 = QSE_AWK_RTX_GETINTFROMVAL (rtx, right); qse_awk_int_t v2 = QSE_AWK_RTX_GETINTFROMVAL (rtx, right);
if (((qse_awk_val_flt_t*)left)->val > v2) return 1; if (((qse_awk_val_flt_t*)left)->val > v2) return 1;
@ -4334,7 +4433,7 @@ static int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t
return 0; return 0;
} }
static int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
if (((qse_awk_val_flt_t*)left)->val > if (((qse_awk_val_flt_t*)left)->val >
((qse_awk_val_flt_t*)right)->val) return 1; ((qse_awk_val_flt_t*)right)->val) return 1;
@ -4343,9 +4442,10 @@ static int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t
return 0; return 0;
} }
static int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_rtx_valtostr_out_t out; qse_char_t* str0;
qse_size_t len0;
int n; int n;
/* SCO CC doesn't seem to handle right->nstr > 0 properly */ /* SCO CC doesn't seem to handle right->nstr > 0 properly */
@ -4354,54 +4454,71 @@ static int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t
const qse_char_t* end; const qse_char_t* end;
qse_awk_flt_t rr; qse_awk_flt_t rr;
rr = qse_awk_strxtoflt ( rr = qse_awk_strxtoflt(rtx->awk, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len, &end);
rtx->awk, if (end == ((qse_awk_val_str_t*)right)->val.ptr + ((qse_awk_val_str_t*)right)->val.len)
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len,
&end
);
if (end == ((qse_awk_val_str_t*)right)->val.ptr +
((qse_awk_val_str_t*)right)->val.len)
{ {
return (((qse_awk_val_flt_t*)left)->val > rr)? 1: return (((qse_awk_val_flt_t*)left)->val > rr)? 1:
(((qse_awk_val_flt_t*)left)->val < rr)? -1: 0; (((qse_awk_val_flt_t*)left)->val < rr)? -1: 0;
} }
} }
out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; str0 = qse_awk_rtx_valtostrdup(rtx, left, &len0);
if (qse_awk_rtx_valtostr(rtx, left, &out) <= -1) return CMP_ERROR; if (!str0) return CMP_ERROR;
if (rtx->gbl.ignorecase) if (rtx->gbl.ignorecase)
{ {
n = qse_strxncasecmp ( n = qse_strxncasecmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len);
out.u.cpldup.ptr,
out.u.cpldup.len,
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len
);
} }
else else
{ {
n = qse_strxncmp ( n = qse_strxncmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len);
out.u.cpldup.ptr,
out.u.cpldup.len,
((qse_awk_val_str_t*)right)->val.ptr,
((qse_awk_val_str_t*)right)->val.len
);
} }
QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr); qse_awk_rtx_freemem (rtx, str0);
return n; return n;
} }
static int __cmp_flt_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_flt_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a float with a byte array */ qse_mchar_t* str0;
SETERR_COD (rtx, QSE_AWK_EOPERAND); qse_size_t len0;
return CMP_ERROR; int n;
if (rtx->awk->opt.trait & QSE_AWK_NCMPONSTR || right->nstr /*> 0*/)
{
const qse_mchar_t* end;
qse_awk_flt_t rr;
rr = qse_awk_mbsxtoflt(rtx->awk, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len, &end);
if (end == ((qse_awk_val_mbs_t*)right)->val.ptr + ((qse_awk_val_mbs_t*)right)->val.len)
{
return (((qse_awk_val_flt_t*)left)->val > rr)? 1:
(((qse_awk_val_flt_t*)left)->val < rr)? -1: 0;
}
}
str0 = qse_awk_rtx_valtombsdup(rtx, left, &len0);
if (!str0) return CMP_ERROR;
if (rtx->gbl.ignorecase)
{
n = qse_mbsxncasecmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len);
}
else
{
n = qse_mbsxncmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len);
}
qse_awk_rtx_freemem (rtx, str0);
return n;
} }
static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_flt_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* compare a float with the size of a map */ /* compare a float with the size of a map */
qse_awk_int_t v2 = QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map); qse_awk_int_t v2 = QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map);
@ -4410,22 +4527,30 @@ static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
return 0; return 0;
} }
static QSE_INLINE int __cmp_str_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) /* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_str_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return (((qse_awk_val_str_t*)left)->val.len == 0)? 0: 1; return (((qse_awk_val_str_t*)left)->val.len == 0)? 0: 1;
} }
static QSE_INLINE int __cmp_str_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_int_str(rtx, right, left); int n;
n = __cmp_int_str(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
} }
static QSE_INLINE int __cmp_str_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_flt_str (rtx, right, left); int n;
n = __cmp_flt_str(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
} }
static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_val_str_t* ls, * rs; qse_awk_val_str_t* ls, * rs;
@ -4498,7 +4623,7 @@ static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs
} }
} }
static QSE_INLINE int __cmp_str_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_val_str_t* ls = (qse_awk_val_str_t*)left; qse_awk_val_str_t* ls = (qse_awk_val_str_t*)left;
qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right; qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right;
@ -4526,34 +4651,48 @@ static QSE_INLINE int __cmp_str_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left
#endif #endif
} }
static QSE_INLINE int __cmp_str_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a map with a string */ return __cmp_ensure_not_equal(op_hint);
SETERR_COD (rtx, QSE_AWK_EOPERAND);
return CMP_ERROR;
} }
static QSE_INLINE int __cmp_bytearr_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_str_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
/* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_mbs_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return (((qse_awk_val_mbs_t*)left)->val.len == 0)? 0: 1; return (((qse_awk_val_mbs_t*)left)->val.len == 0)? 0: 1;
} }
static QSE_INLINE int __cmp_bytearr_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_mbs_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_int_bytearr(rtx, right, left); int n;
n = __cmp_int_mbs(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
} }
static QSE_INLINE int __cmp_bytearr_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_mbs_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_flt_bytearr(rtx, right, left); int n;
n = __cmp_flt_mbs(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
} }
static QSE_INLINE int __cmp_bytearr_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_mbs_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_str_bytearr(rtx, right, left); int n;
n = __cmp_str_mbs(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
} }
static QSE_INLINE int __cmp_bytearr_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_mbs_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_val_mbs_t* ls = (qse_awk_val_mbs_t*)left; qse_awk_val_mbs_t* ls = (qse_awk_val_mbs_t*)left;
qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right; qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right;
@ -4563,66 +4702,119 @@ static QSE_INLINE int __cmp_bytearr_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t*
return qse_mbsxncmp(ls->val.ptr, ls->val.len, rs->val.ptr, rs->val.len); return qse_mbsxncmp(ls->val.ptr, ls->val.len, rs->val.ptr, rs->val.len);
} }
static QSE_INLINE int __cmp_bytearr_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_mbs_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a byte array with a map */ return __cmp_ensure_not_equal(op_hint);
SETERR_COD (rtx, QSE_AWK_EOPERAND);
return CMP_ERROR;
} }
static QSE_INLINE int __cmp_mbs_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
static QSE_INLINE int __cmp_map_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
return -__cmp_nil_map (rtx, right, left); return __cmp_ensure_not_equal(op_hint);
} }
static QSE_INLINE int __cmp_map_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) /* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_fun_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_int_map (rtx, right, left); return __cmp_ensure_not_equal(op_hint);
} }
static QSE_INLINE int __cmp_map_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_fun_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
return -__cmp_flt_map (rtx, right, left); return __cmp_ensure_not_equal(op_hint);
} }
static QSE_INLINE int __cmp_map_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_fun_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a map with a string */ return __cmp_ensure_not_equal(op_hint);
SETERR_COD (rtx, QSE_AWK_EOPERAND);
return CMP_ERROR;
} }
static QSE_INLINE int __cmp_map_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_fun_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a map with a byte array */ return __cmp_ensure_not_equal(op_hint);
SETERR_COD (rtx, QSE_AWK_EOPERAND);
return CMP_ERROR;
} }
static QSE_INLINE int __cmp_map_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_fun_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_fun_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return (((qse_awk_val_fun_t*)left)->fun == ((qse_awk_val_fun_t*)right)->fun)? 0: __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_fun_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
/* -------------------------------------------------------------------- */
static QSE_INLINE int __cmp_map_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
int n;
n = __cmp_nil_map(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
}
static QSE_INLINE int __cmp_map_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
int n;
n = __cmp_int_map(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
}
static QSE_INLINE int __cmp_map_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
int n;
n = __cmp_flt_map(rtx, right, left, inverse_cmp_op(op_hint));
if (n == CMP_ERROR) return CMP_ERROR;
return -n;
}
static QSE_INLINE int __cmp_map_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_map_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_map_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{
return __cmp_ensure_not_equal(op_hint);
}
static QSE_INLINE int __cmp_map_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
/* can't compare a map with a map */ /* can't compare a map with a map */
SETERR_COD (rtx, QSE_AWK_EOPERAND); SETERR_COD (rtx, QSE_AWK_EOPERAND);
return CMP_ERROR; return CMP_ERROR;
} }
/* -------------------------------------------------------------------- */
static int __cmp_val(
qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static QSE_INLINE int __cmp_val(qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint)
{ {
qse_awk_val_type_t lvtype, rvtype; qse_awk_val_type_t lvtype, rvtype;
typedef int (*cmp_val_t) (qse_awk_rtx_t*, qse_awk_val_t*, qse_awk_val_t*); typedef int (*cmp_val_t) (qse_awk_rtx_t*, qse_awk_val_t*, qse_awk_val_t*, cmp_op_t op_hint);
static cmp_val_t func[] = static cmp_val_t func[] =
{ {
/* this table must be synchronized with /* this table must be synchronized with
* the QSE_AWK_VAL_XXX values in awk.h */ * the QSE_AWK_VAL_XXX values in awk.h */
__cmp_nil_nil, __cmp_nil_int, __cmp_nil_flt, __cmp_nil_str, __cmp_nil_bytearr, __cmp_nil_map, __cmp_nil_nil, __cmp_nil_int, __cmp_nil_flt, __cmp_nil_str, __cmp_nil_mbs, __cmp_nil_fun, __cmp_nil_map,
__cmp_int_nil, __cmp_int_int, __cmp_int_flt, __cmp_int_str, __cmp_int_bytearr, __cmp_int_map, __cmp_int_nil, __cmp_int_int, __cmp_int_flt, __cmp_int_str, __cmp_int_mbs, __cmp_int_fun, __cmp_int_map,
__cmp_flt_nil, __cmp_flt_int, __cmp_flt_flt, __cmp_flt_str, __cmp_flt_bytearr, __cmp_flt_map, __cmp_flt_nil, __cmp_flt_int, __cmp_flt_flt, __cmp_flt_str, __cmp_flt_mbs, __cmp_flt_fun, __cmp_flt_map,
__cmp_str_nil, __cmp_str_int, __cmp_str_flt, __cmp_str_str, __cmp_str_bytearr, __cmp_str_map, __cmp_str_nil, __cmp_str_int, __cmp_str_flt, __cmp_str_str, __cmp_str_mbs, __cmp_str_fun, __cmp_str_map,
__cmp_bytearr_nil, __cmp_bytearr_int, __cmp_bytearr_flt, __cmp_bytearr_str, __cmp_bytearr_bytearr, __cmp_bytearr_map, __cmp_mbs_nil, __cmp_mbs_int, __cmp_mbs_flt, __cmp_mbs_str, __cmp_mbs_mbs, __cmp_mbs_fun, __cmp_mbs_map,
__cmp_map_nil, __cmp_map_int, __cmp_map_flt, __cmp_map_str, __cmp_map_bytearr, __cmp_map_map __cmp_fun_nil, __cmp_fun_int, __cmp_fun_flt, __cmp_fun_str, __cmp_fun_mbs, __cmp_fun_fun, __cmp_fun_map,
__cmp_map_nil, __cmp_map_int, __cmp_map_flt, __cmp_map_str, __cmp_map_mbs, __cmp_map_fun, __cmp_map_map
}; };
lvtype = QSE_AWK_RTX_GETVALTYPE(rtx, left); lvtype = QSE_AWK_RTX_GETVALTYPE(rtx, left);
@ -4639,14 +4831,20 @@ static int __cmp_val(
QSE_ASSERT (rvtype >= QSE_AWK_VAL_NIL && rvtype <= QSE_AWK_VAL_MAP); QSE_ASSERT (rvtype >= QSE_AWK_VAL_NIL && rvtype <= QSE_AWK_VAL_MAP);
/* mapping fomula and table layout assume: /* mapping fomula and table layout assume:
* QSE_AWK_VAL_NIL = 0 * QSE_AWK_VAL_NIL = 0
* QSE_AWK_VAL_INT = 1 * QSE_AWK_VAL_INT = 1
* QSE_AWK_VAL_FLT = 2 * QSE_AWK_VAL_FLT = 2
* QSE_AWK_VAL_STR = 3 * QSE_AWK_VAL_STR = 3
* QSE_AWK_VAL_MBS = 4 * QSE_AWK_VAL_MBS = 4
* QSE_AWK_VAL_MAP = 5 * QSE_AWK_VAL_FUN = 5
* QSE_AWK_VAL_MAP = 6
*
* op_hint indicate the operation in progress when this function is called.
* this hint doesn't require the comparison function to compare using this
* operation. the comparision function should return 0 if equal, -1 if less,
* 1 if greater, CMP_ERROR upon error regardless of this hint.
*/ */
return func[lvtype * 6 + rvtype](rtx, left, right); return func[lvtype * 7 + rvtype](rtx, left, right, op_hint);
} }
static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
@ -4693,6 +4891,10 @@ static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* righ
((qse_awk_val_mbs_t*)right)->val.len) == 0; ((qse_awk_val_mbs_t*)right)->val.len) == 0;
break; break;
case QSE_AWK_VAL_FUN:
n = ((qse_awk_val_fun_t*)left)->fun == ((qse_awk_val_fun_t*)right)->fun;
break;
default: default:
/* map-x and map-y are always different regardless of /* map-x and map-y are always different regardless of
* their contents. however, if they are pointing to the * their contents. however, if they are pointing to the
@ -4709,52 +4911,52 @@ static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* righ
static qse_awk_val_t* eval_binop_teq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_teq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
return teq_val (rtx, left, right)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return teq_val(rtx, left, right)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_tne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_tne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
return teq_val (rtx, left, right)? QSE_AWK_VAL_ZERO: QSE_AWK_VAL_ONE; return teq_val(rtx, left, right)? QSE_AWK_VAL_ZERO: QSE_AWK_VAL_ONE;
} }
static qse_awk_val_t* eval_binop_eq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_eq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_EQ);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n == 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n == 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_ne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_ne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_NE);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n != 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n != 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_gt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_gt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_GT);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n > 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n > 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_ge (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_ge (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_GE);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n >= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n >= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_lt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_lt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_LT);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n < 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n < 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
static qse_awk_val_t* eval_binop_le (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) static qse_awk_val_t* eval_binop_le (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right)
{ {
int n = __cmp_val(rtx, left, right); int n = __cmp_val(rtx, left, right, CMP_OP_LE);
if (n == CMP_ERROR) return QSE_NULL; if (n == CMP_ERROR) return QSE_NULL;
return (n <= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; return (n <= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO;
} }
@ -6267,11 +6469,13 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
{ {
qse_awk_val_t* val; qse_awk_val_t* val;
qse_awk_fun_t* fun; qse_awk_fun_t* fun;
qse_htb_pair_t* pair;
fun = ((qse_awk_nde_fun_t*)nde)->ptr;
fun = ((qse_awk_nde_fun_t*)nde)->funptr;
if (!fun) if (!fun)
{ {
qse_htb_pair_t* pair;
/* TODO: support bultin functions?, support module functions? */ /* TODO: support bultin functions?, support module functions? */
pair = qse_htb_search(rtx->awk->tree.funs, ((qse_awk_nde_fun_t*)nde)->name.ptr, ((qse_awk_nde_fun_t*)nde)->name.len); pair = qse_htb_search(rtx->awk->tree.funs, ((qse_awk_nde_fun_t*)nde)->name.ptr, ((qse_awk_nde_fun_t*)nde)->name.len);
if (!pair) if (!pair)

View File

@ -179,7 +179,7 @@ struct qse_awk_nde_fun_t
{ {
QSE_AWK_NDE_HDR; QSE_AWK_NDE_HDR;
qse_cstr_t name; /* function name */ qse_cstr_t name; /* function name */
qse_awk_fun_t* ptr; /* QSE_NULL or actual pointer */ qse_awk_fun_t* funptr; /* QSE_NULL or actual pointer */
}; };
/* QSE_AWK_NDE_NAMED, QSE_AWK_NDE_GBL, /* QSE_AWK_NDE_NAMED, QSE_AWK_NDE_GBL,

View File

@ -759,10 +759,10 @@ const qse_char_t* qse_awk_rtx_getvaltypename(qse_awk_rtx_t* rtx, qse_awk_val_t*
QSE_T("flt"), QSE_T("flt"),
QSE_T("str"), QSE_T("str"),
QSE_T("mbs"), QSE_T("mbs"),
QSE_T("fun"),
QSE_T("map"), QSE_T("map"),
QSE_T("rex"), QSE_T("rex"),
QSE_T("ref"), QSE_T("ref")
QSE_T("fun")
}; };
return __val_type_name[QSE_AWK_RTX_GETVALTYPE(rtx, val)]; return __val_type_name[QSE_AWK_RTX_GETVALTYPE(rtx, val)];
@ -854,6 +854,10 @@ void qse_awk_rtx_freeval (qse_awk_rtx_t* rtx, qse_awk_val_t* val, int cache)
break; break;
} }
case QSE_AWK_VAL_FUN:
QSE_AWK_FREE (rtx->awk, val);
break;
case QSE_AWK_VAL_MAP: case QSE_AWK_VAL_MAP:
{ {
qse_htb_fini (((qse_awk_val_map_t*)val)->map); qse_htb_fini (((qse_awk_val_map_t*)val)->map);
@ -871,10 +875,6 @@ void qse_awk_rtx_freeval (qse_awk_rtx_t* rtx, qse_awk_val_t* val, int cache)
break; break;
} }
case QSE_AWK_VAL_FUN:
QSE_AWK_FREE (rtx->awk, val);
break;
} }
} }
} }
@ -1007,14 +1007,14 @@ int qse_awk_rtx_valtobool (qse_awk_rtx_t* rtx, const qse_awk_val_t* val)
return ((qse_awk_val_mbs_t*)val)->val.len > 0; return ((qse_awk_val_mbs_t*)val)->val.len > 0;
case QSE_AWK_VAL_REX: /* TODO: is this correct? */ case QSE_AWK_VAL_REX: /* TODO: is this correct? */
return ((qse_awk_val_rex_t*)val)->str.len > 0; return ((qse_awk_val_rex_t*)val)->str.len > 0;
case QSE_AWK_VAL_FUN:
/* return always true */
return 1;
case QSE_AWK_VAL_MAP: case QSE_AWK_VAL_MAP:
/* true if the map size is greater than 0. false if not */ /* true if the map size is greater than 0. false if not */
return QSE_HTB_SIZE(((qse_awk_val_map_t*)val)->map) > 0; return QSE_HTB_SIZE(((qse_awk_val_map_t*)val)->map) > 0;
case QSE_AWK_VAL_REF: case QSE_AWK_VAL_REF:
return val_ref_to_bool (rtx, (qse_awk_val_ref_t*)val); return val_ref_to_bool (rtx, (qse_awk_val_ref_t*)val);
case QSE_AWK_VAL_FUN:
/* return always true */
return 1;
} }
QSE_ASSERTX ( QSE_ASSERTX (
@ -1506,6 +1506,11 @@ int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rt
#endif #endif
} }
case QSE_AWK_VAL_FUN:
{
return str_to_str(rtx, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len, out);
}
case QSE_AWK_VAL_MAP: case QSE_AWK_VAL_MAP:
{ {
if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP) if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP)
@ -1519,11 +1524,6 @@ int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rt
{ {
return val_ref_to_str(rtx, (qse_awk_val_ref_t*)v, out); return val_ref_to_str(rtx, (qse_awk_val_ref_t*)v, out);
} }
case QSE_AWK_VAL_FUN:
{
return str_to_str(rtx, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len, out);
}
} }
@ -1809,6 +1809,12 @@ int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_in
); );
} }
case QSE_AWK_VAL_FUN:
{
/* unable to convert a function to a number */
break;
}
case QSE_AWK_VAL_MAP: case QSE_AWK_VAL_MAP:
{ {
if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP) if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP)
@ -1823,12 +1829,6 @@ int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_in
{ {
return val_ref_to_num(rtx, (qse_awk_val_ref_t*)v, l, r); return val_ref_to_num(rtx, (qse_awk_val_ref_t*)v, l, r);
} }
case QSE_AWK_VAL_FUN:
{
/* unable to convert a function to a number */
break;
}
} }
#ifdef DEBUG_VAL #ifdef DEBUG_VAL
@ -2153,6 +2153,10 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val)
qse_errputstrf (QSE_T("/%s/"), ((qse_awk_val_rex_t*)val)->ptr); qse_errputstrf (QSE_T("/%s/"), ((qse_awk_val_rex_t*)val)->ptr);
break; break;
case QSE_AWK_VAL_FUN:
qse_errputstrf (QSE_T("%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr);
break;
case QSE_AWK_VAL_MAP: case QSE_AWK_VAL_MAP:
qse_errputstrf (QSE_T("MAP[")); qse_errputstrf (QSE_T("MAP["));
qse_htb_walk (((qse_awk_val_map_t*)val)->map, print_pair, run); qse_htb_walk (((qse_awk_val_map_t*)val)->map, print_pair, run);
@ -2165,10 +2169,6 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val)
qse_errputstrf (QSE_T("]")); qse_errputstrf (QSE_T("]"));
break; break;
case QSE_AWK_VAL_FUN:
qse_errputstrf (QSE_T("%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr);
break;
default: default:
qse_errputstrf (QSE_T("**** INTERNAL ERROR - INVALID VALUE TYPE ****\n")); qse_errputstrf (QSE_T("**** INTERNAL ERROR - INVALID VALUE TYPE ****\n"));
} }