From 08ddf7ad0a257c1b27b5fdb8e32fcd40b4dbdad1 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Mon, 2 Oct 2017 21:57:26 +0000 Subject: [PATCH] ap_expr: open string expressions to the . Introduces the syntax "%{::}", borrowed from the '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 construct allows that (say the syntax "%{::}" 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///") 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 --- include/ap_regex.h | 3 + server/util_expr_eval.c | 426 ++++++++++-- server/util_expr_parse.c | 754 ++++++++++++-------- server/util_expr_parse.h | 65 +- server/util_expr_parse.y | 157 +++-- server/util_expr_private.h | 32 +- server/util_expr_scan.c | 1348 +++++++++++++++++++++--------------- server/util_expr_scan.l | 566 ++++++++------- server/util_pcre.c | 4 + 9 files changed, 2117 insertions(+), 1238 deletions(-) diff --git a/include/ap_regex.h b/include/ap_regex.h index dbe9b24690..8f891fae98 100644 --- a/include/ap_regex.h +++ b/include/ap_regex.h @@ -76,6 +76,9 @@ extern "C" { #define AP_REG_MULTI 0x10 /**< perl's /g (needs fixing) */ #define AP_REG_NOMEM 0x20 /**< nomem in our code */ #define AP_REG_DOTALL 0x40 /**< perl's /s flag */ + +#define AP_REG_NOTEMPTY 0x080 /**< Empty match not valid */ +#define AP_REG_ANCHORED 0x100 /**< Match at the first position */ #define AP_REG_MATCH "MATCH_" /**< suggested prefix for ap_regname */ 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); } - break; - - case 38: -/* Line 1787 of yacc.c */ -#line 160 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } - break; - - case 39: -/* Line 1787 of yacc.c */ -#line 161 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } - 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); } - 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); } - 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); } - 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); } - break; - - case 44: -/* Line 1787 of yacc.c */ -#line 170 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } - break; - - case 45: -/* Line 1787 of yacc.c */ #line 171 "util_expr_parse.y" { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; - case 46: + case 38: /* Line 1787 of yacc.c */ #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 173 "util_expr_parse.y" + { YYABORT; } + break; + + case 40: +/* Line 1787 of yacc.c */ +#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 177 "util_expr_parse.y" { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; + case 42: +/* Line 1787 of yacc.c */ +#line 178 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 43: +/* Line 1787 of yacc.c */ +#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 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 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 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" - { - ap_regex_t *regex; - if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal), - AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { - ctx->error = "Failed to compile regular expression"; - YYERROR; - } - (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); - } +#line 189 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } break; case 50: /* Line 1787 of yacc.c */ -#line 186 "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) { - ctx->error = "Failed to compile regular expression"; - YYERROR; - } - (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); - } +#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 197 "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); - } +#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 204 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } +#line 192 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; case 53: /* Line 1787 of yacc.c */ -#line 207 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } +#line 193 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; case 54: /* Line 1787 of yacc.c */ -#line 208 "util_expr_parse.y" +#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" + { + (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) = e; + } + break; + + case 60: +/* Line 1787 of yacc.c */ +#line 216 "util_expr_parse.y" + { + 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) = e; + } + break; + + case 61: +/* Line 1787 of yacc.c */ +#line 225 "util_expr_parse.y" + { + /* Returns a list: + * ~= split/:// + * => split around ':', replace it with empty + * ~= split/:/\n/ + * => split around ':', replace it with '\n' + * ~= 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_Regref, n, NULL, ctx); + } + break; + + case 66: +/* Line 1787 of yacc.c */ +#line 254 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } + break; + + case 67: +/* Line 1787 of yacc.c */ +#line 258 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } + break; + + case 68: +/* Line 1787 of yacc.c */ +#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 T_DIGIT "number" %token T_ID "identifier" -%token T_STRING "cstring" -%token T_REGEX "regex" -%token T_REGEX_I "case-indendent regex" -%token T_REGEX_BACKREF "regex back reference" +%token T_STRING "string" + +%token T_REGEX "match regex" +%token T_REGSUB "substitution regex" +%token T_REG_MATCH "match pattern of the regex" +%token T_REG_SUBST "substitution pattern of the regex" +%token T_REG_FLAGS "flags of the regex" +%token T_REG_REF "regex back reference" + %token T_OP_UNARY "unary operator" %token 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 expr -%type comparison -%type strfunccall "function" -%type lstfunccall "listfunction" -%type regex -%type words -%type wordlist -%type word -%type string -%type strpart "stringpart" -%type var "variable" -%type backref "rebackref" +%type cond "condition" +%type comp "comparison" +%type strfunc "string function" +%type lstfunc "list function" +%type wordlist "list of words" +%type words "tuple of words" +%type word "word expression" +%type string "string expression" +%type strany "any string expression" +%type var "variable expression" +%type regex "regular expression match" +%type regsub "regular expression substitution" +%type regsplit "regular expression split" +%type regany "any regular expression" +%type 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); } - | word T_OP_CONCAT word { $$ = ap_expr_make(op_Concat, $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); } + | 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; } + | 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; } - $$ = ap_expr_make(op_Regex, regex, NULL, ctx); + $$ = e; } ; +regsplit : T_OP_SPLIT T_REG_MATCH string T_REG_FLAGS { + /* Returns a list: + * ~= split/:// + * => split around ':', replace it with empty + * ~= split/:/\n/ + * => split around ':', replace it with '\n' + * ~= 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; + } + $$ = 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, + 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, - 7, 8, 9, 20, 60, 46, 48, 50, 45, 49, - 51, 47, 38, 64, 42, 64, 5, 6, 64, 61, - 5, 62, 0 + 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, + 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, - 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, + 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, + 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, - 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 + 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, + 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, - 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 + 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, + 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, - 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, + 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, - 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, + 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, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123 + 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, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 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, 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, 5, 5, + 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, + 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, - 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, + 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, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123 + 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 str_ptr (yyextra->scan_ptr) -#define str_buf (yyextra->scan_buf) -#define str_del (yyextra->scan_del) +#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 STR_APPEND(c) do { \ - *str_ptr++ = (c); \ - if (str_ptr >= str_buf + sizeof(str_buf)) \ - PERROR("String too long"); \ - } 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) -#line 630 "util_expr_scan.c" +#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_APPEND_NOCHECK(chr) \ + STR_APPEND_CHECK((chr), 0) + +#define STR_EMPTY() \ + (str_ptr == str_buf) + +#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 YY_STATE_EOF(str): +#line 201 "util_expr_scan.l" +{ + STATE_POP(0); /* */ + if (YY_START != INITIAL) { + PERROR("Unterminated string"); + } + yylval->cpVal = STR_RETURN(); + STACK_POP(); /* ^ after this */ + return T_STRING; +} + YY_BREAK +case YY_STATE_EOF(expr): +#line 210 "util_expr_scan.l" +{ + STATE_POP(1); /* */ + if (YY_START != INITIAL) { + PERROR("Unterminated expression"); + } +} + YY_BREAK case 1: -/* rule 1 can match eol */ YY_RULE_SETUP -#line 118 "util_expr_scan.l" -{ - /* NOP */ -} - YY_BREAK -/* - * strings ("..." and '...') - */ -case 2: -YY_RULE_SETUP -#line 125 "util_expr_scan.l" +#line 217 "util_expr_scan.l" { - str_ptr = str_buf; - str_del = yytext[0]; - BEGIN(str); - return T_STR_BEGIN; -} - YY_BREAK -case 3: -YY_RULE_SETUP -#line 131 "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); /* */ + return T_STR_END; } - else { - STR_APPEND(yytext[0]); + STR_APPEND_NOCHECK(yytext[0]); +} + YY_BREAK +/* regexp backref inside string/arg */ +case 2: +YY_RULE_SETUP +#line 231 "util_expr_scan.l" +{ + 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 +/* variable inside string/arg */ +case 3: +YY_RULE_SETUP +#line 242 "util_expr_scan.l" +{ + 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 4: -/* rule 4 can match eol */ YY_RULE_SETUP -#line 153 "util_expr_scan.l" +#line 252 "util_expr_scan.l" { - PERROR("Unterminated string or variable"); -} - YY_BREAK -case YY_STATE_EOF(var): -case YY_STATE_EOF(vararg): -#line 156 "util_expr_scan.l" -{ - PERROR("Unterminated string or variable"); -} - YY_BREAK -case YY_STATE_EOF(str): -#line 159 "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); /* */ + 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" +{ + STATE_PUSH(var, 1); + return T_VAR_BEGIN; +} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 315 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; } YY_BREAK -case 21: -YY_RULE_SETUP -#line 259 "util_expr_scan.l" -{ - yy_pop_state(yyscanner); - return T_VAR_END; -} - 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 handle */ + yylval->cpVal = STR_RETURN(); + STATE_POP(0); /* */ + 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 +case 25: +YY_RULE_SETUP +#line 332 "util_expr_scan.l" +{ + STATE_POP(1); /* */ + return T_VAR_END; +} + YY_BREAK +case 26: +/* rule 26 can match eol */ +YY_RULE_SETUP +#line 336 "util_expr_scan.l" +{ + 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 25: -YY_RULE_SETUP -#line 293 "util_expr_scan.l" -{ - regex_del = yytext[1]; - regex_ptr = regex_buf; - BEGIN(regex); -} - YY_BREAK -case 26: -YY_RULE_SETUP -#line 298 "util_expr_scan.l" -{ - regex_del = yytext[0]; - regex_ptr = regex_buf; - BEGIN(regex); -} - YY_BREAK 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); /* */ + 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); /* */ + 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); /* */ + return T_REG_FLAGS; + } +} + YY_BREAK +case YY_STATE_EOF(regflags): +#line 396 "util_expr_scan.l" +{ + yylval->cpVal = STR_RETURN(); + STATE_POP(1); /* */ + 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: -YY_RULE_SETUP -#line 334 "util_expr_scan.l" -{ return T_OP_STR_EQ; } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 335 "util_expr_scan.l" -{ return T_OP_STR_NE; } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 336 "util_expr_scan.l" -{ return T_OP_STR_LT; } - YY_BREAK case 33: YY_RULE_SETUP -#line 337 "util_expr_scan.l" -{ return T_OP_STR_LE; } +#line 413 "util_expr_scan.l" +{ return T_OP_STR_EQ; } YY_BREAK case 34: YY_RULE_SETUP -#line 338 "util_expr_scan.l" -{ return T_OP_STR_GT; } +#line 414 "util_expr_scan.l" +{ return T_OP_STR_NE; } YY_BREAK case 35: YY_RULE_SETUP -#line 339 "util_expr_scan.l" -{ return T_OP_STR_GE; } +#line 415 "util_expr_scan.l" +{ return T_OP_STR_LT; } YY_BREAK case 36: YY_RULE_SETUP -#line 340 "util_expr_scan.l" -{ return T_OP_REG; } +#line 416 "util_expr_scan.l" +{ return T_OP_STR_LE; } YY_BREAK case 37: YY_RULE_SETUP -#line 341 "util_expr_scan.l" -{ return T_OP_NRE; } +#line 417 "util_expr_scan.l" +{ return T_OP_STR_GT; } YY_BREAK case 38: YY_RULE_SETUP -#line 342 "util_expr_scan.l" -{ return T_OP_AND; } +#line 418 "util_expr_scan.l" +{ return T_OP_STR_GE; } YY_BREAK case 39: YY_RULE_SETUP -#line 343 "util_expr_scan.l" -{ return T_OP_AND; } +#line 419 "util_expr_scan.l" +{ return T_OP_REG; } YY_BREAK case 40: YY_RULE_SETUP -#line 344 "util_expr_scan.l" -{ return T_OP_OR; } +#line 420 "util_expr_scan.l" +{ return T_OP_NRE; } YY_BREAK case 41: YY_RULE_SETUP -#line 345 "util_expr_scan.l" -{ return T_OP_OR; } +#line 421 "util_expr_scan.l" +{ return T_OP_AND; } YY_BREAK case 42: YY_RULE_SETUP -#line 346 "util_expr_scan.l" -{ return T_OP_NOT; } +#line 422 "util_expr_scan.l" +{ return T_OP_AND; } YY_BREAK case 43: YY_RULE_SETUP -#line 347 "util_expr_scan.l" -{ return T_OP_NOT; } +#line 423 "util_expr_scan.l" +{ return T_OP_OR; } YY_BREAK case 44: YY_RULE_SETUP -#line 348 "util_expr_scan.l" -{ return T_OP_CONCAT; } +#line 424 "util_expr_scan.l" +{ return T_OP_OR; } YY_BREAK case 45: YY_RULE_SETUP -#line 349 "util_expr_scan.l" -{ return T_OP_IN; } +#line 425 "util_expr_scan.l" +{ return T_OP_NOT; } YY_BREAK case 46: YY_RULE_SETUP -#line 350 "util_expr_scan.l" -{ return T_OP_EQ; } +#line 426 "util_expr_scan.l" +{ return T_OP_NOT; } YY_BREAK case 47: YY_RULE_SETUP -#line 351 "util_expr_scan.l" -{ return T_OP_NE; } +#line 427 "util_expr_scan.l" +{ return T_OP_CONCAT; } YY_BREAK case 48: YY_RULE_SETUP -#line 352 "util_expr_scan.l" -{ return T_OP_GE; } +#line 428 "util_expr_scan.l" +{ return T_OP_IN; } YY_BREAK case 49: YY_RULE_SETUP -#line 353 "util_expr_scan.l" -{ return T_OP_LE; } +#line 429 "util_expr_scan.l" +{ return T_OP_EQ; } YY_BREAK case 50: YY_RULE_SETUP -#line 354 "util_expr_scan.l" -{ return T_OP_GT; } +#line 430 "util_expr_scan.l" +{ return T_OP_NE; } YY_BREAK case 51: YY_RULE_SETUP -#line 355 "util_expr_scan.l" -{ return T_OP_LT; } +#line 431 "util_expr_scan.l" +{ return T_OP_GE; } YY_BREAK -/* for compatibility with ssl_expr */ case 52: YY_RULE_SETUP -#line 358 "util_expr_scan.l" -{ return T_OP_LT; } +#line 432 "util_expr_scan.l" +{ return T_OP_LE; } YY_BREAK case 53: YY_RULE_SETUP -#line 359 "util_expr_scan.l" -{ return T_OP_LE; } +#line 433 "util_expr_scan.l" +{ return T_OP_GT; } YY_BREAK case 54: YY_RULE_SETUP -#line 360 "util_expr_scan.l" -{ return T_OP_GT; } +#line 434 "util_expr_scan.l" +{ return T_OP_LT; } YY_BREAK +/* for compatibility with ssl_expr */ case 55: YY_RULE_SETUP -#line 361 "util_expr_scan.l" -{ return T_OP_GE; } +#line 437 "util_expr_scan.l" +{ return T_OP_LT; } YY_BREAK case 56: YY_RULE_SETUP -#line 362 "util_expr_scan.l" -{ return T_OP_NE; } +#line 438 "util_expr_scan.l" +{ return T_OP_LE; } YY_BREAK case 57: YY_RULE_SETUP -#line 363 "util_expr_scan.l" -{ return T_OP_EQ; } +#line 439 "util_expr_scan.l" +{ return T_OP_GT; } YY_BREAK case 58: YY_RULE_SETUP -#line 364 "util_expr_scan.l" -{ return T_OP_IN; } +#line 440 "util_expr_scan.l" +{ return T_OP_GE; } YY_BREAK case 59: YY_RULE_SETUP -#line 366 "util_expr_scan.l" -{ - yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_UNARY; -} +#line 441 "util_expr_scan.l" +{ return T_OP_NE; } YY_BREAK case 60: YY_RULE_SETUP -#line 371 "util_expr_scan.l" +#line 442 "util_expr_scan.l" +{ return T_OP_EQ; } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 443 "util_expr_scan.l" +{ return T_OP_IN; } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 445 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); return T_OP_BINARY; } YY_BREAK +case 63: +YY_RULE_SETUP +#line 450 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + 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); /* */ + 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 str_ptr (yyextra->scan_ptr) -#define str_buf (yyextra->scan_buf) -#define str_del (yyextra->scan_del) +#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 STR_APPEND(c) do { \ - *str_ptr++ = (c); \ - if (str_ptr >= str_buf + sizeof(str_buf)) \ - PERROR("String too long"); \ - } 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_APPEND_NOCHECK(chr) \ + STR_APPEND_CHECK((chr), 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 */ +<> { + STATE_POP(0); /* */ + if (YY_START != INITIAL) { + PERROR("Unterminated string"); + } + yylval->cpVal = STR_RETURN(); + STACK_POP(); /* ^ after this */ + return T_STRING; +} +<> { + STATE_POP(1); /* */ + if (YY_START != INITIAL) { + PERROR("Unterminated expression"); + } } - /* - * strings ("..." and '...') - */ -["'] { - str_ptr = str_buf; - str_del = yytext[0]; - BEGIN(str); - return T_STR_BEGIN; -} -["'] { - 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; +{QUOTE} { + if (yytext[0] == str_stop) { + if (!STR_EMPTY()) { + yyless(0); /* come back below */ + yylval->cpVal = STR_RETURN(); return T_STRING; } + STATE_POP(1); /* */ + return T_STR_END; } - else { - STR_APPEND(yytext[0]); - } + STR_APPEND_NOCHECK(yytext[0]); } -\n { - PERROR("Unterminated string or variable"); -} -<> { - PERROR("Unterminated string or variable"); -} -<> { - 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); - return T_STRING; - } -} - -\\[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); - } -} -\\[0-9]+ { - PERROR("Bad escape sequence"); -} -\\n { STR_APPEND('\n'); } -\\r { STR_APPEND('\r'); } -\\t { STR_APPEND('\t'); } -\\b { STR_APPEND('\b'); } -\\f { STR_APPEND('\f'); } -\\(.|\n) { STR_APPEND(yytext[1]); } /* regexp backref inside string/arg */ -[$][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); +{REG_REF} { + 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; - } -} - -[^\\\n"'%}$]+ { - char *cp = yytext; - while (*cp != '\0') { - STR_APPEND(*cp); - cp++; - } + yylval->num = yytext[1] - '0'; + return T_REG_REF; } /* variable inside string/arg */ -%\{ { - 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; +{VAR_BEGIN} { + if (!STR_EMPTY()) { + yyless(0); /* come back below */ + yylval->cpVal = STR_RETURN(); return T_STRING; } - else { - yy_push_state(var, yyscanner); - return T_VAR_BEGIN; - } -} - -[%$] { - STR_APPEND(yytext[0]); -} - -[%}$] { - STR_APPEND(yytext[0]); -} - -%\{ { - yy_push_state(var, yyscanner); + STATE_PUSH(var, 1); return T_VAR_BEGIN; } -[$][0-9] { - yylval->num = yytext[1] - '0'; - return T_REGEX_BACKREF; +{VAREXP_BEGIN} { + if (!STR_EMPTY()) { + yyless(0); /* come back below */ + yylval->cpVal = STR_RETURN(); + return T_STRING; + } + STATE_PUSH(expr, 1); + return T_VAREXP_BEGIN; } - /* - * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax - */ -[a-ij-rs-zA-IJ-RS-Z][a-ij-rs-zA-IJ-RS-Z0-9_]* { + /* Any non-octal or octal higher than 377 (decimal 255) is invalid */ +\\([4-9][0-9]{2}|[8-9][0-9]{0,2}) { + PERROR("Bad character escape sequence"); +} +\\[0-7]{1,3} { + int result; + (void)sscanf(yytext+1, "%o", &result); + STR_APPEND_NOCHECK(result); +} +\\x[0-9A-Fa-f]{1,2} { + int result; + (void)sscanf(yytext+1, "%x", &result); + STR_APPEND_NOCHECK(result); +} +\\n { STR_APPEND_NOCHECK('\n'); } +\\r { STR_APPEND_NOCHECK('\r'); } +\\t { STR_APPEND_NOCHECK('\t'); } +\\b { STR_APPEND_NOCHECK('\b'); } +\\f { STR_APPEND_NOCHECK('\f'); } +\\. { STR_APPEND_CHECK(yytext[1], 1); } + +\n { + PERROR("Unterminated string or variable"); +} + +{ANY} { + STR_APPEND_CHECK(yytext[0], 1); +} + +{SPACE}+ { + /* NOP */ +} + +{QUOTE} { + STATE_PUSH(str, 1); + str_stop = yytext[0]; + return T_STR_BEGIN; +} + +{VAREXP_BEGIN} { + STATE_PUSH(expr, 1); + return T_VAREXP_BEGIN; +} +{VAREXP_END} { + STATE_POP(1); /* */ + return T_VAREXP_END; +} + + +{VAR_BEGIN} { + STATE_PUSH(var, 1); + return T_VAR_BEGIN; +} +{TOKEN} { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; } - -\} { - yy_pop_state(yyscanner); - return T_VAR_END; -} - -: { - BEGIN(vararg); +{VAR_ARG} { + STATE_PUSH(vararg, 0); return yytext[0]; } - -.|\n { - char *msg = apr_psprintf(yyextra->pool, - "Invalid character in variable name '%c'", yytext[0]); - PERROR(msg); +{VAR_END} { + yyless(0); /* let handle */ + yylval->cpVal = STR_RETURN(); + STATE_POP(0); /* */ + return T_STRING; +} +{ANY} { + STR_APPEND_CHECK(yytext[0], 1); +} +{VAR_END} { + STATE_POP(1); /* */ + return T_VAR_END; +} +{ANY} { + PERROR_CHAR("Unexpected variable character ", yytext[0]); +} +<> { + PERROR("Unterminated variable"); } -\} { - 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); +\/ { + STATE_PUSH(regex, 1); + str_stop = yytext[0]; + str_flag = 'm'; + return T_REGEX; } -"/" { - regex_del = yytext[0]; - regex_ptr = regex_buf; - BEGIN(regex); +[ms]{REG_SEP} { + STATE_PUSH(regex, 1); + str_stop = yytext[1]; + str_flag = yytext[0]; + return (str_flag == 'm') ? T_REGEX : T_REGSUB; } -.|\n { - if (yytext[0] == regex_del) { - *regex_ptr = '\0'; - BEGIN(regex_flags); +{ANY} { + if (yytext[0] == str_stop) { + STATE_POP(0); /* */ + 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); +} +{ANY} { + if (yytext[0] == str_stop) { + STATE_POP(0); /* */ + 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); } } -i { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX_I; +{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); /* */ + return T_REG_FLAGS; + } } -.|\n { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; +<> { + yylval->cpVal = STR_RETURN(); + STATE_POP(1); /* */ + return T_REG_FLAGS; } -<> { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX; +<> { + PERROR("Unterminated regexp"); +} + +{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; } +==? { 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; } /* 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; } +"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_] { +"-"[a-zA-Z_][a-zA-Z_0-9]+ { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_BINARY; +} + +"-"[a-zA-Z_] { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); return T_OP_UNARY; } -"-"[a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z_0-9]+ { - yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_BINARY; + /* Split a string (or list) into a(nother) list */ +"split" { + STATE_PUSH(split, 0); + return T_OP_SPLIT; +} +{REG_SEP} { + STATE_POP(0); /* */ + STATE_PUSH(regex, 1); + str_stop = yytext[0]; + str_flag = 'S'; +} +{ANY} { + PERROR("Expecting split regular expression"); +} +<> { + PERROR("Unterminated split"); +} + + /* Join a list into a string */ +"join" { + return T_OP_JOIN; } /* * Specials */ -"true" { return T_TRUE; } -"false" { return T_FALSE; } +"true" { return T_TRUE; } +"false" { return T_FALSE; } /* * Digits */ --?[0-9]+ { +\-?[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_]* { +{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 */ -[(){},:] { +[(){},] { return yytext[0]; } /* * Anything else is an error */ -.|\n { - char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]); - PERROR(msg); +{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,