diff --git a/ase/awk/func.c b/ase/awk/func.c index d7f5bd4f..2e78c377 100644 --- a/ase/awk/func.c +++ b/ase/awk/func.c @@ -1,5 +1,5 @@ /* - * $Id: func.c,v 1.49 2006-09-12 15:20:18 bacon Exp $ + * $Id: func.c,v 1.50 2006-09-13 14:16:13 bacon Exp $ */ #include @@ -42,7 +42,7 @@ static xp_awk_bfn_t __sys_bfn[] = { XP_T("split"), 5, 0, 2, 3, XP_T("vrv"), __bfn_split }, { XP_T("tolower"), 7, 0, 1, 1, XP_NULL, __bfn_tolower }, { XP_T("toupper"), 7, 0, 1, 1, XP_NULL, __bfn_toupper }, - { XP_T("gsub"), 4, 0, 2, 3, XP_T("vvr"), __bfn_gsub }, + { XP_T("gsub"), 4, 0, 2, 3, XP_T("xvr"), __bfn_gsub }, /* TODO: remove these two functions */ { XP_T("system"), 6, 0, 1, 1, XP_NULL, __bfn_system }, @@ -500,7 +500,7 @@ static int __bfn_substr (xp_awk_t* awk, void* run) static int __bfn_split (xp_awk_t* awk, void* run) { xp_size_t nargs; - xp_awk_val_t* a0, * a1, * a2, * t1, * t2, ** a1ref; + xp_awk_val_t* a0, * a1, * a2, * t1, * t2, ** a1_ref; xp_char_t* str, * str_free, * p, * tok; xp_size_t str_len, str_left, tok_len; xp_long_t num; @@ -529,9 +529,9 @@ static int __bfn_split (xp_awk_t* awk, void* run) return -1; } - a1ref = (xp_awk_val_t**)((xp_awk_val_ref_t*)a1)->adr; - if ((*a1ref)->type != XP_AWK_VAL_NIL && - (*a1ref)->type != XP_AWK_VAL_MAP) + a1_ref = (xp_awk_val_t**)((xp_awk_val_ref_t*)a1)->adr; + if ((*a1_ref)->type != XP_AWK_VAL_NIL && + (*a1_ref)->type != XP_AWK_VAL_MAP) { /* cannot change a scalar value to a map */ xp_awk_seterrnum (run, XP_AWK_ESCALARTOMAP); @@ -633,9 +633,9 @@ static int __bfn_split (xp_awk_t* awk, void* run) return -1; } - xp_awk_refdownval (run, *a1ref); - *a1ref = t1; - xp_awk_refupval (*a1ref); + xp_awk_refdownval (run, *a1_ref); + *a1_ref = t1; + xp_awk_refupval (*a1_ref); p = str; str_left = str_len; num = 0; while (p != XP_NULL) @@ -800,7 +800,7 @@ static int __bfn_toupper (xp_awk_t* awk, void* run) static int __bfn_gsub (xp_awk_t* awk, void* run) { xp_size_t nargs; - xp_awk_val_t* a0, * a1, * a2; + xp_awk_val_t* a0, * a1, * a2, ** a2_ref, * v; xp_char_t* a0_ptr, * a1_ptr, * a2_ptr; xp_size_t a0_len, a1_len, a2_len; xp_char_t* a0_ptr_free = XP_NULL; @@ -811,6 +811,7 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) const xp_char_t* cur_ptr, * match_ptr; xp_size_t cur_len, match_len; xp_awk_str_t new; + xp_long_t sub_count; nargs = xp_awk_getnargs (run); xp_assert (nargs >= 2 && nargs <= 3); @@ -821,7 +822,11 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) xp_assert (a2 == XP_NULL || a2->type == XP_AWK_VAL_REF); - if (a0->type == XP_AWK_VAL_STR) + if (a0->type == XP_AWK_VAL_REX) + { + rex = ((xp_awk_val_rex_t*)a0)->code; + } + else if (a0->type == XP_AWK_VAL_STR) { a0_ptr = ((xp_awk_val_str_t*)a0)->buf; a0_len = ((xp_awk_val_str_t*)a0)->len; @@ -859,23 +864,48 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) else { /* operation is on a2 */ + a2_ref = (xp_awk_val_t**)((xp_awk_val_ref_t*)a2)->adr; /* - a2ref = (xp_awk_val_t**)((xp_awk_val_ref_t*)a2)->adr; - if ((*a2ref)->type != XP_AWK_VAL_NIL && - (*a2ref)->type != XP_AWK_VAL_MAP) + if ((*a2_ref)->type != XP_AWK_VAL_NIL && + (*a2_ref)->type != XP_AWK_VAL_MAP) { } */ + if ((*a2_ref)->type == XP_AWK_VAL_STR) + { + a2_ptr = ((xp_awk_val_str_t*)(*a2_ref))->buf; + a2_len = ((xp_awk_val_str_t*)(*a2_ref))->len; + } + else + { + a2_ptr = xp_awk_valtostr ( + run, *a2_ref, xp_true, XP_NULL, &a2_len); + if (a2_ptr == XP_NULL) + { + if (a1_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a1_ptr_free); + if (a0_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a0_ptr_free); + return -1; + } + a2_ptr_free = a2_ptr; + } } - rex = xp_awk_buildrex (awk, - a0_ptr, a0_len, &((xp_awk_run_t*)run)->errnum); - if (rex == XP_NULL) + if (a0->type != XP_AWK_VAL_REX) { - if (a2_ptr_free != XP_NULL) XP_AWK_FREE (awk, a2_ptr_free); - if (a1_ptr_free != XP_NULL) XP_AWK_FREE (awk, a1_ptr_free); - if (a0_ptr_free != XP_NULL) XP_AWK_FREE (awk, a0_ptr_free); - return -1; + rex = xp_awk_buildrex (awk, + a0_ptr, a0_len, &((xp_awk_run_t*)run)->errnum); + if (rex == XP_NULL) + { + if (a2_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a2_ptr_free); + if (a1_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a1_ptr_free); + if (a0_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a0_ptr_free); + return -1; + } } opt = (((xp_awk_run_t*)run)->rex.ignorecase)? XP_AWK_REX_IGNORECASE: 0; @@ -892,6 +922,8 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) return -1; } + sub_count = 0; + while (1) { n = xp_awk_matchrex ( @@ -942,7 +974,7 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) XP_AWK_FREE (awk, a0_ptr_free); return -1; } - /*TODO: handle & */ +/*TODO: handle & */ if (xp_awk_str_ncat (&new, a1_ptr, a1_len) == (xp_size_t)-1) { xp_awk_str_close (&new); @@ -956,13 +988,13 @@ static int __bfn_gsub (xp_awk_t* awk, void* run) return -1; } + sub_count++; cur_ptr = match_ptr + match_len; cur_len = cur_len - ((match_ptr - cur_ptr) + match_len); } - xp_awk_freerex (awk, rex); + if (a0->type != XP_AWK_VAL_REX) xp_awk_freerex (awk, rex); -xp_printf (XP_T("NEW STRING [%s]\n"), XP_AWK_STR_BUF(&new)); if (a2 == XP_NULL) { if (xp_awk_setrecord (run, @@ -980,7 +1012,23 @@ xp_printf (XP_T("NEW STRING [%s]\n"), XP_AWK_STR_BUF(&new)); } else { - /* TODO: */ + v = xp_awk_makestrval (run, + XP_AWK_STR_BUF(&new), XP_AWK_STR_LEN(&new)); + if (v == XP_NULL) + { + xp_awk_str_close (&new); + if (a2_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a2_ptr_free); + if (a1_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a1_ptr_free); + if (a0_ptr_free != XP_NULL) + XP_AWK_FREE (awk, a0_ptr_free); + return -1; + } + + xp_awk_refdownval (run, *a2_ref); + *a2_ref = v; + xp_awk_refupval (*a2_ref); } xp_awk_str_close (&new); @@ -989,6 +1037,14 @@ xp_printf (XP_T("NEW STRING [%s]\n"), XP_AWK_STR_BUF(&new)); if (a1_ptr_free != XP_NULL) XP_AWK_FREE (awk, a1_ptr_free); if (a0_ptr_free != XP_NULL) XP_AWK_FREE (awk, a0_ptr_free); + v = xp_awk_makeintval (run, sub_count); + if (v == XP_NULL) + { + xp_awk_seterrnum (run, XP_AWK_ENOMEM); + return -1; + } + + xp_awk_setretval (run, v); return 0; } diff --git a/ase/awk/run.c b/ase/awk/run.c index 8ad7e002..cf3da02c 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.202 2006-09-12 15:21:32 bacon Exp $ + * $Id: run.c,v 1.203 2006-09-13 14:16:13 bacon Exp $ */ #include @@ -4163,52 +4163,60 @@ static xp_awk_val_t* __eval_call ( p = call->args; while (p != XP_NULL) { - v = __eval_expression (run, p); + xp_assert (bfn_arg_spec == XP_NULL || + (bfn_arg_spec != XP_NULL && + xp_awk_strlen(bfn_arg_spec) > nargs)); + + if (bfn_arg_spec != XP_NULL && + bfn_arg_spec[nargs] == XP_T('x')) + { + /* a regular expression is passed to + * the function as it is */ + v = __eval_expression0 (run, p); + } + else + { + v = __eval_expression (run, p); + } if (v == XP_NULL) { UNWIND_RUN_STACK (run, nargs); return XP_NULL; } - if (bfn_arg_spec != XP_NULL) + if (bfn_arg_spec != XP_NULL && + bfn_arg_spec[nargs] == XP_T('r')) { - xp_char_t spec; - - /* TODO: spec length check */ - spec = bfn_arg_spec[nargs]; - if (spec == XP_T('r')) + xp_awk_val_t** ref; + xp_awk_val_t* tmp; + + ref = __get_reference (run, p); + if (ref == XP_NULL) { - xp_awk_val_t** ref; - xp_awk_val_t* tmp; - - ref = __get_reference (run, p); - if (ref == XP_NULL) - { - xp_awk_refupval (v); - xp_awk_refdownval (run, v); - - UNWIND_RUN_STACK (run, nargs); - return XP_NULL; - } - - /* p->type-XP_AWK_NDE_NAMED assumes that the - * derived value matches XP_AWK_VAL_REF_XXX */ - tmp = xp_awk_makerefval ( - run, p->type-XP_AWK_NDE_NAMED, ref); - if (tmp == XP_NULL) - { - xp_awk_refupval (v); - xp_awk_refdownval (run, v); - - UNWIND_RUN_STACK (run, nargs); - PANIC (run, XP_AWK_ENOMEM); - } - xp_awk_refupval (v); xp_awk_refdownval (run, v); - v = tmp; + UNWIND_RUN_STACK (run, nargs); + return XP_NULL; } + + /* p->type-XP_AWK_NDE_NAMED assumes that the + * derived value matches XP_AWK_VAL_REF_XXX */ + tmp = xp_awk_makerefval ( + run, p->type-XP_AWK_NDE_NAMED, ref); + if (tmp == XP_NULL) + { + xp_awk_refupval (v); + xp_awk_refdownval (run, v); + + UNWIND_RUN_STACK (run, nargs); + PANIC (run, XP_AWK_ENOMEM); + } + + xp_awk_refupval (v); + xp_awk_refdownval (run, v); + + v = tmp; } if (__raw_push(run,v) == -1) diff --git a/ase/test/awk/t43.awk b/ase/test/awk/t43.awk index 9707789f..6b168030 100644 --- a/ase/test/awk/t43.awk +++ b/ase/test/awk/t43.awk @@ -1,2 +1,3 @@ #BEGIN { t = "abc"; gsub ("abc", "[&]", t); print t; } { gsub ("abc", "ABC"); print $0; } +{ gsub (/ABC/, "XYZ"); print $0; } diff --git a/ase/test/awk/t44.awk b/ase/test/awk/t44.awk new file mode 100644 index 00000000..c54f09c8 --- /dev/null +++ b/ase/test/awk/t44.awk @@ -0,0 +1,3 @@ +#BEGIN { t = "abc"; gsub ("abc", "[&]", t); print t; } +{ c=$0; print gsub ("abc", "ABC", c); print c; } +{ gsub (/ABC/, "XYZ", c); print c; }