diff --git a/ase/awk/awk.h b/ase/awk/awk.h index ab8c1176..9d22c0f8 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.50 2006-04-16 13:30:18 bacon Exp $ + * $Id: awk.h,v 1.51 2006-04-17 16:12:02 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -41,46 +41,47 @@ enum /* error code */ enum { - XP_AWK_ENOERR, /* no error */ - XP_AWK_ENOMEM, /* out of memory */ + XP_AWK_ENOERR, /* no error */ + XP_AWK_ENOMEM, /* out of memory */ XP_AWK_ESRCOP, XP_AWK_ESRCCL, - XP_AWK_ESRCDT, /* error in reading source */ + XP_AWK_ESRCDT, /* error in reading source */ - XP_AWK_ELXCHR, /* lexer came accross an wrong character */ - XP_AWK_ELXUNG, /* lexer failed to unget a character */ + XP_AWK_ELXCHR, /* lexer came accross an wrong character */ + XP_AWK_ELXUNG, /* lexer failed to unget a character */ - XP_AWK_EENDSRC, /* unexpected end of source */ - XP_AWK_EENDSTR, /* unexpected end of a string */ - XP_AWK_ELBRACE, /* left brace expected */ - XP_AWK_ELPAREN, /* left parenthesis expected */ - XP_AWK_ERPAREN, /* right parenthesis expected */ - XP_AWK_ERBRACK, /* right bracket expected */ - XP_AWK_ECOMMA, /* comma expected */ - XP_AWK_ESEMICOLON, /* semicolon expected */ - XP_AWK_ECOLON, /* colon expected */ - XP_AWK_EEXPRESSION, /* expression expected */ + XP_AWK_EENDSRC, /* unexpected end of source */ + XP_AWK_EENDSTR, /* unexpected end of a string */ + XP_AWK_ELBRACE, /* left brace expected */ + XP_AWK_ELPAREN, /* left parenthesis expected */ + XP_AWK_ERPAREN, /* right parenthesis expected */ + XP_AWK_ERBRACK, /* right bracket expected */ + XP_AWK_ECOMMA, /* comma expected */ + XP_AWK_ESEMICOLON, /* semicolon expected */ + XP_AWK_ECOLON, /* colon expected */ + XP_AWK_EEXPRESSION, /* expression expected */ - XP_AWK_EWHILE, /* keyword 'while' is expected */ - XP_AWK_EASSIGNMENT, /* assignment statement expected */ - XP_AWK_EIDENT, /* identifier expected */ - XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ - XP_AWK_EDUPEND, /* duplicate END */ - XP_AWK_EDUPFUNC, /* duplicate function name */ - XP_AWK_EDUPPARAM, /* duplicate parameter name */ - XP_AWK_EDUPVAR, /* duplicate variable name */ - XP_AWK_EDUPNAME, /* duplicate name - function, variable, etc */ - XP_AWK_EUNDEF, /* undefined identifier */ - XP_AWK_ELVALUE, /* l-value required */ + XP_AWK_EWHILE, /* keyword 'while' is expected */ + XP_AWK_EASSIGNMENT, /* assignment statement expected */ + XP_AWK_EIDENT, /* identifier expected */ + XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ + XP_AWK_EDUPEND, /* duplicate END */ + XP_AWK_EDUPFUNC, /* duplicate function name */ + XP_AWK_EDUPPARAM, /* duplicate parameter name */ + XP_AWK_EDUPVAR, /* duplicate variable name */ + XP_AWK_EDUPNAME, /* duplicate name - function, variable, etc */ + XP_AWK_EUNDEF, /* undefined identifier */ + XP_AWK_ELVALUE, /* l-value required */ /* run time error */ - XP_AWK_EDIVBYZERO, /* divide by zero */ - XP_AWK_EOPERAND, /* invalid operand */ - XP_AWK_ENOSUCHFUNC, /* no such function */ - XP_AWK_ENOTINDEXABLE, /* not indexable value */ - XP_AWK_EINDEX, /* wrong index */ - XP_AWK_EINTERNAL /* internal error */ + XP_AWK_EDIVBYZERO, /* divide by zero */ + XP_AWK_EOPERAND, /* invalid operand */ + XP_AWK_ENOSUCHFUNC, /* no such function */ + XP_AWK_ENOTASSIGNABLE, /* not indexable value */ + XP_AWK_ENOTINDEXABLE, /* not indexable value */ + XP_AWK_EINDEX, /* wrong index */ + XP_AWK_EINTERNAL /* internal error */ }; #ifdef __cplusplus diff --git a/ase/awk/err.c b/ase/awk/err.c index 3ae783f5..0ce2348e 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.10 2006-04-16 13:30:19 bacon Exp $ + * $Id: err.c,v 1.11 2006-04-17 16:12:02 bacon Exp $ */ #include @@ -47,6 +47,7 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) XP_TEXT("divide by zero"), XP_TEXT("invalid operand"), XP_TEXT("no such function"), + XP_TEXT("value not assignable"), XP_TEXT("value not indexable"), XP_TEXT("wrong index value"), diff --git a/ase/awk/run.c b/ase/awk/run.c index c1d81733..d9a725e4 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.53 2006-04-16 16:30:59 bacon Exp $ + * $Id: run.c,v 1.54 2006-04-17 16:12:02 bacon Exp $ */ #include @@ -48,6 +48,8 @@ static xp_awk_val_t* __eval_expression (xp_awk_t* awk, xp_awk_nde_t* nde); static xp_awk_val_t* __eval_assignment (xp_awk_t* awk, xp_awk_nde_t* nde); static xp_awk_val_t* __do_assignment ( xp_awk_t* awk, xp_awk_nde_var_t* var, xp_awk_val_t* val); +static xp_awk_val_t* __do_assignment_globalidx ( + xp_awk_t* awk, xp_awk_nde_var_t* var, xp_awk_val_t* val); static xp_awk_val_t* __eval_binary (xp_awk_t* awk, xp_awk_nde_t* nde); static xp_awk_val_t* __eval_binop_lor ( @@ -749,11 +751,11 @@ static xp_awk_val_t* __eval_assignment (xp_awk_t* awk, xp_awk_nde_t* nde) static xp_awk_val_t* __do_assignment ( xp_awk_t* awk, xp_awk_nde_var_t* var, xp_awk_val_t* val) { + if (val->type == XP_AWK_VAL_MAP) { -/* TODO */ /* a map cannot be assigned to a variable */ - PANIC (awk, XP_AWK_EMAPASS); + PANIC (awk, XP_AWK_ENOTASSIGNABLE); } if (var->type == XP_AWK_NDE_NAMED) @@ -811,62 +813,8 @@ static xp_awk_val_t* __do_assignment ( } else if (var->type == XP_AWK_NDE_GLOBALIDX) { - xp_awk_nde_var_t* tgt = (xp_awk_nde_var_t*)nde; - xp_awk_val_t* v = STACK_GLOBAL(awk,tgt->id.idxa); - xp_awk_val_t* idx, *res; - xp_char_t* str; - xp_awk_map_val_t* mv; - - if (v->type != XP_AWK_VAL_NIL || - v->type != XP_AWK_VAL_MAP) PANIC (awk, XP_AWK_ENOTINDEXABLE); - xp_assert (tgt->idx != XP_NULL); - idx = __eval_expression (awk, tgt->idx); - if (idx == XP_NULL) return XP_NULL; - - xp_awk_refupval (idx); - - str = __val_to_str (idx); - if (str == XP_NULL) - { - /* TODO: how to tell memory error from conversion error? */ - xp_awk_refdownval (awk, idx); - /*PANIC (awk, XP_AWK_ENOMEM);*/ - PANIC (awk, XP_AWK_EINDEX); - } - - if (v->type == XP_AWK_VAL_NIL) - { - mv = xp_awk_makemap_val (awk); - if (mv == XP_NULL) - { - xp_free (str); - xp_awk_refdownval (awk, idx); - PANIC (awk, XP_AWK_ENOMEM); - } - - xp_awk_refdownval (awk, v); - STACK_GLOBAL(awk,var->id.idxa) = mv; - xp_awk_refupval (awk, mv); - } - else - { - mv = STACK_GLOBAL(awk,var->id.idxa); - - } - - // TODO: refdown old val.... - if (xp_awk_map_put(awk, str, val) == XP_NULL) - { -// TODO:............ - xp_free (str); - xp_awk_refdownval (awk, idx); - PANIC (awk, XP_AWK_ENOMEM); - } - - xp_free (str); - xp_awk_refdownval (awk, idx); - - xp_awk_refupval (val); + if (__do_assignment_globalidx(awk,var,val) == XP_NULL) + return XP_NULL; } else if (var->type == XP_AWK_NDE_LOCALIDX) { @@ -885,6 +833,84 @@ static xp_awk_val_t* __do_assignment ( return val; } +static xp_awk_val_t* __do_assignment_globalidx ( + xp_awk_t* awk, xp_awk_nde_var_t* var, xp_awk_val_t* val) +{ + xp_awk_val_map_t* map; + xp_awk_nde_t* nde; + xp_char_t* str; + xp_awk_pair_t* pair; + + xp_assert (var->type == XP_AWK_NDE_GLOBALIDX && var->idx != XP_NULL); + + map = (xp_awk_val_map_t*)STACK_GLOBAL(awk,var->id.idxa); + if (map->type == XP_AWK_VAL_NIL) + { + /* the map is not initialized yet */ + xp_awk_val_t* tmp; + + tmp = xp_awk_makemapval (awk); + if (tmp == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + + xp_awk_refdownval (awk, (xp_awk_val_t*)map); + STACK_GLOBAL(awk,var->id.idxa) = tmp; + xp_awk_refupval (tmp); + + map = (xp_awk_val_map_t*) tmp; + } + else if (map->type != XP_AWK_VAL_MAP) + { + PANIC (awk, XP_AWK_ENOTINDEXABLE); + } + + /* compose a map index */ + nde = var->idx; +/* TODO: while (nde != XP_NULL) */ + { + xp_awk_val_t* tmp; + + tmp = __eval_expression (awk, nde); + if (tmp == XP_NULL) + { + /* TODO: clearing previous idx values... */ + return XP_NULL; + } + + xp_awk_refupval (tmp); + + str = __val_to_str (tmp); + if (str == XP_NULL) + { + /* TODO: how to tell memory from conversion error? */ + xp_awk_refdownval (awk, tmp); + /*PANIC (awk, XP_AWK_ENOMEM);*/ + PANIC (awk, XP_AWK_EINDEX); + } + + xp_awk_refdownval (awk, tmp); + /* TODO: nde = nde->next; */ + } + +xp_printf (XP_TEXT("**** index str=>%s, map->ref=%d, map->type=%d\n"), str, map->ref, map->type); + pair = xp_awk_map_get (map->map, str); + if (xp_awk_map_put(map->map, str, val) == XP_NULL) + { + xp_free (str); + PANIC (awk, XP_AWK_ENOMEM); + } + + xp_free (str); + if (pair != XP_NULL) + { + /* decrease the reference count for the old value + * only when the assignment is successful */ + xp_awk_refdownval (awk, pair->val); + } + + xp_awk_refupval (val); + return val; +} + static xp_awk_val_t* __eval_binary (xp_awk_t* awk, xp_awk_nde_t* nde) { static binop_func_t __binop_func[] = diff --git a/ase/awk/val.c b/ase/awk/val.c index 137e945e..101fa8e8 100644 --- a/ase/awk/val.c +++ b/ase/awk/val.c @@ -1,5 +1,5 @@ /* - * $Id: val.c,v 1.19 2006-04-16 04:31:38 bacon Exp $ + * $Id: val.c,v 1.20 2006-04-17 16:12:02 bacon Exp $ */ #include @@ -89,7 +89,8 @@ xp_awk_val_t* xp_awk_makestrval (const xp_char_t* str, xp_size_t len) val->ref = 0; val->len = len; val->buf = xp_strxdup (str, len); - if (val->buf == XP_NULL) { + if (val->buf == XP_NULL) + { xp_free (val); return XP_NULL; } @@ -110,7 +111,32 @@ xp_awk_val_t* xp_awk_makestrval2 ( val->ref = 0; val->len = len1 + len2; val->buf = xp_strxdup2 (str1, len1, str2, len2); - if (val->buf == XP_NULL) { + if (val->buf == XP_NULL) + { + xp_free (val); + return XP_NULL; + } + + return (xp_awk_val_t*)val; +} + +static void __free_map_val (xp_awk_t* awk, void* v) +{ + xp_awk_refdownval (awk, v); +} + +xp_awk_val_t* xp_awk_makemapval (xp_awk_t* awk) +{ + xp_awk_val_map_t* val; + + val = (xp_awk_val_map_t*)xp_malloc(xp_sizeof(xp_awk_val_map_t)); + if (val == XP_NULL) return XP_NULL; + + val->type = XP_AWK_VAL_MAP; + val->ref = 0; + val->map = xp_awk_map_open (XP_NULL, awk, 256, __free_map_val); + if (val->map == XP_NULL) + { xp_free (val); return XP_NULL; } @@ -133,7 +159,7 @@ void xp_awk_freeval (xp_awk_t* awk, xp_awk_val_t* val) { case XP_AWK_VAL_NIL: xp_free (val); - break; + return; case XP_AWK_VAL_INT: if (awk->run.icache_count < xp_countof(awk->run.icache)) @@ -141,11 +167,8 @@ void xp_awk_freeval (xp_awk_t* awk, xp_awk_val_t* val) awk->run.icache[awk->run.icache_count++] = (xp_awk_val_int_t*)val; } - else - { - xp_free (val); - } - break; + else xp_free (val); + return; case XP_AWK_VAL_REAL: if (awk->run.rcache_count < xp_countof(awk->run.rcache)) @@ -153,19 +176,21 @@ void xp_awk_freeval (xp_awk_t* awk, xp_awk_val_t* val) awk->run.rcache[awk->run.rcache_count++] = (xp_awk_val_real_t*)val; } - else - { - xp_free (val); - } - break; + else xp_free (val); + return; case XP_AWK_VAL_STR: xp_free (((xp_awk_val_str_t*)val)->buf); xp_free (val); - break; + return; + + case XP_AWK_VAL_MAP: + xp_awk_map_close (((xp_awk_val_map_t*)val)->map); + xp_free (val); + return; } - /* should never reach here */ + xp_assert (!"should never happen - invalid value type"); } void xp_awk_refupval (xp_awk_val_t* val) @@ -227,8 +252,12 @@ xp_awk_val_t* xp_awk_cloneval (xp_awk_t* awk, xp_awk_val_t* val) return xp_awk_makestrval ( ((xp_awk_val_str_t*)val)->buf, ((xp_awk_val_str_t*)val)->len); + case XP_AWK_VAL_MAP: + /* TODO: .... */ + return XP_NULL; } + xp_assert (!"should never happen - invalid value type"); return XP_NULL; } @@ -246,9 +275,11 @@ xp_bool_t xp_awk_boolval (xp_awk_val_t* val) return ((xp_awk_val_real_t*)val)->val != 0.0; case XP_AWK_VAL_STR: return ((xp_awk_val_str_t*)val)->len > 0; + case XP_AWK_VAL_MAP: + return xp_false; /* TODO: is this correct? */ } - xp_assert (!"should never happen - invalid vlaue type"); + xp_assert (!"should never happen - invalid value type"); return xp_false; } @@ -286,6 +317,10 @@ void xp_awk_printval (xp_awk_val_t* val) xp_printf (XP_TEXT("%s"), ((xp_awk_val_str_t*)val)->buf); break; + case XP_AWK_VAL_MAP: + xp_printf (XP_TEXT("***MAP***")); + break; + default: xp_assert (!"should never happen - invalid value type"); xp_printf (XP_TEXT("**** INTERNAL ERROR - INVALID VALUE TYPE ****\n")); diff --git a/ase/awk/val.h b/ase/awk/val.h index 18a1a09f..446a8277 100644 --- a/ase/awk/val.h +++ b/ase/awk/val.h @@ -1,5 +1,5 @@ /* - * $Id: val.h,v 1.16 2006-04-16 16:30:59 bacon Exp $ + * $Id: val.h,v 1.17 2006-04-17 16:12:02 bacon Exp $ */ #ifndef _XP_AWK_VAL_H_ @@ -26,8 +26,13 @@ typedef struct xp_awk_val_str_t xp_awk_val_str_t; typedef struct xp_awk_val_map_t xp_awk_val_map_t; #define XP_AWK_VAL_HDR \ - int type: 3; \ - int ref: 29 + unsigned int type: 3; \ + unsigned int ref: 28 +/* +#define XP_AWK_VAL_HDR \ + int type: 4; \ + int ref: 27 +*/ struct xp_awk_val_t { @@ -81,7 +86,7 @@ xp_awk_val_t* xp_awk_makestrval (const xp_char_t* str, xp_size_t len); 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_t* xp_awk_makemapval ();*/ +xp_awk_val_t* xp_awk_makemapval (xp_awk_t* awk); xp_bool_t xp_awk_isbuiltinval (xp_awk_val_t* val); void xp_awk_freeval (xp_awk_t* awk, xp_awk_val_t* val);