aboutsummaryrefslogtreecommitdiffstats
path: root/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/builtin.c b/builtin.c
index 7926a320..c222ce78 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3000,7 +3000,10 @@ NODE *
call_sub_func(const char *name, int nargs)
{
unsigned int flags = 0;
- NODE *regex, *replace;
+ NODE *regex, *replace, *glob_flag;
+ NODE **lhs, *rhs;
+ NODE *zero = make_number(0.0);
+ NODE *result;
if (name[0] == 'g') {
if (name[1] == 'e')
@@ -3009,17 +3012,62 @@ call_sub_func(const char *name, int nargs)
flags = GSUB;
}
- if ((flags == 0 || flags == GSUB) && nargs != 2)
- fatal(_("%s: can be called indirectly only with two arguments"), name);
+ if (flags == 0 || flags == GSUB) {
+ /* sub or gsub */
+ if (nargs != 2)
+ fatal(_("%s: can be called indirectly only with two arguments"), name);
- replace = POP();
+ replace = POP_STRING();
+ regex = POP(); /* the regex */
+ /*
+ * push regex
+ * push replace
+ * push $0
+ */
+ regex = make_regnode(Node_regex, regex);
+ PUSH(regex);
+ PUSH(replace);
+ lhs = r_get_field(zero, (Func_ptr *) 0, true);
+ nargs++;
+ PUSH_ADDRESS(lhs);
+ } else {
+ /* gensub */
+ if (nargs == 4)
+ rhs = POP();
+ else
+ rhs = NULL;
+ glob_flag = POP_STRING();
+ replace = POP_STRING();
+ regex = POP(); /* the regex */
+ /*
+ * push regex
+ * push replace
+ * push glob_flag
+ * if (nargs = 3) {
+ * push $0
+ * nargs++
+ * }
+ */
+ regex = make_regnode(Node_regex, regex);
+ PUSH(regex);
+ PUSH(replace);
+ PUSH(glob_flag);
+ if (rhs == NULL) {
+ lhs = r_get_field(zero, (Func_ptr *) 0, true);
+ rhs = *lhs;
+ UPREF(rhs);
+ PUSH(rhs);
+ nargs++;
+ }
+ PUSH(rhs);
+ }
- regex = POP(); /* the regex */
- regex = make_regnode(Node_regex, regex);
- PUSH(regex);
- PUSH(replace);
- return do_sub(nargs, flags);
+ unref(zero);
+ result = do_sub(nargs, flags);
+ if (flags != GENSUB)
+ reset_record();
+ return result;
}