qse/ase/awk/val.c

501 lines
10 KiB
C
Raw Normal View History

2006-03-04 15:54:37 +00:00
/*
2006-06-26 15:09:28 +00:00
* $Id: val.c,v 1.32 2006-06-26 15:09:28 bacon Exp $
2006-03-04 15:54:37 +00:00
*/
2006-03-31 16:35:37 +00:00
#include <xp/awk/awk_i.h>
2006-03-04 15:54:37 +00:00
2006-04-16 04:31:38 +00:00
#ifndef XP_AWK_STAND_ALONE
2006-03-07 16:09:18 +00:00
#include <xp/bas/string.h>
#include <xp/bas/memory.h>
2006-03-27 11:43:17 +00:00
#include <xp/bas/assert.h>
2006-03-07 16:09:18 +00:00
#endif
2006-03-22 16:05:50 +00:00
static xp_awk_val_nil_t __awk_nil = { XP_AWK_VAL_NIL, 0 };
2006-03-07 15:55:14 +00:00
xp_awk_val_t* xp_awk_val_nil = (xp_awk_val_t*)&__awk_nil;
2006-03-22 16:05:50 +00:00
static xp_awk_val_int_t __awk_int[] =
{
{ XP_AWK_VAL_INT, 0, -1 },
{ XP_AWK_VAL_INT, 0, 0 },
{ XP_AWK_VAL_INT, 0, 1 },
{ XP_AWK_VAL_INT, 0, 2 },
{ XP_AWK_VAL_INT, 0, 3 },
{ XP_AWK_VAL_INT, 0, 4 },
{ XP_AWK_VAL_INT, 0, 5 },
{ XP_AWK_VAL_INT, 0, 6 },
{ XP_AWK_VAL_INT, 0, 7 },
{ XP_AWK_VAL_INT, 0, 8 },
{ XP_AWK_VAL_INT, 0, 9 },
};
2006-04-21 17:24:31 +00:00
xp_awk_val_t* xp_awk_makeintval (xp_awk_run_t* run, xp_long_t v)
2006-03-04 15:54:37 +00:00
{
xp_awk_val_int_t* val;
2006-03-22 16:05:50 +00:00
if (v >= __awk_int[0].val &&
v <= __awk_int[xp_countof(__awk_int)-1].val)
{
return (xp_awk_val_t*)&__awk_int[v-__awk_int[0].val];
}
2006-04-21 17:24:31 +00:00
if (run->icache_count > 0)
2006-03-27 11:43:17 +00:00
{
2006-04-21 17:24:31 +00:00
val = run->icache[--run->icache_count];
2006-03-27 11:43:17 +00:00
}
else
{
2006-03-28 16:33:09 +00:00
val = (xp_awk_val_int_t*)
2006-04-24 14:38:46 +00:00
xp_malloc (xp_sizeof(xp_awk_val_int_t));
2006-03-27 11:43:17 +00:00
if (val == XP_NULL) return XP_NULL;
}
2006-03-04 15:54:37 +00:00
2006-03-05 17:07:33 +00:00
val->type = XP_AWK_VAL_INT;
2006-03-26 16:36:30 +00:00
val->ref = 0;
2006-03-04 15:54:37 +00:00
val->val = v;
2006-03-05 17:07:33 +00:00
return (xp_awk_val_t*)val;
}
2006-04-21 17:24:31 +00:00
xp_awk_val_t* xp_awk_makerealval (xp_awk_run_t* run, xp_real_t v)
2006-03-05 17:07:33 +00:00
{
xp_awk_val_real_t* val;
2006-04-21 17:24:31 +00:00
if (run->rcache_count > 0)
2006-03-28 16:33:09 +00:00
{
2006-04-21 17:24:31 +00:00
val = run->rcache[--run->rcache_count];
2006-03-28 16:33:09 +00:00
}
else
{
val = (xp_awk_val_real_t*)
xp_malloc (xp_sizeof(xp_awk_val_real_t));
if (val == XP_NULL) return XP_NULL;
}
2006-03-05 17:07:33 +00:00
val->type = XP_AWK_VAL_REAL;
2006-03-26 16:36:30 +00:00
val->ref = 0;
2006-03-05 17:07:33 +00:00
val->val = v;
return (xp_awk_val_t*)val;
}
2006-06-26 15:09:28 +00:00
xp_awk_val_t* xp_awk_makestrval0 (const xp_char_t* str)
{
return xp_awk_makestrval (str, xp_strlen(str));
}
2006-03-05 17:07:33 +00:00
xp_awk_val_t* xp_awk_makestrval (const xp_char_t* str, xp_size_t len)
{
xp_awk_val_str_t* val;
2006-04-24 14:38:46 +00:00
val = (xp_awk_val_str_t*) xp_malloc (xp_sizeof(xp_awk_val_str_t));
2006-03-05 17:07:33 +00:00
if (val == XP_NULL) return XP_NULL;
val->type = XP_AWK_VAL_STR;
2006-03-26 16:36:30 +00:00
val->ref = 0;
2006-03-05 17:07:33 +00:00
val->len = len;
val->buf = xp_strxdup (str, len);
2006-04-17 16:12:02 +00:00
if (val->buf == XP_NULL)
{
2006-03-05 17:07:33 +00:00
xp_free (val);
return XP_NULL;
}
2006-03-04 15:54:37 +00:00
return (xp_awk_val_t*)val;
}
2006-03-05 17:07:33 +00:00
2006-04-06 16:25:37 +00:00
xp_awk_val_t* xp_awk_makestrval2 (
const xp_char_t* str1, xp_size_t len1,
const xp_char_t* str2, xp_size_t len2)
{
xp_awk_val_str_t* val;
2006-04-24 14:38:46 +00:00
val = (xp_awk_val_str_t*) xp_malloc (xp_sizeof(xp_awk_val_str_t));
2006-04-06 16:25:37 +00:00
if (val == XP_NULL) return XP_NULL;
val->type = XP_AWK_VAL_STR;
val->ref = 0;
val->len = len1 + len2;
val->buf = xp_strxdup2 (str1, len1, str2, len2);
2006-04-17 16:12:02 +00:00
if (val->buf == XP_NULL)
{
xp_free (val);
return XP_NULL;
}
return (xp_awk_val_t*)val;
}
2006-04-24 11:26:00 +00:00
xp_awk_val_t* xp_awk_makerexval (const xp_char_t* str, xp_size_t len)
{
xp_awk_val_rex_t* val;
2006-04-24 14:38:46 +00:00
/* TDOO: XXXXXXXXXXXXXX */
val = (xp_awk_val_rex_t*) xp_malloc (xp_sizeof(xp_awk_val_rex_t));
2006-04-24 11:26:00 +00:00
if (val == XP_NULL) return XP_NULL;
val->type = XP_AWK_VAL_STR;
val->ref = 0;
val->len = len;
val->buf = xp_strxdup (str, len);
if (val->buf == XP_NULL)
{
xp_free (val);
return XP_NULL;
}
return (xp_awk_val_t*)val;
}
2006-04-21 17:24:31 +00:00
static void __free_map_val (void* run, void* v)
2006-04-17 16:12:02 +00:00
{
2006-04-18 10:28:03 +00:00
/*
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("refdown in map free..."));
2006-04-18 10:28:03 +00:00
xp_awk_printval (v);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("\n"));
2006-04-18 10:28:03 +00:00
*/
2006-04-21 17:24:31 +00:00
xp_awk_refdownval (run, v);
2006-04-17 16:12:02 +00:00
}
2006-04-21 17:24:31 +00:00
xp_awk_val_t* xp_awk_makemapval (xp_awk_run_t* run)
2006-04-17 16:12:02 +00:00
{
xp_awk_val_map_t* val;
2006-04-18 10:28:03 +00:00
val = (xp_awk_val_map_t*) xp_malloc (xp_sizeof(xp_awk_val_map_t));
2006-04-17 16:12:02 +00:00
if (val == XP_NULL) return XP_NULL;
val->type = XP_AWK_VAL_MAP;
val->ref = 0;
2006-04-21 17:24:31 +00:00
val->map = xp_awk_map_open (XP_NULL, run, 256, __free_map_val);
2006-04-17 16:12:02 +00:00
if (val->map == XP_NULL)
{
2006-04-06 16:25:37 +00:00
xp_free (val);
return XP_NULL;
}
return (xp_awk_val_t*)val;
}
2006-04-24 11:26:00 +00:00
2006-03-26 16:36:30 +00:00
xp_bool_t xp_awk_isbuiltinval (xp_awk_val_t* val)
{
return val == XP_NULL || val == xp_awk_val_nil ||
(val >= (xp_awk_val_t*)&__awk_int[0] &&
val <= (xp_awk_val_t*)&__awk_int[xp_countof(__awk_int)-1]);
}
2006-04-21 17:24:31 +00:00
void xp_awk_freeval (xp_awk_run_t* run, xp_awk_val_t* val, xp_bool_t cache)
2006-03-04 15:54:37 +00:00
{
2006-03-26 16:36:30 +00:00
if (xp_awk_isbuiltinval(val)) return;
2006-03-22 16:05:50 +00:00
2006-05-13 16:33:07 +00:00
/*xp_printf (XP_T("freeing [cache=%d] ... "), cache);
2006-04-18 10:28:03 +00:00
xp_awk_printval (val);
2006-05-13 16:33:07 +00:00
xp_printf (XP_T("\n"));*/
2006-03-04 15:54:37 +00:00
switch (val->type)
{
2006-03-27 11:43:17 +00:00
case XP_AWK_VAL_NIL:
xp_free (val);
2006-04-17 16:12:02 +00:00
return;
2006-03-27 11:43:17 +00:00
case XP_AWK_VAL_INT:
2006-04-20 16:17:01 +00:00
if (cache == xp_true &&
2006-04-21 17:24:31 +00:00
run->icache_count < xp_countof(run->icache))
2006-03-27 11:43:17 +00:00
{
2006-04-21 17:24:31 +00:00
run->icache[run->icache_count++] =
2006-03-27 11:43:17 +00:00
(xp_awk_val_int_t*)val;
}
2006-04-17 16:12:02 +00:00
else xp_free (val);
return;
2006-03-27 11:43:17 +00:00
case XP_AWK_VAL_REAL:
2006-04-20 16:17:01 +00:00
if (cache == xp_true &&
2006-04-21 17:24:31 +00:00
run->rcache_count < xp_countof(run->rcache))
2006-03-28 16:33:09 +00:00
{
2006-04-21 17:24:31 +00:00
run->rcache[run->rcache_count++] =
2006-03-28 16:33:09 +00:00
(xp_awk_val_real_t*)val;
}
2006-04-17 16:12:02 +00:00
else xp_free (val);
return;
2006-03-27 11:43:17 +00:00
2006-03-04 15:54:37 +00:00
case XP_AWK_VAL_STR:
xp_free (((xp_awk_val_str_t*)val)->buf);
xp_free (val);
2006-04-17 16:12:02 +00:00
return;
2006-04-24 11:26:00 +00:00
case XP_AWK_VAL_REX:
/* TODO: XXXX */
xp_free (((xp_awk_val_rex_t*)val)->buf);
xp_free (val);
return;
2006-04-17 16:12:02 +00:00
case XP_AWK_VAL_MAP:
xp_awk_map_close (((xp_awk_val_map_t*)val)->map);
xp_free (val);
return;
2006-03-04 15:54:37 +00:00
}
2006-03-27 11:43:17 +00:00
2006-04-17 16:12:02 +00:00
xp_assert (!"should never happen - invalid value type");
2006-03-04 15:54:37 +00:00
}
2006-03-23 13:26:04 +00:00
void xp_awk_refupval (xp_awk_val_t* val)
{
2006-03-26 16:36:30 +00:00
if (xp_awk_isbuiltinval(val)) return;
2006-03-23 15:36:20 +00:00
/*
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("ref up "));
2006-03-23 15:36:20 +00:00
xp_awk_printval (val);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("\n"));
2006-03-23 15:36:20 +00:00
*/
2006-03-23 13:26:04 +00:00
val->ref++;
}
2006-04-21 17:24:31 +00:00
void xp_awk_refdownval (xp_awk_run_t* run, xp_awk_val_t* val)
2006-03-23 13:26:04 +00:00
{
2006-03-26 16:36:30 +00:00
if (xp_awk_isbuiltinval(val)) return;
2006-03-23 15:36:20 +00:00
/*
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%p, %p, %p\n"), xp_awk_val_nil, &__awk_nil, val);
xp_printf (XP_T("ref down [count=>%d]\n"), (int)val->ref);
2006-03-23 15:36:20 +00:00
xp_awk_printval (val);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("\n"));
2006-03-23 15:36:20 +00:00
*/
2006-03-23 13:26:04 +00:00
xp_assert (val->ref > 0);
val->ref--;
2006-03-26 16:36:30 +00:00
if (val->ref <= 0)
{
/*
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("**FREEING "));
2006-03-26 16:36:30 +00:00
xp_awk_printval (val);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("\n"));
2006-03-26 16:36:30 +00:00
*/
2006-04-21 17:24:31 +00:00
xp_awk_freeval(run, val, xp_true);
2006-03-26 16:36:30 +00:00
}
}
2006-04-21 17:24:31 +00:00
void xp_awk_refdownval_nofree (xp_awk_run_t* run, xp_awk_val_t* val)
2006-03-26 16:36:30 +00:00
{
if (xp_awk_isbuiltinval(val)) return;
xp_assert (val->ref > 0);
val->ref--;
2006-03-23 13:26:04 +00:00
}
2006-04-21 17:24:31 +00:00
xp_awk_val_t* xp_awk_cloneval (xp_awk_run_t* run, xp_awk_val_t* val)
2006-03-07 15:55:14 +00:00
{
if (val == XP_NULL) return xp_awk_val_nil;
switch (val->type)
{
case XP_AWK_VAL_NIL:
return xp_awk_val_nil;
case XP_AWK_VAL_INT:
2006-04-21 17:24:31 +00:00
return xp_awk_makeintval (run, ((xp_awk_val_int_t*)val)->val);
2006-03-07 15:55:14 +00:00
case XP_AWK_VAL_REAL:
2006-04-21 17:24:31 +00:00
return xp_awk_makerealval (run, ((xp_awk_val_real_t*)val)->val);
2006-03-07 15:55:14 +00:00
case XP_AWK_VAL_STR:
return xp_awk_makestrval (
((xp_awk_val_str_t*)val)->buf,
((xp_awk_val_str_t*)val)->len);
2006-04-17 16:12:02 +00:00
case XP_AWK_VAL_MAP:
2006-04-21 17:24:31 +00:00
/* TODO: .... */
2006-04-17 16:12:02 +00:00
return XP_NULL;
2006-03-07 15:55:14 +00:00
}
2006-04-17 16:12:02 +00:00
xp_assert (!"should never happen - invalid value type");
2006-03-07 15:55:14 +00:00
return XP_NULL;
}
2006-06-21 11:45:26 +00:00
xp_bool_t xp_awk_valtobool (xp_awk_val_t* val)
2006-03-15 15:34:59 +00:00
{
if (val == XP_NULL) return xp_false;
switch (val->type)
{
case XP_AWK_VAL_NIL:
return xp_false;
case XP_AWK_VAL_INT:
2006-04-07 04:23:11 +00:00
return ((xp_awk_val_int_t*)val)->val != 0;
2006-03-15 15:34:59 +00:00
case XP_AWK_VAL_REAL:
2006-04-07 04:23:11 +00:00
return ((xp_awk_val_real_t*)val)->val != 0.0;
2006-03-15 15:34:59 +00:00
case XP_AWK_VAL_STR:
2006-04-07 04:23:11 +00:00
return ((xp_awk_val_str_t*)val)->len > 0;
2006-04-17 16:12:02 +00:00
case XP_AWK_VAL_MAP:
return xp_false; /* TODO: is this correct? */
2006-03-15 15:34:59 +00:00
}
2006-04-17 16:12:02 +00:00
xp_assert (!"should never happen - invalid value type");
2006-03-22 16:05:50 +00:00
return xp_false;
2006-03-15 15:34:59 +00:00
}
2006-06-21 11:45:26 +00:00
xp_char_t* xp_awk_valtostr (xp_awk_val_t* v, int* errnum, xp_str_t* buf)
{
if (v->type == XP_AWK_VAL_INT)
{
xp_char_t* tmp;
xp_long_t t;
xp_size_t len = 0;
t = ((xp_awk_val_int_t*)v)->val;
if (t == 0)
{
/* handle zero */
if (buf == XP_NULL)
{
tmp = xp_malloc (2 * xp_sizeof(xp_char_t));
if (tmp == XP_NULL)
{
*errnum = XP_AWK_ENOMEM;
return XP_NULL;
}
tmp[0] = XP_T('0');
tmp[1] = XP_T('\0');
return tmp;
}
else
{
if (xp_str_cat (buf, XP_T("0")) == (xp_size_t)-1)
{
*errnum = XP_AWK_ENOMEM;
return XP_NULL;
}
return XP_STR_BUF(buf);
}
}
/* non-zero values */
if (t < 0) { t = -t; len++; }
while (t > 0) { len++; t /= 10; }
if (buf == XP_NULL)
{
tmp = xp_malloc (len + 1 * xp_sizeof(xp_char_t));
if (tmp == XP_NULL)
{
*errnum = XP_AWK_ENOMEM;
return XP_NULL;
}
tmp[len] = XP_T('\0');
}
else
{
/* get the current end of the buffer */
tmp = XP_STR_BUF(buf) + XP_STR_LEN(buf);
/* extend the buffer */
if (xp_str_nccat (
buf, XP_T(' '), len) == (xp_size_t)-1)
{
*errnum = XP_AWK_ENOMEM;
return XP_NULL;
}
}
t = ((xp_awk_val_int_t*)v)->val;
if (t < 0) t = -t;
while (t > 0)
{
tmp[--len] = (xp_char_t)(t % 10) + XP_T('0');
t /= 10;
}
if (((xp_awk_val_int_t*)v)->val < 0) tmp[--len] = XP_T('-');
/*return (buf == XP_NULL) tmp: XP_STR_BUF(buf);*/
return tmp;
}
if (v->type == XP_AWK_VAL_STR)
{
xp_char_t* tmp;
if (buf == XP_NULL)
{
tmp = xp_strxdup (
((xp_awk_val_str_t*)v)->buf,
((xp_awk_val_str_t*)v)->len);
if (tmp == XP_NULL) *errnum = XP_AWK_ENOMEM;
}
else
{
tmp = XP_STR_BUF(buf) + XP_STR_LEN(buf);
if (xp_str_ncat (buf,
((xp_awk_val_str_t*)v)->buf,
((xp_awk_val_str_t*)v)->len) == (xp_size_t)-1)
{
*errnum = XP_AWK_ENOMEM;
tmp = XP_NULL;
}
}
return tmp;
}
/* TODO: process more value types */
2006-06-26 15:09:28 +00:00
*errnum = XP_AWK_EVALTYPE;
2006-06-21 11:45:26 +00:00
return XP_NULL;
}
2006-04-30 17:12:51 +00:00
static int __print_pair (xp_awk_pair_t* pair, void* arg)
2006-04-20 05:44:29 +00:00
{
2006-05-06 12:52:36 +00:00
xp_printf (XP_T(" %s=>"), pair->key);
2006-04-20 05:44:29 +00:00
xp_awk_printval (pair->val);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T(" "));
2006-04-20 05:44:29 +00:00
return 0;
}
2006-03-04 15:54:37 +00:00
void xp_awk_printval (xp_awk_val_t* val)
{
2006-04-14 10:56:42 +00:00
/* TODO: better value printing...................... */
2006-03-04 15:54:37 +00:00
switch (val->type)
{
2006-03-07 15:55:14 +00:00
case XP_AWK_VAL_NIL:
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("nil"));
2006-03-07 15:55:14 +00:00
break;
2006-03-04 15:54:37 +00:00
case XP_AWK_VAL_INT:
2006-03-15 15:34:59 +00:00
#if defined(__LCC__)
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%lld"),
2006-03-15 15:34:59 +00:00
(long long)((xp_awk_val_int_t*)val)->val);
#elif defined(__BORLANDC__) || defined(_MSC_VER)
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%I64d"),
2006-03-14 16:40:00 +00:00
(__int64)((xp_awk_nde_int_t*)val)->val);
2006-04-14 10:56:42 +00:00
#elif defined(vax) || defined(__vax) || defined(_SCO_DS)
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%ld"),
2006-03-15 15:34:59 +00:00
(long)((xp_awk_val_int_t*)val)->val);
2006-03-14 16:40:00 +00:00
#else
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%lld"),
2006-03-04 15:54:37 +00:00
(long long)((xp_awk_val_int_t*)val)->val);
2006-03-14 16:40:00 +00:00
#endif
2006-03-04 15:54:37 +00:00
break;
case XP_AWK_VAL_REAL:
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%Lf"),
2006-03-04 15:54:37 +00:00
(long double)((xp_awk_val_real_t*)val)->val);
break;
case XP_AWK_VAL_STR:
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("%s"), ((xp_awk_val_str_t*)val)->buf);
2006-03-04 15:54:37 +00:00
break;
2006-04-24 11:26:00 +00:00
case XP_AWK_VAL_REX:
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("REX[%s]"), ((xp_awk_val_rex_t*)val)->buf);
2006-04-24 11:26:00 +00:00
break;
2006-04-17 16:12:02 +00:00
case XP_AWK_VAL_MAP:
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("MAP["));
2006-04-30 17:12:51 +00:00
xp_awk_map_walk (((xp_awk_val_map_t*)val)->map, __print_pair, XP_NULL);
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("]"));
2006-04-17 16:12:02 +00:00
break;
2006-03-04 15:54:37 +00:00
default:
2006-04-16 04:31:38 +00:00
xp_assert (!"should never happen - invalid value type");
2006-05-06 12:52:36 +00:00
xp_printf (XP_T("**** INTERNAL ERROR - INVALID VALUE TYPE ****\n"));
2006-03-04 15:54:37 +00:00
}
}