MINOR: cfgcond: support terms made of parenthesis around expressions
Now it's possible to form a term using parenthesis around an expression.
This will soon allow to build more complex expressions. For now they're
still pretty limited but parenthesis do work.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index a66350f..1b42a3c 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -811,6 +811,7 @@
- the integer zero ('0'), always returns "false"
- a non-nul integer (e.g. '1'), always returns "true".
- a predicate optionally followed by argument(s) in parenthesis.
+ - a condition placed between a pair of parenthesis '(' and ')'
- a question mark ('!') preceeding any of the non-empty elements above, and
which will negate its status.
- expressions combined with a logical AND ('&&'), which will be evaluated
@@ -861,7 +862,7 @@
.endif
.endif
- .if streq("$WITH_SSL",yes) && feature(OPENSSL)
+ .if feature(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes))
bind :443 ssl crt ...
.endif
diff --git a/include/haproxy/cfgcond-t.h b/include/haproxy/cfgcond-t.h
index f4f2796..bb19612 100644
--- a/include/haproxy/cfgcond-t.h
+++ b/include/haproxy/cfgcond-t.h
@@ -58,6 +58,7 @@
CCTT_FALSE,
CCTT_TRUE,
CCTT_PRED,
+ CCTT_PAREN, // '(' EXPR ')'
};
/* keyword for a condition predicate */
@@ -74,6 +75,7 @@
int neg; // 0: direct result; 1: negate
union {
const struct cond_pred_kw *pred; // predicate (function)
+ struct cfg_cond_expr *expr; // expression for CCTT_PAREN
};
};
diff --git a/src/cfgcond.c b/src/cfgcond.c
index a96832f..fd03196 100644
--- a/src/cfgcond.c
+++ b/src/cfgcond.c
@@ -51,6 +51,9 @@
if (!term || !*term)
return;
+ if ((*term)->type == CCTT_PAREN)
+ cfg_free_cond_expr(&(*term)->expr);
+
free_args((*term)->args);
free((*term)->args);
ha_free(term);
@@ -104,6 +107,32 @@
return 1;
}
+ /* Try to parse '(' EXPR ')' */
+ if (*in == '(') {
+ int ret;
+
+ t->type = CCTT_PAREN;
+ t->args = NULL;
+
+ do { in++; } while (*in == ' ' || *in == '\t');
+ ret = cfg_parse_cond_expr(&in, &t->expr, err, errptr);
+ if (ret == -1)
+ goto fail2;
+ if (ret == 0)
+ goto fail0;
+
+ /* find the closing ')' */
+ while (*in == ' ' || *in == '\t')
+ in++;
+ if (*in != ')') {
+ memprintf(err, "expected ')' after conditional expression '%s'", *text);
+ goto fail1;
+ }
+ do { in++; } while (*in == ' ' || *in == '\t');
+ *text = in;
+ return 1;
+ }
+
/* below we'll likely all make_arg_list() so we must return only via
* the <done> label which frees the arg list.
*/
@@ -123,6 +152,7 @@
return 1;
}
+ fail0:
memprintf(err, "unparsable conditional expression '%s'", *text);
fail1:
if (errptr)
@@ -196,6 +226,9 @@
break;
}
}
+ else if (term->type == CCTT_PAREN) {
+ ret = cfg_eval_cond_expr(term->expr, err);
+ }
else {
memprintf(err, "internal error: unhandled condition term type %d", (int)term->type);
}