diff --git a/ase/awk/run.c b/ase/awk/run.c index 5ebc4b48..a79f53a0 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.127 2006-07-09 16:06:04 bacon Exp $ + * $Id: run.c,v 1.128 2006-07-10 04:51:38 bacon Exp $ */ #include @@ -80,6 +80,10 @@ static xp_awk_val_t* __do_assignment_map ( static xp_awk_val_t* __do_assignment_pos ( xp_awk_run_t* run, xp_awk_nde_pos_t* pos, xp_awk_val_t* val); +static int __recomp_record_fields ( + xp_awk_run_t* run, xp_size_t lv, + xp_char_t* str, xp_size_t len, int* errnum); + static xp_awk_val_t* __eval_binary ( xp_awk_run_t* run, xp_awk_nde_t* nde); static xp_awk_val_t* __eval_binop_lor ( @@ -1780,60 +1784,24 @@ static xp_awk_val_t* __do_assignment_pos ( } else { - xp_char_t* ptr; - xp_size_t len; - xp_long_t i; + /* TODO: change xp_awk_valtostr to return the length + * so that xp_strlen doesn't have to be called here */ + xp_size_t xlen = xp_strlen(str); xp_str_clear (&run->inrec.line); - - for (i = 0; i < lv - 1; i++) - { - ptr = XP_T(""); len = 0; - if (i < run->inrec.nflds) - { - ptr = run->inrec.flds[i].ptr; - len = run->inrec.flds[i].len; - } - - /* TODO: use OFS for record recomputation */ - if ((i > 0 && xp_str_ccat (&run->inrec.line, XP_T(' ')) == (xp_size_t)-1) || - xp_str_ncat (&run->inrec.line, ptr, len) == (xp_size_t)-1) - { - xp_free (str); - __clear_record (run, xp_false); - PANIC (run, XP_AWK_ENOMEM); - } - } - - if (xp_str_cat (&run->inrec.line, str) == (xp_size_t)-1) + if (__recomp_record_fields ( + run, (xp_size_t)lv, str, xlen, &errnum) == -1) { xp_free (str); __clear_record (run, xp_false); - PANIC (run, XP_AWK_ENOMEM); + PANIC (run, errnum); } - xp_free (str); - for (i = lv; i < run->inrec.nflds; i++) - { - ptr = XP_T(""); len = 0; - if (i < run->inrec.nflds) - { - ptr = run->inrec.flds[i].ptr; - len = run->inrec.flds[i].len; - } - - /* TODO: use OFS for record recomputation */ - if (xp_str_ccat (&run->inrec.line, XP_T(' ')) == (xp_size_t)-1 || - xp_str_ncat (&run->inrec.line, ptr, len) == (xp_size_t)-1) - { - __clear_record (run, xp_false); - PANIC (run, XP_AWK_ENOMEM); - } - } - - - v = xp_awk_makestrval (XP_STR_BUF(&run->inrec.line), XP_STR_LEN(&run->inrec.line)); + /* recompose $0 */ + v = xp_awk_makestrval ( + XP_STR_BUF(&run->inrec.line), + XP_STR_LEN(&run->inrec.line)); if (v == XP_NULL) { __clear_record (run, xp_false); @@ -1841,15 +1809,118 @@ static xp_awk_val_t* __do_assignment_pos ( } xp_awk_refdownval (run, run->inrec.d0); - run->inrec.d0 = val; - xp_awk_refupval (val); - - /* TODO: adjust fields */ + run->inrec.d0 = v; + xp_awk_refupval (v); } return val; } +static int __recomp_record_fields ( + xp_awk_run_t* run, xp_size_t lv, + xp_char_t* str, xp_size_t len, int* errnum) +{ + xp_size_t max, i, nflds; + + xp_assert (lv > 0); + max = (lv > run->inrec.nflds)? lv: run->inrec.nflds; + + nflds = run->inrec.nflds; + if (max > run->inrec.maxflds) + { + void* tmp = xp_realloc ( + run->inrec.flds, xp_sizeof(*run->inrec.flds) * max); + if (tmp == XP_NULL) PANIC_I (run, XP_AWK_ENOMEM); + + run->inrec.flds = tmp; + run->inrec.maxflds = max; + } + + lv = lv - 1; /* adjust the value to 0-based index */ + + for (i = 0; i < max; i++) + { + if (i > 0) + { + /* TODO: use OFS */ + if (xp_str_ccat ( + &run->inrec.line, XP_T(' ')) == (xp_size_t)-1) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } + } + + if (i == lv) + { + xp_awk_val_t* tmp; + + run->inrec.flds[i].ptr = + XP_STR_BUF(&run->inrec.line) + + XP_STR_LEN(&run->inrec.line); + run->inrec.flds[i].len = len; + + if (xp_str_ncat ( + &run->inrec.line, str, len) == (xp_size_t)-1) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } + + tmp = xp_awk_makestrval (str,len); + if (tmp == XP_NULL) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } + + if (i < nflds) + xp_awk_refdownval (run, run->inrec.flds[i].val); + run->inrec.flds[i].val = tmp; + xp_awk_refupval (tmp); + } + else if (i >= nflds) + { + run->inrec.flds[i].ptr = + XP_STR_BUF(&run->inrec.line) + + XP_STR_LEN(&run->inrec.line); + run->inrec.flds[i].len = 0; + + if (xp_str_cat ( + &run->inrec.line, XP_T("")) == (xp_size_t)-1) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } + + /*xp_awk_refdownval (run, run->inrec.flds[i].val);*/ + run->inrec.flds[i].val = xp_awk_val_zls; + xp_awk_refupval (xp_awk_val_zls); + run->inrec.nflds++; + } + else + { + xp_awk_val_str_t* tmp; + + tmp = (xp_awk_val_str_t*)run->inrec.flds[i].val; + + run->inrec.flds[i].ptr = + XP_STR_BUF(&run->inrec.line) + + XP_STR_LEN(&run->inrec.line); + run->inrec.flds[i].len = tmp->len; + + if (xp_str_ncat (&run->inrec.line, + tmp->buf, tmp->len) == (xp_size_t)-1) + { + *errnum = XP_AWK_ENOMEM; + return -1; + } + } + } + + return 0; +} + static xp_awk_val_t* __eval_binary (xp_awk_run_t* run, xp_awk_nde_t* nde) { static binop_func_t __binop_func[] = @@ -3495,7 +3566,7 @@ static xp_awk_val_t* __eval_pos (xp_awk_run_t* run, xp_awk_nde_t* nde) if (lv == 0) v = run->inrec.d0; else if (lv > 0 && lv <= run->inrec.nflds) v = run->inrec.flds[lv-1].val; - else v = xp_awk_val_nil; + else v = xp_awk_val_zls; /*xp_awk_val_nil;*/ return v; } diff --git a/ase/awk/val.c b/ase/awk/val.c index 9364f6e2..4bf27391 100644 --- a/ase/awk/val.c +++ b/ase/awk/val.c @@ -1,5 +1,5 @@ /* - * $Id: val.c,v 1.37 2006-07-06 15:54:41 bacon Exp $ + * $Id: val.c,v 1.38 2006-07-10 04:51:38 bacon Exp $ */ #include @@ -13,6 +13,9 @@ static xp_awk_val_nil_t __awk_nil = { XP_AWK_VAL_NIL, 0 }; xp_awk_val_t* xp_awk_val_nil = (xp_awk_val_t*)&__awk_nil; +static xp_awk_val_str_t __awk_zls = { XP_AWK_VAL_STR, 0, XP_T(""), 0 }; +xp_awk_val_t* xp_awk_val_zls = (xp_awk_val_t*)&__awk_zls; + static xp_awk_val_int_t __awk_int[] = { { XP_AWK_VAL_INT, 0, -1 }, @@ -183,7 +186,9 @@ xp_awk_val_t* xp_awk_makemapval (xp_awk_run_t* run) xp_bool_t xp_awk_isbuiltinval (xp_awk_val_t* val) { - return val == XP_NULL || val == xp_awk_val_nil || + return val == XP_NULL || + val == xp_awk_val_nil || + val == xp_awk_val_zls || (val >= (xp_awk_val_t*)&__awk_int[0] && val <= (xp_awk_val_t*)&__awk_int[xp_countof(__awk_int)-1]); } @@ -198,7 +203,7 @@ xp_printf (XP_T("\n"));*/ switch (val->type) { case XP_AWK_VAL_NIL: - if (val != xp_awk_val_nil) xp_free (val); + xp_free (val); return; case XP_AWK_VAL_INT: diff --git a/ase/awk/val.h b/ase/awk/val.h index 3b16963d..f4035fdd 100644 --- a/ase/awk/val.h +++ b/ase/awk/val.h @@ -1,5 +1,5 @@ /* - * $Id: val.h,v 1.27 2006-07-01 16:07:06 bacon Exp $ + * $Id: val.h,v 1.28 2006-07-10 04:51:38 bacon Exp $ */ #ifndef _XP_AWK_VAL_H_ @@ -93,6 +93,7 @@ extern "C" { #endif extern xp_awk_val_t* xp_awk_val_nil; +extern xp_awk_val_t* xp_awk_val_zls; xp_awk_val_t* xp_awk_makeintval (xp_awk_run_t* run, xp_long_t v); xp_awk_val_t* xp_awk_makerealval (xp_awk_run_t* run, xp_real_t v); diff --git a/ase/test/awk/t14.awk b/ase/test/awk/t14.awk index b7d4deff..7c7e2ca5 100644 --- a/ase/test/awk/t14.awk +++ b/ase/test/awk/t14.awk @@ -23,9 +23,11 @@ END //print $0 = "wow this is just a test"; //print $0 = ""; //print $0; - $1="abcdefghi"; + + $7="abcdefghi"; print a = $6; print "[" $0 "],[" a "]"; + /* print $6; */