diff --git a/include/types/pattern.h b/include/types/pattern.h index 811625e79..01fb69ca8 100644 --- a/include/types/pattern.h +++ b/include/types/pattern.h @@ -59,6 +59,9 @@ struct pattern_conv { union pattern_data *data); /* process function */ unsigned int in_type; /* input needed pattern type */ unsigned int out_type; /* output pattern type */ + int (*parse_args)(const char *arg_str, + void **arg_p, + int *arg_i); /* argument parser. Can be NULL. */ }; /* pattern conversion expression */ diff --git a/src/pattern.c b/src/pattern.c index a5cb31f3a..aef151a47 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -432,9 +432,18 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx) conv_expr->conv = conv; if (end != endw) { - conv_expr->arg_i = end - endw - 2; - conv_expr->arg_p = calloc(1, conv_expr->arg_i + 1); - memcpy(conv_expr->arg_p, endw + 1, conv_expr->arg_i); + int i = end - endw - 2; + char *p = my_strndup(endw + 1, i); + + if (conv->parse_args) { + i = conv->parse_args(p, &conv_expr->arg_p, &conv_expr->arg_i); + free(p); + if (!i) + goto out_error; + } else { + conv_expr->arg_i = i; + conv_expr->arg_p = p; + } } } return expr;