summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2017-10-02 23:57:26 +0200
committerYann Ylavic <ylavic@apache.org>2017-10-02 23:57:26 +0200
commit08ddf7ad0a257c1b27b5fdb8e32fcd40b4dbdad1 (patch)
treee851b15724aa86321e5aaae317ec8fa6bacd127a /server
parentxforms (diff)
downloadapache2-08ddf7ad0a257c1b27b5fdb8e32fcd40b4dbdad1.tar.xz
apache2-08ddf7ad0a257c1b27b5fdb8e32fcd40b4dbdad1.zip
ap_expr: open string expressions to the <word>.
Introduces the syntax "%{:<word>:}", borrowed from the <var>'s one, and which likewise can be embedded anywhere in a string expression (the same reserved character ':' gets reused in an unambiguous manner). This allows the two types of expressions (boolean and string) to now share fully the same language set, namely: strings, lists, vars, regexes, backrefs, functions with multiple or complex arguments, and especially combinations thereof. Most of them were reserved to boolean expressions only, while complex string constructions can also benefit to, well, strings. The <word> construct allows that (say the syntax "%{:<word>:}" looks like a temporary variable constructed in a string). Since string expressions may now have to deal with lists (arrays), they also need a way to produce/extract strings from list and vice versa. This can be done with the new "join" and "split" operators, while the new substitution regexes (like "s/<pattern>/<substitute>/<flags>") may be used to manipulate strings in place. All this of course available for both string and boolean expressions. Tests and doc updates upcoming.. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1810605 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r--server/util_expr_eval.c426
-rw-r--r--server/util_expr_parse.c674
-rw-r--r--server/util_expr_parse.h65
-rw-r--r--server/util_expr_parse.y155
-rw-r--r--server/util_expr_private.h32
-rw-r--r--server/util_expr_scan.c1308
-rw-r--r--server/util_expr_scan.l552
-rw-r--r--server/util_pcre.c4
8 files changed, 2046 insertions, 1170 deletions
diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c
index 697bc4dcc0..8500fa26d9 100644
--- a/server/util_expr_eval.c
+++ b/server/util_expr_eval.c
@@ -27,6 +27,7 @@
#include "util_varbuf.h"
#include "util_expr_private.h"
#include "util_md5.h"
+#include "util_varbuf.h"
#include "apr_lib.h"
#include "apr_fnmatch.h"
@@ -54,6 +55,8 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms),
#define LOG_MARK(info) __FILE__, __LINE__, (info)->module_index
+static int ap_expr_eval_cond(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node);
+
static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
const ap_expr_t *info,
const ap_expr_t *args);
@@ -63,6 +66,19 @@ static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
ap_expr_var_func_t *func,
const void *data);
+typedef struct {
+ int type, flags;
+ const ap_expr_t *subst;
+} ap_expr_regctx_t;
+
+static const char *ap_expr_regexec(const char *subject,
+ const ap_expr_t *reg,
+ apr_array_header_t *list,
+ ap_expr_eval_ctx_t *ctx);
+
+static apr_array_header_t *ap_expr_list_make(ap_expr_eval_ctx_t *ctx,
+ const ap_expr_t *node);
+
/* define AP_EXPR_DEBUG to log the parse tree when parsing an expression */
#ifdef AP_EXPR_DEBUG
static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
@@ -71,7 +87,7 @@ static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
/*
* To reduce counting overhead, we only count calls to
- * ap_expr_eval_word() and ap_expr_eval(). The max number of
+ * ap_expr_eval_word() and ap_expr_eval_cond(). The max number of
* stack frames is larger by some factor.
*/
#define AP_EXPR_MAX_RECURSION 20
@@ -87,6 +103,37 @@ static int inc_rec(ap_expr_eval_ctx_t *ctx)
return 1;
}
+static const char *ap_expr_list_pstrcat(apr_pool_t *p,
+ const apr_array_header_t *list,
+ const char *sep)
+{
+ if (list->nelts <= 0) {
+ return NULL;
+ }
+ else if (list->nelts == 1) {
+ return APR_ARRAY_IDX(list, 0, const char*);
+ }
+ else {
+ struct ap_varbuf vb;
+ int n = list->nelts - 1, i;
+ apr_size_t slen = strlen(sep), vlen;
+ const char *val;
+
+ ap_varbuf_init(p, &vb, 0);
+ for (i = 0; i < n; ++i) {
+ val = APR_ARRAY_IDX(list, i, const char*);
+ vlen = strlen(val);
+ ap_varbuf_grow(&vb, vlen + slen + 1);
+ ap_varbuf_strmemcat(&vb, val, vlen);
+ ap_varbuf_strmemcat(&vb, sep, slen);
+ }
+ val = APR_ARRAY_IDX(list, n, const char*);
+ ap_varbuf_strmemcat(&vb, val, strlen(val));
+
+ return vb.buf;
+ }
+}
+
static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
const ap_expr_t *node)
{
@@ -98,6 +145,12 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
case op_String:
result = node->node_arg1;
break;
+ case op_Word:
+ result = ap_expr_eval_word(ctx, node->node_arg1);
+ break;
+ case op_Bool:
+ result = ap_expr_eval_cond(ctx, node->node_arg1) ? "true" : "false";
+ break;
case op_Var:
result = ap_expr_eval_var(ctx, (ap_expr_var_func_t *)node->node_arg1,
node->node_arg2);
@@ -168,7 +221,20 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
result = ap_expr_eval_string_func(ctx, info, args);
break;
}
- case op_RegexBackref: {
+ case op_Join: {
+ const char *sep;
+ apr_array_header_t *list = ap_expr_list_make(ctx, node->node_arg1);
+ sep = node->node_arg2 ? ap_expr_eval_word(ctx, node->node_arg2) : "";
+ result = ap_expr_list_pstrcat(ctx->p, list, sep);
+ break;
+ }
+ case op_Regsub: {
+ const ap_expr_t *reg = node->node_arg2;
+ const char *subject = ap_expr_eval_word(ctx, node->node_arg1);
+ result = ap_expr_regexec(subject, reg, NULL, ctx);
+ break;
+ }
+ case op_Regref: {
const unsigned int *np = node->node_arg1;
result = ap_expr_eval_re_backref(ctx, *np);
break;
@@ -219,15 +285,7 @@ static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
if (arg->node_op == op_ListElement) {
/* Evaluate the list elements and store them in apr_array_header. */
ap_expr_string_list_func_t *func = (ap_expr_string_list_func_t *)info->node_arg1;
- apr_array_header_t *args = apr_array_make(ctx->p, 2, sizeof(char *));
- do {
- const ap_expr_t *val = arg->node_arg1;
- const char **new = apr_array_push(args);
- *new = ap_expr_eval_word(ctx, val);
-
- arg = arg->node_arg2;
- } while (arg != NULL);
-
+ apr_array_header_t *args = ap_expr_list_make(ctx, arg->node_arg1);
return (*func)(ctx, data, args);
}
else {
@@ -249,6 +307,170 @@ static int intstrcmp(const char *s1, const char *s2)
return 1;
}
+static const char *ap_expr_regexec(const char *subject,
+ const ap_expr_t *reg,
+ apr_array_header_t *list,
+ ap_expr_eval_ctx_t *ctx)
+{
+ struct ap_varbuf vb;
+ const char *val = subject;
+ const ap_regex_t *regex = reg->node_arg1;
+ const ap_expr_regctx_t *regctx = reg->node_arg2;
+ ap_regmatch_t *pmatch = NULL, match0;
+ apr_size_t nmatch = 0;
+ const char *str = "";
+ apr_size_t len = 0;
+ int empty = 0, rv;
+
+ ap_varbuf_init(ctx->p, &vb, 0);
+ if (ctx->re_nmatch > 0) {
+ nmatch = ctx->re_nmatch;
+ pmatch = ctx->re_pmatch;
+ }
+ else if (regctx->type != 'm') {
+ nmatch = 1;
+ pmatch = &match0;
+ }
+ do {
+ /* If previous match was empty, we can't issue the exact same one or
+ * we'd loop indefinitively. So let's instead ask for an anchored and
+ * non-empty match (i.e. something not empty at the start of the value)
+ * and if nothing is found advance by one character below.
+ */
+ rv = ap_regexec(regex, val, nmatch, pmatch,
+ empty ? AP_REG_ANCHORED | AP_REG_NOTEMPTY : 0);
+ if (regctx->type == 'm') {
+ /* Simple match "m//", just return whether it matched (subject)
+ * or not (NULL)
+ */
+ return (rv == 0) ? subject : NULL;
+ }
+ if (rv == 0) {
+ /* Substitution "s//" or split "S//" matched.
+ * s// => replace $0 with evaluated regctx->subst
+ * S// => split at $0 (keeping evaluated regctx->subst if any)
+ */
+ int pos = pmatch[0].rm_so,
+ end = pmatch[0].rm_eo;
+ AP_DEBUG_ASSERT(pos >= 0 && pos <= end);
+
+ if (regctx->subst) {
+ *ctx->re_source = val;
+ str = ap_expr_eval_word(ctx, regctx->subst);
+ len = strlen(str);
+ }
+ /* Splitting makes sense into a given list only, if NULL we fall
+ * back into returning a s// string...
+ */
+ if (list) {
+ char *tmp = apr_palloc(ctx->p, pos + len + 1);
+ memcpy(tmp, val, pos);
+ memcpy(tmp + pos, str, len);
+ tmp[pos + len] = '\0';
+ APR_ARRAY_PUSH(list, const char*) = tmp;
+ }
+ else { /* regctx->type == 's' */
+ ap_varbuf_grow(&vb, pos + len + 1);
+ ap_varbuf_strmemcat(&vb, val, pos);
+ ap_varbuf_strmemcat(&vb, str, len);
+ if (!(regctx->flags & AP_REG_MULTI)) {
+ /* Single substitution, preserve remaining data */
+ ap_varbuf_strmemcat(&vb, val + end, strlen(val) - end);
+ break;
+ }
+ }
+ /* Note an empty match */
+ empty = (end == 0);
+ val += end;
+ }
+ else if (empty) {
+ /* Skip this non-matching character (or CRLF) and restart
+ * another "normal" match (possibly empty) from there.
+ */
+ if (val[0] == APR_ASCII_CR && val[1] == APR_ASCII_LF) {
+ val += 2;
+ }
+ else {
+ val++;
+ }
+ empty = 0;
+ }
+ else {
+ if (list) {
+ APR_ARRAY_PUSH(list, const char*) = val;
+ }
+ else if (vb.avail) {
+ ap_varbuf_strmemcat(&vb, val, strlen(val));
+ }
+ else {
+ return val;
+ }
+ break;
+ }
+ } while (*val);
+
+ return vb.buf;
+}
+
+static apr_array_header_t *ap_expr_list_make(ap_expr_eval_ctx_t *ctx,
+ const ap_expr_t *node)
+{
+ apr_array_header_t *list = NULL;
+
+ if (node->node_op == op_ListRegex) {
+ const ap_expr_t *arg = node->node_arg1;
+ const ap_expr_t *reg = node->node_arg2;
+ const ap_expr_regctx_t *regctx = reg->node_arg2;
+ const apr_array_header_t *source = ap_expr_list_make(ctx, arg);
+ int i;
+
+ list = apr_array_make(ctx->p, source->nelts, sizeof(const char*));
+ for (i = 0; i < source->nelts; ++i) {
+ const char *val = APR_ARRAY_IDX(source, i, const char*);
+ if (regctx->type == 'S') {
+ (void)ap_expr_regexec(val, reg, list, ctx);
+ }
+ else {
+ val = ap_expr_regexec(val, reg, NULL, ctx);
+ if (val) {
+ APR_ARRAY_PUSH(list, const char*) = val;
+ }
+ }
+ }
+ }
+ else if (node->node_op == op_ListElement) {
+ int n = 0;
+ const ap_expr_t *elem;
+ for (elem = node; elem; elem = elem->node_arg2) {
+ AP_DEBUG_ASSERT(elem->node_op == op_ListElement);
+ n++;
+ }
+
+ list = apr_array_make(ctx->p, n, sizeof(const char*));
+ for (elem = node; elem; elem = elem->node_arg2) {
+ APR_ARRAY_PUSH(list, const char*) =
+ ap_expr_eval_word(ctx, elem->node_arg1);
+ }
+ }
+ else if (node->node_op == op_ListFuncCall) {
+ const ap_expr_t *info = node->node_arg1;
+ ap_expr_list_func_t *func = info->node_arg1;
+
+ AP_DEBUG_ASSERT(func != NULL);
+ AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
+ list = (*func)(ctx, info->node_arg2,
+ ap_expr_eval_word(ctx, node->node_arg2));
+ }
+ else {
+ const char *subject = ap_expr_eval_word(ctx, node);
+
+ list = apr_array_make(ctx->p, 8, sizeof(const char*));
+ (void)ap_expr_regexec(subject, node->node_arg2, list, ctx);
+ }
+
+ return list;
+}
+
static int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
{
const ap_expr_t *e1 = node->node_arg1;
@@ -279,30 +501,17 @@ static int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
case op_STR_GE:
return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
case op_IN: {
- const char *needle = ap_expr_eval_word(ctx, e1);
- if (e2->node_op == op_ListElement) {
- do {
- const ap_expr_t *val = e2->node_arg1;
- AP_DEBUG_ASSERT(e2->node_op == op_ListElement);
- if (strcmp(needle, ap_expr_eval_word(ctx, val)) == 0)
+ int n;
+ const char *needle, *subject;
+ apr_array_header_t *haystack;
+ haystack = ap_expr_list_make(ctx, e2);
+ if (haystack) {
+ needle = ap_expr_eval_word(ctx, e1);
+ for (n = 0; n < haystack->nelts; ++n) {
+ subject = APR_ARRAY_IDX(haystack, n, const char*);
+ if (strcmp(needle, subject) == 0) {
return 1;
- e2 = e2->node_arg2;
- } while (e2 != NULL);
- }
- else if (e2->node_op == op_ListFuncCall) {
- const ap_expr_t *info = e2->node_arg1;
- const ap_expr_t *arg = e2->node_arg2;
- ap_expr_list_func_t *func = (ap_expr_list_func_t *)info->node_arg1;
- apr_array_header_t *haystack;
-
- AP_DEBUG_ASSERT(func != NULL);
- AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
- haystack = (*func)(ctx, info->node_arg2, ap_expr_eval_word(ctx, arg));
- if (haystack == NULL) {
- return 0;
- }
- if (ap_array_str_contains(haystack, needle)) {
- return 1;
+ }
}
}
return 0;
@@ -326,10 +535,7 @@ static int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
result = (0 == ap_regexec(regex, word, 0, NULL, 0));
}
- if (node->node_op == op_REG)
- return result;
- else
- return !result;
+ return result ^ (node->node_op == op_NRE);
}
default:
*ctx->err = "Internal evaluation error: Unknown comp expression node";
@@ -401,18 +607,13 @@ AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp,
ap_expr_parse_ctx_t ctx;
int rc;
+ memset(&ctx, 0, sizeof ctx);
ctx.pool = pool;
ctx.ptemp = ptemp;
ctx.inputbuf = expr;
ctx.inputlen = strlen(expr);
ctx.inputptr = ctx.inputbuf;
- ctx.expr = NULL;
- ctx.error = NULL; /* generic bison error message (XXX: usually not very useful, should be axed) */
- ctx.error2 = NULL; /* additional error message */
ctx.flags = info->flags;
- ctx.scan_del = '\0';
- ctx.scan_buf[0] = '\0';
- ctx.scan_ptr = ctx.scan_buf;
ctx.lookup_fn = lookup_fn ? lookup_fn : ap_expr_lookup_default;
ctx.at_start = 1;
@@ -420,6 +621,11 @@ AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp,
ap_expr_yyset_extra(&ctx, ctx.scanner);
rc = ap_expr_yyparse(&ctx);
ap_expr_yylex_destroy(ctx.scanner);
+
+ /* ctx.error: the generic bison error message
+ * (XXX: usually not very useful, should be axed)
+ * ctx.error2: an additional error message
+ */
if (ctx.error) {
if (ctx.error2)
return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2);
@@ -464,7 +670,7 @@ AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd_mi(const cmd_parms *cmd,
}
ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *a1, const void *a2,
- ap_expr_parse_ctx_t *ctx)
+ ap_expr_parse_ctx_t *ctx)
{
ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
node->node_op = op;
@@ -473,6 +679,100 @@ ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *a1, const void *a2,
return node;
}
+ap_expr_t *ap_expr_concat_make(const void *a1, const void *a2,
+ ap_expr_parse_ctx_t *ctx)
+{
+ const ap_expr_t *node;
+
+ /* Optimize out empty string(s) concatenation */
+ if ((node = a1)
+ && node->node_op == op_String
+ && !*(const char *)node->node_arg1) {
+ return (ap_expr_t *)a2;
+ }
+ if ((node = a2)
+ && node->node_op == op_String
+ && !*(const char *)node->node_arg1) {
+ return (ap_expr_t *)a1;
+ }
+
+ return ap_expr_make(op_Concat, a1, a2, ctx);
+}
+
+ap_expr_t *ap_expr_str_word_make(const ap_expr_t *arg,
+ ap_expr_parse_ctx_t *ctx)
+{
+ ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
+ node->node_op = op_Word;
+ node->node_arg1 = arg;
+ node->node_arg2 = NULL;
+ return node;
+}
+
+ap_expr_t *ap_expr_str_bool_make(const ap_expr_t *arg,
+ ap_expr_parse_ctx_t *ctx)
+{
+ ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
+ node->node_op = op_Bool;
+ node->node_arg1 = arg;
+ node->node_arg2 = NULL;
+ return node;
+}
+
+ap_expr_t *ap_expr_regex_make(const char *pattern, const char *flags,
+ const ap_expr_t *subst, int split,
+ ap_expr_parse_ctx_t *ctx)
+{
+ ap_expr_t *node = NULL;
+ ap_expr_regctx_t *regctx;
+ ap_regex_t *regex;
+
+ regctx = apr_palloc(ctx->pool, sizeof *regctx);
+ regctx->subst = subst;
+ regctx->flags = 0;
+ if (flags) {
+ for (; *flags; ++flags) {
+ switch (*flags) {
+ case 'i':
+ regctx->flags |= AP_REG_ICASE;
+ break;
+ case 'm':
+ regctx->flags |= AP_REG_NEWLINE;
+ break;
+ case 's':
+ regctx->flags |= AP_REG_DOTALL;
+ break;
+ case 'g':
+ regctx->flags |= AP_REG_MULTI;
+ break;
+ }
+ }
+ }
+ if (subst) {
+ if (split) {
+ regctx->type = 'S';
+ regctx->flags |= AP_REG_MULTI;
+ }
+ else {
+ regctx->type = 's';
+ }
+ }
+ else {
+ regctx->type = 'm';
+ }
+
+ regex = ap_pregcomp(ctx->pool, pattern, regctx->flags);
+ if (!regex) {
+ return NULL;
+ }
+
+ node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
+ node->node_op = op_Regex;
+ node->node_arg1 = regex;
+ node->node_arg2 = regctx;
+ return node;
+}
+
static ap_expr_t *ap_expr_info_make(int type, const char *name,
ap_expr_parse_ctx_t *ctx,
const ap_expr_t *arg)
@@ -533,6 +833,16 @@ ap_expr_t *ap_expr_list_func_make(const char *name, const ap_expr_t *arg,
return ap_expr_make(op_ListFuncCall, info, arg, ctx);
}
+ap_expr_t *ap_expr_list_regex_make(const ap_expr_t *arg, const ap_expr_t *reg,
+ ap_expr_parse_ctx_t *ctx)
+{
+ ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
+ node->node_op = op_ListRegex;
+ node->node_arg1 = arg;
+ node->node_arg2 = reg;
+ return node;
+}
+
ap_expr_t *ap_expr_unary_op_make(const char *name, const ap_expr_t *arg,
ap_expr_parse_ctx_t *ctx)
{
@@ -654,10 +964,15 @@ static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
case op_IN:
case op_REG:
case op_NRE:
+ case op_Word:
+ case op_Bool:
+ case op_Join:
+ case op_Regsub:
case op_Concat:
case op_StringFuncCall:
case op_ListFuncCall:
case op_ListElement:
+ case op_ListRegex:
{
char *name;
switch (e->node_op) {
@@ -680,10 +995,15 @@ static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
CASE_OP(op_IN);
CASE_OP(op_REG);
CASE_OP(op_NRE);
+ CASE_OP(op_Word);
+ CASE_OP(op_Bool);
+ CASE_OP(op_Join);
+ CASE_OP(op_Regsub);
CASE_OP(op_Concat);
CASE_OP(op_StringFuncCall);
CASE_OP(op_ListFuncCall);
CASE_OP(op_ListElement);
+ CASE_OP(op_ListRegex);
default:
ap_assert(0);
}
@@ -729,8 +1049,8 @@ static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
DUMP_P("op_Regex", e->node_arg1);
break;
/* arg1: pointer to int */
- case op_RegexBackref:
- DUMP_IP("op_RegexBackref", e->node_arg1);
+ case op_Regref:
+ DUMP_IP("op_Regref", e->node_arg1);
break;
default:
ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
@@ -769,7 +1089,7 @@ static int ap_expr_eval_binary_op(ap_expr_eval_ctx_t *ctx,
}
-static int ap_expr_eval(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
+static int ap_expr_eval_cond(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
{
const ap_expr_t *e1 = node->node_arg1;
const ap_expr_t *e2 = node->node_arg2;
@@ -791,13 +1111,13 @@ static int ap_expr_eval(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
case op_Or:
do {
if (e1->node_op == op_Not) {
- if (!ap_expr_eval(ctx, e1->node_arg1)) {
+ if (!ap_expr_eval_cond(ctx, e1->node_arg1)) {
result ^= TRUE;
goto out;
}
}
else {
- if (ap_expr_eval(ctx, e1)) {
+ if (ap_expr_eval_cond(ctx, e1)) {
result ^= TRUE;
goto out;
}
@@ -809,13 +1129,13 @@ static int ap_expr_eval(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
case op_And:
do {
if (e1->node_op == op_Not) {
- if (ap_expr_eval(ctx, e1->node_arg1)) {
+ if (ap_expr_eval_cond(ctx, e1->node_arg1)) {
result ^= FALSE;
goto out;
}
}
else {
- if (!ap_expr_eval(ctx, e1)) {
+ if (!ap_expr_eval_cond(ctx, e1)) {
result ^= FALSE;
goto out;
}
@@ -889,7 +1209,7 @@ AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx)
}
}
else {
- rc = ap_expr_eval(ctx, ctx->info->root_node);
+ rc = ap_expr_eval_cond(ctx, ctx->info->root_node);
if (*ctx->err != NULL) {
ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
APLOGNO(03299)
diff --git a/server/util_expr_parse.c b/server/util_expr_parse.c
index d5891c6f61..27b45dc336 100644
--- a/server/util_expr_parse.c
+++ b/server/util_expr_parse.c
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.7.1. */
/* Bison implementation for Yacc-like parsers in C
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.7.12-4996"
+#define YYBISON_VERSION "2.7.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -120,33 +120,40 @@ extern int ap_expr_yydebug;
T_ID = 264,
T_STRING = 265,
T_REGEX = 266,
- T_REGEX_I = 267,
- T_REGEX_BACKREF = 268,
- T_OP_UNARY = 269,
- T_OP_BINARY = 270,
- T_STR_BEGIN = 271,
- T_STR_END = 272,
- T_VAR_BEGIN = 273,
- T_VAR_END = 274,
- T_OP_EQ = 275,
- T_OP_NE = 276,
- T_OP_LT = 277,
- T_OP_LE = 278,
- T_OP_GT = 279,
- T_OP_GE = 280,
- T_OP_REG = 281,
- T_OP_NRE = 282,
- T_OP_IN = 283,
- T_OP_STR_EQ = 284,
- T_OP_STR_NE = 285,
- T_OP_STR_LT = 286,
- T_OP_STR_LE = 287,
- T_OP_STR_GT = 288,
- T_OP_STR_GE = 289,
- T_OP_CONCAT = 290,
- T_OP_OR = 291,
- T_OP_AND = 292,
- T_OP_NOT = 293
+ T_REGSUB = 267,
+ T_REG_MATCH = 268,
+ T_REG_SUBST = 269,
+ T_REG_FLAGS = 270,
+ T_REG_REF = 271,
+ T_OP_UNARY = 272,
+ T_OP_BINARY = 273,
+ T_STR_BEGIN = 274,
+ T_STR_END = 275,
+ T_VAR_BEGIN = 276,
+ T_VAR_END = 277,
+ T_VAREXP_BEGIN = 278,
+ T_VAREXP_END = 279,
+ T_OP_EQ = 280,
+ T_OP_NE = 281,
+ T_OP_LT = 282,
+ T_OP_LE = 283,
+ T_OP_GT = 284,
+ T_OP_GE = 285,
+ T_OP_REG = 286,
+ T_OP_NRE = 287,
+ T_OP_IN = 288,
+ T_OP_STR_EQ = 289,
+ T_OP_STR_NE = 290,
+ T_OP_STR_LT = 291,
+ T_OP_STR_LE = 292,
+ T_OP_STR_GT = 293,
+ T_OP_STR_GE = 294,
+ T_OP_CONCAT = 295,
+ T_OP_SPLIT = 296,
+ T_OP_JOIN = 297,
+ T_OP_OR = 298,
+ T_OP_AND = 299,
+ T_OP_NOT = 300
};
#endif
@@ -163,7 +170,7 @@ typedef union YYSTYPE
/* Line 387 of yacc.c */
-#line 167 "util_expr_parse.c"
+#line 174 "util_expr_parse.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -189,7 +196,7 @@ int ap_expr_yyparse ();
/* Copy the second part of user declarations. */
/* Line 390 of yacc.c */
-#line 102 "util_expr_parse.y"
+#line 116 "util_expr_parse.y"
#include "util_expr_private.h"
#define yyscanner ctx->scanner
@@ -197,7 +204,7 @@ int ap_expr_yyparse ();
int ap_expr_yylex(YYSTYPE *lvalp, void *scanner);
/* Line 390 of yacc.c */
-#line 201 "util_expr_parse.c"
+#line 208 "util_expr_parse.c"
#ifdef short
# undef short
@@ -424,22 +431,22 @@ union yyalloc
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 28
+#define YYFINAL 30
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 134
+#define YYLAST 300
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 50
+#define YYNTOKENS 66
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 14
+#define YYNNTS 17
/* YYNRULES -- Number of rules. */
-#define YYNRULES 54
+#define YYNRULES 68
/* YYNRULES -- Number of states. */
-#define YYNSTATES 98
+#define YYNSTATES 139
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 298
+#define YYMAXUTOK 314
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -451,15 +458,15 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 44, 45, 2, 2, 48, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 49, 2,
+ 60, 61, 2, 2, 64, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 65, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 46, 2, 47, 2, 2, 2, 2,
+ 2, 2, 2, 62, 2, 63, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -476,7 +483,9 @@ static const yytype_uint8 yytranslate[] =
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59
};
#if YYDEBUG
@@ -487,43 +496,51 @@ static const yytype_uint8 yyprhs[] =
0, 0, 3, 6, 9, 11, 13, 15, 18, 22,
26, 28, 31, 35, 39, 41, 45, 49, 53, 57,
61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
- 101, 103, 107, 109, 113, 116, 118, 120, 122, 124,
- 126, 130, 136, 138, 142, 144, 146, 148, 152, 155,
- 157, 159, 161, 166, 171
+ 101, 103, 107, 111, 115, 119, 121, 125, 127, 130,
+ 132, 134, 136, 138, 142, 148, 152, 156, 158, 161,
+ 165, 169, 173, 175, 177, 179, 182, 187, 194, 198,
+ 202, 207, 212, 214, 216, 218, 220, 225, 230
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 51, 0, -1, 5, 52, -1, 6, 56, -1, 7,
- -1, 3, -1, 4, -1, 38, 52, -1, 52, 36,
- 52, -1, 52, 37, 52, -1, 53, -1, 14, 59,
- -1, 59, 15, 59, -1, 44, 52, 45, -1, 7,
- -1, 59, 20, 59, -1, 59, 21, 59, -1, 59,
- 22, 59, -1, 59, 23, 59, -1, 59, 24, 59,
- -1, 59, 25, 59, -1, 59, 29, 59, -1, 59,
- 30, 59, -1, 59, 31, 59, -1, 59, 32, 59,
- -1, 59, 33, 59, -1, 59, 34, 59, -1, 59,
- 28, 54, -1, 59, 26, 60, -1, 59, 27, 60,
- -1, 62, -1, 46, 55, 47, -1, 59, -1, 55,
- 48, 59, -1, 56, 57, -1, 57, -1, 7, -1,
- 10, -1, 58, -1, 61, -1, 18, 9, 19, -1,
- 18, 9, 49, 56, 19, -1, 8, -1, 59, 35,
- 59, -1, 58, -1, 61, -1, 63, -1, 16, 56,
- 17, -1, 16, 17, -1, 11, -1, 12, -1, 13,
- -1, 9, 44, 59, 45, -1, 9, 44, 59, 45,
- -1, 9, 44, 55, 45, -1
+ 67, 0, -1, 5, 68, -1, 6, 72, -1, 7,
+ -1, 3, -1, 4, -1, 45, 68, -1, 68, 43,
+ 68, -1, 68, 44, 68, -1, 69, -1, 17, 75,
+ -1, 75, 18, 75, -1, 60, 68, 61, -1, 7,
+ -1, 75, 25, 75, -1, 75, 26, 75, -1, 75,
+ 27, 75, -1, 75, 28, 75, -1, 75, 29, 75,
+ -1, 75, 30, 75, -1, 75, 34, 75, -1, 75,
+ 35, 75, -1, 75, 36, 75, -1, 75, 37, 75,
+ -1, 75, 38, 75, -1, 75, 39, 75, -1, 75,
+ 33, 70, -1, 75, 31, 76, -1, 75, 32, 76,
+ -1, 81, -1, 75, 31, 78, -1, 70, 31, 79,
+ -1, 62, 71, 63, -1, 60, 70, 61, -1, 75,
+ -1, 75, 64, 71, -1, 73, -1, 72, 73, -1,
+ 7, -1, 10, -1, 74, -1, 80, -1, 21, 9,
+ 22, -1, 21, 9, 65, 72, 22, -1, 23, 75,
+ 24, -1, 23, 68, 24, -1, 8, -1, 19, 20,
+ -1, 19, 72, 20, -1, 75, 40, 75, -1, 75,
+ 31, 77, -1, 74, -1, 80, -1, 82, -1, 42,
+ 70, -1, 42, 70, 64, 75, -1, 42, 60, 70,
+ 64, 75, 61, -1, 60, 75, 61, -1, 11, 13,
+ 15, -1, 12, 13, 72, 15, -1, 41, 13, 72,
+ 15, -1, 76, -1, 77, -1, 78, -1, 16, -1,
+ 9, 60, 75, 61, -1, 9, 60, 75, 61, -1,
+ 9, 60, 71, 61, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint8 yyrline[] =
+static const yytype_uint16 yyrline[] =
{
- 0, 112, 112, 113, 114, 117, 118, 119, 120, 121,
- 122, 123, 124, 125, 126, 129, 130, 131, 132, 133,
- 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 146, 147, 150, 151, 154, 155, 156, 159, 160, 161,
- 164, 165, 168, 169, 170, 171, 172, 173, 174, 177,
- 186, 197, 204, 207, 208
+ 0, 126, 126, 127, 128, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 160, 161, 162, 163, 164, 167, 168, 171, 172, 173,
+ 176, 177, 178, 181, 182, 183, 184, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 198, 201, 204, 207,
+ 216, 225, 242, 243, 244, 247, 254, 258, 259
};
#endif
@@ -534,22 +551,30 @@ static const char *const yytname[] =
{
"$end", "error", "$undefined", "\"true\"", "\"false\"",
"\"boolean expression\"", "\"string expression\"", "\"error token\"",
- "\"number\"", "\"identifier\"", "\"cstring\"", "\"regex\"",
- "\"case-indendent regex\"", "\"regex back reference\"",
- "\"unary operator\"", "\"binary operator\"", "\"start of string\"",
- "\"end of string\"", "\"start of variable name\"",
- "\"end of variable name\"", "\"integer equal\"", "\"integer not equal\"",
- "\"integer less than\"", "\"integer less or equal\"",
- "\"integer greater than\"", "\"integer greater or equal\"",
- "\"regex match\"", "\"regex non-match\"", "\"contained in\"",
- "\"string equal\"", "\"string not equal\"", "\"string less than\"",
- "\"string less or equal\"", "\"string greater than\"",
- "\"string greater or equal\"", "\"string concatenation\"",
- "\"logical or\"", "\"logical and\"", "\"logical not\"", "\"function\"",
- "\"listfunction\"", "\"stringpart\"", "\"variable\"", "\"rebackref\"",
- "'('", "')'", "'{'", "'}'", "','", "':'", "$accept", "root", "expr",
- "comparison", "wordlist", "words", "string", "strpart", "var", "word",
- "regex", "backref", "lstfunccall", "strfunccall", YY_NULL
+ "\"number\"", "\"identifier\"", "\"string\"", "\"match regex\"",
+ "\"substitution regex\"", "\"match pattern of the regex\"",
+ "\"substitution pattern of the regex\"", "\"flags of the regex\"",
+ "\"regex back reference\"", "\"unary operator\"", "\"binary operator\"",
+ "\"start of string\"", "\"end of string\"", "\"start of variable name\"",
+ "\"end of variable name\"", "\"start of variable expression\"",
+ "\"end of variable expression\"", "\"integer equal\"",
+ "\"integer not equal\"", "\"integer less than\"",
+ "\"integer less or equal\"", "\"integer greater than\"",
+ "\"integer greater or equal\"", "\"regex match\"", "\"regex non-match\"",
+ "\"contained in\"", "\"string equal\"", "\"string not equal\"",
+ "\"string less than\"", "\"string less or equal\"",
+ "\"string greater than\"", "\"string greater or equal\"",
+ "\"string concatenation\"", "\"split operator\"", "\"join operator\"",
+ "\"logical or\"", "\"logical and\"", "\"logical not\"", "\"condition\"",
+ "\"comparison\"", "\"string function\"", "\"list function\"",
+ "\"list of words\"", "\"tuple of words\"", "\"word expression\"",
+ "\"any string expression\"", "\"variable expression\"",
+ "\"regular expression match\"", "\"regular expression substitution\"",
+ "\"regular expression split\"", "\"any regular expression\"",
+ "\"regular expression back reference\"", "'('", "')'", "'{'", "'}'",
+ "','", "':'", "$accept", "root", "cond", "comp", "wordlist", "words",
+ "string", "strany", "var", "word", "regex", "regsub", "regsplit",
+ "regany", "regref", "lstfunc", "strfunc", YY_NULL
};
#endif
@@ -562,19 +587,22 @@ static const yytype_uint16 yytoknum[] =
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 40, 41, 123, 125, 44, 58
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 40, 41, 123, 125, 44, 58
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 50, 51, 51, 51, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 54, 54, 55, 55, 56, 56, 56, 57, 57, 57,
- 58, 58, 59, 59, 59, 59, 59, 59, 59, 60,
- 60, 61, 62, 63, 63
+ 0, 66, 67, 67, 67, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 70, 70, 70, 70, 70, 71, 71, 72, 72, 72,
+ 73, 73, 73, 74, 74, 74, 74, 75, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 76,
+ 77, 78, 79, 79, 79, 80, 81, 82, 82
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -583,9 +611,10 @@ static const yytype_uint8 yyr2[] =
0, 2, 2, 2, 1, 1, 1, 2, 3, 3,
1, 2, 3, 3, 1, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 1, 3, 1, 3, 2, 1, 1, 1, 1, 1,
- 3, 5, 1, 3, 1, 1, 1, 3, 2, 1,
- 1, 1, 4, 4, 4
+ 1, 3, 3, 3, 3, 1, 3, 1, 2, 1,
+ 1, 1, 1, 3, 5, 3, 3, 1, 2, 3,
+ 3, 3, 1, 1, 1, 2, 4, 6, 3, 3,
+ 4, 4, 1, 1, 1, 1, 4, 4, 4
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -593,47 +622,55 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 0, 4, 0, 5, 6, 14, 42, 0,
- 51, 0, 0, 0, 0, 0, 2, 10, 44, 0,
- 45, 46, 36, 37, 3, 35, 38, 39, 1, 0,
- 11, 48, 0, 0, 7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 5, 6, 14, 47, 0,
+ 65, 0, 0, 0, 0, 0, 0, 0, 2, 10,
+ 52, 0, 53, 54, 39, 40, 3, 37, 41, 42,
+ 1, 0, 0, 11, 48, 0, 0, 0, 0, 0,
+ 0, 0, 55, 0, 30, 7, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 34, 0, 32, 47, 40,
- 0, 13, 8, 9, 12, 15, 16, 17, 18, 19,
- 20, 49, 50, 28, 29, 0, 0, 27, 30, 21,
- 22, 23, 24, 25, 26, 43, 54, 0, 53, 0,
- 0, 0, 32, 33, 41, 0, 31, 52
+ 0, 0, 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 49, 43, 0, 46, 45, 0, 0, 0,
+ 0, 0, 35, 0, 0, 0, 13, 58, 8, 9,
+ 12, 15, 16, 17, 18, 19, 20, 0, 0, 28,
+ 51, 29, 27, 21, 22, 23, 24, 25, 26, 50,
+ 68, 67, 0, 0, 0, 0, 34, 0, 33, 0,
+ 62, 63, 64, 32, 56, 31, 0, 0, 36, 44,
+ 66, 0, 0, 59, 0, 57, 0, 60, 61
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 4, 16, 17, 77, 56, 24, 25, 18, 19,
- 73, 20, 78, 21
+ -1, 4, 18, 19, 42, 68, 26, 27, 20, 21,
+ 99, 100, 122, 123, 22, 44, 23
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -41
-static const yytype_int8 yypact[] =
+#define YYPACT_NINF -46
+static const yytype_int16 yypact[] =
{
- 22, 48, 60, -41, 16, -41, -41, -41, -41, -24,
- -41, 102, 8, 32, 48, 48, -23, -41, -41, 74,
- -41, -41, -41, -41, 50, -41, -41, -41, -41, 102,
- -3, -41, 116, 23, -41, 87, 48, 48, 102, 102,
- 102, 102, 102, 102, 102, 68, 68, -6, 102, 102,
- 102, 102, 102, 102, 102, -41, -40, -28, -41, -41,
- 60, -41, -23, 28, -3, -3, -3, -3, -3, -3,
- -3, -41, -41, -41, -41, 30, 102, -41, -41, -3,
- -3, -3, -3, -3, -3, -3, -41, 102, -41, 103,
- 102, 36, -3, -3, -41, -26, -41, -41
+ 257, 136, 277, -46, 29, -46, -46, -46, -46, -29,
+ -46, 164, 216, 39, 136, 7, 136, 136, 27, -46,
+ -46, 243, -46, -46, -46, -46, 276, -46, -46, -46,
+ -46, 164, 164, -22, -46, 100, -18, 75, 220, 8,
+ 142, 164, -9, 19, -46, -46, 0, 182, 136, 136,
+ 164, 164, 164, 164, 164, 164, 164, 83, 47, 142,
+ 164, 164, 164, 164, 164, 164, 164, -46, 21, 107,
+ 1, 48, -46, -46, 277, -46, -46, 164, 142, 32,
+ 66, 37, -19, 42, 164, -6, -46, -46, 27, 57,
+ -22, -22, -22, -22, -22, -22, -22, 91, 92, -46,
+ -46, -46, 77, -22, -22, -22, -22, -22, -22, -22,
+ -46, -46, 164, 154, 129, -24, -46, 164, -46, 101,
+ -46, -46, -46, -46, -22, -46, 109, 277, -46, -46,
+ -46, 67, 277, -46, 176, -46, 219, -46, -46
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -41, -41, 39, -41, -41, 1, -10, -20, -2, -5,
- 35, -1, -41, -41
+ -46, -46, 3, -46, -32, -38, -10, -21, -2, 25,
+ -45, 46, 51, -46, -1, -46, -46
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -642,60 +679,98 @@ static const yytype_int8 yypgoto[] =
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
- 26, 27, 32, 75, 55, 86, 30, 54, 87, 54,
- 26, 27, 55, 36, 37, 22, 28, 88, 23, 97,
- 29, 10, 26, 27, 57, 31, 13, 1, 2, 3,
- 26, 27, 54, 64, 65, 66, 67, 68, 69, 70,
- 76, 33, 59, 79, 80, 81, 82, 83, 84, 85,
- 89, 5, 6, 34, 35, 7, 8, 9, 26, 27,
- 23, 10, 11, 10, 12, 37, 13, 22, 13, 55,
- 23, 92, 60, 10, 90, 62, 63, 91, 13, 71,
- 72, 74, 93, 96, 87, 95, 14, 26, 27, 38,
- 0, 0, 15, 0, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 8, 9, 0, 23, 0, 10, 10, 0, 12, 0,
- 13, 13, 94, 36, 37, 0, 23, 0, 0, 10,
- 0, 0, 61, 58, 13
+ 28, 29, 35, 81, 73, 67, 98, 83, 79, 71,
+ 28, 29, 71, 101, 67, 8, 39, 37, 66, 45,
+ 46, 66, 83, 10, 28, 29, 12, 102, 13, 30,
+ 14, 31, 71, 28, 29, 119, 33, 116, 120, 38,
+ 43, 66, 47, 48, 49, 112, 115, 74, 36, 15,
+ 85, 88, 89, 97, 98, 84, 69, 70, 97, 66,
+ 98, 86, 87, 83, 113, 80, 82, 40, 77, 41,
+ 48, 49, 28, 29, 128, 90, 91, 92, 93, 94,
+ 95, 96, 110, 119, 43, 103, 104, 105, 106, 107,
+ 108, 109, 67, 116, 97, 98, 117, 85, 71, 75,
+ 118, 49, 114, 80, 126, 127, 66, 66, 83, 124,
+ 25, 28, 29, 67, 132, 67, 10, 134, 48, 49,
+ 72, 13, 136, 14, 133, 28, 29, 87, 135, 121,
+ 28, 29, 28, 29, 28, 29, 125, 82, 71, 5,
+ 6, 0, 131, 7, 8, 9, 0, 66, 0, 0,
+ 8, 39, 10, 11, 0, 12, 0, 13, 10, 14,
+ 71, 12, 0, 13, 25, 14, 0, 0, 111, 66,
+ 10, 112, 8, 9, 0, 13, 129, 14, 15, 0,
+ 10, 16, 0, 12, 15, 13, 25, 14, 0, 0,
+ 130, 137, 10, 112, 0, 0, 17, 13, 0, 14,
+ 50, 0, 78, 0, 41, 0, 15, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 24, 32, 0, 25, 0, 0, 25,
+ 0, 0, 10, 0, 138, 10, 34, 13, 50, 14,
+ 13, 0, 14, 87, 76, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 50, 1, 2, 3, 0, 0, 0, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 24, 0, 25, 25, 0, 0,
+ 0, 0, 10, 10, 0, 0, 0, 13, 13, 14,
+ 14
};
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-41)))
+ (!!((Yystate) == (-46)))
#define yytable_value_is_error(Yytable_value) \
YYID (0)
-static const yytype_int8 yycheck[] =
+static const yytype_int16 yycheck[] =
{
- 2, 2, 12, 9, 24, 45, 11, 35, 48, 35,
- 12, 12, 32, 36, 37, 7, 0, 45, 10, 45,
- 44, 13, 24, 24, 29, 17, 18, 5, 6, 7,
- 32, 32, 35, 38, 39, 40, 41, 42, 43, 44,
- 46, 9, 19, 48, 49, 50, 51, 52, 53, 54,
- 60, 3, 4, 14, 15, 7, 8, 9, 60, 60,
- 10, 13, 14, 13, 16, 37, 18, 7, 18, 89,
- 10, 76, 49, 13, 44, 36, 37, 76, 18, 11,
- 12, 46, 87, 47, 48, 90, 38, 89, 89, 15,
- -1, -1, 44, -1, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 8, 9, -1, 10, -1, 13, 13, -1, 16, -1,
- 18, 18, 19, 36, 37, -1, 10, -1, -1, 13,
- -1, -1, 45, 17, 18
+ 2, 2, 12, 41, 22, 26, 12, 31, 40, 31,
+ 12, 12, 31, 58, 35, 8, 9, 14, 40, 16,
+ 17, 40, 31, 16, 26, 26, 19, 59, 21, 0,
+ 23, 60, 31, 35, 35, 41, 11, 61, 83, 14,
+ 15, 40, 17, 43, 44, 64, 78, 65, 9, 42,
+ 31, 48, 49, 11, 12, 64, 31, 32, 11, 40,
+ 12, 61, 61, 31, 74, 40, 41, 60, 60, 62,
+ 43, 44, 74, 74, 112, 50, 51, 52, 53, 54,
+ 55, 56, 61, 41, 59, 60, 61, 62, 63, 64,
+ 65, 66, 113, 61, 11, 12, 64, 31, 31, 24,
+ 63, 44, 77, 78, 13, 13, 40, 40, 31, 84,
+ 10, 113, 113, 134, 13, 136, 16, 127, 43, 44,
+ 20, 21, 132, 23, 15, 127, 127, 61, 61, 83,
+ 132, 132, 134, 134, 136, 136, 85, 112, 31, 3,
+ 4, -1, 117, 7, 8, 9, -1, 40, -1, -1,
+ 8, 9, 16, 17, -1, 19, -1, 21, 16, 23,
+ 31, 19, -1, 21, 10, 23, -1, -1, 61, 40,
+ 16, 64, 8, 9, -1, 21, 22, 23, 42, -1,
+ 16, 45, -1, 19, 42, 21, 10, 23, -1, -1,
+ 61, 15, 16, 64, -1, -1, 60, 21, -1, 23,
+ 18, -1, 60, -1, 62, -1, 42, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 7, 60, -1, 10, -1, -1, 10,
+ -1, -1, 16, -1, 15, 16, 20, 21, 18, 23,
+ 21, -1, 23, 61, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 18, 5, 6, 7, -1, -1, -1, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 7, -1, 10, 10, -1, -1,
+ -1, -1, 16, 16, -1, -1, -1, 21, 21, 23,
+ 23
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 5, 6, 7, 51, 3, 4, 7, 8, 9,
- 13, 14, 16, 18, 38, 44, 52, 53, 58, 59,
- 61, 63, 7, 10, 56, 57, 58, 61, 0, 44,
- 59, 17, 56, 9, 52, 52, 36, 37, 15, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 57, 55, 59, 17, 19,
- 49, 45, 52, 52, 59, 59, 59, 59, 59, 59,
- 59, 11, 12, 60, 60, 9, 46, 54, 62, 59,
- 59, 59, 59, 59, 59, 59, 45, 48, 45, 56,
- 44, 55, 59, 59, 19, 59, 47, 45
+ 0, 5, 6, 7, 67, 3, 4, 7, 8, 9,
+ 16, 17, 19, 21, 23, 42, 45, 60, 68, 69,
+ 74, 75, 80, 82, 7, 10, 72, 73, 74, 80,
+ 0, 60, 60, 75, 20, 72, 9, 68, 75, 9,
+ 60, 62, 70, 75, 81, 68, 68, 75, 43, 44,
+ 18, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 73, 71, 75,
+ 75, 31, 20, 22, 65, 24, 24, 60, 60, 70,
+ 75, 71, 75, 31, 64, 31, 61, 61, 68, 68,
+ 75, 75, 75, 75, 75, 75, 75, 11, 12, 76,
+ 77, 76, 70, 75, 75, 75, 75, 75, 75, 75,
+ 61, 61, 64, 72, 75, 70, 61, 64, 63, 41,
+ 76, 77, 78, 79, 75, 78, 13, 13, 71, 22,
+ 61, 75, 13, 15, 72, 61, 72, 15, 15
};
#define yyerrok (yyerrstatus = 0)
@@ -1507,345 +1582,448 @@ yyreduce:
{
case 2:
/* Line 1787 of yacc.c */
-#line 112 "util_expr_parse.y"
+#line 126 "util_expr_parse.y"
{ ctx->expr = (yyvsp[(2) - (2)].exVal); }
break;
case 3:
/* Line 1787 of yacc.c */
-#line 113 "util_expr_parse.y"
+#line 127 "util_expr_parse.y"
{ ctx->expr = (yyvsp[(2) - (2)].exVal); }
break;
case 4:
/* Line 1787 of yacc.c */
-#line 114 "util_expr_parse.y"
+#line 128 "util_expr_parse.y"
{ YYABORT; }
break;
case 5:
/* Line 1787 of yacc.c */
-#line 117 "util_expr_parse.y"
+#line 131 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_True, NULL, NULL, ctx); }
break;
case 6:
/* Line 1787 of yacc.c */
-#line 118 "util_expr_parse.y"
+#line 132 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_False, NULL, NULL, ctx); }
break;
case 7:
/* Line 1787 of yacc.c */
-#line 119 "util_expr_parse.y"
+#line 133 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_Not, (yyvsp[(2) - (2)].exVal), NULL, ctx); }
break;
case 8:
/* Line 1787 of yacc.c */
-#line 120 "util_expr_parse.y"
+#line 134 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_Or, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 9:
/* Line 1787 of yacc.c */
-#line 121 "util_expr_parse.y"
+#line 135 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_And, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 10:
/* Line 1787 of yacc.c */
-#line 122 "util_expr_parse.y"
+#line 136 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_Comp, (yyvsp[(1) - (1)].exVal), NULL, ctx); }
break;
case 11:
/* Line 1787 of yacc.c */
-#line 123 "util_expr_parse.y"
+#line 137 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_unary_op_make( (yyvsp[(1) - (2)].cpVal), (yyvsp[(2) - (2)].exVal), ctx); }
break;
case 12:
/* Line 1787 of yacc.c */
-#line 124 "util_expr_parse.y"
+#line 138 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_binary_op_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 13:
/* Line 1787 of yacc.c */
-#line 125 "util_expr_parse.y"
+#line 139 "util_expr_parse.y"
{ (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
break;
case 14:
/* Line 1787 of yacc.c */
-#line 126 "util_expr_parse.y"
+#line 140 "util_expr_parse.y"
{ YYABORT; }
break;
case 15:
/* Line 1787 of yacc.c */
-#line 129 "util_expr_parse.y"
+#line 143 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 16:
/* Line 1787 of yacc.c */
-#line 130 "util_expr_parse.y"
+#line 144 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 17:
/* Line 1787 of yacc.c */
-#line 131 "util_expr_parse.y"
+#line 145 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 18:
/* Line 1787 of yacc.c */
-#line 132 "util_expr_parse.y"
+#line 146 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 19:
/* Line 1787 of yacc.c */
-#line 133 "util_expr_parse.y"
+#line 147 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 20:
/* Line 1787 of yacc.c */
-#line 134 "util_expr_parse.y"
+#line 148 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 21:
/* Line 1787 of yacc.c */
-#line 135 "util_expr_parse.y"
+#line 149 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 22:
/* Line 1787 of yacc.c */
-#line 136 "util_expr_parse.y"
+#line 150 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 23:
/* Line 1787 of yacc.c */
-#line 137 "util_expr_parse.y"
+#line 151 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 24:
/* Line 1787 of yacc.c */
-#line 138 "util_expr_parse.y"
+#line 152 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 25:
/* Line 1787 of yacc.c */
-#line 139 "util_expr_parse.y"
+#line 153 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 26:
/* Line 1787 of yacc.c */
-#line 140 "util_expr_parse.y"
+#line 154 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_STR_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 27:
/* Line 1787 of yacc.c */
-#line 141 "util_expr_parse.y"
+#line 155 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_IN, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 28:
/* Line 1787 of yacc.c */
-#line 142 "util_expr_parse.y"
+#line 156 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_REG, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 29:
/* Line 1787 of yacc.c */
-#line 143 "util_expr_parse.y"
+#line 157 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_NRE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 30:
/* Line 1787 of yacc.c */
-#line 146 "util_expr_parse.y"
+#line 160 "util_expr_parse.y"
{ (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
break;
case 31:
/* Line 1787 of yacc.c */
-#line 147 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
+#line 161 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_list_regex_make((yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 32:
/* Line 1787 of yacc.c */
-#line 150 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); }
+#line 162 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_list_regex_make((yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 33:
/* Line 1787 of yacc.c */
-#line 151 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(3) - (3)].exVal), (yyvsp[(1) - (3)].exVal), ctx); }
+#line 163 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
break;
case 34:
/* Line 1787 of yacc.c */
-#line 154 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (2)].exVal), (yyvsp[(2) - (2)].exVal), ctx); }
+#line 164 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
break;
case 35:
/* Line 1787 of yacc.c */
-#line 155 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 167 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); }
break;
case 36:
/* Line 1787 of yacc.c */
-#line 156 "util_expr_parse.y"
- { YYABORT; }
+#line 168 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
break;
case 37:
/* Line 1787 of yacc.c */
-#line 159 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx); }
+#line 171 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
break;
case 38:
/* Line 1787 of yacc.c */
-#line 160 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 172 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_concat_make((yyvsp[(1) - (2)].exVal), (yyvsp[(2) - (2)].exVal), ctx); }
break;
case 39:
/* Line 1787 of yacc.c */
-#line 161 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 173 "util_expr_parse.y"
+ { YYABORT; }
break;
case 40:
/* Line 1787 of yacc.c */
-#line 164 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); }
+#line 176 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx); }
break;
case 41:
/* Line 1787 of yacc.c */
-#line 165 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); }
+#line 177 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
break;
case 42:
/* Line 1787 of yacc.c */
-#line 168 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, ctx); }
+#line 178 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
break;
case 43:
/* Line 1787 of yacc.c */
-#line 169 "util_expr_parse.y"
- { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
+#line 181 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); }
break;
case 44:
/* Line 1787 of yacc.c */
-#line 170 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 182 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); }
break;
case 45:
/* Line 1787 of yacc.c */
-#line 171 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 183 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_str_word_make((yyvsp[(2) - (3)].exVal), ctx); }
break;
case 46:
/* Line 1787 of yacc.c */
-#line 172 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+#line 184 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_str_bool_make((yyvsp[(2) - (3)].exVal), ctx); }
break;
case 47:
/* Line 1787 of yacc.c */
-#line 173 "util_expr_parse.y"
- { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
+#line 187 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, ctx); }
break;
case 48:
/* Line 1787 of yacc.c */
-#line 174 "util_expr_parse.y"
+#line 188 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); }
break;
case 49:
/* Line 1787 of yacc.c */
-#line 177 "util_expr_parse.y"
+#line 189 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
+ break;
+
+ case 50:
+/* Line 1787 of yacc.c */
+#line 190 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
+ break;
+
+ case 51:
+/* Line 1787 of yacc.c */
+#line 191 "util_expr_parse.y"
+ { (yyval.exVal) = ap_expr_make(op_Regsub, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); }
+ break;
+
+ case 52:
+/* Line 1787 of yacc.c */
+#line 192 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 53:
+/* Line 1787 of yacc.c */
+#line 193 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 54:
+/* Line 1787 of yacc.c */
+#line 194 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 55:
+/* Line 1787 of yacc.c */
+#line 195 "util_expr_parse.y"
+ {
+ (yyval.exVal) = ap_expr_make(op_Join, (yyvsp[(2) - (2)].exVal), NULL, ctx);
+ }
+ break;
+
+ case 56:
+/* Line 1787 of yacc.c */
+#line 198 "util_expr_parse.y"
{
- ap_regex_t *regex;
- if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal),
- AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) {
+ (yyval.exVal) = ap_expr_make(op_Join, (yyvsp[(2) - (4)].exVal), (yyvsp[(4) - (4)].exVal), ctx);
+ }
+ break;
+
+ case 57:
+/* Line 1787 of yacc.c */
+#line 201 "util_expr_parse.y"
+ {
+ (yyval.exVal) = ap_expr_make(op_Join, (yyvsp[(3) - (6)].exVal), (yyvsp[(5) - (6)].exVal), ctx);
+ }
+ break;
+
+ case 58:
+/* Line 1787 of yacc.c */
+#line 204 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); }
+ break;
+
+ case 59:
+/* Line 1787 of yacc.c */
+#line 207 "util_expr_parse.y"
+ {
+ ap_expr_t *e = ap_expr_regex_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(3) - (3)].cpVal), NULL, 0, ctx);
+ if (!e) {
ctx->error = "Failed to compile regular expression";
YYERROR;
}
- (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx);
+ (yyval.exVal) = e;
}
break;
- case 50:
+ case 60:
/* Line 1787 of yacc.c */
-#line 186 "util_expr_parse.y"
+#line 216 "util_expr_parse.y"
{
- ap_regex_t *regex;
- if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal),
- AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) {
+ ap_expr_t *e = ap_expr_regex_make((yyvsp[(2) - (4)].cpVal), (yyvsp[(4) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), 0, ctx);
+ if (!e) {
ctx->error = "Failed to compile regular expression";
YYERROR;
}
- (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx);
+ (yyval.exVal) = e;
}
break;
- case 51:
+ case 61:
/* Line 1787 of yacc.c */
-#line 197 "util_expr_parse.y"
+#line 225 "util_expr_parse.y"
+ {
+ /* Returns a list:
+ * <word> ~= split/://
+ * => split around ':', replace it with empty
+ * <word> ~= split/:/\n/
+ * => split around ':', replace it with '\n'
+ * <list> ~= split/.*?Ip Address:([^,]+)/$1/
+ * => split around the whole match, replace it with $1
+ */
+ ap_expr_t *e = ap_expr_regex_make((yyvsp[(2) - (4)].cpVal), (yyvsp[(4) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), 1, ctx);
+ if (!e) {
+ ctx->error = "Failed to compile regular expression";
+ YYERROR;
+ }
+ (yyval.exVal) = e;
+ }
+ break;
+
+ case 62:
+/* Line 1787 of yacc.c */
+#line 242 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 63:
+/* Line 1787 of yacc.c */
+#line 243 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 64:
+/* Line 1787 of yacc.c */
+#line 244 "util_expr_parse.y"
+ { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); }
+ break;
+
+ case 65:
+/* Line 1787 of yacc.c */
+#line 247 "util_expr_parse.y"
{
int *n = apr_palloc(ctx->pool, sizeof(int));
*n = (yyvsp[(1) - (1)].num);
- (yyval.exVal) = ap_expr_make(op_RegexBackref, n, NULL, ctx);
+ (yyval.exVal) = ap_expr_make(op_Regref, n, NULL, ctx);
}
break;
- case 52:
+ case 66:
/* Line 1787 of yacc.c */
-#line 204 "util_expr_parse.y"
+#line 254 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); }
break;
- case 53:
+ case 67:
/* Line 1787 of yacc.c */
-#line 207 "util_expr_parse.y"
+#line 258 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); }
break;
- case 54:
+ case 68:
/* Line 1787 of yacc.c */
-#line 208 "util_expr_parse.y"
+#line 259 "util_expr_parse.y"
{ (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); }
break;
/* Line 1787 of yacc.c */
-#line 1849 "util_expr_parse.c"
+#line 2027 "util_expr_parse.c"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -2077,7 +2255,7 @@ yyreturn:
/* Line 2050 of yacc.c */
-#line 211 "util_expr_parse.y"
+#line 262 "util_expr_parse.y"
void yyerror(ap_expr_parse_ctx_t *ctx, const char *s)
diff --git a/server/util_expr_parse.h b/server/util_expr_parse.h
index 21b0ffba56..3f9ee26377 100644
--- a/server/util_expr_parse.h
+++ b/server/util_expr_parse.h
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.7.1. */
/* Bison interface for Yacc-like parsers in C
@@ -55,33 +55,40 @@ extern int ap_expr_yydebug;
T_ID = 264,
T_STRING = 265,
T_REGEX = 266,
- T_REGEX_I = 267,
- T_REGEX_BACKREF = 268,
- T_OP_UNARY = 269,
- T_OP_BINARY = 270,
- T_STR_BEGIN = 271,
- T_STR_END = 272,
- T_VAR_BEGIN = 273,
- T_VAR_END = 274,
- T_OP_EQ = 275,
- T_OP_NE = 276,
- T_OP_LT = 277,
- T_OP_LE = 278,
- T_OP_GT = 279,
- T_OP_GE = 280,
- T_OP_REG = 281,
- T_OP_NRE = 282,
- T_OP_IN = 283,
- T_OP_STR_EQ = 284,
- T_OP_STR_NE = 285,
- T_OP_STR_LT = 286,
- T_OP_STR_LE = 287,
- T_OP_STR_GT = 288,
- T_OP_STR_GE = 289,
- T_OP_CONCAT = 290,
- T_OP_OR = 291,
- T_OP_AND = 292,
- T_OP_NOT = 293
+ T_REGSUB = 267,
+ T_REG_MATCH = 268,
+ T_REG_SUBST = 269,
+ T_REG_FLAGS = 270,
+ T_REG_REF = 271,
+ T_OP_UNARY = 272,
+ T_OP_BINARY = 273,
+ T_STR_BEGIN = 274,
+ T_STR_END = 275,
+ T_VAR_BEGIN = 276,
+ T_VAR_END = 277,
+ T_VAREXP_BEGIN = 278,
+ T_VAREXP_END = 279,
+ T_OP_EQ = 280,
+ T_OP_NE = 281,
+ T_OP_LT = 282,
+ T_OP_LE = 283,
+ T_OP_GT = 284,
+ T_OP_GE = 285,
+ T_OP_REG = 286,
+ T_OP_NRE = 287,
+ T_OP_IN = 288,
+ T_OP_STR_EQ = 289,
+ T_OP_STR_NE = 290,
+ T_OP_STR_LT = 291,
+ T_OP_STR_LE = 292,
+ T_OP_STR_GT = 293,
+ T_OP_STR_GE = 294,
+ T_OP_CONCAT = 295,
+ T_OP_SPLIT = 296,
+ T_OP_JOIN = 297,
+ T_OP_OR = 298,
+ T_OP_AND = 299,
+ T_OP_NOT = 300
};
#endif
@@ -98,7 +105,7 @@ typedef union YYSTYPE
/* Line 2053 of yacc.c */
-#line 102 "util_expr_parse.h"
+#line 109 "util_expr_parse.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/server/util_expr_parse.y b/server/util_expr_parse.y
index 9e02602139..ce1d6188df 100644
--- a/server/util_expr_parse.y
+++ b/server/util_expr_parse.y
@@ -48,10 +48,15 @@
%token <cpVal> T_DIGIT "number"
%token <cpVal> T_ID "identifier"
-%token <cpVal> T_STRING "cstring"
-%token <cpVal> T_REGEX "regex"
-%token <cpVal> T_REGEX_I "case-indendent regex"
-%token <num> T_REGEX_BACKREF "regex back reference"
+%token <cpVal> T_STRING "string"
+
+%token T_REGEX "match regex"
+%token T_REGSUB "substitution regex"
+%token <cpVal> T_REG_MATCH "match pattern of the regex"
+%token <cpVal> T_REG_SUBST "substitution pattern of the regex"
+%token <cpVal> T_REG_FLAGS "flags of the regex"
+%token <num> T_REG_REF "regex back reference"
+
%token <cpVal> T_OP_UNARY "unary operator"
%token <cpVal> T_OP_BINARY "binary operator"
@@ -59,6 +64,8 @@
%token T_STR_END "end of string"
%token T_VAR_BEGIN "start of variable name"
%token T_VAR_END "end of variable name"
+%token T_VAREXP_BEGIN "start of variable expression"
+%token T_VAREXP_END "end of variable expression"
%token T_OP_EQ "integer equal"
%token T_OP_NE "integer not equal"
@@ -75,8 +82,12 @@
%token T_OP_STR_LE "string less or equal"
%token T_OP_STR_GT "string greater than"
%token T_OP_STR_GE "string greater or equal"
+
%token T_OP_CONCAT "string concatenation"
+%token T_OP_SPLIT "split operator"
+%token T_OP_JOIN "join operator"
+
%token T_OP_OR "logical or"
%token T_OP_AND "logical and"
%token T_OP_NOT "logical not"
@@ -86,18 +97,21 @@
%right T_OP_NOT
%right T_OP_CONCAT
-%type <exVal> expr
-%type <exVal> comparison
-%type <exVal> strfunccall "function"
-%type <exVal> lstfunccall "listfunction"
-%type <exVal> regex
-%type <exVal> words
-%type <exVal> wordlist
-%type <exVal> word
-%type <exVal> string
-%type <exVal> strpart "stringpart"
-%type <exVal> var "variable"
-%type <exVal> backref "rebackref"
+%type <exVal> cond "condition"
+%type <exVal> comp "comparison"
+%type <exVal> strfunc "string function"
+%type <exVal> lstfunc "list function"
+%type <exVal> wordlist "list of words"
+%type <exVal> words "tuple of words"
+%type <exVal> word "word expression"
+%type <exVal> string "string expression"
+%type <exVal> strany "any string expression"
+%type <exVal> var "variable expression"
+%type <exVal> regex "regular expression match"
+%type <exVal> regsub "regular expression substitution"
+%type <exVal> regsplit "regular expression split"
+%type <exVal> regany "any regular expression"
+%type <exVal> regref "regular expression back reference"
%{
#include "util_expr_private.h"
@@ -109,24 +123,24 @@ int ap_expr_yylex(YYSTYPE *lvalp, void *scanner);
%%
-root : T_EXPR_BOOL expr { ctx->expr = $2; }
+root : T_EXPR_BOOL cond { ctx->expr = $2; }
| T_EXPR_STRING string { ctx->expr = $2; }
| T_ERROR { YYABORT; }
;
-expr : T_TRUE { $$ = ap_expr_make(op_True, NULL, NULL, ctx); }
+cond : T_TRUE { $$ = ap_expr_make(op_True, NULL, NULL, ctx); }
| T_FALSE { $$ = ap_expr_make(op_False, NULL, NULL, ctx); }
- | T_OP_NOT expr { $$ = ap_expr_make(op_Not, $2, NULL, ctx); }
- | expr T_OP_OR expr { $$ = ap_expr_make(op_Or, $1, $3, ctx); }
- | expr T_OP_AND expr { $$ = ap_expr_make(op_And, $1, $3, ctx); }
- | comparison { $$ = ap_expr_make(op_Comp, $1, NULL, ctx); }
+ | T_OP_NOT cond { $$ = ap_expr_make(op_Not, $2, NULL, ctx); }
+ | cond T_OP_OR cond { $$ = ap_expr_make(op_Or, $1, $3, ctx); }
+ | cond T_OP_AND cond { $$ = ap_expr_make(op_And, $1, $3, ctx); }
+ | comp { $$ = ap_expr_make(op_Comp, $1, NULL, ctx); }
| T_OP_UNARY word { $$ = ap_expr_unary_op_make( $1, $2, ctx); }
| word T_OP_BINARY word { $$ = ap_expr_binary_op_make($2, $1, $3, ctx); }
- | '(' expr ')' { $$ = $2; }
+ | '(' cond ')' { $$ = $2; }
| T_ERROR { YYABORT; }
;
-comparison: word T_OP_EQ word { $$ = ap_expr_make(op_EQ, $1, $3, ctx); }
+comp : word T_OP_EQ word { $$ = ap_expr_make(op_EQ, $1, $3, ctx); }
| word T_OP_NE word { $$ = ap_expr_make(op_NE, $1, $3, ctx); }
| word T_OP_LT word { $$ = ap_expr_make(op_LT, $1, $3, ctx); }
| word T_OP_LE word { $$ = ap_expr_make(op_LE, $1, $3, ctx); }
@@ -143,70 +157,107 @@ comparison: word T_OP_EQ word { $$ = ap_expr_make(op_EQ, $1, $3,
| word T_OP_NRE regex { $$ = ap_expr_make(op_NRE, $1, $3, ctx); }
;
-wordlist : lstfunccall { $$ = $1; }
+wordlist : lstfunc { $$ = $1; }
+ | word T_OP_REG regsplit { $$ = ap_expr_list_regex_make($1, $3, ctx); }
+ | wordlist T_OP_REG regany { $$ = ap_expr_list_regex_make($1, $3, ctx); }
| '{' words '}' { $$ = $2; }
+ | '(' wordlist ')' { $$ = $2; }
;
words : word { $$ = ap_expr_make(op_ListElement, $1, NULL, ctx); }
- | words ',' word { $$ = ap_expr_make(op_ListElement, $3, $1, ctx); }
+ | word ',' words { $$ = ap_expr_make(op_ListElement, $1, $3, ctx); }
;
-string : string strpart { $$ = ap_expr_make(op_Concat, $1, $2, ctx); }
- | strpart { $$ = $1; }
+string : strany { $$ = $1; }
+ | string strany { $$ = ap_expr_concat_make($1, $2, ctx); }
| T_ERROR { YYABORT; }
;
-strpart : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); }
+strany : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); }
| var { $$ = $1; }
- | backref { $$ = $1; }
+ | regref { $$ = $1; }
;
var : T_VAR_BEGIN T_ID T_VAR_END { $$ = ap_expr_var_make($2, ctx); }
| T_VAR_BEGIN T_ID ':' string T_VAR_END { $$ = ap_expr_str_func_make($2, $4, ctx); }
+ | T_VAREXP_BEGIN word T_VAREXP_END { $$ = ap_expr_str_word_make($2, ctx); }
+ | T_VAREXP_BEGIN cond T_VAREXP_END { $$ = ap_expr_str_bool_make($2, ctx); }
;
word : T_DIGIT { $$ = ap_expr_make(op_Digit, $1, NULL, ctx); }
+ | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, ctx); }
+ | T_STR_BEGIN string T_STR_END { $$ = $2; }
| word T_OP_CONCAT word { $$ = ap_expr_make(op_Concat, $1, $3, ctx); }
+ | word T_OP_REG regsub { $$ = ap_expr_make(op_Regsub, $1, $3, ctx); }
| var { $$ = $1; }
- | backref { $$ = $1; }
- | strfunccall { $$ = $1; }
- | T_STR_BEGIN string T_STR_END { $$ = $2; }
- | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, ctx); }
+ | regref { $$ = $1; }
+ | strfunc { $$ = $1; }
+ | T_OP_JOIN wordlist {
+ $$ = ap_expr_make(op_Join, $2, NULL, ctx);
+ }
+ | T_OP_JOIN wordlist ',' word {
+ $$ = ap_expr_make(op_Join, $2, $4, ctx);
+ }
+ | T_OP_JOIN '(' wordlist ',' word ')' {
+ $$ = ap_expr_make(op_Join, $3, $5, ctx);
+ }
+ | '(' word ')' { $$ = $2; }
;
-regex : T_REGEX {
- ap_regex_t *regex;
- if ((regex = ap_pregcomp(ctx->pool, $1,
- AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) {
+regex : T_REGEX T_REG_MATCH T_REG_FLAGS {
+ ap_expr_t *e = ap_expr_regex_make($2, $3, NULL, 0, ctx);
+ if (!e) {
ctx->error = "Failed to compile regular expression";
YYERROR;
}
- $$ = ap_expr_make(op_Regex, regex, NULL, ctx);
+ $$ = e;
}
- | T_REGEX_I {
- ap_regex_t *regex;
- if ((regex = ap_pregcomp(ctx->pool, $1,
- AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) {
+ ;
+regsub : T_REGSUB T_REG_MATCH string T_REG_FLAGS {
+ ap_expr_t *e = ap_expr_regex_make($2, $4, $3, 0, ctx);
+ if (!e) {
+ ctx->error = "Failed to compile regular expression";
+ YYERROR;
+ }
+ $$ = e;
+ }
+ ;
+regsplit : T_OP_SPLIT T_REG_MATCH string T_REG_FLAGS {
+ /* Returns a list:
+ * <word> ~= split/://
+ * => split around ':', replace it with empty
+ * <word> ~= split/:/\n/
+ * => split around ':', replace it with '\n'
+ * <list> ~= split/.*?Ip Address:([^,]+)/$1/
+ * => split around the whole match, replace it with $1
+ */
+ ap_expr_t *e = ap_expr_regex_make($2, $4, $3, 1, ctx);
+ if (!e) {
ctx->error = "Failed to compile regular expression";
YYERROR;
}
- $$ = ap_expr_make(op_Regex, regex, NULL, ctx);
+ $$ = e;
}
;
+regany : regex { $$ = $1; }
+ | regsub { $$ = $1; }
+ | regsplit { $$ = $1; }
+ ;
-backref : T_REGEX_BACKREF {
+regref : T_REG_REF {
int *n = apr_palloc(ctx->pool, sizeof(int));
*n = $1;
- $$ = ap_expr_make(op_RegexBackref, n, NULL, ctx);
+ $$ = ap_expr_make(op_Regref, n, NULL, ctx);
}
- ;
+ ;
-lstfunccall : T_ID '(' word ')' { $$ = ap_expr_list_func_make($1, $3, ctx); }
- ;
+lstfunc : T_ID '(' word ')' { $$ = ap_expr_list_func_make($1, $3, ctx); }
+ /* | T_ID '(' words ')' { $$ = ap_expr_list_func_make($1, $3, ctx); } */
+ ;
-strfunccall : T_ID '(' word ')' { $$ = ap_expr_str_func_make($1, $3, ctx); }
- | T_ID '(' words ')' { $$ = ap_expr_str_func_make($1, $3, ctx); }
- ;
+strfunc : T_ID '(' word ')' { $$ = ap_expr_str_func_make($1, $3, ctx); }
+ | T_ID '(' words ')' { $$ = ap_expr_str_func_make($1, $3, ctx); }
+ ;
%%
diff --git a/server/util_expr_private.h b/server/util_expr_private.h
index 14cc4e3ccc..b0fcacefef 100644
--- a/server/util_expr_private.h
+++ b/server/util_expr_private.h
@@ -54,9 +54,10 @@ typedef enum {
op_REG, op_NRE,
op_STR_EQ, op_STR_NE, op_STR_LT, op_STR_LE, op_STR_GT, op_STR_GE,
op_Concat,
- op_Digit, op_String, op_Regex, op_RegexBackref,
- op_Var,
- op_ListElement,
+ op_Digit, op_String,
+ op_Var, op_Word, op_Bool, op_Join,
+ op_Regex, op_Regsub, op_Regref,
+ op_ListElement, op_ListRegex,
/*
* call external functions/operators.
* The info node contains the function pointer and some function specific
@@ -79,6 +80,15 @@ struct ap_expr_node {
const void *node_arg2;
};
+/** The stack used by scanner and parser */
+typedef struct ap_expr_parser_stack {
+ char *scan_ptr;
+ char scan_buf[MAX_STRING_LEN];
+ int scan_stop;
+ int scan_flag;
+ struct ap_expr_parser_stack *next;
+} ap_expr_parser_stack_t;
+
/** The context used by scanner and parser */
typedef struct {
/* internal state of the scanner */
@@ -86,9 +96,8 @@ typedef struct {
int inputlen;
const char *inputptr;
void *scanner;
- char *scan_ptr;
- char scan_buf[MAX_STRING_LEN];
- char scan_del;
+ ap_expr_parser_stack_t *current,
+ *spares;
int at_start;
/* pools for result and temporary usage */
@@ -119,12 +128,23 @@ void ap_expr_yyset_extra(ap_expr_parse_ctx_t *context, void *scanner);
/* create a parse tree node */
ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *arg1,
const void *arg2, ap_expr_parse_ctx_t *ctx);
+ap_expr_t *ap_expr_concat_make(const void *a1, const void *a2,
+ ap_expr_parse_ctx_t *ctx);
+ap_expr_t *ap_expr_str_word_make(const ap_expr_t *arg,
+ ap_expr_parse_ctx_t *ctx);
+ap_expr_t *ap_expr_str_bool_make(const ap_expr_t *arg,
+ ap_expr_parse_ctx_t *ctx);
+ap_expr_t *ap_expr_regex_make(const char *pattern, const char *flags,
+ const ap_expr_t *subst, int split,
+ ap_expr_parse_ctx_t *ctx);
/* create parse tree node for the string-returning function 'name' */
ap_expr_t *ap_expr_str_func_make(const char *name, const ap_expr_t *arg,
ap_expr_parse_ctx_t *ctx);
/* create parse tree node for the list-returning function 'name' */
ap_expr_t *ap_expr_list_func_make(const char *name, const ap_expr_t *arg,
ap_expr_parse_ctx_t *ctx);
+ap_expr_t *ap_expr_list_regex_make(const ap_expr_t *lst, const ap_expr_t *re,
+ ap_expr_parse_ctx_t *ctx);
/* create parse tree node for the variable 'name' */
ap_expr_t *ap_expr_var_make(const char *name, ap_expr_parse_ctx_t *ctx);
/* create parse tree node for the unary operator 'name' */
diff --git a/server/util_expr_scan.c b/server/util_expr_scan.c
index 2f014e5ba1..fdb9da7aa2 100644
--- a/server/util_expr_scan.c
+++ b/server/util_expr_scan.c
@@ -8,8 +8,8 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -88,25 +88,13 @@ typedef unsigned int flex_uint32_t;
#endif /* ! FLEXINT_H */
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
+/* TODO: this is always defined, so inline it */
#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
#else
-#define yyconst
+#define yynoreturn
#endif
/* Returned upon end-of-file. */
@@ -179,11 +167,17 @@ typedef void* yyscan_t;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
#define YY_LESS_LINENO(n)
+ #define YY_LINENO_REWIND_TO(ptr)
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
@@ -201,11 +195,6 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
@@ -218,7 +207,7 @@ struct yy_buffer_state
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
- yy_size_t yy_buf_size;
+ int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
@@ -246,7 +235,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@@ -334,7 +323,7 @@ void ap_expr_yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
-#define ap_expr_yywrap(n) 1
+#define ap_expr_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
typedef unsigned char YY_CHAR;
@@ -346,20 +335,20 @@ typedef int yy_state_type;
static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (int) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 67
-#define YY_END_OF_BUFFER 68
+#define YY_NUM_RULES 74
+#define YY_END_OF_BUFFER 75
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -367,40 +356,43 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[124] =
+static yyconst flex_int16_t yy_accept[157] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 68, 66, 1, 43, 2, 66, 66, 66,
- 65, 66, 44, 26, 63, 32, 30, 34, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 66,
- 14, 4, 3, 17, 17, 67, 17, 23, 4, 22,
- 20, 21, 67, 16, 16, 24, 27, 29, 28, 1,
- 31, 37, 19, 18, 39, 63, 59, 59, 59, 59,
- 59, 59, 33, 30, 36, 35, 64, 64, 57, 64,
- 55, 54, 58, 53, 52, 25, 25, 56, 64, 40,
- 64, 41, 14, 13, 15, 12, 5, 6, 10, 11,
-
- 7, 8, 9, 20, 60, 46, 48, 50, 45, 49,
- 51, 47, 38, 64, 42, 64, 5, 6, 64, 61,
- 5, 62, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 75, 73,
+ 15, 14, 1, 15, 15, 15, 16, 46, 17, 73,
+ 73, 73, 72, 73, 47, 27, 70, 73, 35, 33,
+ 37, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 73, 26, 22, 21, 25, 24,
+ 14, 24, 24, 24, 23, 66, 65, 29, 30, 14,
+ 30, 30, 30, 31, 2, 3, 13, 6, 6, 5,
+ 11, 12, 8, 9, 10, 13, 16, 34, 40, 32,
+ 20, 42, 70, 63, 63, 63, 63, 63, 63, 19,
+
+ 36, 33, 39, 38, 71, 71, 60, 71, 58, 57,
+ 61, 71, 56, 55, 28, 28, 59, 71, 43, 71,
+ 71, 44, 21, 4, 6, 6, 0, 5, 7, 18,
+ 62, 49, 51, 53, 48, 52, 54, 50, 41, 71,
+ 71, 45, 71, 71, 6, 5, 5, 5, 7, 71,
+ 67, 71, 68, 69, 64, 0
} ;
-static yyconst flex_int32_t yy_ec[256] =
+static yyconst YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 5, 6, 7, 8, 9, 5, 10,
10, 1, 1, 11, 12, 13, 14, 15, 15, 15,
- 15, 15, 15, 15, 15, 16, 16, 17, 6, 18,
- 19, 20, 6, 1, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 1, 22, 1, 6, 23, 1, 24, 25, 21, 26,
-
- 27, 28, 29, 21, 30, 21, 21, 31, 32, 33,
- 34, 21, 35, 36, 37, 38, 39, 21, 21, 21,
- 21, 21, 40, 41, 42, 43, 1, 1, 1, 1,
+ 15, 16, 16, 16, 16, 17, 17, 18, 6, 19,
+ 20, 21, 6, 1, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 1, 24, 1, 6, 25, 1, 26, 27, 22, 28,
+
+ 29, 30, 31, 23, 32, 33, 23, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 23, 23, 44,
+ 23, 23, 45, 46, 47, 48, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -417,129 +409,177 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[44] =
+static yyconst YY_CHAR yy_meta[49] =
{ 0,
- 1, 1, 2, 1, 2, 1, 2, 2, 1, 1,
- 1, 1, 1, 1, 3, 3, 1, 1, 1, 1,
- 3, 2, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
- 1, 2, 1
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 3, 3, 1, 1, 1,
+ 1, 3, 4, 1, 4, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 1, 1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[133] =
+static yyconst flex_uint16_t yy_base[171] =
{ 0,
- 0, 0, 41, 47, 89, 0, 130, 136, 0, 0,
- 147, 146, 175, 275, 54, 28, 275, 43, 134, 164,
- 275, 164, 275, 275, 45, 152, 32, 151, 0, 136,
- 133, 143, 26, 133, 35, 194, 38, 129, 128, 122,
- 0, 275, 275, 51, 122, 221, 275, 275, 275, 275,
- 0, 275, 275, 61, 121, 275, 275, 275, 275, 76,
- 275, 275, 275, 275, 275, 65, 0, 125, 47, 126,
- 107, 130, 275, 275, 275, 275, 0, 130, 0, 124,
- 0, 0, 0, 0, 0, 275, 0, 0, 104, 0,
- 101, 275, 0, 275, 275, 275, 71, 131, 275, 275,
-
- 275, 275, 275, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 99, 0, 61, 133, 135, 57, 0,
- 138, 0, 275, 259, 262, 265, 79, 67, 268, 271,
- 65, 42
+ 0, 0, 0, 6, 30, 0, 78, 0, 124, 126,
+ 170, 213, 0, 0, 132, 134, 0, 0, 244, 455,
+ 455, 455, 455, 0, 198, 245, 16, 116, 455, 5,
+ 197, 232, 455, 275, 455, 455, 10, 193, 219, 118,
+ 217, 0, 200, 196, 208, 101, 197, 195, 115, 308,
+ 116, 190, 191, 188, 177, 455, 455, 0, 455, 455,
+ 455, 144, 177, 340, 455, 455, 455, 455, 455, 455,
+ 152, 170, 370, 455, 455, 196, 455, 13, 170, 174,
+ 455, 455, 455, 455, 455, 0, 144, 455, 455, 455,
+ 195, 455, 177, 0, 173, 120, 175, 123, 181, 455,
+
+ 455, 455, 455, 455, 0, 181, 0, 174, 0, 0,
+ 0, 175, 0, 0, 455, 0, 0, 164, 0, 171,
+ 137, 455, 0, 455, 139, 181, 184, 187, 0, 455,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 138,
+ 136, 0, 138, 134, 455, 455, 455, 455, 455, 122,
+ 0, 86, 0, 0, 0, 455, 414, 418, 422, 426,
+ 430, 434, 438, 442, 444, 446, 448, 3, 450, 1
} ;
-static yyconst flex_int16_t yy_def[133] =
+static yyconst flex_int16_t yy_def[171] =
{ 0,
- 123, 1, 124, 124, 123, 5, 124, 124, 125, 125,
- 126, 126, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 127, 123, 123, 123, 123, 123, 123, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 123,
- 129, 123, 123, 123, 123, 130, 123, 123, 123, 123,
- 131, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 132, 132, 132, 132,
- 132, 132, 123, 123, 123, 123, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 123, 128, 128, 128, 128,
- 128, 123, 129, 123, 123, 123, 123, 123, 123, 123,
-
- 123, 123, 123, 131, 132, 132, 132, 132, 132, 132,
- 132, 132, 128, 128, 128, 128, 123, 123, 128, 128,
- 123, 128, 0, 123, 123, 123, 123, 123, 123, 123,
- 123, 123
+ 157, 157, 158, 158, 156, 5, 156, 7, 159, 159,
+ 160, 160, 161, 161, 162, 162, 163, 163, 156, 156,
+ 156, 156, 156, 156, 156, 164, 156, 156, 156, 156,
+ 156, 156, 156, 165, 156, 156, 156, 156, 156, 156,
+ 156, 166, 166, 166, 166, 166, 166, 166, 166, 166,
+ 166, 166, 50, 166, 156, 156, 156, 167, 156, 156,
+ 156, 156, 156, 164, 156, 156, 156, 156, 156, 156,
+ 156, 156, 164, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 168, 156, 156, 156, 156,
+ 156, 156, 156, 169, 169, 169, 169, 169, 169, 156,
+
+ 156, 156, 156, 156, 166, 166, 166, 166, 166, 166,
+ 166, 166, 166, 166, 156, 166, 166, 166, 166, 166,
+ 166, 156, 167, 156, 156, 156, 156, 156, 170, 156,
+ 169, 169, 169, 169, 169, 169, 169, 169, 166, 166,
+ 166, 166, 166, 166, 156, 156, 156, 156, 156, 166,
+ 166, 166, 166, 166, 166, 0, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156
} ;
-static yyconst flex_int16_t yy_nxt[319] =
+static yyconst flex_uint16_t yy_nxt[504] =
{ 0,
- 14, 15, 15, 16, 17, 14, 18, 19, 20, 21,
- 21, 22, 23, 24, 25, 25, 21, 26, 27, 28,
- 29, 14, 14, 30, 29, 29, 31, 32, 33, 34,
- 35, 36, 37, 38, 29, 29, 29, 39, 29, 21,
- 40, 21, 14, 42, 105, 43, 61, 44, 45, 42,
- 74, 43, 81, 44, 45, 60, 60, 63, 63, 66,
- 66, 84, 46, 82, 88, 94, 94, 104, 46, 77,
- 62, 89, 85, 107, 75, 94, 94, 60, 60, 66,
- 66, 67, 47, 122, 108, 117, 118, 120, 47, 48,
- 48, 49, 48, 48, 48, 48, 48, 48, 48, 48,
-
- 48, 48, 48, 48, 48, 50, 48, 48, 48, 51,
- 48, 48, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 48, 48,
- 52, 48, 42, 110, 53, 119, 54, 55, 42, 116,
- 53, 115, 54, 55, 111, 118, 118, 121, 118, 118,
- 118, 46, 118, 118, 114, 113, 112, 46, 109, 106,
- 95, 95, 92, 91, 90, 83, 80, 79, 78, 76,
- 73, 56, 65, 64, 123, 59, 59, 56, 66, 66,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 68, 123, 69, 70, 71, 123, 72, 86, 86, 86,
-
- 86, 86, 123, 123, 86, 86, 86, 86, 123, 123,
- 86, 123, 123, 123, 123, 123, 87, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 86, 97, 98, 123, 123, 123,
- 123, 123, 123, 123, 123, 99, 123, 123, 100, 123,
- 123, 123, 123, 101, 123, 123, 102, 123, 103, 41,
- 41, 41, 57, 57, 57, 58, 58, 58, 93, 123,
- 93, 96, 96, 96, 13, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
-
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123
+ 156, 156, 22, 149, 23, 129, 24, 25, 22, 156,
+ 23, 156, 24, 25, 75, 75, 75, 87, 87, 90,
+ 90, 90, 156, 26, 93, 93, 93, 125, 125, 26,
+ 20, 27, 27, 28, 29, 20, 30, 31, 32, 33,
+ 33, 34, 35, 36, 37, 37, 37, 38, 39, 40,
+ 41, 42, 42, 20, 20, 43, 42, 42, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 42, 42, 42,
+ 53, 54, 42, 42, 33, 55, 33, 20, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 57, 56, 56, 56, 58,
+
+ 58, 56, 56, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 56, 56, 59, 56, 61, 155, 61, 109,
+ 62, 63, 62, 63, 70, 88, 70, 102, 71, 72,
+ 71, 72, 110, 113, 117, 87, 87, 64, 133, 64,
+ 154, 136, 118, 145, 145, 73, 114, 73, 75, 75,
+ 75, 134, 153, 89, 137, 103, 75, 75, 75, 152,
+ 65, 151, 65, 67, 67, 67, 67, 67, 150, 144,
+ 67, 67, 67, 67, 126, 126, 127, 67, 128, 128,
+ 128, 93, 93, 93, 67, 146, 146, 147, 147, 147,
+
+ 147, 148, 148, 148, 143, 142, 141, 140, 139, 138,
+ 135, 132, 130, 124, 76, 67, 67, 67, 67, 67,
+ 67, 76, 122, 67, 67, 67, 67, 121, 120, 119,
+ 67, 112, 111, 108, 107, 106, 104, 67, 101, 100,
+ 92, 91, 76, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 67, 78,
+ 79, 80, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 81, 156, 156, 82, 156, 156, 156, 156, 156,
+ 83, 156, 156, 156, 84, 156, 85, 156, 86, 93,
+ 93, 93, 156, 156, 156, 156, 156, 156, 156, 156,
+
+ 156, 156, 156, 95, 156, 96, 97, 156, 98, 156,
+ 99, 115, 115, 115, 115, 115, 156, 156, 115, 115,
+ 115, 115, 156, 156, 156, 115, 156, 156, 156, 156,
+ 156, 156, 116, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 115, 78, 79, 80, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 81, 156, 156, 82,
+ 156, 156, 156, 156, 156, 83, 156, 156, 156, 84,
+ 156, 85, 156, 86, 78, 79, 80, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 81, 156, 156, 82,
+
+ 156, 156, 156, 156, 156, 83, 156, 156, 156, 84,
+ 156, 85, 156, 86, 20, 20, 20, 20, 21, 21,
+ 21, 21, 60, 60, 60, 60, 66, 66, 66, 66,
+ 68, 68, 68, 68, 69, 69, 69, 69, 74, 74,
+ 74, 74, 77, 156, 77, 77, 94, 94, 105, 105,
+ 123, 123, 131, 131, 19, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+
+ 156, 156, 156
} ;
-static yyconst flex_int16_t yy_chk[319] =
+static yyconst flex_int16_t yy_chk[504] =
{ 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 3, 132, 3, 16, 3, 3, 4,
- 27, 4, 33, 4, 4, 15, 15, 18, 18, 25,
- 25, 35, 3, 33, 37, 44, 44, 131, 4, 128,
- 16, 37, 35, 69, 27, 54, 54, 60, 60, 66,
- 66, 127, 3, 119, 69, 97, 97, 116, 4, 5,
+ 0, 0, 3, 170, 3, 168, 3, 3, 4, 0,
+ 4, 0, 4, 4, 24, 24, 24, 27, 27, 30,
+ 30, 30, 0, 3, 37, 37, 37, 78, 78, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 7, 71, 7, 114, 7, 7, 8, 91,
- 8, 89, 8, 8, 71, 98, 98, 117, 117, 118,
- 118, 7, 121, 121, 80, 78, 72, 8, 70, 68,
- 55, 45, 40, 39, 38, 34, 32, 31, 30, 28,
- 26, 7, 20, 19, 13, 12, 11, 8, 22, 22,
+ 5, 5, 5, 5, 5, 5, 5, 5, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 9, 152, 10, 46,
+ 9, 9, 10, 10, 15, 28, 16, 40, 15, 15,
+ 16, 16, 46, 49, 51, 87, 87, 9, 96, 10,
+ 150, 98, 51, 125, 125, 15, 49, 16, 62, 62,
+ 62, 96, 144, 28, 98, 40, 71, 71, 71, 143,
+ 9, 141, 10, 11, 11, 11, 11, 11, 140, 121,
+ 11, 11, 11, 11, 79, 79, 79, 11, 80, 80,
+ 80, 93, 93, 93, 11, 126, 126, 126, 127, 127,
+
+ 127, 128, 128, 128, 120, 118, 112, 108, 106, 99,
+ 97, 95, 91, 76, 72, 11, 12, 12, 12, 12,
+ 12, 63, 55, 12, 12, 12, 12, 54, 53, 52,
+ 12, 48, 47, 45, 44, 43, 41, 12, 39, 38,
+ 32, 31, 25, 19, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 12, 26,
+ 26, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 0, 0, 26, 0, 0, 0, 0, 0,
+ 26, 0, 0, 0, 26, 0, 26, 0, 26, 34,
+ 34, 34, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 34, 0, 34, 34, 0, 34, 0,
+ 34, 50, 50, 50, 50, 50, 0, 0, 50, 50,
+ 50, 50, 0, 0, 0, 50, 0, 0, 0, 0,
+ 0, 0, 50, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 22, 0, 22, 22, 22, 0, 22, 36, 36, 36,
-
- 36, 36, 0, 0, 36, 36, 36, 36, 0, 0,
- 36, 0, 0, 0, 0, 0, 36, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 36, 46, 46, 0, 0, 0,
- 0, 0, 0, 0, 0, 46, 0, 0, 46, 0,
- 0, 0, 0, 46, 0, 0, 46, 0, 46, 124,
- 124, 124, 125, 125, 125, 126, 126, 126, 129, 0,
- 129, 130, 130, 130, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
-
- 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 123, 123, 123
+ 0, 0, 0, 50, 64, 64, 64, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 64, 0, 0, 64,
+ 0, 0, 0, 0, 0, 64, 0, 0, 0, 64,
+ 0, 64, 0, 64, 73, 73, 73, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 73, 0, 0, 73,
+
+ 0, 0, 0, 0, 0, 73, 0, 0, 0, 73,
+ 0, 73, 0, 73, 157, 157, 157, 157, 158, 158,
+ 158, 158, 159, 159, 159, 159, 160, 160, 160, 160,
+ 161, 161, 161, 161, 162, 162, 162, 162, 163, 163,
+ 163, 163, 164, 0, 164, 164, 165, 165, 166, 166,
+ 167, 167, 169, 169, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+
+ 156, 156, 156
} ;
/* The intent behind this definition is that it'll catch
@@ -577,12 +617,12 @@ static yyconst flex_int16_t yy_chk[319] =
-
#line 43 "util_expr_scan.l"
#include "util_expr_private.h"
#include "util_expr_parse.h"
#include "http_main.h"
#include "http_log.h"
+#include "apr_lib.h"
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
@@ -604,37 +644,113 @@ static yyconst flex_int16_t yy_chk[319] =
* XXX: longjmp. It is not clear if the scanner is in any state
* XXX: to be cleaned up, though.
*/
+static int unreachable = 0;
#define YY_FATAL_ERROR(msg) \
do { \
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, \
APLOGNO(03296) \
"expr parser fatal error (BUG?): " \
"%s, exiting", msg); \
- abort(); \
+ if (unreachable) { \
+ /* Not reached, silence [-Wunused-function] */ \
+ yy_fatal_error(msg, yyscanner); \
+ } \
+ else { \
+ abort(); \
+ } \
} while (0)
#define YY_EXTRA_TYPE ap_expr_parse_ctx_t*
-#define PERROR(msg) do { yyextra->error2 = msg ; return T_ERROR; } while (0)
+#define PERROR(msg) do { \
+ yyextra->error2 = msg; \
+ return T_ERROR; \
+} while (0)
+
+#define PERROR_CHAR(prefix, chr) do { \
+ char *msg; \
+ if (apr_isprint((chr))) { \
+ msg = apr_psprintf(yyextra->pool, prefix "'%c'", (char)(chr)); \
+ } \
+ else { \
+ msg = apr_psprintf(yyextra->pool, prefix "'\\x%.2X'", (int)(chr)); \
+ } \
+ PERROR(msg); \
+} while (0)
+
+#define STACK_PUSH() do { \
+ ap_expr_parser_stack_t *sk; \
+ if (yyextra->spares) { \
+ sk = yyextra->spares; \
+ yyextra->spares = sk->next; \
+ } \
+ else { \
+ sk = apr_palloc(yyextra->ptemp, sizeof(*sk)); \
+ } \
+ sk->scan_ptr = sk->scan_buf; \
+ sk->scan_stop = sk->scan_buf[0] = '\0'; \
+ sk->scan_flag = 0; \
+ sk->next = yyextra->current; \
+ yyextra->current = sk; \
+} while (0)
+
+#define STACK_POP() do { \
+ ap_expr_parser_stack_t *sk; \
+ sk = yyextra->current; \
+ yyextra->current = sk->next; \
+ sk->next = yyextra->spares; \
+ yyextra->spares = sk; \
+} while (0)
+
+#define STATE_PUSH(st, sk) do { \
+ yy_push_state((st), yyscanner); \
+ if ((sk)) { \
+ STACK_PUSH(); \
+ } \
+} while (0)
+
+#define STATE_POP(sk) do { \
+ if ((sk)) { \
+ STACK_POP(); \
+ } \
+ yy_pop_state(yyscanner); \
+} while (0)
+
+#define str_ptr (yyextra->current->scan_ptr)
+#define str_buf (yyextra->current->scan_buf)
+#define str_stop (yyextra->current->scan_stop)
+#define str_flag (yyextra->current->scan_flag)
+
+#define STR_APPEND_CHECK(chr, chk) do { \
+ if ((chk) && apr_iscntrl((chr))) { \
+ PERROR_CHAR("Invalid string character ", (chr)); \
+ } \
+ if (str_ptr >= str_buf + sizeof(str_buf) - 1) { \
+ PERROR("String too long"); \
+ } \
+ *str_ptr++ = (char)(chr); \
+} while (0)
-#define str_ptr (yyextra->scan_ptr)
-#define str_buf (yyextra->scan_buf)
-#define str_del (yyextra->scan_del)
+#define STR_APPEND_NOCHECK(chr) \
+ STR_APPEND_CHECK((chr), 0)
-#define STR_APPEND(c) do { \
- *str_ptr++ = (c); \
- if (str_ptr >= str_buf + sizeof(str_buf)) \
- PERROR("String too long"); \
- } while (0)
+#define STR_EMPTY() \
+ (str_ptr == str_buf)
-#line 630 "util_expr_scan.c"
+#define STR_RETURN() \
+ (apr_pstrdup(yyextra->pool, (*str_ptr = '\0', str_ptr = str_buf)))
+
+#line 744 "util_expr_scan.c"
#define INITIAL 0
#define str 1
-#define var 2
-#define vararg 3
-#define regex 4
-#define regex_flags 5
+#define expr 2
+#define var 3
+#define vararg 4
+#define split 5
+#define regex 6
+#define regsub 7
+#define regflags 8
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -709,19 +825,23 @@ void ap_expr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *ap_expr_yyget_in (yyscan_t yyscanner );
-void ap_expr_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+void ap_expr_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
FILE *ap_expr_yyget_out (yyscan_t yyscanner );
-void ap_expr_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+void ap_expr_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
-int ap_expr_yyget_leng (yyscan_t yyscanner );
+ int ap_expr_yyget_leng (yyscan_t yyscanner );
char *ap_expr_yyget_text (yyscan_t yyscanner );
int ap_expr_yyget_lineno (yyscan_t yyscanner );
-void ap_expr_yyset_lineno (int line_number ,yyscan_t yyscanner );
+void ap_expr_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int ap_expr_yyget_column (yyscan_t yyscanner );
+
+void ap_expr_yyset_column (int _column_no ,yyscan_t yyscanner );
YYSTYPE * ap_expr_yyget_lval (yyscan_t yyscanner );
@@ -739,6 +859,10 @@ extern int ap_expr_yywrap (yyscan_t yyscanner );
#endif
#endif
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
@@ -757,7 +881,7 @@ static int input (yyscan_t yyscanner );
#endif
- static void yy_push_state (int new_state ,yyscan_t yyscanner);
+ static void yy_push_state (int _new_state ,yyscan_t yyscanner);
static void yy_pop_state (yyscan_t yyscanner );
@@ -776,7 +900,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -800,7 +924,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -857,7 +981,7 @@ extern int ap_expr_yylex \
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
-#define YY_BREAK break;
+#define YY_BREAK /*LINTED*/break;
#endif
#define YY_RULE_SETUP \
@@ -867,39 +991,11 @@ extern int ap_expr_yylex \
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 93 "util_expr_scan.l"
-
-
- char regex_buf[MAX_STRING_LEN];
- char *regex_ptr = NULL;
- char regex_del = '\0';
-
-
- /*
- * Set initial state for string expressions
- */
- if (yyextra->at_start) {
- yyextra->at_start = 0;
- if (yyextra->flags & AP_EXPR_FLAG_STRING_RESULT) {
- BEGIN(str);
- return T_EXPR_STRING;
- }
- else {
- return T_EXPR_BOOL;
- }
- }
-
-
- /*
- * Whitespaces
- */
-#line 901 "util_expr_scan.c"
-
yylval = yylval_param;
if ( !yyg->yy_init )
@@ -928,7 +1024,33 @@ YY_DECL
ap_expr_yy_load_buffer_state(yyscanner );
}
- while ( 1 ) /* loops until end-of-file is reached */
+ {
+#line 179 "util_expr_scan.l"
+
+
+
+ /*
+ * Set initial state for string expressions
+ */
+ if (yyextra->at_start) {
+ yyextra->at_start = 0;
+ if (yyextra->flags & AP_EXPR_FLAG_STRING_RESULT) {
+ STATE_PUSH(str, 1);
+ return T_EXPR_STRING;
+ }
+ else {
+ STATE_PUSH(expr, 1);
+ return T_EXPR_BOOL;
+ }
+ }
+
+
+ /*
+ * Back off INITIAL pushes
+ */
+#line 1052 "util_expr_scan.c"
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
yy_cp = yyg->yy_c_buf_p;
@@ -944,7 +1066,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -953,13 +1075,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 124 )
+ if ( yy_current_state >= 157 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp;
}
- while ( yy_current_state != 123 );
+ while ( yy_current_state != 156 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@@ -979,519 +1101,577 @@ do_action: /* This label is used only to access EOF actions. */
yy_current_state = yyg->yy_last_accepting_state;
goto yy_find_action;
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 118 "util_expr_scan.l"
-{
- /* NOP */
+case YY_STATE_EOF(str):
+#line 201 "util_expr_scan.l"
+{
+ STATE_POP(0); /* <str> */
+ if (YY_START != INITIAL) {
+ PERROR("Unterminated string");
+ }
+ yylval->cpVal = STR_RETURN();
+ STACK_POP(); /* ^ after this */
+ return T_STRING;
}
YY_BREAK
-/*
- * strings ("..." and '...')
- */
-case 2:
-YY_RULE_SETUP
-#line 125 "util_expr_scan.l"
+case YY_STATE_EOF(expr):
+#line 210 "util_expr_scan.l"
{
- str_ptr = str_buf;
- str_del = yytext[0];
- BEGIN(str);
- return T_STR_BEGIN;
+ STATE_POP(1); /* <expr> */
+ if (YY_START != INITIAL) {
+ PERROR("Unterminated expression");
+ }
}
YY_BREAK
-case 3:
+case 1:
YY_RULE_SETUP
-#line 131 "util_expr_scan.l"
+#line 217 "util_expr_scan.l"
{
- if (yytext[0] == str_del) {
- if (YY_START == var) {
- PERROR("Unterminated variable in string");
- }
- else if (str_ptr == str_buf) {
- BEGIN(INITIAL);
- return T_STR_END;
- }
- else {
- /* return what we have so far and scan delimiter again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- yyless(0);
- str_ptr = str_buf;
+ if (yytext[0] == str_stop) {
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
return T_STRING;
}
+ STATE_POP(1); /* <str> */
+ return T_STR_END;
}
- else {
- STR_APPEND(yytext[0]);
- }
+ STR_APPEND_NOCHECK(yytext[0]);
}
YY_BREAK
-case 4:
-/* rule 4 can match eol */
+/* regexp backref inside string/arg */
+case 2:
YY_RULE_SETUP
-#line 153 "util_expr_scan.l"
+#line 231 "util_expr_scan.l"
{
- PERROR("Unterminated string or variable");
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
+ return T_STRING;
+ }
+ yylval->num = yytext[1] - '0';
+ return T_REG_REF;
}
YY_BREAK
-case YY_STATE_EOF(var):
-case YY_STATE_EOF(vararg):
-#line 156 "util_expr_scan.l"
+/* variable inside string/arg */
+case 3:
+YY_RULE_SETUP
+#line 242 "util_expr_scan.l"
{
- PERROR("Unterminated string or variable");
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
+ return T_STRING;
+ }
+ STATE_PUSH(var, 1);
+ return T_VAR_BEGIN;
}
YY_BREAK
-case YY_STATE_EOF(str):
-#line 159 "util_expr_scan.l"
+case 4:
+YY_RULE_SETUP
+#line 252 "util_expr_scan.l"
{
- if (!(yyextra->flags & AP_EXPR_FLAG_STRING_RESULT)) {
- PERROR("Unterminated string or variable");
- }
- else {
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- BEGIN(INITIAL);
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
return T_STRING;
}
+ STATE_PUSH(expr, 1);
+ return T_VAREXP_BEGIN;
}
YY_BREAK
+/* Any non-octal or octal higher than 377 (decimal 255) is invalid */
case 5:
YY_RULE_SETUP
-#line 172 "util_expr_scan.l"
+#line 263 "util_expr_scan.l"
{
- int result;
-
- (void)sscanf(yytext+1, "%o", &result);
- if (result > 0xff) {
- PERROR("Escape sequence out of bound");
- }
- else {
- STR_APPEND(result);
- }
+ PERROR("Bad character escape sequence");
}
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 183 "util_expr_scan.l"
+#line 266 "util_expr_scan.l"
{
- PERROR("Bad escape sequence");
+ int result;
+ (void)sscanf(yytext+1, "%o", &result);
+ STR_APPEND_NOCHECK(result);
}
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 186 "util_expr_scan.l"
-{ STR_APPEND('\n'); }
+#line 271 "util_expr_scan.l"
+{
+ int result;
+ (void)sscanf(yytext+1, "%x", &result);
+ STR_APPEND_NOCHECK(result);
+}
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 187 "util_expr_scan.l"
-{ STR_APPEND('\r'); }
+#line 276 "util_expr_scan.l"
+{ STR_APPEND_NOCHECK('\n'); }
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 188 "util_expr_scan.l"
-{ STR_APPEND('\t'); }
+#line 277 "util_expr_scan.l"
+{ STR_APPEND_NOCHECK('\r'); }
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 189 "util_expr_scan.l"
-{ STR_APPEND('\b'); }
+#line 278 "util_expr_scan.l"
+{ STR_APPEND_NOCHECK('\t'); }
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 190 "util_expr_scan.l"
-{ STR_APPEND('\f'); }
+#line 279 "util_expr_scan.l"
+{ STR_APPEND_NOCHECK('\b'); }
YY_BREAK
case 12:
-/* rule 12 can match eol */
YY_RULE_SETUP
-#line 191 "util_expr_scan.l"
-{ STR_APPEND(yytext[1]); }
+#line 280 "util_expr_scan.l"
+{ STR_APPEND_NOCHECK('\f'); }
YY_BREAK
-/* regexp backref inside string/arg */
case 13:
YY_RULE_SETUP
-#line 194 "util_expr_scan.l"
-{
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '$x' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- yyless(0);
- return T_STRING;
- }
- else {
- yylval->num = yytext[1] - '0';
- return T_REGEX_BACKREF;
- }
-}
+#line 281 "util_expr_scan.l"
+{ STR_APPEND_CHECK(yytext[1], 1); }
YY_BREAK
case 14:
+/* rule 14 can match eol */
YY_RULE_SETUP
-#line 209 "util_expr_scan.l"
+#line 283 "util_expr_scan.l"
{
- char *cp = yytext;
- while (*cp != '\0') {
- STR_APPEND(*cp);
- cp++;
- }
+ PERROR("Unterminated string or variable");
}
YY_BREAK
-/* variable inside string/arg */
case 15:
+/* rule 15 can match eol */
YY_RULE_SETUP
-#line 218 "util_expr_scan.l"
+#line 287 "util_expr_scan.l"
{
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '%{' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- yyless(0);
- str_ptr = str_buf;
- return T_STRING;
- }
- else {
- yy_push_state(var, yyscanner);
- return T_VAR_BEGIN;
- }
+ STR_APPEND_CHECK(yytext[0], 1);
}
YY_BREAK
case 16:
+/* rule 16 can match eol */
YY_RULE_SETUP
-#line 233 "util_expr_scan.l"
-{
- STR_APPEND(yytext[0]);
+#line 291 "util_expr_scan.l"
+{
+ /* NOP */
}
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 237 "util_expr_scan.l"
+#line 295 "util_expr_scan.l"
{
- STR_APPEND(yytext[0]);
+ STATE_PUSH(str, 1);
+ str_stop = yytext[0];
+ return T_STR_BEGIN;
}
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 241 "util_expr_scan.l"
+#line 301 "util_expr_scan.l"
{
- yy_push_state(var, yyscanner);
- return T_VAR_BEGIN;
+ STATE_PUSH(expr, 1);
+ return T_VAREXP_BEGIN;
}
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 246 "util_expr_scan.l"
+#line 305 "util_expr_scan.l"
{
- yylval->num = yytext[1] - '0';
- return T_REGEX_BACKREF;
+ STATE_POP(1); /* <expr> */
+ return T_VAREXP_END;
}
YY_BREAK
-/*
- * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
- */
case 20:
YY_RULE_SETUP
-#line 254 "util_expr_scan.l"
+#line 311 "util_expr_scan.l"
{
- yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
- return T_ID;
+ STATE_PUSH(var, 1);
+ return T_VAR_BEGIN;
}
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 259 "util_expr_scan.l"
+#line 315 "util_expr_scan.l"
{
- yy_pop_state(yyscanner);
- return T_VAR_END;
+ yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
+ return T_ID;
}
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 264 "util_expr_scan.l"
+#line 319 "util_expr_scan.l"
{
- BEGIN(vararg);
+ STATE_PUSH(vararg, 0);
return yytext[0];
}
YY_BREAK
case 23:
-/* rule 23 can match eol */
YY_RULE_SETUP
-#line 269 "util_expr_scan.l"
+#line 323 "util_expr_scan.l"
{
- char *msg = apr_psprintf(yyextra->pool,
- "Invalid character in variable name '%c'", yytext[0]);
- PERROR(msg);
+ yyless(0); /* let <var> handle */
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(0); /* <vararg> */
+ return T_STRING;
}
YY_BREAK
case 24:
+/* rule 24 can match eol */
YY_RULE_SETUP
-#line 275 "util_expr_scan.l"
+#line 329 "util_expr_scan.l"
{
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '}' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- yyless(0);
- return T_STRING;
- }
- else {
- yy_pop_state(yyscanner);
- return T_VAR_END;
- }
+ STR_APPEND_CHECK(yytext[0], 1);
}
YY_BREAK
-/*
- * Regular Expression
- */
case 25:
YY_RULE_SETUP
-#line 293 "util_expr_scan.l"
+#line 332 "util_expr_scan.l"
{
- regex_del = yytext[1];
- regex_ptr = regex_buf;
- BEGIN(regex);
+ STATE_POP(1); /* <var> */
+ return T_VAR_END;
}
YY_BREAK
case 26:
+/* rule 26 can match eol */
YY_RULE_SETUP
-#line 298 "util_expr_scan.l"
+#line 336 "util_expr_scan.l"
{
- regex_del = yytext[0];
- regex_ptr = regex_buf;
- BEGIN(regex);
+ PERROR_CHAR("Unexpected variable character ", yytext[0]);
}
YY_BREAK
+case YY_STATE_EOF(var):
+case YY_STATE_EOF(vararg):
+#line 339 "util_expr_scan.l"
+{
+ PERROR("Unterminated variable");
+}
+ YY_BREAK
+/*
+ * Regular Expression
+ */
case 27:
-/* rule 27 can match eol */
YY_RULE_SETUP
-#line 303 "util_expr_scan.l"
+#line 347 "util_expr_scan.l"
{
- if (yytext[0] == regex_del) {
- *regex_ptr = '\0';
- BEGIN(regex_flags);
- }
- else {
- *regex_ptr++ = yytext[0];
- if (regex_ptr >= regex_buf + sizeof(regex_buf))
- PERROR("Regexp too long");
- }
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[0];
+ str_flag = 'm';
+ return T_REGEX;
}
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 314 "util_expr_scan.l"
+#line 353 "util_expr_scan.l"
{
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- BEGIN(INITIAL);
- return T_REGEX_I;
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[1];
+ str_flag = yytext[0];
+ return (str_flag == 'm') ? T_REGEX : T_REGSUB;
}
YY_BREAK
case 29:
/* rule 29 can match eol */
YY_RULE_SETUP
-#line 319 "util_expr_scan.l"
+#line 359 "util_expr_scan.l"
{
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- yyless(0);
- BEGIN(INITIAL);
- return T_REGEX;
+ if (yytext[0] == str_stop) {
+ STATE_POP(0); /* <regex> */
+ if (str_flag == 'm') {
+ STATE_PUSH(regflags, 0);
+ }
+ else {
+ STATE_PUSH(regsub, 0);
+ }
+ yylval->cpVal = STR_RETURN();
+ return T_REG_MATCH;
+ }
+ STR_APPEND_CHECK(yytext[0], 1);
}
YY_BREAK
-case YY_STATE_EOF(regex_flags):
-#line 325 "util_expr_scan.l"
+case 30:
+/* rule 30 can match eol */
+YY_RULE_SETUP
+#line 373 "util_expr_scan.l"
{
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- BEGIN(INITIAL);
- return T_REGEX;
+ if (yytext[0] == str_stop) {
+ STATE_POP(0); /* <regsub> */
+ STATE_PUSH(regflags, 0);
+ }
+ else {
+ STR_APPEND_CHECK(yytext[0], 1);
+ }
+}
+ YY_BREAK
+case 31:
+/* rule 31 can match eol */
+YY_RULE_SETUP
+#line 382 "util_expr_scan.l"
+{
+ if (ap_strchr_c("ismg", yytext[0])) {
+ STR_APPEND_NOCHECK(yytext[0]);
+ }
+ else if (apr_isalnum(yytext[0])) {
+ PERROR("Invalid regexp flag(s)");
+ }
+ else {
+ yyless(0); /* not a flags, rewind */
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(1); /* <regflags> */
+ return T_REG_FLAGS;
+ }
+}
+ YY_BREAK
+case YY_STATE_EOF(regflags):
+#line 396 "util_expr_scan.l"
+{
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(1); /* <regflags> */
+ return T_REG_FLAGS;
+}
+ YY_BREAK
+case YY_STATE_EOF(regex):
+case YY_STATE_EOF(regsub):
+#line 401 "util_expr_scan.l"
+{
+ PERROR("Unterminated regexp");
+}
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 405 "util_expr_scan.l"
+{
+ yylval->num = yytext[1] - '0';
+ return T_REG_REF;
}
YY_BREAK
/*
* Operators
*/
-case 30:
+case 33:
YY_RULE_SETUP
-#line 334 "util_expr_scan.l"
+#line 413 "util_expr_scan.l"
{ return T_OP_STR_EQ; }
YY_BREAK
-case 31:
+case 34:
YY_RULE_SETUP
-#line 335 "util_expr_scan.l"
+#line 414 "util_expr_scan.l"
{ return T_OP_STR_NE; }
YY_BREAK
-case 32:
+case 35:
YY_RULE_SETUP
-#line 336 "util_expr_scan.l"
+#line 415 "util_expr_scan.l"
{ return T_OP_STR_LT; }
YY_BREAK
-case 33:
+case 36:
YY_RULE_SETUP
-#line 337 "util_expr_scan.l"
+#line 416 "util_expr_scan.l"
{ return T_OP_STR_LE; }
YY_BREAK
-case 34:
+case 37:
YY_RULE_SETUP
-#line 338 "util_expr_scan.l"
+#line 417 "util_expr_scan.l"
{ return T_OP_STR_GT; }
YY_BREAK
-case 35:
+case 38:
YY_RULE_SETUP
-#line 339 "util_expr_scan.l"
+#line 418 "util_expr_scan.l"
{ return T_OP_STR_GE; }
YY_BREAK
-case 36:
+case 39:
YY_RULE_SETUP
-#line 340 "util_expr_scan.l"
+#line 419 "util_expr_scan.l"
{ return T_OP_REG; }
YY_BREAK
-case 37:
+case 40:
YY_RULE_SETUP
-#line 341 "util_expr_scan.l"
+#line 420 "util_expr_scan.l"
{ return T_OP_NRE; }
YY_BREAK
-case 38:
+case 41:
YY_RULE_SETUP
-#line 342 "util_expr_scan.l"
+#line 421 "util_expr_scan.l"
{ return T_OP_AND; }
YY_BREAK
-case 39:
+case 42:
YY_RULE_SETUP
-#line 343 "util_expr_scan.l"
+#line 422 "util_expr_scan.l"
{ return T_OP_AND; }
YY_BREAK
-case 40:
+case 43:
YY_RULE_SETUP
-#line 344 "util_expr_scan.l"
+#line 423 "util_expr_scan.l"
{ return T_OP_OR; }
YY_BREAK
-case 41:
+case 44:
YY_RULE_SETUP
-#line 345 "util_expr_scan.l"
+#line 424 "util_expr_scan.l"
{ return T_OP_OR; }
YY_BREAK
-case 42:
+case 45:
YY_RULE_SETUP
-#line 346 "util_expr_scan.l"
+#line 425 "util_expr_scan.l"
{ return T_OP_NOT; }
YY_BREAK
-case 43:
+case 46:
YY_RULE_SETUP
-#line 347 "util_expr_scan.l"
+#line 426 "util_expr_scan.l"
{ return T_OP_NOT; }
YY_BREAK
-case 44:
+case 47:
YY_RULE_SETUP
-#line 348 "util_expr_scan.l"
+#line 427 "util_expr_scan.l"
{ return T_OP_CONCAT; }
YY_BREAK
-case 45:
+case 48:
YY_RULE_SETUP
-#line 349 "util_expr_scan.l"
+#line 428 "util_expr_scan.l"
{ return T_OP_IN; }
YY_BREAK
-case 46:
+case 49:
YY_RULE_SETUP
-#line 350 "util_expr_scan.l"
+#line 429 "util_expr_scan.l"
{ return T_OP_EQ; }
YY_BREAK
-case 47:
+case 50:
YY_RULE_SETUP
-#line 351 "util_expr_scan.l"
+#line 430 "util_expr_scan.l"
{ return T_OP_NE; }
YY_BREAK
-case 48:
+case 51:
YY_RULE_SETUP
-#line 352 "util_expr_scan.l"
+#line 431 "util_expr_scan.l"
{ return T_OP_GE; }
YY_BREAK
-case 49:
+case 52:
YY_RULE_SETUP
-#line 353 "util_expr_scan.l"
+#line 432 "util_expr_scan.l"
{ return T_OP_LE; }
YY_BREAK
-case 50:
+case 53:
YY_RULE_SETUP
-#line 354 "util_expr_scan.l"
+#line 433 "util_expr_scan.l"
{ return T_OP_GT; }
YY_BREAK
-case 51:
+case 54:
YY_RULE_SETUP
-#line 355 "util_expr_scan.l"
+#line 434 "util_expr_scan.l"
{ return T_OP_LT; }
YY_BREAK
/* for compatibility with ssl_expr */
-case 52:
+case 55:
YY_RULE_SETUP
-#line 358 "util_expr_scan.l"
+#line 437 "util_expr_scan.l"
{ return T_OP_LT; }
YY_BREAK
-case 53:
+case 56:
YY_RULE_SETUP
-#line 359 "util_expr_scan.l"
+#line 438 "util_expr_scan.l"
{ return T_OP_LE; }
YY_BREAK
-case 54:
+case 57:
YY_RULE_SETUP
-#line 360 "util_expr_scan.l"
+#line 439 "util_expr_scan.l"
{ return T_OP_GT; }
YY_BREAK
-case 55:
+case 58:
YY_RULE_SETUP
-#line 361 "util_expr_scan.l"
+#line 440 "util_expr_scan.l"
{ return T_OP_GE; }
YY_BREAK
-case 56:
+case 59:
YY_RULE_SETUP
-#line 362 "util_expr_scan.l"
+#line 441 "util_expr_scan.l"
{ return T_OP_NE; }
YY_BREAK
-case 57:
+case 60:
YY_RULE_SETUP
-#line 363 "util_expr_scan.l"
+#line 442 "util_expr_scan.l"
{ return T_OP_EQ; }
YY_BREAK
-case 58:
+case 61:
YY_RULE_SETUP
-#line 364 "util_expr_scan.l"
+#line 443 "util_expr_scan.l"
{ return T_OP_IN; }
YY_BREAK
-case 59:
+case 62:
YY_RULE_SETUP
-#line 366 "util_expr_scan.l"
+#line 445 "util_expr_scan.l"
{
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
- return T_OP_UNARY;
+ return T_OP_BINARY;
}
YY_BREAK
-case 60:
+case 63:
YY_RULE_SETUP
-#line 371 "util_expr_scan.l"
+#line 450 "util_expr_scan.l"
{
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
- return T_OP_BINARY;
+ return T_OP_UNARY;
+}
+ YY_BREAK
+/* Split a string (or list) into a(nother) list */
+case 64:
+YY_RULE_SETUP
+#line 456 "util_expr_scan.l"
+{
+ STATE_PUSH(split, 0);
+ return T_OP_SPLIT;
+}
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 460 "util_expr_scan.l"
+{
+ STATE_POP(0); /* <split> */
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[0];
+ str_flag = 'S';
+}
+ YY_BREAK
+case 66:
+/* rule 66 can match eol */
+YY_RULE_SETUP
+#line 466 "util_expr_scan.l"
+{
+ PERROR("Expecting split regular expression");
+}
+ YY_BREAK
+case YY_STATE_EOF(split):
+#line 469 "util_expr_scan.l"
+{
+ PERROR("Unterminated split");
+}
+ YY_BREAK
+/* Join a list into a string */
+case 67:
+YY_RULE_SETUP
+#line 474 "util_expr_scan.l"
+{
+ return T_OP_JOIN;
}
YY_BREAK
/*
* Specials
*/
-case 61:
+case 68:
YY_RULE_SETUP
-#line 379 "util_expr_scan.l"
+#line 481 "util_expr_scan.l"
{ return T_TRUE; }
YY_BREAK
-case 62:
+case 69:
YY_RULE_SETUP
-#line 380 "util_expr_scan.l"
+#line 482 "util_expr_scan.l"
{ return T_FALSE; }
YY_BREAK
/*
* Digits
*/
-case 63:
+case 70:
YY_RULE_SETUP
-#line 385 "util_expr_scan.l"
+#line 487 "util_expr_scan.l"
{
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
return T_DIGIT;
@@ -1500,9 +1680,9 @@ YY_RULE_SETUP
/*
* Identifiers
*/
-case 64:
+case 71:
YY_RULE_SETUP
-#line 393 "util_expr_scan.l"
+#line 495 "util_expr_scan.l"
{
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
return T_ID;
@@ -1511,9 +1691,9 @@ YY_RULE_SETUP
/*
* These are parts of the grammar and are returned as is
*/
-case 65:
+case 72:
YY_RULE_SETUP
-#line 401 "util_expr_scan.l"
+#line 503 "util_expr_scan.l"
{
return yytext[0];
}
@@ -1521,23 +1701,21 @@ YY_RULE_SETUP
/*
* Anything else is an error
*/
-case 66:
-/* rule 66 can match eol */
+case 73:
+/* rule 73 can match eol */
YY_RULE_SETUP
-#line 408 "util_expr_scan.l"
+#line 510 "util_expr_scan.l"
{
- char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);
- PERROR(msg);
+ PERROR_CHAR("Parse error near character ", yytext[0]);
}
YY_BREAK
-case 67:
+case 74:
YY_RULE_SETUP
-#line 413 "util_expr_scan.l"
+#line 514 "util_expr_scan.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1538 "util_expr_scan.c"
+#line 1718 "util_expr_scan.c"
case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(regex):
yyterminate();
case YY_END_OF_BUFFER:
@@ -1668,6 +1846,7 @@ case YY_STATE_EOF(regex):
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
+ } /* end of user's declarations */
} /* end of ap_expr_yylex */
/* yy_get_next_buffer - try to read in a new buffer
@@ -1680,9 +1859,9 @@ case YY_STATE_EOF(regex):
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1711,7 +1890,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1731,7 +1910,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{ /* Not enough room in the buffer - grow it. */
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
int yy_c_buf_p_offset =
(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
@@ -1751,7 +1930,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
else
/* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
+ b->yy_ch_buf = NULL;
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
@@ -1769,7 +1948,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, (size_t) num_to_read );
+ yyg->yy_n_chars, num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -1793,9 +1972,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
- yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ap_expr_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
@@ -1814,15 +1993,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1831,10 +2010,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 124 )
+ if ( yy_current_state >= 157 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
}
return yy_current_state;
@@ -1847,11 +2026,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register char *yy_cp = yyg->yy_c_buf_p;
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1860,15 +2039,20 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 124 )
+ if ( yy_current_state >= 157 )
yy_c = yy_meta[(unsigned int) yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 123);
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_is_jam = (yy_current_state == 156);
+ (void)yyg;
return yy_is_jam ? 0 : yy_current_state;
}
+#ifndef YY_NO_UNPUT
+
+#endif
+
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (yyscan_t yyscanner)
@@ -1918,7 +2102,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
case EOB_ACT_END_OF_FILE:
{
if ( ap_expr_yywrap(yyscanner ) )
- return EOF;
+ return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
@@ -2022,7 +2206,7 @@ static void ap_expr_yy_load_buffer_state (yyscan_t yyscanner)
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_create_buffer()" );
- b->yy_buf_size = size;
+ b->yy_buf_size = (yy_size_t)size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
@@ -2183,15 +2367,15 @@ static void ap_expr_yyensure_buffer_stack (yyscan_t yyscanner)
* scanner will even need a stack. We use 2 instead of 1 to avoid an
* immediate realloc on the next call.
*/
- num_to_alloc = 1;
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
yyg->yy_buffer_stack = (struct yy_buffer_state**)ap_expr_yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yyensure_buffer_stack()" );
-
+
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
yyg->yy_buffer_stack_max = num_to_alloc;
yyg->yy_buffer_stack_top = 0;
return;
@@ -2200,7 +2384,7 @@ static void ap_expr_yyensure_buffer_stack (yyscan_t yyscanner)
if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
/* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
yyg->yy_buffer_stack = (struct yy_buffer_state**)ap_expr_yyrealloc
@@ -2220,7 +2404,7 @@ static void ap_expr_yyensure_buffer_stack (yyscan_t yyscanner)
* @param base the character buffer
* @param size the size in bytes of the character buffer
* @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE ap_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
@@ -2230,7 +2414,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */
- return 0;
+ return NULL;
b = (YY_BUFFER_STATE) ap_expr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
if ( ! b )
@@ -2239,7 +2423,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
+ b->yy_input_file = NULL;
b->yy_n_chars = b->yy_buf_size;
b->yy_is_interactive = 0;
b->yy_at_bol = 1;
@@ -2262,7 +2446,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t
YY_BUFFER_STATE ap_expr_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
- return ap_expr_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+ return ap_expr_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
}
/** Setup the input buffer state to scan the given bytes. The next call to ap_expr_yylex() will
@@ -2280,7 +2464,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_le
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
+ n = (yy_size_t) (_yybytes_len + 2);
buf = (char *) ap_expr_yyalloc(n ,yyscanner );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_scan_bytes()" );
@@ -2302,7 +2486,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_le
return b;
}
- static void yy_push_state (int new_state , yyscan_t yyscanner)
+ static void yy_push_state (int _new_state , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
@@ -2310,7 +2494,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_le
yy_size_t new_size;
yyg->yy_start_stack_depth += YY_START_STACK_INCR;
- new_size = yyg->yy_start_stack_depth * sizeof( int );
+ new_size = (yy_size_t) yyg->yy_start_stack_depth * sizeof( int );
if ( ! yyg->yy_start_stack )
yyg->yy_start_stack = (int *) ap_expr_yyalloc(new_size ,yyscanner );
@@ -2324,7 +2508,7 @@ YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_le
yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
- BEGIN(new_state);
+ BEGIN(_new_state);
}
static void yy_pop_state (yyscan_t yyscanner)
@@ -2340,9 +2524,11 @@ YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_le
#define YY_EXIT_FAILURE 2
#endif
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
{
- (void) fprintf( stderr, "%s\n", msg );
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ (void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2380,7 +2566,7 @@ YY_EXTRA_TYPE ap_expr_yyget_extra (yyscan_t yyscanner)
int ap_expr_yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
+
if (! YY_CURRENT_BUFFER)
return 0;
@@ -2439,41 +2625,41 @@ void ap_expr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
}
/** Set the current line number.
- * @param line_number
+ * @param _line_number line number
* @param yyscanner The scanner object.
*/
-void ap_expr_yyset_lineno (int line_number , yyscan_t yyscanner)
+void ap_expr_yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "ap_expr_yyset_lineno called with no buffer" , yyscanner);
+ YY_FATAL_ERROR( "ap_expr_yyset_lineno called with no buffer" );
- yylineno = line_number;
+ yylineno = _line_number;
}
/** Set the current column.
- * @param line_number
+ * @param _column_no column number
* @param yyscanner The scanner object.
*/
/** Set the input stream. This does not discard the current
* input buffer.
- * @param in_str A readable stream.
+ * @param _in_str A readable stream.
* @param yyscanner The scanner object.
* @see ap_expr_yy_switch_to_buffer
*/
-void ap_expr_yyset_in (FILE * in_str , yyscan_t yyscanner)
+void ap_expr_yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
+ yyin = _in_str ;
}
-void ap_expr_yyset_out (FILE * out_str , yyscan_t yyscanner)
+void ap_expr_yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
+ yyout = _out_str ;
}
int ap_expr_yyget_debug (yyscan_t yyscanner)
@@ -2482,10 +2668,10 @@ int ap_expr_yyget_debug (yyscan_t yyscanner)
return yy_flex_debug;
}
-void ap_expr_yyset_debug (int bdebug , yyscan_t yyscanner)
+void ap_expr_yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
+ yy_flex_debug = _bdebug ;
}
/* Accessor methods for yylval and yylloc */
@@ -2549,20 +2735,20 @@ int ap_expr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_glob
errno = EINVAL;
return 1;
}
-
+
*ptr_yy_globals = (yyscan_t) ap_expr_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-
+
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
return 1;
}
-
+
/* By setting to 0xAA, we expose bugs in
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
+
ap_expr_yyset_extra (yy_user_defined, *ptr_yy_globals);
-
+
return yy_init_globals ( *ptr_yy_globals );
}
@@ -2573,10 +2759,10 @@ static int yy_init_globals (yyscan_t yyscanner)
* This function is called from ap_expr_yylex_destroy(), so don't allocate here.
*/
- yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack = NULL;
yyg->yy_buffer_stack_top = 0;
yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_c_buf_p = NULL;
yyg->yy_init = 0;
yyg->yy_start = 0;
@@ -2589,8 +2775,8 @@ static int yy_init_globals (yyscan_t yyscanner)
yyin = stdin;
yyout = stdout;
#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
+ yyin = NULL;
+ yyout = NULL;
#endif
/* For future reference: Set errno on error, since we are called by
@@ -2636,7 +2822,10 @@ int ap_expr_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2645,7 +2834,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
@@ -2655,11 +2844,16 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
void *ap_expr_yyalloc (yy_size_t size , yyscan_t yyscanner)
{
- return (void *) malloc( size );
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ return malloc(size);
}
void *ap_expr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
@@ -2667,17 +2861,19 @@ void *ap_expr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
* any pointer type to void*, and deal with argument conversions
* as though doing an assignment.
*/
- return (void *) realloc( (char *) ptr, size );
+ return realloc(ptr, size);
}
void ap_expr_yyfree (void * ptr , yyscan_t yyscanner)
{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
free( (char *) ptr ); /* see ap_expr_yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 413 "util_expr_scan.l"
+#line 514 "util_expr_scan.l"
diff --git a/server/util_expr_scan.l b/server/util_expr_scan.l
index f048d0dcf5..a7d5e99267 100644
--- a/server/util_expr_scan.l
+++ b/server/util_expr_scan.l
@@ -34,16 +34,17 @@
%option warn
%option noinput nounput noyy_top_state
%option stack
-%x str
-%x var
-%x vararg
-%x regex regex_flags
+
+%x str expr
+%x var vararg
+%x split regex regsub regflags
%{
#include "util_expr_private.h"
#include "util_expr_parse.h"
#include "http_main.h"
#include "http_log.h"
+#include "apr_lib.h"
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
@@ -65,38 +66,118 @@
* XXX: longjmp. It is not clear if the scanner is in any state
* XXX: to be cleaned up, though.
*/
+static int unreachable = 0;
#define YY_FATAL_ERROR(msg) \
do { \
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, \
APLOGNO(03296) \
"expr parser fatal error (BUG?): " \
"%s, exiting", msg); \
- abort(); \
+ if (unreachable) { \
+ /* Not reached, silence [-Wunused-function] */ \
+ yy_fatal_error(msg, yyscanner); \
+ } \
+ else { \
+ abort(); \
+ } \
} while (0)
#define YY_EXTRA_TYPE ap_expr_parse_ctx_t*
-#define PERROR(msg) do { yyextra->error2 = msg ; return T_ERROR; } while (0)
+#define PERROR(msg) do { \
+ yyextra->error2 = msg; \
+ return T_ERROR; \
+} while (0)
+
+#define PERROR_CHAR(prefix, chr) do { \
+ char *msg; \
+ if (apr_isprint((chr))) { \
+ msg = apr_psprintf(yyextra->pool, prefix "'%c'", (char)(chr)); \
+ } \
+ else { \
+ msg = apr_psprintf(yyextra->pool, prefix "'\\x%.2X'", (int)(chr)); \
+ } \
+ PERROR(msg); \
+} while (0)
+
+#define STACK_PUSH() do { \
+ ap_expr_parser_stack_t *sk; \
+ if (yyextra->spares) { \
+ sk = yyextra->spares; \
+ yyextra->spares = sk->next; \
+ } \
+ else { \
+ sk = apr_palloc(yyextra->ptemp, sizeof(*sk)); \
+ } \
+ sk->scan_ptr = sk->scan_buf; \
+ sk->scan_stop = sk->scan_buf[0] = '\0'; \
+ sk->scan_flag = 0; \
+ sk->next = yyextra->current; \
+ yyextra->current = sk; \
+} while (0)
+
+#define STACK_POP() do { \
+ ap_expr_parser_stack_t *sk; \
+ sk = yyextra->current; \
+ yyextra->current = sk->next; \
+ sk->next = yyextra->spares; \
+ yyextra->spares = sk; \
+} while (0)
+
+#define STATE_PUSH(st, sk) do { \
+ yy_push_state((st), yyscanner); \
+ if ((sk)) { \
+ STACK_PUSH(); \
+ } \
+} while (0)
+
+#define STATE_POP(sk) do { \
+ if ((sk)) { \
+ STACK_POP(); \
+ } \
+ yy_pop_state(yyscanner); \
+} while (0)
+
+#define str_ptr (yyextra->current->scan_ptr)
+#define str_buf (yyextra->current->scan_buf)
+#define str_stop (yyextra->current->scan_stop)
+#define str_flag (yyextra->current->scan_flag)
+
+#define STR_APPEND_CHECK(chr, chk) do { \
+ if ((chk) && apr_iscntrl((chr))) { \
+ PERROR_CHAR("Invalid string character ", (chr)); \
+ } \
+ if (str_ptr >= str_buf + sizeof(str_buf) - 1) { \
+ PERROR("String too long"); \
+ } \
+ *str_ptr++ = (char)(chr); \
+} while (0)
-#define str_ptr (yyextra->scan_ptr)
-#define str_buf (yyextra->scan_buf)
-#define str_del (yyextra->scan_del)
+#define STR_APPEND_NOCHECK(chr) \
+ STR_APPEND_CHECK((chr), 0)
-#define STR_APPEND(c) do { \
- *str_ptr++ = (c); \
- if (str_ptr >= str_buf + sizeof(str_buf)) \
- PERROR("String too long"); \
- } while (0)
+#define STR_EMPTY() \
+ (str_ptr == str_buf)
+
+#define STR_RETURN() \
+ (apr_pstrdup(yyextra->pool, (*str_ptr = '\0', str_ptr = str_buf)))
%}
+ANY (.|\n)
+SPACE [ \t\n]
+QUOTE ["']
+TOKEN ([a-zA-Z][a-zA-Z0-9_]*)
+VAR_BEGIN (\%\{)
+VAR_ARG (\:)
+VAR_END (\})
+VAREXP_BEGIN (\%\{\:)
+VAREXP_END (\:\})
+REG_SEP [/#$%^|?!'",;:._-]
+REG_REF (\$[0-9])
%%
- char regex_buf[MAX_STRING_LEN];
- char *regex_ptr = NULL;
- char regex_del = '\0';
-
%{
/*
* Set initial state for string expressions
@@ -104,286 +185,306 @@
if (yyextra->at_start) {
yyextra->at_start = 0;
if (yyextra->flags & AP_EXPR_FLAG_STRING_RESULT) {
- BEGIN(str);
+ STATE_PUSH(str, 1);
return T_EXPR_STRING;
}
else {
+ STATE_PUSH(expr, 1);
return T_EXPR_BOOL;
}
}
%}
/*
- * Whitespaces
+ * Back off INITIAL pushes
*/
-[ \t\n]+ {
- /* NOP */
+<str><<EOF>> {
+ STATE_POP(0); /* <str> */
+ if (YY_START != INITIAL) {
+ PERROR("Unterminated string");
+ }
+ yylval->cpVal = STR_RETURN();
+ STACK_POP(); /* ^ after this */
+ return T_STRING;
+}
+<expr><<EOF>> {
+ STATE_POP(1); /* <expr> */
+ if (YY_START != INITIAL) {
+ PERROR("Unterminated expression");
+ }
}
- /*
- * strings ("..." and '...')
- */
-["'] {
- str_ptr = str_buf;
- str_del = yytext[0];
- BEGIN(str);
- return T_STR_BEGIN;
-}
-<str>["'] {
- if (yytext[0] == str_del) {
- if (YY_START == var) {
- PERROR("Unterminated variable in string");
- }
- else if (str_ptr == str_buf) {
- BEGIN(INITIAL);
- return T_STR_END;
- }
- else {
- /* return what we have so far and scan delimiter again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- yyless(0);
- str_ptr = str_buf;
+<str>{QUOTE} {
+ if (yytext[0] == str_stop) {
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
return T_STRING;
}
+ STATE_POP(1); /* <str> */
+ return T_STR_END;
}
- else {
- STR_APPEND(yytext[0]);
- }
-}
-<str,var,vararg>\n {
- PERROR("Unterminated string or variable");
+ STR_APPEND_NOCHECK(yytext[0]);
}
-<var,vararg><<EOF>> {
- PERROR("Unterminated string or variable");
-}
-<str><<EOF>> {
- if (!(yyextra->flags & AP_EXPR_FLAG_STRING_RESULT)) {
- PERROR("Unterminated string or variable");
- }
- else {
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- BEGIN(INITIAL);
+
+ /* regexp backref inside string/arg */
+<str,vararg,regsub>{REG_REF} {
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
return T_STRING;
}
+ yylval->num = yytext[1] - '0';
+ return T_REG_REF;
}
-<str,vararg>\\[0-7]{1,3} {
- int result;
-
- (void)sscanf(yytext+1, "%o", &result);
- if (result > 0xff) {
- PERROR("Escape sequence out of bound");
- }
- else {
- STR_APPEND(result);
+ /* variable inside string/arg */
+<str,vararg,regsub>{VAR_BEGIN} {
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
+ return T_STRING;
}
+ STATE_PUSH(var, 1);
+ return T_VAR_BEGIN;
}
-<str,vararg>\\[0-9]+ {
- PERROR("Bad escape sequence");
-}
-<str,vararg>\\n { STR_APPEND('\n'); }
-<str,vararg>\\r { STR_APPEND('\r'); }
-<str,vararg>\\t { STR_APPEND('\t'); }
-<str,vararg>\\b { STR_APPEND('\b'); }
-<str,vararg>\\f { STR_APPEND('\f'); }
-<str,vararg>\\(.|\n) { STR_APPEND(yytext[1]); }
- /* regexp backref inside string/arg */
-<str,vararg>[$][0-9] {
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '$x' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- yyless(0);
+<str,vararg,regsub>{VAREXP_BEGIN} {
+ if (!STR_EMPTY()) {
+ yyless(0); /* come back below */
+ yylval->cpVal = STR_RETURN();
return T_STRING;
}
- else {
- yylval->num = yytext[1] - '0';
- return T_REGEX_BACKREF;
- }
+ STATE_PUSH(expr, 1);
+ return T_VAREXP_BEGIN;
}
-<str,vararg>[^\\\n"'%}$]+ {
- char *cp = yytext;
- while (*cp != '\0') {
- STR_APPEND(*cp);
- cp++;
- }
+ /* Any non-octal or octal higher than 377 (decimal 255) is invalid */
+<str,vararg,regsub>\\([4-9][0-9]{2}|[8-9][0-9]{0,2}) {
+ PERROR("Bad character escape sequence");
}
+<str,vararg,regsub>\\[0-7]{1,3} {
+ int result;
+ (void)sscanf(yytext+1, "%o", &result);
+ STR_APPEND_NOCHECK(result);
+}
+<str,vararg,regsub>\\x[0-9A-Fa-f]{1,2} {
+ int result;
+ (void)sscanf(yytext+1, "%x", &result);
+ STR_APPEND_NOCHECK(result);
+}
+<str,vararg,regsub>\\n { STR_APPEND_NOCHECK('\n'); }
+<str,vararg,regsub>\\r { STR_APPEND_NOCHECK('\r'); }
+<str,vararg,regsub>\\t { STR_APPEND_NOCHECK('\t'); }
+<str,vararg,regsub>\\b { STR_APPEND_NOCHECK('\b'); }
+<str,vararg,regsub>\\f { STR_APPEND_NOCHECK('\f'); }
+<str,vararg,regsub>\\. { STR_APPEND_CHECK(yytext[1], 1); }
- /* variable inside string/arg */
-<str,vararg>%\{ {
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '%{' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- yyless(0);
- str_ptr = str_buf;
- return T_STRING;
- }
- else {
- yy_push_state(var, yyscanner);
- return T_VAR_BEGIN;
- }
+<str,vararg,regsub>\n {
+ PERROR("Unterminated string or variable");
}
-<vararg>[%$] {
- STR_APPEND(yytext[0]);
+<str>{ANY} {
+ STR_APPEND_CHECK(yytext[0], 1);
}
-<str>[%}$] {
- STR_APPEND(yytext[0]);
+<expr>{SPACE}+ {
+ /* NOP */
}
-%\{ {
- yy_push_state(var, yyscanner);
- return T_VAR_BEGIN;
+<expr>{QUOTE} {
+ STATE_PUSH(str, 1);
+ str_stop = yytext[0];
+ return T_STR_BEGIN;
}
-[$][0-9] {
- yylval->num = yytext[1] - '0';
- return T_REGEX_BACKREF;
+<expr>{VAREXP_BEGIN} {
+ STATE_PUSH(expr, 1);
+ return T_VAREXP_BEGIN;
+}
+<expr>{VAREXP_END} {
+ STATE_POP(1); /* <expr> */
+ return T_VAREXP_END;
}
- /*
- * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
- */
-<var>[a-ij-rs-zA-IJ-RS-Z][a-ij-rs-zA-IJ-RS-Z0-9_]* {
+
+<expr>{VAR_BEGIN} {
+ STATE_PUSH(var, 1);
+ return T_VAR_BEGIN;
+}
+<var>{TOKEN} {
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
return T_ID;
}
-
-<var>\} {
- yy_pop_state(yyscanner);
+<var>{VAR_ARG} {
+ STATE_PUSH(vararg, 0);
+ return yytext[0];
+}
+<vararg>{VAR_END} {
+ yyless(0); /* let <var> handle */
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(0); /* <vararg> */
+ return T_STRING;
+}
+<vararg>{ANY} {
+ STR_APPEND_CHECK(yytext[0], 1);
+}
+<var>{VAR_END} {
+ STATE_POP(1); /* <var> */
return T_VAR_END;
}
-
-<var>: {
- BEGIN(vararg);
- return yytext[0];
+<var>{ANY} {
+ PERROR_CHAR("Unexpected variable character ", yytext[0]);
}
-
-<var>.|\n {
- char *msg = apr_psprintf(yyextra->pool,
- "Invalid character in variable name '%c'", yytext[0]);
- PERROR(msg);
+<var,vararg><<EOF>> {
+ PERROR("Unterminated variable");
}
-<vararg>\} {
- if (str_ptr != str_buf) {
- /* return what we have so far and scan '}' again */
- *str_ptr = '\0';
- yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
- str_ptr = str_buf;
- yyless(0);
- return T_STRING;
- }
- else {
- yy_pop_state(yyscanner);
- return T_VAR_END;
- }
-}
/*
* Regular Expression
*/
-"m"[/#$%^,;:_\?\|\^\-\!\.\'\"] {
- regex_del = yytext[1];
- regex_ptr = regex_buf;
- BEGIN(regex);
-}
-"/" {
- regex_del = yytext[0];
- regex_ptr = regex_buf;
- BEGIN(regex);
-}
-<regex>.|\n {
- if (yytext[0] == regex_del) {
- *regex_ptr = '\0';
- BEGIN(regex_flags);
+<expr>\/ {
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[0];
+ str_flag = 'm';
+ return T_REGEX;
+}
+<expr>[ms]{REG_SEP} {
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[1];
+ str_flag = yytext[0];
+ return (str_flag == 'm') ? T_REGEX : T_REGSUB;
+}
+<regex>{ANY} {
+ if (yytext[0] == str_stop) {
+ STATE_POP(0); /* <regex> */
+ if (str_flag == 'm') {
+ STATE_PUSH(regflags, 0);
+ }
+ else {
+ STATE_PUSH(regsub, 0);
+ }
+ yylval->cpVal = STR_RETURN();
+ return T_REG_MATCH;
+ }
+ STR_APPEND_CHECK(yytext[0], 1);
+}
+<regsub>{ANY} {
+ if (yytext[0] == str_stop) {
+ STATE_POP(0); /* <regsub> */
+ STATE_PUSH(regflags, 0);
}
else {
- *regex_ptr++ = yytext[0];
- if (regex_ptr >= regex_buf + sizeof(regex_buf))
- PERROR("Regexp too long");
+ STR_APPEND_CHECK(yytext[0], 1);
}
}
-<regex_flags>i {
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- BEGIN(INITIAL);
- return T_REGEX_I;
+<regflags>{ANY} {
+ if (ap_strchr_c("ismg", yytext[0])) {
+ STR_APPEND_NOCHECK(yytext[0]);
+ }
+ else if (apr_isalnum(yytext[0])) {
+ PERROR("Invalid regexp flag(s)");
+ }
+ else {
+ yyless(0); /* not a flags, rewind */
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(1); /* <regflags> */
+ return T_REG_FLAGS;
+ }
}
-<regex_flags>.|\n {
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- yyless(0);
- BEGIN(INITIAL);
- return T_REGEX;
+<regflags><<EOF>> {
+ yylval->cpVal = STR_RETURN();
+ STATE_POP(1); /* <regflags> */
+ return T_REG_FLAGS;
}
-<regex_flags><<EOF>> {
- yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
- BEGIN(INITIAL);
- return T_REGEX;
+<regex,regsub><<EOF>> {
+ PERROR("Unterminated regexp");
+}
+
+<expr>{REG_REF} {
+ yylval->num = yytext[1] - '0';
+ return T_REG_REF;
}
/*
* Operators
*/
-==? { return T_OP_STR_EQ; }
-"!=" { return T_OP_STR_NE; }
-"<" { return T_OP_STR_LT; }
-"<=" { return T_OP_STR_LE; }
-">" { return T_OP_STR_GT; }
-">=" { return T_OP_STR_GE; }
-"=~" { return T_OP_REG; }
-"!~" { return T_OP_NRE; }
-"and" { return T_OP_AND; }
-"&&" { return T_OP_AND; }
-"or" { return T_OP_OR; }
-"||" { return T_OP_OR; }
-"not" { return T_OP_NOT; }
-"!" { return T_OP_NOT; }
-"." { return T_OP_CONCAT; }
-"-in" { return T_OP_IN; }
-"-eq" { return T_OP_EQ; }
-"-ne" { return T_OP_NE; }
-"-ge" { return T_OP_GE; }
-"-le" { return T_OP_LE; }
-"-gt" { return T_OP_GT; }
-"-lt" { return T_OP_LT; }
+<expr>==? { return T_OP_STR_EQ; }
+<expr>"!=" { return T_OP_STR_NE; }
+<expr>"<" { return T_OP_STR_LT; }
+<expr>"<=" { return T_OP_STR_LE; }
+<expr>">" { return T_OP_STR_GT; }
+<expr>">=" { return T_OP_STR_GE; }
+<expr>"=~" { return T_OP_REG; }
+<expr>"!~" { return T_OP_NRE; }
+<expr>"and" { return T_OP_AND; }
+<expr>"&&" { return T_OP_AND; }
+<expr>"or" { return T_OP_OR; }
+<expr>"||" { return T_OP_OR; }
+<expr>"not" { return T_OP_NOT; }
+<expr>"!" { return T_OP_NOT; }
+<expr>"." { return T_OP_CONCAT; }
+<expr>"-in" { return T_OP_IN; }
+<expr>"-eq" { return T_OP_EQ; }
+<expr>"-ne" { return T_OP_NE; }
+<expr>"-ge" { return T_OP_GE; }
+<expr>"-le" { return T_OP_LE; }
+<expr>"-gt" { return T_OP_GT; }
+<expr>"-lt" { return T_OP_LT; }
/* for compatibility with ssl_expr */
-"lt" { return T_OP_LT; }
-"le" { return T_OP_LE; }
-"gt" { return T_OP_GT; }
-"ge" { return T_OP_GE; }
-"ne" { return T_OP_NE; }
-"eq" { return T_OP_EQ; }
-"in" { return T_OP_IN; }
-
-"-"[a-ij-rs-zA-IJ-RS-Z_] {
+<expr>"lt" { return T_OP_LT; }
+<expr>"le" { return T_OP_LE; }
+<expr>"gt" { return T_OP_GT; }
+<expr>"ge" { return T_OP_GE; }
+<expr>"ne" { return T_OP_NE; }
+<expr>"eq" { return T_OP_EQ; }
+<expr>"in" { return T_OP_IN; }
+
+<expr>"-"[a-zA-Z_][a-zA-Z_0-9]+ {
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
- return T_OP_UNARY;
+ return T_OP_BINARY;
}
-"-"[a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z_0-9]+ {
+<expr>"-"[a-zA-Z_] {
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
- return T_OP_BINARY;
+ return T_OP_UNARY;
+}
+
+ /* Split a string (or list) into a(nother) list */
+<expr>"split" {
+ STATE_PUSH(split, 0);
+ return T_OP_SPLIT;
+}
+<split>{REG_SEP} {
+ STATE_POP(0); /* <split> */
+ STATE_PUSH(regex, 1);
+ str_stop = yytext[0];
+ str_flag = 'S';
+}
+<split>{ANY} {
+ PERROR("Expecting split regular expression");
+}
+<split><<EOF>> {
+ PERROR("Unterminated split");
+}
+
+ /* Join a list into a string */
+<expr>"join" {
+ return T_OP_JOIN;
}
/*
* Specials
*/
-"true" { return T_TRUE; }
-"false" { return T_FALSE; }
+<expr>"true" { return T_TRUE; }
+<expr>"false" { return T_FALSE; }
/*
* Digits
*/
--?[0-9]+ {
+<expr>\-?[0-9]+ {
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
return T_DIGIT;
}
@@ -391,7 +492,7 @@
/*
* Identifiers
*/
-[a-ij-rs-zA-IJ-RS-Z][a-ij-rs-zA-IJ-RS-Z0-9_]* {
+<expr>{TOKEN} {
yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
return T_ID;
}
@@ -399,16 +500,15 @@
/*
* These are parts of the grammar and are returned as is
*/
-[(){},:] {
+<expr>[(){},] {
return yytext[0];
}
/*
* Anything else is an error
*/
-.|\n {
- char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);
- PERROR(msg);
+<INITIAL,expr>{ANY} {
+ PERROR_CHAR("Parse error near character ", yytext[0]);
}
%%
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 40dbf0787f..73e7fc6b1f 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -246,6 +246,10 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
options |= PCREn(NOTBOL);
if ((eflags & AP_REG_NOTEOL) != 0)
options |= PCREn(NOTEOL);
+ if ((eflags & AP_REG_NOTEMPTY) != 0)
+ options |= PCREn(NOTEMPTY);
+ if ((eflags & AP_REG_ANCHORED) != 0)
+ options |= PCREn(ANCHORED);
#ifdef HAVE_PCRE2
/* TODO: create a generic TLS matchdata buffer of some nmatch limit,