diff --git a/ase/awk/awk.c b/ase/awk/awk.c index 1ba41c17..3c44b097 100644 --- a/ase/awk/awk.c +++ b/ase/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.77 2006-09-22 14:04:25 bacon Exp $ + * $Id: awk.c,v 1.78 2006-10-02 14:53:44 bacon Exp $ */ #include @@ -10,10 +10,25 @@ xp_awk_t* xp_awk_open (xp_awk_syscas_t* syscas) { xp_awk_t* awk; - if (syscas == XP_NULL || - syscas->malloc == XP_NULL || + if (syscas == XP_NULL) return XP_NULL; + + if (syscas->malloc == XP_NULL || syscas->free == XP_NULL) return XP_NULL; + if (syscas->is_upper == XP_NULL || + syscas->is_lower == XP_NULL || + syscas->is_alpha == XP_NULL || + syscas->is_digit == XP_NULL || + syscas->is_xdigit == XP_NULL || + syscas->is_alnum == XP_NULL || + syscas->is_space == XP_NULL || + syscas->is_print == XP_NULL || + syscas->is_graph == XP_NULL || + syscas->is_cntrl == XP_NULL || + syscas->is_punct == XP_NULL || + syscas->to_upper == XP_NULL || + syscas->to_lower == XP_NULL) return XP_NULL; + #if defined(_WIN32) && defined(_DEBUG) awk = (xp_awk_t*) malloc (xp_sizeof(xp_awk_t)); #else diff --git a/ase/awk/awk.h b/ase/awk/awk.h index fb917910..6e5e38dd 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.118 2006-09-25 06:17:18 bacon Exp $ + * $Id: awk.h,v 1.119 2006-10-02 14:53:44 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -350,7 +350,11 @@ xp_awk_val_t* xp_awk_getglobal (void* run, xp_size_t idx); int xp_awk_setglobal (void* run, xp_size_t idx, xp_awk_val_t* val); void xp_awk_seterrnum (void* run, int errnum); void xp_awk_setretval (void* run, xp_awk_val_t* val); -int xp_awk_setrecord (void* run, const xp_char_t* str, xp_size_t len); + +int xp_awk_setrecord ( + void* run, const xp_char_t* str, xp_size_t len); +int xp_awk_setfield ( + void* run, xp_size_t idx, const xp_char_t* str, xp_size_t len); /* utility functions exported by awk.h */ xp_long_t xp_awk_strtolong ( diff --git a/ase/awk/func.c b/ase/awk/func.c index 449e0db7..531268d1 100644 --- a/ase/awk/func.c +++ b/ase/awk/func.c @@ -1,5 +1,5 @@ /* - * $Id: func.c,v 1.54 2006-09-30 17:02:35 bacon Exp $ + * $Id: func.c,v 1.55 2006-10-02 14:53:44 bacon Exp $ */ #include @@ -521,6 +521,7 @@ static int __bfn_split (xp_awk_t* awk, void* run) xp_assert (a1->type == XP_AWK_VAL_REF); +/* TODO: XP_AWK_VAL_REF_POS */ if (((xp_awk_val_ref_t*)a1)->id >= XP_AWK_VAL_REF_NAMEDIDX && ((xp_awk_val_ref_t*)a1)->id <= XP_AWK_VAL_REF_ARGIDX) { @@ -809,6 +810,7 @@ static int __bfn_sub (xp_awk_t* awk, void* run) static int __substitute (xp_awk_t* awk, void* run, xp_long_t max_count) { + xp_awk_run_t* r = run; xp_size_t nargs; xp_awk_val_t* a0, * a1, * a2, ** a2_ref, * v; xp_char_t* a0_ptr, * a1_ptr, * a2_ptr; @@ -882,21 +884,34 @@ static int __substitute (xp_awk_t* awk, void* run, xp_long_t max_count) if (a2 == XP_NULL) { /* is this correct? any needs to use inrec.d0? */ - a2_ptr = XP_AWK_STR_BUF(&((xp_awk_run_t*)run)->inrec.line); - a2_len = XP_AWK_STR_LEN(&((xp_awk_run_t*)run)->inrec.line); + a2_ptr = XP_AWK_STR_BUF(&r->inrec.line); + a2_len = XP_AWK_STR_LEN(&r->inrec.line); + } + else if (((xp_awk_val_ref_t*)a2)->id == XP_AWK_VAL_REF_POS) + { + xp_size_t idx; + + idx = (xp_size_t)((xp_awk_val_ref_t*)a2)->adr; + if (idx == 0) + { + a2_ptr = XP_AWK_STR_BUF(&r->inrec.line); + a2_len = XP_AWK_STR_LEN(&r->inrec.line); + } + else if (idx <= r->inrec.nflds) + { + a2_ptr = r->inrec.flds[idx-1].ptr; + a2_len = r->inrec.flds[idx-1].len; + } + else + { + a2_ptr = XP_T(""); + a2_len = 0; + } } else { - /* operation is on a2 */ -if (((xp_awk_val_ref_t*)a2)->id == XP_AWK_VAL_REF_POS) -{ -FREE_A_PTRS (awk); -/* a map is not allowed as the third parameter */ -xp_awk_seterrnum (run, XP_AWK_EMAPNOTALLOWED); -return -1; -} - a2_ref = (xp_awk_val_t**)((xp_awk_val_ref_t*)a2)->adr; + if ((*a2_ref)->type == XP_AWK_VAL_MAP) { FREE_A_PTRS (awk); @@ -913,7 +928,7 @@ return -1; else { a2_ptr = xp_awk_valtostr ( - run, *a2_ref, xp_true, XP_NULL, &a2_len); + r, *a2_ref, xp_true, XP_NULL, &a2_len); if (a2_ptr == XP_NULL) { FREE_A_PTRS (awk); @@ -1023,30 +1038,57 @@ return -1; FREE_A0_REX (awk, rex); - if (a2 == XP_NULL) + if (sub_count > 0) { - if (xp_awk_setrecord (run, - XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)) == -1) + if (a2 == XP_NULL) { - xp_awk_str_close (&new); - FREE_A_PTRS (awk); - return -1; + if (xp_awk_setrecord (run, + XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)) == -1) + { + xp_awk_str_close (&new); + FREE_A_PTRS (awk); + return -1; + } } - } - else - { - v = xp_awk_makestrval (run, - XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)); - if (v == XP_NULL) + else if (((xp_awk_val_ref_t*)a2)->id == XP_AWK_VAL_REF_POS) { - xp_awk_str_close (&new); - FREE_A_PTRS (awk); - return -1; - } + int n; + xp_size_t idx; - xp_awk_refdownval (run, *a2_ref); - *a2_ref = v; - xp_awk_refupval (*a2_ref); + idx = (xp_size_t)((xp_awk_val_ref_t*)a2)->adr; + if (idx == 0) + { + n = xp_awk_setrecord (run, + XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)); + } + else + { + n = xp_awk_setfield (run, idx, + XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)); + } + + if (n == -1) + { + xp_awk_str_close (&new); + FREE_A_PTRS (awk); + return -1; + } + } + else + { + v = xp_awk_makestrval (run, + XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)); + if (v == XP_NULL) + { + xp_awk_str_close (&new); + FREE_A_PTRS (awk); + return -1; + } + + xp_awk_refdownval (run, *a2_ref); + *a2_ref = v; + xp_awk_refupval (*a2_ref); + } } xp_awk_str_close (&new); diff --git a/ase/awk/run.c b/ase/awk/run.c index c7d3583b..b8a09334 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.215 2006-10-01 14:48:48 bacon Exp $ + * $Id: run.c,v 1.216 2006-10-02 14:53:44 bacon Exp $ */ #include @@ -199,7 +199,8 @@ static int __set_record ( static int __split_record (xp_awk_run_t* run); static int __clear_record (xp_awk_run_t* run, xp_bool_t noline); static int __recomp_record_fields ( - xp_awk_run_t* run, xp_size_t lv, xp_char_t* str, xp_size_t len); + xp_awk_run_t* run, xp_size_t lv, + const xp_char_t* str, xp_size_t len); static int __shorten_record (xp_awk_run_t* run, xp_size_t nflds); static xp_char_t* __idxnde_to_str ( @@ -2537,6 +2538,7 @@ static xp_awk_val_t* __do_assignment_pos ( run->inrec.d0 = v; xp_awk_refupval (v); +/* TODO: this return value is wrong. consider reimplementing this function with setrecord and setfield... also verify setreocrd and setfield.. */ val = v; } @@ -4278,7 +4280,7 @@ static xp_awk_val_t* __eval_call ( } /*xp_printf (XP_T("got return value\n")); */ - /* this is the trick mentioned in __run_return. + /* this trick has been mentioned in __run_return. * adjust the reference count of the return value. * the value must not be freed even if the reference count * is decremented to zero because its reference has been incremented @@ -4301,7 +4303,7 @@ static int __get_reference ( xp_awk_nde_var_t* tgt = (xp_awk_nde_var_t*)nde; xp_awk_val_t** tmp; - /* refer to __eval_indexed for application of similar concept */ + /* refer to __eval_indexed for application of a similar concept */ if (nde->type == XP_AWK_NDE_NAMED) { @@ -4320,28 +4322,24 @@ static int __get_reference ( if (pair == XP_NULL) PANIC_I (run, XP_AWK_ENOMEM); } - //return (xp_awk_val_t**)&pair->val; *ref = (xp_awk_val_t**)&pair->val; return 0; } if (nde->type == XP_AWK_NDE_GLOBAL) { - //return (xp_awk_val_t**)&STACK_GLOBAL(run,tgt->id.idxa); *ref = (xp_awk_val_t**)&STACK_GLOBAL(run,tgt->id.idxa); return 0; } if (nde->type == XP_AWK_NDE_LOCAL) { - //return (xp_awk_val_t**)&STACK_LOCAL(run,tgt->id.idxa); *ref = (xp_awk_val_t**)&STACK_LOCAL(run,tgt->id.idxa); return 0; } if (nde->type == XP_AWK_NDE_ARG) { - //return (xp_awk_val_t**)&STACK_ARG(run,tgt->id.idxa); *ref = (xp_awk_val_t**)&STACK_ARG(run,tgt->id.idxa); return 0; } @@ -4360,8 +4358,6 @@ static int __get_reference ( if (pair == XP_NULL) PANIC_I (run, XP_AWK_ENOMEM); } - //return __get_reference_indexed ( - // run, tgt, (xp_awk_val_t**)&pair->val); tmp = __get_reference_indexed ( run, tgt, (xp_awk_val_t**)&pair->val); if (tmp == XP_NULL) return -1; @@ -4412,7 +4408,7 @@ static int __get_reference ( if (n == 1) lv = (xp_long_t)rv; if (!IS_VALID_POSIDX(lv)) PANIC_I (run, XP_AWK_EPOSIDX); - *ref = (xp_awk_val_t**)(lv); + *ref = (xp_awk_val_t**)lv; return 0; } @@ -4848,19 +4844,61 @@ static int __read_record (xp_awk_run_t* run) int xp_awk_setrecord (void* run, const xp_char_t* str, xp_size_t len) { - if (__clear_record (run, xp_false) == -1) return -1; + xp_awk_run_t* r = (xp_awk_run_t*)run; - if (xp_awk_str_ncpy ( - &((xp_awk_run_t*)run)->inrec.line, str, len) == (xp_size_t)-1) + if (__clear_record (r, xp_false) == -1) return -1; + + if (xp_awk_str_ncpy (&r->inrec.line, str, len) == (xp_size_t)-1) { __clear_record (run, xp_false); - ((xp_awk_run_t*)run)->errnum = XP_AWK_ENOMEM; + r->errnum = XP_AWK_ENOMEM; return -1; } return __set_record (run, str, len); } +int xp_awk_setfield ( + void* run, xp_size_t idx, const xp_char_t* str, xp_size_t len) +{ + xp_awk_run_t* r = (xp_awk_run_t*)run; + xp_awk_val_t* v; + int errnum; + + if (!IS_VALID_POSIDX(idx)) + { + r->errnum = XP_AWK_EPOSIDX; + return -1; + } + + if (idx == 0) return xp_awk_setrecord (run, str, len); + + if (__recomp_record_fields (r, idx, str, len) == -1) + { + errnum = r->errnum; + __clear_record (r, xp_false); + r->errnum = errnum; + return -1; + } + + /* recompose $0 */ + v = xp_awk_makestrval (r, + XP_AWK_STR_BUF(&r->inrec.line), + XP_AWK_STR_LEN(&r->inrec.line)); + if (v == XP_NULL) + { + __clear_record (run, xp_false); + r->errnum = XP_AWK_ENOMEM; + return -1; + } + + xp_awk_refdownval (run, r->inrec.d0); + r->inrec.d0 = v; + xp_awk_refupval (v); + + return 0; +} + static int __set_record ( xp_awk_run_t* run, const xp_char_t* str, xp_size_t len) { @@ -5071,7 +5109,8 @@ static int __clear_record (xp_awk_run_t* run, xp_bool_t noline) } static int __recomp_record_fields ( - xp_awk_run_t* run, xp_size_t lv, xp_char_t* str, xp_size_t len) + xp_awk_run_t* run, xp_size_t lv, + const xp_char_t* str, xp_size_t len) { xp_awk_val_t* v; xp_size_t max, i, nflds; diff --git a/ase/test/awk/t49.awk b/ase/test/awk/t49.awk new file mode 100644 index 00000000..6b907471 --- /dev/null +++ b/ase/test/awk/t49.awk @@ -0,0 +1,5 @@ +BEGIN { OFS=":"; } +{ + print $5 = "abc"; + print $0; +}