This patch adds support for functions with variable arity and implements a version of regexp() with flags. Currently, only the 'i' flag is supported and makes regexp() case-insensitive.<br><br><br><div class="gmail_quote">
On Wed, Aug 1, 2012 at 12:19 AM, Raphaël Pinson <span dir="ltr"><<a href="mailto:raphael.pinson@camptocamp.com" target="_blank">raphael.pinson@camptocamp.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
src/pathx.c | 54 +++++++++++++++++++++++++++++++++++++++++++-----------<br>
1 file changed, 43 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/src/pathx.c b/src/pathx.c<br>
index c6aa4c4..2908223 100644<br>
--- a/src/pathx.c<br>
+++ b/src/pathx.c<br>
@@ -199,6 +199,7 @@ struct expr {<br>
char *ident; /* E_VAR */<br>
struct { /* E_APP */<br>
const struct func *func;<br>
+ unsigned int arity;<br>
struct expr **args;<br>
};<br>
};<br>
@@ -283,6 +284,7 @@ static void func_position(struct state *state);<br>
static void func_count(struct state *state);<br>
static void func_label(struct state *state);<br>
static void func_regexp(struct state *state);<br>
+static void func_regexp_flag(struct state *state);<br>
static void func_glob(struct state *state);<br>
static void func_int(struct state *state);<br>
<br>
@@ -290,6 +292,9 @@ static const enum type const arg_types_nodeset[] = { T_NODESET };<br>
static const enum type const arg_types_string[] = { T_STRING };<br>
static const enum type const arg_types_bool[] = { T_BOOLEAN };<br>
<br>
+static const enum type const arg_types_string_string[] = { T_STRING, T_STRING };<br>
+static const enum type const arg_types_nodeset_string[] = { T_STRING, T_STRING };<br>
+<br>
static const struct func builtin_funcs[] = {<br>
{ .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL,<br>
.impl = func_last },<br>
@@ -306,6 +311,12 @@ static const struct func builtin_funcs[] = {<br>
{ .name = "regexp", .arity = 1, .type = T_REGEXP,<br>
.arg_types = arg_types_nodeset,<br>
.impl = func_regexp },<br>
+ { .name = "regexp", .arity = 2, .type = T_REGEXP,<br>
+ .arg_types = arg_types_string_string,<br>
+ .impl = func_regexp_flag },<br>
+ { .name = "regexp", .arity = 2, .type = T_REGEXP,<br>
+ .arg_types = arg_types_nodeset_string,<br>
+ .impl = func_regexp_flag },<br>
{ .name = "glob", .arity = 1, .type = T_REGEXP,<br>
.arg_types = arg_types_string,<br>
.impl = func_glob },<br>
@@ -689,7 +700,7 @@ static void func_int(struct state *state) {<br>
}<br>
<br>
static struct regexp *<br>
-nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) {<br>
+nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob, int nocase) {<br>
struct regexp *result = NULL;<br>
struct regexp **rx = NULL;<br>
int used = 0;<br>
@@ -702,7 +713,7 @@ nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) {<br>
if (used == 0) {<br>
/* If the nodeset is empty, make sure we produce a regexp<br>
* that never matches anything */<br>
- result = make_regexp_unescape(info, "[^\001-\7ff]", 0);<br>
+ result = make_regexp_unescape(info, "[^\001-\7ff]", nocase);<br>
} else {<br>
if (ALLOC_N(rx, ns->used) < 0)<br>
goto error;<br>
@@ -729,7 +740,7 @@ nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) {<br>
return result;<br>
}<br>
<br>
-static void func_regexp_or_glob(struct state *state, int glob) {<br>
+static void func_regexp_or_glob(struct state *state, int glob, int nocase) {<br>
value_ind_t vind = make_value(T_REGEXP, state);<br>
int r;<br>
<br>
@@ -742,9 +753,9 @@ static void func_regexp_or_glob(struct state *state, int glob) {<br>
if (glob)<br>
rx = make_regexp_from_glob(state->error->info, v->string);<br>
else<br>
- rx = make_regexp_unescape(state->error->info, v->string, 0);<br>
+ rx = make_regexp_unescape(state->error->info, v->string, nocase);<br>
} else if (v->tag == T_NODESET) {<br>
- rx = nodeset_as_regexp(state->error->info, v->nodeset, glob);<br>
+ rx = nodeset_as_regexp(state->error->info, v->nodeset, glob, nocase);<br>
} else {<br>
assert(0);<br>
}<br>
@@ -767,11 +778,21 @@ static void func_regexp_or_glob(struct state *state, int glob) {<br>
}<br>
<br>
static void func_regexp(struct state *state) {<br>
- func_regexp_or_glob(state, 0);<br>
+ func_regexp_or_glob(state, 0, 0);<br>
+}<br>
+<br>
+static void func_regexp_flag(struct state *state) {<br>
+ int nocase = 0;<br>
+ struct value *f = pop_value(state);<br>
+<br>
+ if (STREQ("i", f->string))<br>
+ nocase = 1;<br>
+<br>
+ func_regexp_or_glob(state, 0, nocase);<br>
}<br>
<br>
static void func_glob(struct state *state) {<br>
- func_regexp_or_glob(state, 1);<br>
+ func_regexp_or_glob(state, 1, 0);<br>
}<br>
<br>
static bool coerce_to_bool(struct value *v) {<br>
@@ -1345,7 +1366,8 @@ static void check_app(struct expr *expr, struct state *state) {<br>
int f;<br>
for (f=0; f < ARRAY_CARDINALITY(builtin_funcs); f++) {<br>
const struct func *fn = builtin_funcs + f;<br>
- if (STRNEQ(expr->func->name, fn->name))<br>
+ if (STRNEQ(expr->func->name, fn->name) ||<br>
+ expr->arity != fn->arity)<br>
continue;<br>
<br>
int match = 1;<br>
@@ -1921,12 +1943,14 @@ static void parse_function_call(struct state *state) {<br>
const struct func *func = NULL;<br>
struct expr *expr = NULL;<br>
int nargs = 0;<br>
+ const char *func_name = NULL;<br>
<br>
for (int i=0; i < ARRAY_CARDINALITY(builtin_funcs); i++) {<br>
if (looking_at(state, builtin_funcs[i].name, "("))<br>
- func = builtin_funcs + i;<br>
+ func_name = builtin_funcs[i].name;<br>
}<br>
- if (func == NULL) {<br>
+<br>
+ if (func_name == NULL) {<br>
STATE_ERROR(state, PATHX_ENAME);<br>
return;<br>
}<br>
@@ -1944,7 +1968,14 @@ static void parse_function_call(struct state *state) {<br>
}<br>
}<br>
<br>
- if (nargs != func->arity) {<br>
+ for (int i=0; i < ARRAY_CARDINALITY(builtin_funcs); i++) {<br>
+ if (STREQ(func_name, builtin_funcs[i].name)<br>
+ && nargs == builtin_funcs[i].arity) {<br>
+ func = builtin_funcs + i;<br>
+ }<br>
+ }<br>
+<br>
+ if (func == NULL) {<br>
STATE_ERROR(state, PATHX_EARITY);<br>
return;<br>
}<br>
@@ -1960,6 +1991,7 @@ static void parse_function_call(struct state *state) {<br>
return;<br>
}<br>
expr->func = func;<br>
+ expr->arity = nargs;<br>
for (int i = nargs - 1; i >= 0; i--)<br>
expr->args[i] = pop_expr(state);<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
1.7.9.5<br>
<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Raphaël Pinson<br>Administrateur Systèmes & Réseaux<br>
Camptocamp France<br>
Savoie Technolac<br>
BP 352<br>
48, avenue du Lac du Bourget<br>
73372 Le Bourget du Lac, Cedex<br>
<a href="http://www.camptocamp.com" target="_blank">www.camptocamp.com</a><br>
<br>