2006-03-04 15:54:37 +00:00
|
|
|
/*
|
2006-04-07 04:23:11 +00:00
|
|
|
* $Id: val.c,v 1.17 2006-04-07 04:23:11 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-03-07 16:09:18 +00:00
|
|
|
#ifndef __STAND_ALONE
|
|
|
|
#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-03-27 11:43:17 +00:00
|
|
|
xp_awk_val_t* xp_awk_makeintval (xp_awk_t* awk, 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-03-27 11:43:17 +00:00
|
|
|
if (awk->run.icache_count > 0)
|
|
|
|
{
|
|
|
|
val = awk->run.icache[--awk->run.icache_count];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-03-28 16:33:09 +00:00
|
|
|
val = (xp_awk_val_int_t*)
|
|
|
|
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-03-28 16:33:09 +00:00
|
|
|
xp_awk_val_t* xp_awk_makerealval (xp_awk_t* awk, xp_real_t v)
|
2006-03-05 17:07:33 +00:00
|
|
|
{
|
|
|
|
xp_awk_val_real_t* val;
|
|
|
|
|
2006-03-28 16:33:09 +00:00
|
|
|
if (awk->run.rcache_count > 0)
|
|
|
|
{
|
|
|
|
val = awk->run.rcache[--awk->run.rcache_count];
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
xp_awk_val_t* xp_awk_makestrval (const xp_char_t* str, xp_size_t len)
|
|
|
|
{
|
|
|
|
xp_awk_val_str_t* val;
|
|
|
|
|
2006-03-07 16:09:18 +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);
|
|
|
|
if (val->buf == XP_NULL) {
|
|
|
|
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;
|
|
|
|
|
|
|
|
val = (xp_awk_val_str_t*)xp_malloc(xp_sizeof(xp_awk_val_str_t));
|
|
|
|
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);
|
|
|
|
if (val->buf == XP_NULL) {
|
|
|
|
xp_free (val);
|
|
|
|
return XP_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (xp_awk_val_t*)val;
|
|
|
|
}
|
|
|
|
|
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-03-27 11:43:17 +00:00
|
|
|
void xp_awk_freeval (xp_awk_t* awk, xp_awk_val_t* val)
|
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-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);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XP_AWK_VAL_INT:
|
|
|
|
if (awk->run.icache_count < xp_countof(awk->run.icache))
|
|
|
|
{
|
|
|
|
awk->run.icache[awk->run.icache_count++] =
|
|
|
|
(xp_awk_val_int_t*)val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xp_free (val);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XP_AWK_VAL_REAL:
|
2006-03-28 16:33:09 +00:00
|
|
|
if (awk->run.rcache_count < xp_countof(awk->run.rcache))
|
|
|
|
{
|
|
|
|
awk->run.rcache[awk->run.rcache_count++] =
|
|
|
|
(xp_awk_val_real_t*)val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xp_free (val);
|
|
|
|
}
|
2006-03-27 11:43:17 +00:00
|
|
|
break;
|
|
|
|
|
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-03-27 11:43:17 +00:00
|
|
|
break;
|
2006-03-04 15:54:37 +00:00
|
|
|
}
|
2006-03-27 11:43:17 +00:00
|
|
|
|
|
|
|
/* should never reach here */
|
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
|
|
|
/*
|
|
|
|
xp_printf (XP_TEXT("ref up "));
|
|
|
|
xp_awk_printval (val);
|
|
|
|
xp_printf (XP_TEXT("\n"));
|
|
|
|
*/
|
2006-03-23 13:26:04 +00:00
|
|
|
val->ref++;
|
|
|
|
}
|
|
|
|
|
2006-03-27 11:43:17 +00:00
|
|
|
void xp_awk_refdownval (xp_awk_t* awk, 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-03-27 14:15:53 +00:00
|
|
|
xp_printf (XP_TEXT("%p, %p, %p\n"), xp_awk_val_nil, &__awk_nil, val);
|
|
|
|
xp_printf (XP_TEXT("ref down [count=>%d]\n"), (int)val->ref);
|
2006-03-23 15:36:20 +00:00
|
|
|
xp_awk_printval (val);
|
|
|
|
xp_printf (XP_TEXT("\n"));
|
|
|
|
*/
|
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)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
xp_printf (XP_TEXT("**FREEING "));
|
|
|
|
xp_awk_printval (val);
|
|
|
|
xp_printf (XP_TEXT("\n"));
|
|
|
|
*/
|
2006-03-27 11:43:17 +00:00
|
|
|
xp_awk_freeval(awk, val);
|
2006-03-26 16:36:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-27 11:43:17 +00:00
|
|
|
void xp_awk_refdownval_nofree (xp_awk_t* awk, 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-03-27 11:43:17 +00:00
|
|
|
xp_awk_val_t* xp_awk_cloneval (xp_awk_t* awk, 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-03-27 11:43:17 +00:00
|
|
|
return xp_awk_makeintval (awk, ((xp_awk_val_int_t*)val)->val);
|
2006-03-07 15:55:14 +00:00
|
|
|
case XP_AWK_VAL_REAL:
|
2006-03-28 16:33:09 +00:00
|
|
|
return xp_awk_makerealval (awk, ((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);
|
|
|
|
}
|
|
|
|
|
|
|
|
return XP_NULL;
|
|
|
|
}
|
|
|
|
|
2006-04-07 04:23:11 +00:00
|
|
|
xp_bool_t xp_awk_boolval (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-03-15 15:34:59 +00:00
|
|
|
}
|
|
|
|
|
2006-04-07 04:23:11 +00:00
|
|
|
xp_assert (!"should never happen");
|
2006-03-22 16:05:50 +00:00
|
|
|
return xp_false;
|
2006-03-15 15:34:59 +00:00
|
|
|
}
|
|
|
|
|
2006-03-04 15:54:37 +00:00
|
|
|
void xp_awk_printval (xp_awk_val_t* val)
|
|
|
|
{
|
|
|
|
// TODO: better value printing......................
|
|
|
|
switch (val->type)
|
|
|
|
{
|
2006-03-07 15:55:14 +00:00
|
|
|
case XP_AWK_VAL_NIL:
|
|
|
|
xp_printf (XP_TEXT("nil"));
|
|
|
|
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__)
|
|
|
|
xp_printf (XP_TEXT("%lld"),
|
|
|
|
(long long)((xp_awk_val_int_t*)val)->val);
|
|
|
|
#elif defined(__BORLANDC__) || defined(_MSC_VER)
|
2006-03-14 16:40:00 +00:00
|
|
|
xp_printf (XP_TEXT("%I64d"),
|
|
|
|
(__int64)((xp_awk_nde_int_t*)val)->val);
|
2006-03-15 15:34:59 +00:00
|
|
|
#elif defined(vax) || defined(__vax)
|
|
|
|
xp_printf (XP_TEXT("%ld"),
|
|
|
|
(long)((xp_awk_val_int_t*)val)->val);
|
2006-03-14 16:40:00 +00:00
|
|
|
#else
|
2006-03-04 15:54:37 +00:00
|
|
|
xp_printf (XP_TEXT("%lld"),
|
|
|
|
(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-04-04 16:50:36 +00:00
|
|
|
xp_printf (XP_TEXT("%Lf"),
|
2006-03-04 15:54:37 +00:00
|
|
|
(long double)((xp_awk_val_real_t*)val)->val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XP_AWK_VAL_STR:
|
|
|
|
xp_printf (XP_TEXT("%s"), ((xp_awk_val_str_t*)val)->buf);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
xp_printf (XP_TEXT("**** INTERNAL ERROR - UNKNOWN VALUE TYPE ****\n"));
|
|
|
|
}
|
|
|
|
}
|