On Wed, Mar 22, 2017 at 1:37 PM, Yann Ylavic <ylavic.dev@xxxxxxxxx> wrote: > > There are two patches attached, one for the changes in httpd code, the > other for the files generated by the bison/flex parser. The second patch was missing the changes in server/util_expr_parse.h, resending... > > Hope that helps, > Yann.
Index: server/util_expr_private.h =================================================================== --- server/util_expr_private.h (revision 1783852) +++ server/util_expr_private.h (working copy) @@ -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]; + char scan_del; + int scan_state; + 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 *stack; + ap_expr_parser_stack_t *stacks; int at_start; /* pools for result and temporary usage */ @@ -119,6 +128,13 @@ void ap_expr_yyset_extra(ap_expr_parse_ctx_t *cont /* 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_regex_make(const char *pattern, const char *flags, + const ap_expr_t *subst, int split, + 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); /* 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); @@ -125,6 +141,8 @@ ap_expr_t *ap_expr_str_func_make(const char *name, /* 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' */ @@ -135,6 +153,9 @@ ap_expr_t *ap_expr_binary_op_make(const char *name const ap_expr_t *arg2, ap_expr_parse_ctx_t *ctx); +/* push/pop a stack in the parser/lexer */ +void ap_expr_parser_stack_push(ap_expr_parse_ctx_t *ctx); +void ap_expr_parser_stack_pop(ap_expr_parse_ctx_t *ctx); #endif /* __AP_EXPR_PRIVATE_H__ */ /** @} */ Index: server/util_expr_eval.c =================================================================== --- server/util_expr_eval.c (revision 1783852) +++ server/util_expr_eval.c (working copy) @@ -26,6 +26,7 @@ #include "ap_provider.h" #include "util_expr_private.h" #include "util_md5.h" +#include "util_varbuf.h" #include "apr_lib.h" #include "apr_fnmatch.h" @@ -47,6 +48,8 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_ #define LOG_MARK(info) __FILE__, __LINE__, (info)->module_index +static int ap_expr_eval(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); @@ -56,6 +59,19 @@ static const char *ap_expr_eval_var(ap_expr_eval_c 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, @@ -80,6 +96,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 (apr_is_empty_array(list)) { + 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) { @@ -91,6 +138,12 @@ static const char *ap_expr_eval_word(ap_expr_eval_ 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(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); @@ -161,7 +214,20 @@ static const char *ap_expr_eval_word(ap_expr_eval_ 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; @@ -226,6 +292,170 @@ static int intstrcmp(const char *s1, const char *s 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; @@ -256,31 +486,18 @@ static int ap_expr_eval_comp(ap_expr_eval_ctx_t *c 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; } @@ -303,10 +520,7 @@ static int ap_expr_eval_comp(ap_expr_eval_ctx_t *c 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"; @@ -387,9 +601,8 @@ AP_DECLARE(const char *) ap_expr_parse(apr_pool_t 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.stack = NULL; + ctx.stacks = NULL; ctx.lookup_fn = lookup_fn ? lookup_fn : ap_expr_lookup_default; ctx.at_start = 1; @@ -450,6 +663,80 @@ ap_expr_t *ap_expr_make(ap_expr_node_op_e op, cons 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->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; + } + } + } + regctx->subst = subst; + 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; +} + +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; +} + static ap_expr_t *ap_expr_info_make(int type, const char *name, ap_expr_parse_ctx_t *ctx, const ap_expr_t *arg) @@ -492,6 +779,16 @@ ap_expr_t *ap_expr_list_func_make(const char *name 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) { @@ -613,10 +910,15 @@ static void expr_dump_tree(const ap_expr_t *e, con 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) { @@ -639,10 +941,15 @@ static void expr_dump_tree(const ap_expr_t *e, con 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); } @@ -688,8 +995,8 @@ static void expr_dump_tree(const ap_expr_t *e, con 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); @@ -1804,3 +2111,32 @@ void ap_expr_init(apr_pool_t *p) ap_hook_post_config(ap_expr_post_config, NULL, NULL, APR_HOOK_MIDDLE); } +void ap_expr_parser_stack_push(ap_expr_parse_ctx_t *ctx) +{ + ap_expr_parser_stack_t *stack; + + if (ctx->stacks) { + stack = ctx->stacks; + ctx->stacks = stack->next; + } + else { + stack = apr_palloc(ctx->ptemp, sizeof *stack); + } + stack->scan_ptr = stack->scan_buf; + stack->scan_buf[0] = '\0'; + stack->scan_del = '\0'; + stack->scan_state = 0; + + stack->next = ctx->stack; + ctx->stack = stack; +} + +void ap_expr_parser_stack_pop(ap_expr_parse_ctx_t *ctx) +{ + ap_expr_parser_stack_t *stack; + + stack = ctx->stack; + ctx->stack = stack->next; + stack->next = ctx->stacks; + ctx->stacks = stack; +} Index: server/util_expr_parse.y =================================================================== --- server/util_expr_parse.y (revision 1783852) +++ server/util_expr_parse.y (working copy) @@ -49,9 +49,14 @@ %token <cpVal> T_DIGIT %token <cpVal> T_ID %token <cpVal> T_STRING -%token <cpVal> T_REGEX -%token <cpVal> T_REGEX_I -%token <num> T_REGEX_BACKREF + +%token T_REGEX +%token T_REGSUB +%token <cpVal> T_REG_MATCH +%token <cpVal> T_REG_SUBST +%token <cpVal> T_REG_FLAGS +%token <num> T_REG_REF + %token <cpVal> T_OP_UNARY %token <cpVal> T_OP_BINARY @@ -77,6 +82,9 @@ %token T_OP_STR_GE %token T_OP_CONCAT +%token T_OP_SPLIT +%token T_OP_JOIN + %token T_OP_OR %token T_OP_AND %token T_OP_NOT @@ -86,11 +94,10 @@ %right T_OP_NOT %right T_OP_CONCAT -%type <exVal> expr -%type <exVal> comparison +%type <exVal> cond +%type <exVal> comp %type <exVal> strfunccall %type <exVal> lstfunccall -%type <exVal> regex %type <exVal> words %type <exVal> wordlist %type <exVal> word @@ -97,7 +104,11 @@ %type <exVal> string %type <exVal> strpart %type <exVal> var -%type <exVal> backref +%type <exVal> regex +%type <exVal> regsub +%type <exVal> regsplit +%type <exVal> reglist +%type <exVal> regref %{ #include "util_expr_private.h" @@ -109,24 +120,22 @@ 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_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 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); } + | T_OP_NOT cond { $$ = ap_expr_make(op_Not, $2, NULL, ctx); } + | comp { $$ = ap_expr_make(op_Comp, $1, NULL, ctx); } + | '(' 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); } @@ -141,10 +150,15 @@ int ap_expr_yylex(YYSTYPE *lvalp, void *scanner); | word T_OP_IN wordlist { $$ = ap_expr_make(op_IN, $1, $3, ctx); } | word T_OP_REG regex { $$ = ap_expr_make(op_REG, $1, $3, ctx); } | word T_OP_NRE regex { $$ = ap_expr_make(op_NRE, $1, $3, ctx); } + | word T_OP_BINARY word { $$ = ap_expr_binary_op_make($2, $1, $3, ctx); } + | T_OP_UNARY word { $$ = ap_expr_unary_op_make( $1, $2, ctx); } ; wordlist : lstfunccall { $$ = $1; } | '{' words '}' { $$ = $2; } + | word T_OP_REG regsplit { $$ = ap_expr_list_regex_make($1, $3, ctx); } + | wordlist T_OP_REG reglist { $$ = ap_expr_list_regex_make($1, $3, ctx); } + | '(' wordlist ')' { $$ = $2; } ; words : word { $$ = ap_expr_make(op_ListElement, $1, NULL, ctx); } @@ -151,53 +165,78 @@ words : word { $$ = ap | words ',' word { $$ = ap_expr_make(op_ListElement, $3, $1, ctx); } ; -string : string strpart { $$ = ap_expr_make(op_Concat, $1, $2, ctx); } - | strpart { $$ = $1; } +string : strpart { $$ = $1; } + | string strpart { $$ = $2 ? ap_expr_make(op_Concat, $1, $2, ctx) : $1; } | T_ERROR { YYABORT; } ; -strpart : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); } +strpart : T_STRING { $$ = $1 ? ap_expr_make(op_String, $1, NULL, ctx) : NULL; } | 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_VAR_BEGIN ':' word ':' T_VAR_END { $$ = ap_expr_str_word_make($3, 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); } +word : 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); } + | cond { $$ = ap_expr_str_bool_make( $1, ctx); } | var { $$ = $1; } - | backref { $$ = $1; } + | regref { $$ = $1; } | strfunccall { $$ = $1; } + | T_OP_JOIN '/' wordlist '/' '/' { $$ = ap_expr_make(op_Join, $3, NULL, ctx); } + | T_OP_JOIN '/' wordlist '/' word '/' { $$ = ap_expr_make(op_Join, $3, $5, ctx); } + | T_DIGIT { $$ = ap_expr_make(op_Digit, $1, NULL, ctx); } + | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, ctx); } | T_STR_BEGIN string T_STR_END { $$ = $2; } - | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, 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: + * <word> ~= split/:// + * => split around ':' + * <word> ~= split/:/\n/ + * => split around ':', use '\n' instead where detected/stripped + * <list> ~= split/.*?Ip Address:([^,]+)/$1/ + * => split around the whole match, use $1 instead where detected/stipped + */ + ap_expr_t *e = ap_expr_regex_make($2, $4, $3, 1, ctx); + if (!e) { + ctx->error = "Failed to compile regular expression"; + YYERROR; + } + $$ = e; + } + ; +reglist : 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); } ; Index: server/util_expr_scan.l =================================================================== --- server/util_expr_scan.l (revision 1783852) +++ server/util_expr_scan.l (working copy) @@ -34,14 +34,16 @@ %option warn %option noinput nounput noyy_top_state %option stack + %x str -%x var -%x vararg -%x regex regex_flags +%x var vararg varext +%x regex regsub regflags +%x split join %{ #include "util_expr_private.h" #include "util_expr_parse.h" +#include "apr_lib.h" /* apr_isalnum */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ @@ -62,10 +64,57 @@ #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) +#if 0 +#define STACK_PUSH() do { \ + fprintf(stderr, "YY_STACK_PUSH()\n"); \ + ap_expr_parser_stack_push(yyextra); \ +} while (0) +#define STACK_POP() do { \ + fprintf(stderr, "YY_STACK_POP()\n"); \ + ap_expr_parser_stack_pop(yyextra); \ +} while (0) +#define STATE_PUSH(st, sk) do { \ + fprintf(stderr, "YY_STATE_PUSH(%i)\n", (st)); \ + yy_push_state((st), yyscanner); \ + if (sk) { \ + STACK_PUSH(); \ + } \ +} while (0) +#define STATE_POP(sk) do { \ + fprintf(stderr, "YY_STATE_POP()\n"); \ + if (sk) { \ + STACK_POP(); \ + } \ + yy_pop_state(yyscanner); \ +} while (0) +#else +#define STACK_PUSH() do { \ + ap_expr_parser_stack_push(yyextra); \ +} while (0) +#define STACK_POP() do { \ + ap_expr_parser_stack_pop(yyextra); \ +} 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) +#endif + +#define str_ptr (yyextra->stack->scan_ptr) +#define str_buf (yyextra->stack->scan_buf) +#define str_del (yyextra->stack->scan_del) +#define str_state (yyextra->stack->scan_state) + #define STR_APPEND(c) do { \ *str_ptr++ = (c); \ if (str_ptr >= str_buf + sizeof(str_buf)) \ @@ -72,15 +121,22 @@ PERROR("String too long"); \ } while (0) +#define STR_EMPTY() (str_ptr == str_buf) +#define STR_FINAL() (*str_ptr = '\0', str_ptr = str_buf) + %} +SPACE [ \t\n] +QUOTE ["'] +TOKEN ([a-zA-Z][a-zA-Z0-9_]*) +VAR_BEGIN (%\{) +VAR_SEP : +VAR_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 @@ -88,7 +144,7 @@ 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 { @@ -100,7 +156,7 @@ /* * Whitespaces */ -[ \t\n]+ { +<INITIAL,varext,split,join>{SPACE}+ { /* NOP */ } @@ -107,267 +163,318 @@ /* * strings ("..." and '...') */ -["'] { - str_ptr = str_buf; +<INITIAL,varext,join>{QUOTE} { + STATE_PUSH(str, 1); str_del = yytext[0]; - BEGIN(str); return T_STR_BEGIN; } -<str>["'] { + +<str>{QUOTE} { 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 { + if (!STR_EMPTY()) { /* 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; + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } + STATE_POP(1); + return T_STR_END; } - else { - STR_APPEND(yytext[0]); - } + STR_APPEND(yytext[0]); } -<str,var,vararg>\n { - PERROR("Unterminated string or variable"); -} -<var,vararg><<EOF>> { - PERROR("Unterminated string or variable"); -} -<str><<EOF>> { - if (!(yyextra->flags & AP_EXPR_FLAG_STRING_RESULT)) { - PERROR("Unterminated string or variable"); - } - else { - *str_ptr = '\0'; - yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); - str_ptr = str_buf; - BEGIN(INITIAL); - return T_STRING; - } -} -<str,vararg>\\[0-7]{1,3} { - int result; - - (void)sscanf(yytext+1, "%o", &result); - if (result > 0xff) { - PERROR("Escape sequence out of bound"); - } - else { - STR_APPEND(result); - } -} -<str,vararg>\\[0-9]+ { - PERROR("Bad escape sequence"); -} -<str,vararg>\\n { STR_APPEND('\n'); } -<str,vararg>\\r { STR_APPEND('\r'); } -<str,vararg>\\t { STR_APPEND('\t'); } -<str,vararg>\\b { STR_APPEND('\b'); } -<str,vararg>\\f { STR_APPEND('\f'); } -<str,vararg>\\(.|\n) { STR_APPEND(yytext[1]); } - /* regexp backref inside string/arg */ -<str,vararg>[$][0-9] { - if (str_ptr != str_buf) { +<str,vararg,regsub>{REG_REF} { + if (!STR_EMPTY()) { /* 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); + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } - else { - yylval->num = yytext[1] - '0'; - return T_REGEX_BACKREF; - } + yylval->num = yytext[1] - '0'; + return T_REG_REF; } -<str,vararg>[^\\\n"'%}$]+ { - char *cp = yytext; - while (*cp != '\0') { - STR_APPEND(*cp); - cp++; - } -} - /* variable inside string/arg */ -<str,vararg>%\{ { - if (str_ptr != str_buf) { +<str,vararg,regsub>{VAR_BEGIN} { + if (!STR_EMPTY()) { /* 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; + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } - else { - yy_push_state(var, yyscanner); - return T_VAR_BEGIN; - } + STATE_PUSH(var, 1); + return T_VAR_BEGIN; } -<vararg>[%$] { - STR_APPEND(yytext[0]); + /* Any non-octal or octal higher than 377 (decimal 255) is invalid */ +<str,vararg,regsub>\\([4-9][0-9]{2}|[8-9][0-9]{0,2}) { + PERROR("Bad character escape sequence"); } +<str,vararg,regsub>\\[0-7]{1,3} { + int result; + (void)sscanf(yytext+1, "%o", &result); + STR_APPEND(result); +} +<str,vararg,regsub>\\x[0-9A-Fa-f]{1,2} { + int result; + (void)sscanf(yytext+1, "%x", &result); + STR_APPEND(result); +} +<str,vararg,regsub>\\n { STR_APPEND('\n'); } +<str,vararg,regsub>\\r { STR_APPEND('\r'); } +<str,vararg,regsub>\\t { STR_APPEND('\t'); } +<str,vararg,regsub>\\b { STR_APPEND('\b'); } +<str,vararg,regsub>\\f { STR_APPEND('\f'); } +<str,vararg,regsub>\\(.|\n) { STR_APPEND(yytext[1]); } -<str>[%}$] { - STR_APPEND(yytext[0]); +<str,vararg,regsub>\n { + PERROR("Unterminated string or variable"); } -%\{ { - yy_push_state(var, yyscanner); - return T_VAR_BEGIN; +<str>. { + STR_APPEND(yytext[0]); } +<str><<EOF>> { + STATE_POP(0); + if (YY_START != INITIAL) { + PERROR("Unterminated string"); + } + if (!STR_EMPTY()) { + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + } + else { + yylval->cpVal = NULL; + } + ap_expr_parser_stack_pop(yyextra); + return T_STRING; +} -[$][0-9] { +<INITIAL,varext,join>{REG_REF} { yylval->num = yytext[1] - '0'; - return T_REGEX_BACKREF; + return T_REG_REF; } - /* - * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax - */ -<var>[a-zA-Z][a-zA-Z0-9_]* { +<INITIAL,varext,join>{VAR_BEGIN} { + STATE_PUSH(var, 1); + return T_VAR_BEGIN; +} + +<var>{TOKEN} { + /* + * fixed name variable expansion %{XXX} and function call + * in %{func:arg} syntax + */ + str_state = 1; yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; } -<var>\} { - yy_pop_state(yyscanner); - return T_VAR_END; +<var>{VAR_SEP} { + /* If we have a T_ID it's a vararg, otherwise a varext */ + if (str_state) { + STATE_PUSH(vararg, 0); + } + else { + STATE_PUSH(varext, 0); + } + return yytext[0]; } -<var>: { - BEGIN(vararg); +<varext>{VAR_SEP} { + STATE_POP(0); return yytext[0]; } -<var>.|\n { +<var>{VAR_END} { + STATE_POP(1); + return T_VAR_END; +} + +<var>(.|\n) { char *msg = apr_psprintf(yyextra->pool, - "Invalid character in variable name '%c'", yytext[0]); + "Invalid character in variable name '%c'", + yytext[0]); PERROR(msg); } -<vararg>\} { - if (str_ptr != str_buf) { +<vararg>{VAR_END} { + yyless(0); + if (!STR_EMPTY()) { /* 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); + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } - else { - yy_pop_state(yyscanner); - return T_VAR_END; - } + STATE_POP(0); } +<vararg>. { + STR_APPEND(yytext[0]); +} +<var,vararg,varext><<EOF>> { + PERROR("Unterminated variable"); +} + /* * Regular Expression */ -"m"[/#$%^,;:_\?\|\^\-\!\.\'\"] { - regex_del = yytext[1]; - regex_ptr = regex_buf; - BEGIN(regex); +<INITIAL,varext>[/] { + STATE_PUSH(regex, 1); + str_state = 'm'; + str_del = yytext[0]; + return T_REGEX; } -"/" { - regex_del = yytext[0]; - regex_ptr = regex_buf; - BEGIN(regex); +<INITIAL,varext>[ms]{REG_SEP} { + STATE_PUSH(regex, 1); + str_state = yytext[0]; + str_del = yytext[1]; + return (str_state == 'm') ? T_REGEX : T_REGSUB; } -<regex>.|\n { - if (yytext[0] == regex_del) { - *regex_ptr = '\0'; - BEGIN(regex_flags); +<regex>(.|\n) { + if (yytext[0] == str_del) { + STATE_POP(0); + STATE_PUSH(regflags, 0); + if (str_state != 'm') { + STATE_PUSH(regsub, 0); + } + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + return T_REG_MATCH; } + STR_APPEND(yytext[0]); +} +<regsub>. { + if (yytext[0] == str_del) { + /* Back to regflags */ + STATE_POP(0); + } else { - *regex_ptr++ = yytext[0]; - if (regex_ptr >= regex_buf + sizeof(regex_buf)) - PERROR("Regexp too long"); + STR_APPEND(yytext[0]); } } -<regex_flags>i { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX_I; +<regsub><<EOF>> { + PERROR("Unterminated regexp"); } -<regex_flags>.|\n { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; +<regflags>. { + if (ap_strchr_c("ismg", yytext[0])) { + STR_APPEND(yytext[0]); + } + else if (apr_isalnum(yytext[0])) { + PERROR("Invalid regexp flag(s)"); + } + else { + yyless(0); + if (!STR_EMPTY()) { + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + } + else { + yylval->cpVal = NULL; + STATE_POP(1); + } + return T_REG_FLAGS; + } } -<regex_flags><<EOF>> { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX; +<regflags><<EOF>> { + STATE_POP(1); + yylval->cpVal = NULL; + return T_REG_FLAGS; } +<regex><<EOF>> { + STATE_POP(1); + if (YY_START != INITIAL) { + PERROR("Unterminated regexp"); + } + yylval->cpVal = NULL; + return T_REG_FLAGS; +} /* * 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; } +<INITIAL,varext,join>==? { return T_OP_STR_EQ; } +<INITIAL,varext,join>"!=" { return T_OP_STR_NE; } +<INITIAL,varext,join>"<" { return T_OP_STR_LT; } +<INITIAL,varext,join>"<=" { return T_OP_STR_LE; } +<INITIAL,varext,join>">" { return T_OP_STR_GT; } +<INITIAL,varext,join>">=" { return T_OP_STR_GE; } +<INITIAL,varext,join>"=~" { return T_OP_REG; } +<INITIAL,varext,join>"!~" { return T_OP_NRE; } +<INITIAL,varext,join>"and" { return T_OP_AND; } +<INITIAL,varext,join>"&&" { return T_OP_AND; } +<INITIAL,varext,join>"or" { return T_OP_OR; } +<INITIAL,varext,join>"||" { return T_OP_OR; } +<INITIAL,varext,join>"not" { return T_OP_NOT; } +<INITIAL,varext,join>"!" { return T_OP_NOT; } +<INITIAL,varext,join>"." { return T_OP_CONCAT; } +<INITIAL,varext,join>"-in" { return T_OP_IN; } +<INITIAL,varext,join>"-eq" { return T_OP_EQ; } +<INITIAL,varext,join>"-ne" { return T_OP_NE; } +<INITIAL,varext,join>"-ge" { return T_OP_GE; } +<INITIAL,varext,join>"-le" { return T_OP_LE; } +<INITIAL,varext,join>"-gt" { return T_OP_GT; } +<INITIAL,varext,join>"-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; } +<INITIAL,varext,join>"lt" { return T_OP_LT; } +<INITIAL,varext,join>"le" { return T_OP_LE; } +<INITIAL,varext,join>"gt" { return T_OP_GT; } +<INITIAL,varext,join>"ge" { return T_OP_GE; } +<INITIAL,varext,join>"ne" { return T_OP_NE; } +<INITIAL,varext,join>"eq" { return T_OP_EQ; } +<INITIAL,varext,join>"in" { return T_OP_IN; } -"-"[a-zA-Z_] { +<INITIAL,varext,join>"-"[a-zA-Z_][a-zA-Z_0-9]+ { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_UNARY; + return T_OP_BINARY; } -"-"[a-zA-Z_][a-zA-Z_0-9]+ { +<INITIAL,varext,join>"-"[a-zA-Z_] { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_BINARY; + return T_OP_UNARY; } + /* Split a string (or list) into a(nother) list */ +<INITIAL,varext,join>"split" { + STATE_PUSH(split, 0); + return T_OP_SPLIT; +} +<split>{REG_SEP} { + STATE_POP(0); + STATE_PUSH(regex, 1); + str_del = yytext[0]; + str_state = 'S'; +} +<split>. { + PERROR("Expecting split regular expression"); +} +<split><<EOF>> { + PERROR("Unterminated split"); +} + + /* Join a list into a string */ +<INITIAL,varext,join>"join" { + STATE_PUSH(join, 1); + return T_OP_JOIN; +} +<join>[/] { + if (++str_state == 3) { + STATE_POP(1); + } + return yytext[0]; +} +<join><<EOF>> { + PERROR("Unterminated join"); +} + /* * Specials */ -"true" { return T_TRUE; } -"false" { return T_FALSE; } +<INITIAL,varext,join>"true" { return T_TRUE; } +<INITIAL,varext,join>"false" { return T_FALSE; } /* * Digits */ --?[0-9]+ { +<INITIAL,varext,join>-?[0-9]+ { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_DIGIT; } @@ -375,7 +482,7 @@ /* * Identifiers */ -[a-zA-Z][a-zA-Z0-9_]* { +<INITIAL,varext,join>[a-zA-Z][a-zA-Z0-9_]* { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; } @@ -383,7 +490,7 @@ /* * These are parts of the grammar and are returned as is */ -[(){},:] { +<INITIAL,varext,join>[(){},] { return yytext[0]; } @@ -390,7 +497,7 @@ /* * Anything else is an error */ -.|\n { +<INITIAL,varext,join>.|\n { char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]); PERROR(msg); } Index: include/ap_regex.h =================================================================== --- include/ap_regex.h (revision 1783852) +++ include/ap_regex.h (working copy) @@ -77,6 +77,9 @@ extern "C" { #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 */ /* Error values: */ Index: server/util_pcre.c =================================================================== --- server/util_pcre.c (revision 1783852) +++ server/util_pcre.c (working copy) @@ -189,6 +189,10 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *p options |= PCRE_NOTBOL; if ((eflags & AP_REG_NOTEOL) != 0) options |= PCRE_NOTEOL; + if ((eflags & AP_REG_NOTEMPTY) != 0) + options |= PCRE_NOTEMPTY; + if ((eflags & AP_REG_ANCHORED) != 0) + options |= PCRE_ANCHORED; ((ap_regex_t *)preg)->re_erroffset = (apr_size_t)(-1); /* Only has meaning after compile */
Index: server/util_expr_parse.h =================================================================== --- server/util_expr_parse.h (revision 1783852) +++ server/util_expr_parse.h (working copy) @@ -46,33 +46,38 @@ 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_OP_EQ = 278, + T_OP_NE = 279, + T_OP_LT = 280, + T_OP_LE = 281, + T_OP_GT = 282, + T_OP_GE = 283, + T_OP_REG = 284, + T_OP_NRE = 285, + T_OP_IN = 286, + T_OP_STR_EQ = 287, + T_OP_STR_NE = 288, + T_OP_STR_LT = 289, + T_OP_STR_LE = 290, + T_OP_STR_GT = 291, + T_OP_STR_GE = 292, + T_OP_CONCAT = 293, + T_OP_SPLIT = 294, + T_OP_JOIN = 295, + T_OP_OR = 296, + T_OP_AND = 297, + T_OP_NOT = 298 }; #endif @@ -92,7 +97,7 @@ typedef union YYSTYPE /* Line 2068 of yacc.c */ -#line 96 "util_expr_parse.h" +#line 101 "util_expr_parse.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ Index: server/util_expr_parse.c =================================================================== --- server/util_expr_parse.c (revision 1783852) +++ server/util_expr_parse.c (working copy) @@ -116,33 +116,38 @@ 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_OP_EQ = 278, + T_OP_NE = 279, + T_OP_LT = 280, + T_OP_LE = 281, + T_OP_GT = 282, + T_OP_GE = 283, + T_OP_REG = 284, + T_OP_NRE = 285, + T_OP_IN = 286, + T_OP_STR_EQ = 287, + T_OP_STR_NE = 288, + T_OP_STR_LT = 289, + T_OP_STR_LE = 290, + T_OP_STR_GT = 291, + T_OP_STR_GE = 292, + T_OP_CONCAT = 293, + T_OP_SPLIT = 294, + T_OP_JOIN = 295, + T_OP_OR = 296, + T_OP_AND = 297, + T_OP_NOT = 298 }; #endif @@ -162,7 +167,7 @@ typedef union YYSTYPE /* Line 293 of yacc.c */ -#line 166 "util_expr_parse.c" +#line 171 "util_expr_parse.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -173,7 +178,7 @@ typedef union YYSTYPE /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ -#line 102 "util_expr_parse.y" +#line 113 "util_expr_parse.y" #include "util_expr_private.h" #define yyscanner ctx->scanner @@ -182,7 +187,7 @@ int ap_expr_yylex(YYSTYPE *lvalp, void *scanner); /* Line 343 of yacc.c */ -#line 186 "util_expr_parse.c" +#line 191 "util_expr_parse.c" #ifdef short # undef short @@ -399,22 +404,22 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 28 +#define YYFINAL 29 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 128 +#define YYLAST 400 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 45 +#define YYNTOKENS 51 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 14 +#define YYNNTS 17 /* YYNRULES -- Number of rules. */ -#define YYNRULES 53 +#define YYNRULES 66 /* YYNRULES -- Number of states. */ -#define YYNSTATES 96 +#define YYNSTATES 132 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 293 +#define YYMAXUTOK 298 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -426,8 +431,8 @@ 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, - 39, 40, 2, 2, 43, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 44, 2, + 44, 45, 2, 2, 48, 2, 2, 50, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 49, 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, @@ -434,7 +439,7 @@ 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, - 2, 2, 2, 41, 2, 42, 2, 2, 2, 2, + 2, 2, 2, 46, 2, 47, 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, @@ -451,7 +456,7 @@ 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 + 35, 36, 37, 38, 39, 40, 41, 42, 43 }; #if YYDEBUG @@ -459,46 +464,53 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ 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 + 0, 0, 3, 6, 9, 11, 13, 15, 19, 23, + 26, 28, 32, 34, 38, 42, 46, 50, 54, 58, + 62, 66, 70, 74, 78, 82, 86, 90, 94, 98, + 101, 103, 107, 111, 115, 119, 121, 125, 127, 130, + 132, 134, 136, 138, 142, 148, 154, 158, 162, 164, + 166, 168, 170, 176, 183, 185, 188, 192, 196, 200, + 205, 210, 212, 214, 216, 218, 223 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 46, 0, -1, 5, 47, -1, 6, 51, -1, 7, - -1, 3, -1, 4, -1, 38, 47, -1, 47, 36, - 47, -1, 47, 37, 47, -1, 48, -1, 14, 54, - -1, 54, 15, 54, -1, 39, 47, 40, -1, 7, - -1, 54, 20, 54, -1, 54, 21, 54, -1, 54, - 22, 54, -1, 54, 23, 54, -1, 54, 24, 54, - -1, 54, 25, 54, -1, 54, 29, 54, -1, 54, - 30, 54, -1, 54, 31, 54, -1, 54, 32, 54, - -1, 54, 33, 54, -1, 54, 34, 54, -1, 54, - 28, 49, -1, 54, 26, 55, -1, 54, 27, 55, - -1, 57, -1, 41, 50, 42, -1, 54, -1, 50, - 43, 54, -1, 51, 52, -1, 52, -1, 7, -1, - 10, -1, 53, -1, 56, -1, 18, 9, 19, -1, - 18, 9, 44, 51, 19, -1, 8, -1, 54, 35, - 54, -1, 53, -1, 56, -1, 58, -1, 16, 51, - 17, -1, 16, 17, -1, 11, -1, 12, -1, 13, - -1, 9, 39, 54, 40, -1, 9, 39, 54, 40, - -1 + 52, 0, -1, 5, 53, -1, 6, 57, -1, 7, + -1, 3, -1, 4, -1, 53, 41, 53, -1, 53, + 42, 53, -1, 43, 53, -1, 54, -1, 44, 53, + 45, -1, 7, -1, 60, 23, 60, -1, 60, 24, + 60, -1, 60, 25, 60, -1, 60, 26, 60, -1, + 60, 27, 60, -1, 60, 28, 60, -1, 60, 32, + 60, -1, 60, 33, 60, -1, 60, 34, 60, -1, + 60, 35, 60, -1, 60, 36, 60, -1, 60, 37, + 60, -1, 60, 31, 55, -1, 60, 29, 61, -1, + 60, 30, 61, -1, 60, 18, 60, -1, 17, 60, + -1, 66, -1, 46, 56, 47, -1, 60, 29, 63, + -1, 55, 29, 64, -1, 44, 55, 45, -1, 60, + -1, 56, 48, 60, -1, 58, -1, 57, 58, -1, + 7, -1, 10, -1, 59, -1, 65, -1, 21, 9, + 22, -1, 21, 9, 49, 57, 22, -1, 21, 49, + 60, 49, 22, -1, 60, 38, 60, -1, 60, 29, + 62, -1, 53, -1, 59, -1, 65, -1, 67, -1, + 40, 50, 55, 50, 50, -1, 40, 50, 55, 50, + 60, 50, -1, 8, -1, 19, 20, -1, 19, 57, + 20, -1, 44, 60, 45, -1, 11, 13, 15, -1, + 12, 13, 57, 15, -1, 39, 13, 57, 15, -1, + 61, -1, 62, -1, 63, -1, 16, -1, 9, 44, + 60, 45, -1, 9, 44, 60, 45, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 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 + 0, 123, 123, 124, 125, 128, 129, 130, 131, 132, + 133, 134, 135, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 157, 158, 159, 160, 161, 164, 165, 168, 169, 170, + 173, 174, 175, 178, 179, 180, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 196, 205, + 214, 231, 232, 233, 236, 243, 246 }; #endif @@ -509,15 +521,16 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "T_TRUE", "T_FALSE", "T_EXPR_BOOL", "T_EXPR_STRING", "T_ERROR", "T_DIGIT", "T_ID", "T_STRING", "T_REGEX", - "T_REGEX_I", "T_REGEX_BACKREF", "T_OP_UNARY", "T_OP_BINARY", - "T_STR_BEGIN", "T_STR_END", "T_VAR_BEGIN", "T_VAR_END", "T_OP_EQ", - "T_OP_NE", "T_OP_LT", "T_OP_LE", "T_OP_GT", "T_OP_GE", "T_OP_REG", - "T_OP_NRE", "T_OP_IN", "T_OP_STR_EQ", "T_OP_STR_NE", "T_OP_STR_LT", - "T_OP_STR_LE", "T_OP_STR_GT", "T_OP_STR_GE", "T_OP_CONCAT", "T_OP_OR", - "T_OP_AND", "T_OP_NOT", "'('", "')'", "'{'", "'}'", "','", "':'", - "$accept", "root", "expr", "comparison", "wordlist", "words", "string", - "strpart", "var", "word", "regex", "backref", "lstfunccall", - "strfunccall", 0 + "T_REGSUB", "T_REG_MATCH", "T_REG_SUBST", "T_REG_FLAGS", "T_REG_REF", + "T_OP_UNARY", "T_OP_BINARY", "T_STR_BEGIN", "T_STR_END", "T_VAR_BEGIN", + "T_VAR_END", "T_OP_EQ", "T_OP_NE", "T_OP_LT", "T_OP_LE", "T_OP_GT", + "T_OP_GE", "T_OP_REG", "T_OP_NRE", "T_OP_IN", "T_OP_STR_EQ", + "T_OP_STR_NE", "T_OP_STR_LT", "T_OP_STR_LE", "T_OP_STR_GT", + "T_OP_STR_GE", "T_OP_CONCAT", "T_OP_SPLIT", "T_OP_JOIN", "T_OP_OR", + "T_OP_AND", "T_OP_NOT", "'('", "')'", "'{'", "'}'", "','", "':'", "'/'", + "$accept", "root", "cond", "comp", "wordlist", "words", "string", + "strpart", "var", "word", "regex", "regsub", "regsplit", "reglist", + "regref", "lstfunccall", "strfunccall", 0 }; #endif @@ -529,8 +542,9 @@ static const yytype_uint16 yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 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, 40, - 41, 123, 125, 44, 58 + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 40, 41, 123, 125, 44, 58, + 47 }; # endif @@ -537,23 +551,25 @@ static const yytype_uint16 yytoknum[] = /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 45, 46, 46, 46, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 49, 49, 50, 50, 51, 51, 51, 52, 52, 52, - 53, 53, 54, 54, 54, 54, 54, 54, 54, 55, - 55, 56, 57, 58 + 0, 51, 52, 52, 52, 53, 53, 53, 53, 53, + 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 55, 55, 55, 55, 55, 56, 56, 57, 57, 57, + 58, 58, 58, 59, 59, 59, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 61, 62, + 63, 64, 64, 64, 65, 66, 67 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ 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 + 0, 2, 2, 2, 1, 1, 1, 3, 3, 2, + 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 1, 3, 3, 3, 3, 1, 3, 1, 2, 1, + 1, 1, 1, 3, 5, 5, 3, 3, 1, 1, + 1, 1, 5, 6, 1, 2, 3, 3, 3, 4, + 4, 1, 1, 1, 1, 4, 4 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -561,91 +577,155 @@ 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, 12, 54, 0, + 64, 0, 0, 0, 0, 0, 0, 48, 10, 49, + 0, 50, 51, 39, 40, 3, 37, 41, 42, 1, + 0, 48, 29, 55, 0, 0, 0, 0, 9, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 34, 0, 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, 53, 0, 0, 0, 32, - 41, 0, 31, 0, 52, 33 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 0, 56, 43, 0, 0, 0, 0, 0, 0, + 0, 30, 11, 57, 7, 8, 28, 13, 14, 15, + 16, 17, 18, 0, 0, 26, 47, 27, 25, 19, + 20, 21, 22, 23, 24, 46, 66, 0, 0, 0, + 0, 0, 0, 35, 0, 0, 0, 0, 0, 44, + 45, 0, 34, 31, 0, 0, 61, 62, 63, 33, + 52, 0, 32, 58, 0, 65, 36, 0, 53, 59, + 0, 60 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 4, 16, 17, 76, 88, 24, 25, 18, 19, - 72, 20, 77, 21 + -1, 4, 31, 18, 69, 102, 25, 26, 19, 20, + 85, 86, 118, 119, 21, 71, 22 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -35 -static const yytype_int8 yypact[] = +#define YYPACT_NINF -47 +static const yytype_int16 yypact[] = { - 48, 60, 73, -35, 7, -35, -35, -35, -35, -34, - -35, 43, 8, 11, 60, 60, 86, -35, -35, 80, - -35, -35, -35, -35, 108, -35, -35, -35, -35, 43, - 25, -35, 79, -17, -35, -8, 60, 60, 43, 43, - 43, 43, 43, 43, 43, 5, 5, 0, 43, 43, - 43, 43, 43, 43, 43, -35, -27, -35, -35, 73, - -35, 86, 3, 25, 25, 25, 25, 25, 25, 25, - -35, -35, -35, -35, 23, 43, -35, -35, 25, 25, - 25, 25, 25, 25, 25, -35, 106, 43, 85, 25, - -35, -21, -35, 43, -35, 25 + 15, 171, 18, -47, 17, -47, -47, -47, -47, 25, + -47, 171, 66, 0, 9, 171, 171, 6, -47, -47, + 341, -47, -47, -47, -47, 69, -47, -47, -47, -47, + 171, 39, 341, -47, 36, -9, 171, 151, -47, 23, + 249, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 80, 56, 151, 171, 171, 171, 171, 171, 171, 171, + -47, 272, -47, -47, 18, 222, 49, 151, 171, -14, + 362, -47, -47, -47, 39, -13, 341, 341, 341, 341, + 341, 341, 341, 48, 84, -47, -47, -47, 70, 341, + 341, 341, 341, 341, 341, 341, -47, 50, 78, 171, + -15, 295, -21, 341, -4, 34, -4, 86, 18, -47, + -47, 318, -47, -47, 171, 90, -47, -47, -47, -47, + -47, 194, -47, -47, 73, -47, 341, 18, -47, -47, + 99, -47 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -35, -35, 57, -35, -35, -35, -9, -20, -2, -5, - -4, -1, -35, -35 + -47, -47, 3, -47, -36, -47, -10, -22, -2, 94, + -46, 7, 10, -47, -1, -47, -47 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 -static const yytype_uint8 yytable[] = +#define YYTABLE_NINF -3 +static const yytype_int16 yytable[] = { - 26, 27, 58, 32, 55, 29, 30, 28, 54, 74, - 26, 27, 55, 85, 54, 22, 70, 71, 23, 94, - 33, 10, 26, 27, 56, 31, 13, 59, 36, 37, - 26, 27, 60, 63, 64, 65, 66, 67, 68, 69, - 37, 75, 73, 78, 79, 80, 81, 82, 83, 84, - 86, 8, 9, 1, 2, 3, 10, 26, 27, 12, - 54, 13, 87, 5, 6, 0, 55, 7, 8, 9, - 89, 34, 35, 10, 11, 0, 12, 0, 13, 0, - 22, 0, 91, 23, 26, 27, 10, 0, 95, 23, - 0, 13, 10, 61, 62, 38, 57, 13, 14, 15, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 23, 0, 23, 10, - 0, 10, 36, 37, 13, 90, 13, 92, 93 + 27, 28, 34, 60, 17, 87, -2, 83, 84, 35, + 27, 28, 60, 63, 104, 104, 88, 29, 38, 39, + 1, 2, 3, 27, 28, 23, 113, 114, 24, 42, + 112, 100, 27, 28, 10, 115, 105, 5, 6, 13, + 64, 7, 8, 9, 74, 75, 24, 41, 42, 36, + 10, 11, 10, 12, 97, 13, 62, 13, 116, 37, + 24, 107, 27, 28, 41, 42, 10, 83, 72, 30, + 39, 13, 109, 23, 14, 60, 24, 15, 16, 24, + 41, 42, 10, 24, 120, 10, 33, 13, 129, 10, + 13, 83, 84, 99, 13, 27, 28, 108, 124, 104, + 110, 123, 60, 127, 0, 32, 27, 28, 60, 24, + 40, 117, 0, 0, 131, 10, 122, 130, 0, 0, + 13, 0, 27, 28, 61, 27, 28, 0, 27, 28, + 65, 70, 0, 0, 0, 0, 0, 76, 77, 78, + 79, 80, 81, 82, 0, 0, 70, 89, 90, 91, + 92, 93, 94, 95, 5, 6, 0, 0, 7, 8, + 66, 101, 103, 0, 0, 0, 0, 10, 11, 0, + 12, 0, 13, 0, 5, 6, 0, 0, 7, 8, + 9, 0, 0, 0, 0, 0, 0, 10, 11, 0, + 12, 14, 13, 111, 15, 67, 0, 68, 0, 121, + 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, + 0, 14, 43, 0, 15, 16, 0, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, + 43, 0, 0, 0, 128, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 0, 0, 0, 0, 0, 0, 43, 0, 0, + 0, 98, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, + 43, 0, 0, 0, 73, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 0, 0, 43, 0, 0, 0, 96, 44, 45, + 46, 47, 48, 49, 106, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 0, 0, 43, 0, 0, 0, + 73, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 0, 0, 43, + 0, 0, 0, 125, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 43, 0, 0, 0, 0, 44, 45, 46, 47, 48, + 49, 106, 51, 52, 53, 54, 55, 56, 57, 58, + 59 }; #define yypact_value_is_default(yystate) \ - ((yystate) == (-35)) + ((yystate) == (-47)) #define yytable_value_is_error(yytable_value) \ YYID (0) -static const yytype_int8 yycheck[] = +static const yytype_int16 yycheck[] = { - 2, 2, 19, 12, 24, 39, 11, 0, 35, 9, - 12, 12, 32, 40, 35, 7, 11, 12, 10, 40, - 9, 13, 24, 24, 29, 17, 18, 44, 36, 37, - 32, 32, 40, 38, 39, 40, 41, 42, 43, 44, - 37, 41, 46, 48, 49, 50, 51, 52, 53, 54, - 59, 8, 9, 5, 6, 7, 13, 59, 59, 16, - 35, 18, 39, 3, 4, -1, 86, 7, 8, 9, - 75, 14, 15, 13, 14, -1, 16, -1, 18, -1, - 7, -1, 87, 10, 86, 86, 13, -1, 93, 10, - -1, 18, 13, 36, 37, 15, 17, 18, 38, 39, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 10, -1, 10, 13, - -1, 13, 36, 37, 18, 19, 18, 42, 43 + 2, 2, 12, 25, 1, 51, 0, 11, 12, 9, + 12, 12, 34, 22, 29, 29, 52, 0, 15, 16, + 5, 6, 7, 25, 25, 7, 47, 48, 10, 42, + 45, 67, 34, 34, 16, 39, 50, 3, 4, 21, + 49, 7, 8, 9, 41, 42, 10, 41, 42, 49, + 16, 17, 16, 19, 64, 21, 20, 21, 104, 50, + 10, 13, 64, 64, 41, 42, 16, 11, 45, 44, + 67, 21, 22, 7, 40, 97, 10, 43, 44, 10, + 41, 42, 16, 10, 50, 16, 20, 21, 15, 16, + 21, 11, 12, 44, 21, 97, 97, 13, 108, 29, + 22, 15, 124, 13, -1, 11, 108, 108, 130, 10, + 16, 104, -1, -1, 15, 16, 106, 127, -1, -1, + 21, -1, 124, 124, 30, 127, 127, -1, 130, 130, + 36, 37, -1, -1, -1, -1, -1, 43, 44, 45, + 46, 47, 48, 49, -1, -1, 52, 53, 54, 55, + 56, 57, 58, 59, 3, 4, -1, -1, 7, 8, + 9, 67, 68, -1, -1, -1, -1, 16, 17, -1, + 19, -1, 21, -1, 3, 4, -1, -1, 7, 8, + 9, -1, -1, -1, -1, -1, -1, 16, 17, -1, + 19, 40, 21, 99, 43, 44, -1, 46, -1, 105, + -1, -1, -1, -1, -1, -1, -1, -1, 114, -1, + -1, 40, 18, -1, 43, 44, -1, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, -1, -1, -1, -1, -1, -1, -1, + 18, -1, -1, -1, 50, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, -1, -1, -1, -1, -1, -1, 18, -1, -1, + -1, 49, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, -1, -1, + 18, -1, -1, -1, 45, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, -1, -1, 18, -1, -1, -1, 45, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, -1, -1, 18, -1, -1, -1, + 45, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, -1, -1, 18, + -1, -1, -1, 45, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 18, -1, -1, -1, -1, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -652,16 +732,20 @@ static const yytype_int8 yypgoto[] = symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 5, 6, 7, 46, 3, 4, 7, 8, 9, - 13, 14, 16, 18, 38, 39, 47, 48, 53, 54, - 56, 58, 7, 10, 51, 52, 53, 56, 0, 39, - 54, 17, 51, 9, 47, 47, 36, 37, 15, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 52, 54, 17, 19, 44, - 40, 47, 47, 54, 54, 54, 54, 54, 54, 54, - 11, 12, 55, 55, 9, 41, 49, 57, 54, 54, - 54, 54, 54, 54, 54, 40, 51, 39, 50, 54, - 19, 54, 42, 43, 40, 54 + 0, 5, 6, 7, 52, 3, 4, 7, 8, 9, + 16, 17, 19, 21, 40, 43, 44, 53, 54, 59, + 60, 65, 67, 7, 10, 57, 58, 59, 65, 0, + 44, 53, 60, 20, 57, 9, 49, 50, 53, 53, + 60, 41, 42, 18, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 58, 60, 20, 22, 49, 60, 9, 44, 46, 55, + 60, 66, 45, 45, 53, 53, 60, 60, 60, 60, + 60, 60, 60, 11, 12, 61, 62, 61, 55, 60, + 60, 60, 60, 60, 60, 60, 45, 57, 49, 44, + 55, 60, 56, 60, 29, 50, 29, 13, 13, 22, + 22, 60, 45, 47, 48, 39, 61, 62, 63, 64, + 50, 60, 63, 15, 57, 45, 60, 13, 50, 15, + 57, 15 }; #define yyerrok (yyerrstatus = 0) @@ -1503,7 +1587,7 @@ yyreduce: case 2: /* Line 1806 of yacc.c */ -#line 112 "util_expr_parse.y" +#line 123 "util_expr_parse.y" { ctx->expr = (yyvsp[(2) - (2)].exVal); } break; @@ -1510,7 +1594,7 @@ yyreduce: case 3: /* Line 1806 of yacc.c */ -#line 113 "util_expr_parse.y" +#line 124 "util_expr_parse.y" { ctx->expr = (yyvsp[(2) - (2)].exVal); } break; @@ -1517,7 +1601,7 @@ yyreduce: case 4: /* Line 1806 of yacc.c */ -#line 114 "util_expr_parse.y" +#line 125 "util_expr_parse.y" { YYABORT; } break; @@ -1524,7 +1608,7 @@ yyreduce: case 5: /* Line 1806 of yacc.c */ -#line 117 "util_expr_parse.y" +#line 128 "util_expr_parse.y" { (yyval.exVal) = ap_expr_make(op_True, NULL, NULL, ctx); } break; @@ -1531,7 +1615,7 @@ yyreduce: case 6: /* Line 1806 of yacc.c */ -#line 118 "util_expr_parse.y" +#line 129 "util_expr_parse.y" { (yyval.exVal) = ap_expr_make(op_False, NULL, NULL, ctx); } break; @@ -1538,28 +1622,28 @@ yyreduce: case 7: /* Line 1806 of yacc.c */ -#line 119 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_Not, (yyvsp[(2) - (2)].exVal), NULL, ctx); } +#line 130 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Or, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 8: /* Line 1806 of yacc.c */ -#line 120 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_Or, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 131 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_And, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 9: /* Line 1806 of yacc.c */ -#line 121 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_And, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 132 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Not, (yyvsp[(2) - (2)].exVal), NULL, ctx); } break; case 10: /* Line 1806 of yacc.c */ -#line 122 "util_expr_parse.y" +#line 133 "util_expr_parse.y" { (yyval.exVal) = ap_expr_make(op_Comp, (yyvsp[(1) - (1)].exVal), NULL, ctx); } break; @@ -1566,140 +1650,140 @@ yyreduce: case 11: /* Line 1806 of yacc.c */ -#line 123 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_unary_op_make( (yyvsp[(1) - (2)].cpVal), (yyvsp[(2) - (2)].exVal), ctx); } +#line 134 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } break; case 12: /* Line 1806 of yacc.c */ -#line 124 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_binary_op_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 135 "util_expr_parse.y" + { YYABORT; } break; case 13: /* Line 1806 of yacc.c */ -#line 125 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } +#line 138 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 14: /* Line 1806 of yacc.c */ -#line 126 "util_expr_parse.y" - { YYABORT; } +#line 139 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 15: /* Line 1806 of yacc.c */ -#line 129 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 140 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 16: /* Line 1806 of yacc.c */ -#line 130 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 141 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 17: /* Line 1806 of yacc.c */ -#line 131 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 142 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 18: /* Line 1806 of yacc.c */ -#line 132 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 143 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 19: /* Line 1806 of yacc.c */ -#line 133 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 144 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 20: /* Line 1806 of yacc.c */ -#line 134 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 145 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 21: /* Line 1806 of yacc.c */ -#line 135 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 146 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 22: /* Line 1806 of yacc.c */ -#line 136 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 147 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 23: /* Line 1806 of yacc.c */ -#line 137 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 148 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 24: /* Line 1806 of yacc.c */ -#line 138 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 149 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 25: /* Line 1806 of yacc.c */ -#line 139 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 150 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_IN, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 26: /* Line 1806 of yacc.c */ -#line 140 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_STR_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 151 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_REG, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 27: /* Line 1806 of yacc.c */ -#line 141 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_IN, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 152 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_NRE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 28: /* Line 1806 of yacc.c */ -#line 142 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_REG, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 153 "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 29: /* Line 1806 of yacc.c */ -#line 143 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_NRE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 154 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_unary_op_make( (yyvsp[(1) - (2)].cpVal), (yyvsp[(2) - (2)].exVal), ctx); } break; case 30: /* Line 1806 of yacc.c */ -#line 146 "util_expr_parse.y" +#line 157 "util_expr_parse.y" { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; @@ -1706,7 +1790,7 @@ yyreduce: case 31: /* Line 1806 of yacc.c */ -#line 147 "util_expr_parse.y" +#line 158 "util_expr_parse.y" { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } break; @@ -1713,174 +1797,278 @@ yyreduce: case 32: /* Line 1806 of yacc.c */ -#line 150 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); } +#line 159 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_list_regex_make((yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 33: /* Line 1806 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 160 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_list_regex_make((yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 34: /* Line 1806 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 161 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } break; case 35: /* Line 1806 of yacc.c */ -#line 155 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 164 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); } break; case 36: /* Line 1806 of yacc.c */ -#line 156 "util_expr_parse.y" - { YYABORT; } +#line 165 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(3) - (3)].exVal), (yyvsp[(1) - (3)].exVal), ctx); } break; case 37: /* Line 1806 of yacc.c */ -#line 159 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx); } +#line 168 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; case 38: /* Line 1806 of yacc.c */ -#line 160 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 169 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (2)].exVal) ? ap_expr_make(op_Concat, (yyvsp[(1) - (2)].exVal), (yyvsp[(2) - (2)].exVal), ctx) : (yyvsp[(1) - (2)].exVal); } break; case 39: /* Line 1806 of yacc.c */ -#line 161 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 170 "util_expr_parse.y" + { YYABORT; } break; case 40: /* Line 1806 of yacc.c */ -#line 164 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); } +#line 173 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].cpVal) ? ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx) : NULL; } break; case 41: /* Line 1806 of yacc.c */ -#line 165 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); } +#line 174 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; case 42: /* Line 1806 of yacc.c */ -#line 168 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, ctx); } +#line 175 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } break; case 43: /* Line 1806 of yacc.c */ -#line 169 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } +#line 178 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); } break; case 44: /* Line 1806 of yacc.c */ -#line 170 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 179 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); } break; case 45: /* Line 1806 of yacc.c */ -#line 171 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 180 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_word_make((yyvsp[(3) - (5)].exVal), ctx); } break; case 46: /* Line 1806 of yacc.c */ -#line 172 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } +#line 183 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 47: /* Line 1806 of yacc.c */ -#line 173 "util_expr_parse.y" - { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } +#line 184 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Regsub, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); } break; case 48: /* Line 1806 of yacc.c */ -#line 174 "util_expr_parse.y" - { (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); } +#line 185 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_bool_make( (yyvsp[(1) - (1)].exVal), ctx); } break; case 49: /* Line 1806 of yacc.c */ -#line 177 "util_expr_parse.y" +#line 186 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 50: + +/* Line 1806 of yacc.c */ +#line 187 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 51: + +/* Line 1806 of yacc.c */ +#line 188 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 52: + +/* Line 1806 of yacc.c */ +#line 189 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Join, (yyvsp[(3) - (5)].exVal), NULL, ctx); } + break; + + case 53: + +/* Line 1806 of yacc.c */ +#line 190 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Join, (yyvsp[(3) - (6)].exVal), (yyvsp[(5) - (6)].exVal), ctx); } + break; + + case 54: + +/* Line 1806 of yacc.c */ +#line 191 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, ctx); } + break; + + case 55: + +/* Line 1806 of yacc.c */ +#line 192 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); } + break; + + case 56: + +/* Line 1806 of yacc.c */ +#line 193 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } + break; + + case 57: + +/* Line 1806 of yacc.c */ +#line 194 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); } + break; + + case 58: + +/* Line 1806 of yacc.c */ +#line 196 "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) { + ap_expr_t *e = ap_expr_regex_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(3) - (3)].cpVal), NULL, 0, ctx); + if (!e) { ctx->error = "Failed to compile regular expression"; YYERROR; } - (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); + (yyval.exVal) = e; } break; - case 50: + case 59: /* Line 1806 of yacc.c */ -#line 186 "util_expr_parse.y" +#line 205 "util_expr_parse.y" { - ap_regex_t *regex; - if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal), - AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { + ap_expr_t *e = ap_expr_regex_make((yyvsp[(2) - (4)].cpVal), (yyvsp[(4) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), 0, ctx); + if (!e) { ctx->error = "Failed to compile regular expression"; YYERROR; } - (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); + (yyval.exVal) = e; } break; - case 51: + case 60: /* Line 1806 of yacc.c */ -#line 197 "util_expr_parse.y" +#line 214 "util_expr_parse.y" { + /* Returns a list: + * <word> ~= split/:// + * => split around ':' + * <word> ~= split/:/\n/ + * => split around ':', use '\n' instead where detected/stripped + * <list> ~= split/.*?Ip Address:([^,]+)/$1/ + * => split around the whole match, use $1 instead where detected/stipped + */ + 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 61: + +/* Line 1806 of yacc.c */ +#line 231 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 62: + +/* Line 1806 of yacc.c */ +#line 232 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 63: + +/* Line 1806 of yacc.c */ +#line 233 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); } + break; + + case 64: + +/* Line 1806 of yacc.c */ +#line 236 "util_expr_parse.y" + { int *n = apr_palloc(ctx->pool, sizeof(int)); *n = (yyvsp[(1) - (1)].num); - (yyval.exVal) = ap_expr_make(op_RegexBackref, n, NULL, ctx); + (yyval.exVal) = ap_expr_make(op_Regref, n, NULL, ctx); } break; - case 52: + case 65: /* Line 1806 of yacc.c */ -#line 204 "util_expr_parse.y" +#line 243 "util_expr_parse.y" { (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } break; - case 53: + case 66: /* Line 1806 of yacc.c */ -#line 207 "util_expr_parse.y" +#line 246 "util_expr_parse.y" { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); } break; @@ -1887,7 +2075,7 @@ yyreduce: /* Line 1806 of yacc.c */ -#line 1891 "util_expr_parse.c" +#line 2079 "util_expr_parse.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2118,7 +2306,7 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 210 "util_expr_parse.y" +#line 249 "util_expr_parse.y" void yyerror(ap_expr_parse_ctx_t *ctx, const char *s) Index: server/util_expr_scan.c =================================================================== --- server/util_expr_scan.c (revision 1783852) +++ server/util_expr_scan.c (working copy) @@ -54,6 +54,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -84,8 +85,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -159,15 +158,7 @@ typedef void* yyscan_t; /* Size of default input buffer. */ #ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else #define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -358,8 +349,8 @@ static void yy_fatal_error (yyconst char msg[] ,yy *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 73 +#define YY_END_OF_BUFFER 74 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -367,22 +358,25 @@ 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[159] = { 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, 0, 0, + 74, 72, 1, 44, 2, 72, 72, 72, 71, 72, + 45, 26, 69, 33, 31, 35, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 72, + 16, 15, 3, 16, 16, 16, 23, 20, 19, 22, + 25, 25, 25, 25, 24, 21, 28, 29, 29, 29, + 29, 30, 73, 64, 1, 1, 63, 66, 70, 1, + 32, 38, 17, 18, 40, 69, 61, 61, 61, 61, + 61, 61, 34, 31, 37, 36, 70, 70, 58, 70, - 7, 8, 9, 20, 60, 46, 48, 50, 45, 49, - 51, 47, 38, 64, 42, 64, 5, 6, 64, 61, - 5, 62, 0 + 56, 55, 59, 70, 54, 53, 27, 27, 57, 70, + 41, 70, 70, 42, 4, 5, 14, 7, 7, 6, + 12, 13, 9, 10, 11, 14, 19, 60, 47, 49, + 51, 46, 50, 52, 48, 39, 70, 70, 43, 70, + 70, 7, 7, 0, 6, 8, 70, 65, 70, 67, + 7, 6, 6, 6, 8, 68, 62, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -392,15 +386,15 @@ static yyconst flex_int32_t yy_ec[256] = 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 +411,177 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[44] = +static yyconst flex_int32_t 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, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, + 1, 2, 3, 1, 3, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[133] = +static yyconst flex_int16_t yy_base[172] = { 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, 46, 52, 76, 0, 122, 124, 237, 236, + 0, 0, 130, 132, 250, 249, 170, 215, 112, 114, + 251, 446, 59, 114, 446, 48, 205, 240, 446, 247, + 446, 446, 51, 228, 116, 227, 0, 210, 206, 218, + 27, 207, 205, 29, 280, 113, 201, 201, 198, 191, + 446, 446, 446, 57, 191, 312, 446, 446, 0, 446, + 446, 128, 190, 342, 446, 446, 446, 446, 142, 189, + 372, 446, 446, 446, 149, 158, 446, 446, 194, 163, + 446, 446, 446, 446, 446, 170, 0, 192, 138, 194, + 150, 196, 446, 446, 446, 446, 0, 196, 0, 181, - 275, 275, 275, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 99, 0, 61, 133, 135, 57, 0, - 138, 0, 275, 259, 262, 265, 79, 67, 268, 271, - 65, 42 + 0, 0, 0, 182, 0, 0, 446, 0, 0, 171, + 0, 178, 168, 446, 446, 446, 446, 174, 181, 184, + 446, 446, 446, 446, 446, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 150, 134, 0, 136, + 134, 178, 187, 190, 193, 0, 112, 0, 33, 0, + 446, 446, 446, 446, 446, 0, 0, 446, 416, 419, + 422, 425, 428, 431, 433, 435, 438, 440, 442, 50, + 48 } ; -static yyconst flex_int16_t yy_def[133] = +static yyconst flex_int16_t yy_def[172] = { 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, + 158, 1, 159, 159, 158, 5, 160, 160, 1, 1, + 161, 161, 162, 162, 163, 163, 164, 164, 1, 1, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 165, + 158, 158, 158, 158, 158, 158, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 45, 166, 158, + 158, 158, 158, 158, 158, 167, 158, 158, 168, 158, + 158, 158, 158, 167, 158, 158, 158, 158, 158, 158, + 167, 158, 158, 158, 158, 158, 158, 158, 166, 158, + 158, 158, 158, 158, 158, 158, 169, 169, 169, 169, + 169, 169, 158, 158, 158, 158, 166, 166, 166, 166, - 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 + 166, 166, 166, 166, 166, 166, 158, 166, 166, 166, + 166, 166, 166, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 170, 168, 169, 169, 169, + 169, 169, 169, 169, 169, 166, 166, 166, 166, 166, + 166, 158, 158, 158, 158, 171, 166, 166, 166, 166, + 158, 158, 158, 158, 158, 166, 166, 0, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158 } ; -static yyconst flex_int16_t yy_nxt[319] = +static yyconst flex_int16_t yy_nxt[495] = { 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, + 22, 23, 23, 24, 25, 22, 26, 27, 28, 29, + 29, 30, 31, 32, 33, 33, 33, 22, 34, 35, + 36, 37, 37, 22, 22, 38, 37, 37, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 37, 37, 37, + 48, 49, 37, 37, 29, 50, 29, 22, 52, 155, + 53, 146, 54, 55, 52, 101, 53, 105, 54, 55, + 80, 80, 83, 83, 83, 86, 86, 86, 102, 56, + 106, 115, 115, 115, 157, 56, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 58, 57, 57, 57, 59, 59, 57, - 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, + 57, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 57, 57, 60, 57, 52, 78, 52, 78, 62, 63, + 62, 63, 52, 81, 52, 94, 69, 70, 69, 70, + 156, 109, 115, 115, 115, 64, 37, 64, 37, 110, + 80, 80, 79, 71, 79, 71, 115, 115, 115, 80, + 80, 82, 150, 95, 80, 80, 130, 149, 65, 148, + 65, 75, 76, 77, 77, 77, 77, 77, 133, 131, + 77, 77, 77, 77, 86, 86, 86, 77, 142, 142, + 147, 134, 151, 151, 77, 143, 143, 144, 145, 145, - 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, + 145, 152, 152, 153, 153, 153, 153, 154, 154, 154, + 141, 140, 139, 138, 137, 77, 75, 76, 77, 77, + 77, 77, 77, 136, 135, 77, 77, 77, 77, 132, + 129, 112, 77, 116, 116, 116, 114, 113, 112, 77, + 111, 104, 103, 100, 99, 98, 96, 93, 85, 84, + 158, 73, 73, 66, 66, 158, 158, 158, 158, 158, + 77, 86, 86, 86, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 88, 158, 89, 90, 158, + 91, 158, 92, 107, 107, 107, 107, 107, 158, 158, + 107, 107, 107, 107, 158, 158, 158, 107, 158, 158, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123 + 158, 158, 158, 158, 108, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 107, 118, 119, 120, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 121, 158, + 158, 122, 158, 158, 158, 158, 158, 123, 158, 158, + 158, 124, 158, 125, 158, 126, 118, 119, 120, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 121, 158, + 158, 122, 158, 158, 158, 158, 158, 123, 158, 158, + 158, 124, 158, 125, 158, 126, 118, 119, 120, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 121, 158, + + 158, 122, 158, 158, 158, 158, 158, 123, 158, 158, + 158, 124, 158, 125, 158, 126, 51, 51, 51, 61, + 61, 61, 67, 67, 67, 68, 68, 68, 72, 72, + 72, 74, 74, 74, 87, 87, 97, 97, 117, 117, + 117, 127, 127, 128, 128, 21, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158 + } ; -static yyconst flex_int16_t yy_chk[319] = +static yyconst flex_int16_t yy_chk[495] = { 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, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 171, + 3, 170, 3, 3, 4, 41, 4, 44, 4, 4, + 23, 23, 26, 26, 26, 33, 33, 33, 41, 3, + 44, 54, 54, 54, 149, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 22, 0, 22, 22, 22, 0, 22, 36, 36, 36, + 5, 5, 5, 5, 7, 19, 8, 20, 7, 7, + 8, 8, 13, 24, 14, 35, 13, 13, 14, 14, + 147, 46, 62, 62, 62, 7, 19, 8, 20, 46, + 75, 75, 19, 13, 20, 14, 69, 69, 69, 76, + 76, 24, 141, 35, 80, 80, 89, 140, 7, 138, + 8, 17, 17, 17, 17, 17, 17, 17, 91, 89, + 17, 17, 17, 17, 86, 86, 86, 17, 118, 118, + 137, 91, 142, 142, 17, 119, 119, 119, 120, 120, - 36, 36, 0, 0, 36, 36, 36, 36, 0, 0, - 36, 0, 0, 0, 0, 0, 36, 0, 0, 0, + 120, 143, 143, 143, 144, 144, 144, 145, 145, 145, + 113, 112, 110, 104, 100, 17, 18, 18, 18, 18, + 18, 18, 18, 98, 92, 18, 18, 18, 18, 90, + 88, 79, 18, 70, 63, 55, 50, 49, 48, 18, + 47, 43, 42, 40, 39, 38, 36, 34, 28, 27, + 21, 16, 15, 10, 9, 0, 0, 0, 0, 0, + 18, 30, 30, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 0, 30, 30, 0, + 30, 0, 30, 45, 45, 45, 45, 45, 0, 0, + 45, 45, 45, 45, 0, 0, 0, 45, 0, 0, + + 0, 0, 0, 0, 45, 0, 0, 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, 45, 56, 56, 56, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 56, 0, 0, 0, 0, 0, 56, 0, 0, + 0, 56, 0, 56, 0, 56, 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, 71, 71, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, - 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123 + 0, 71, 0, 0, 0, 0, 0, 71, 0, 0, + 0, 71, 0, 71, 0, 71, 159, 159, 159, 160, + 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, + 163, 164, 164, 164, 165, 165, 166, 166, 167, 167, + 167, 168, 168, 169, 169, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158 + } ; /* The intent behind this definition is that it'll catch @@ -578,9 +620,10 @@ static yyconst flex_int32_t yy_ec[256] = -#line 43 "util_expr_scan.l" +#line 44 "util_expr_scan.l" #include "util_expr_private.h" #include "util_expr_parse.h" +#include "apr_lib.h" /* apr_isalnum */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ @@ -601,10 +644,57 @@ static yyconst flex_int32_t yy_ec[256] = #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) +#if 0 +#define STACK_PUSH() do { \ + fprintf(stderr, "YY_STACK_PUSH()\n"); \ + ap_expr_parser_stack_push(yyextra); \ +} while (0) +#define STACK_POP() do { \ + fprintf(stderr, "YY_STACK_POP()\n"); \ + ap_expr_parser_stack_pop(yyextra); \ +} while (0) +#define STATE_PUSH(st, sk) do { \ + fprintf(stderr, "YY_STATE_PUSH(%i)\n", (st)); \ + yy_push_state((st), yyscanner); \ + if (sk) { \ + STACK_PUSH(); \ + } \ +} while (0) +#define STATE_POP(sk) do { \ + fprintf(stderr, "YY_STATE_POP()\n"); \ + if (sk) { \ + STACK_POP(); \ + } \ + yy_pop_state(yyscanner); \ +} while (0) +#else +#define STACK_PUSH() do { \ + ap_expr_parser_stack_push(yyextra); \ +} while (0) +#define STACK_POP() do { \ + ap_expr_parser_stack_pop(yyextra); \ +} 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) +#endif + +#define str_ptr (yyextra->stack->scan_ptr) +#define str_buf (yyextra->stack->scan_buf) +#define str_del (yyextra->stack->scan_del) +#define str_state (yyextra->stack->scan_state) + #define STR_APPEND(c) do { \ *str_ptr++ = (c); \ if (str_ptr >= str_buf + sizeof(str_buf)) \ @@ -611,14 +701,21 @@ static yyconst flex_int32_t yy_ec[256] = PERROR("String too long"); \ } while (0) -#line 615 "util_expr_scan.c" +#define STR_EMPTY() (str_ptr == str_buf) +#define STR_FINAL() (*str_ptr = '\0', str_ptr = str_buf) +#line 708 "util_expr_scan.c" + #define INITIAL 0 #define str 1 #define var 2 #define vararg 3 -#define regex 4 -#define regex_flags 5 +#define varext 4 +#define regex 5 +#define regsub 6 +#define regflags 7 +#define split 8 +#define join 9 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way @@ -747,12 +844,7 @@ static int input (yyscan_t yyscanner ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else #define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -760,7 +852,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 fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -771,7 +863,7 @@ static int input (yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -856,14 +948,10 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 78 "util_expr_scan.l" +#line 138 "util_expr_scan.l" - char regex_buf[MAX_STRING_LEN]; - char *regex_ptr = NULL; - char regex_del = '\0'; - /* * Set initial state for string expressions */ @@ -870,7 +958,7 @@ YY_DECL 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 { @@ -882,7 +970,7 @@ YY_DECL /* * Whitespaces */ -#line 886 "util_expr_scan.c" +#line 974 "util_expr_scan.c" yylval = yylval_param; @@ -937,13 +1025,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 >= 159 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 123 ); + while ( yy_current_state != 158 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -966,7 +1054,7 @@ do_action: /* This label is used only to access EO case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 103 "util_expr_scan.l" +#line 159 "util_expr_scan.l" { /* NOP */ } @@ -976,506 +1064,589 @@ YY_RULE_SETUP */ case 2: YY_RULE_SETUP -#line 110 "util_expr_scan.l" +#line 166 "util_expr_scan.l" { - str_ptr = str_buf; + STATE_PUSH(str, 1); str_del = yytext[0]; - BEGIN(str); return T_STR_BEGIN; } YY_BREAK case 3: YY_RULE_SETUP -#line 116 "util_expr_scan.l" +#line 172 "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 { + if (!STR_EMPTY()) { /* 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; + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } + STATE_POP(1); + return T_STR_END; } - else { - STR_APPEND(yytext[0]); - } + STR_APPEND(yytext[0]); } YY_BREAK +/* regexp backref inside string/arg */ case 4: -/* rule 4 can match eol */ YY_RULE_SETUP -#line 138 "util_expr_scan.l" +#line 187 "util_expr_scan.l" { - PERROR("Unterminated string or variable"); + if (!STR_EMPTY()) { + /* return what we have so far and scan '$x' again */ + yyless(0); + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + return T_STRING; + } + yylval->num = yytext[1] - '0'; + return T_REG_REF; } YY_BREAK -case YY_STATE_EOF(var): -case YY_STATE_EOF(vararg): -#line 141 "util_expr_scan.l" +/* variable inside string/arg */ +case 5: +YY_RULE_SETUP +#line 199 "util_expr_scan.l" { - PERROR("Unterminated string or variable"); + if (!STR_EMPTY()) { + /* return what we have so far and scan '%{' again */ + yyless(0); + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + return T_STRING; + } + STATE_PUSH(var, 1); + return T_VAR_BEGIN; } YY_BREAK -case YY_STATE_EOF(str): -#line 144 "util_expr_scan.l" +/* Any non-octal or octal higher than 377 (decimal 255) is invalid */ +case 6: +YY_RULE_SETUP +#line 211 "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); - return T_STRING; - } + PERROR("Bad character escape sequence"); } YY_BREAK -case 5: +case 7: YY_RULE_SETUP -#line 157 "util_expr_scan.l" +#line 214 "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); - } + STR_APPEND(result); } YY_BREAK -case 6: +case 8: YY_RULE_SETUP -#line 168 "util_expr_scan.l" +#line 219 "util_expr_scan.l" { - PERROR("Bad escape sequence"); + int result; + (void)sscanf(yytext+1, "%x", &result); + STR_APPEND(result); } YY_BREAK -case 7: +case 9: YY_RULE_SETUP -#line 171 "util_expr_scan.l" +#line 224 "util_expr_scan.l" { STR_APPEND('\n'); } YY_BREAK -case 8: +case 10: YY_RULE_SETUP -#line 172 "util_expr_scan.l" +#line 225 "util_expr_scan.l" { STR_APPEND('\r'); } YY_BREAK -case 9: +case 11: YY_RULE_SETUP -#line 173 "util_expr_scan.l" +#line 226 "util_expr_scan.l" { STR_APPEND('\t'); } YY_BREAK -case 10: +case 12: YY_RULE_SETUP -#line 174 "util_expr_scan.l" +#line 227 "util_expr_scan.l" { STR_APPEND('\b'); } YY_BREAK -case 11: +case 13: YY_RULE_SETUP -#line 175 "util_expr_scan.l" +#line 228 "util_expr_scan.l" { STR_APPEND('\f'); } YY_BREAK -case 12: -/* rule 12 can match eol */ +case 14: +/* rule 14 can match eol */ YY_RULE_SETUP -#line 176 "util_expr_scan.l" +#line 229 "util_expr_scan.l" { STR_APPEND(yytext[1]); } YY_BREAK -/* regexp backref inside string/arg */ -case 13: +case 15: +/* rule 15 can match eol */ YY_RULE_SETUP -#line 179 "util_expr_scan.l" +#line 231 "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; - } + PERROR("Unterminated string or variable"); } YY_BREAK -case 14: +case 16: YY_RULE_SETUP -#line 194 "util_expr_scan.l" +#line 235 "util_expr_scan.l" { - char *cp = yytext; - while (*cp != '\0') { - STR_APPEND(*cp); - cp++; - } + STR_APPEND(yytext[0]); } YY_BREAK -/* variable inside string/arg */ -case 15: -YY_RULE_SETUP -#line 203 "util_expr_scan.l" +case YY_STATE_EOF(str): +#line 238 "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; + STATE_POP(0); + if (YY_START != INITIAL) { + PERROR("Unterminated string"); } + if (!STR_EMPTY()) { + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + } else { - yy_push_state(var, yyscanner); - return T_VAR_BEGIN; + yylval->cpVal = NULL; } + ap_expr_parser_stack_pop(yyextra); + return T_STRING; } YY_BREAK -case 16: -YY_RULE_SETUP -#line 218 "util_expr_scan.l" -{ - STR_APPEND(yytext[0]); -} - YY_BREAK case 17: YY_RULE_SETUP -#line 222 "util_expr_scan.l" +#line 253 "util_expr_scan.l" { - STR_APPEND(yytext[0]); + yylval->num = yytext[1] - '0'; + return T_REG_REF; } YY_BREAK case 18: YY_RULE_SETUP -#line 226 "util_expr_scan.l" +#line 258 "util_expr_scan.l" { - yy_push_state(var, yyscanner); + STATE_PUSH(var, 1); return T_VAR_BEGIN; } YY_BREAK case 19: YY_RULE_SETUP -#line 231 "util_expr_scan.l" +#line 263 "util_expr_scan.l" { - yylval->num = yytext[1] - '0'; - return T_REGEX_BACKREF; + /* + * fixed name variable expansion %{XXX} and function call + * in %{func:arg} syntax + */ + str_state = 1; + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; } YY_BREAK -/* - * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax - */ case 20: YY_RULE_SETUP -#line 239 "util_expr_scan.l" +#line 273 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); - return T_ID; + /* If we have a T_ID it's a vararg, otherwise a varext */ + if (str_state) { + STATE_PUSH(vararg, 0); + } + else { + STATE_PUSH(varext, 0); + } + return yytext[0]; } YY_BREAK case 21: YY_RULE_SETUP -#line 244 "util_expr_scan.l" +#line 284 "util_expr_scan.l" { - yy_pop_state(yyscanner); - return T_VAR_END; + STATE_POP(0); + return yytext[0]; } YY_BREAK case 22: YY_RULE_SETUP -#line 249 "util_expr_scan.l" +#line 289 "util_expr_scan.l" { - BEGIN(vararg); - return yytext[0]; + STATE_POP(1); + return T_VAR_END; } YY_BREAK case 23: /* rule 23 can match eol */ YY_RULE_SETUP -#line 254 "util_expr_scan.l" +#line 294 "util_expr_scan.l" { char *msg = apr_psprintf(yyextra->pool, - "Invalid character in variable name '%c'", yytext[0]); + "Invalid character in variable name '%c'", + yytext[0]); PERROR(msg); } YY_BREAK case 24: YY_RULE_SETUP -#line 260 "util_expr_scan.l" +#line 301 "util_expr_scan.l" { - if (str_ptr != str_buf) { + yyless(0); + if (!STR_EMPTY()) { /* 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); + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); return T_STRING; } - else { - yy_pop_state(yyscanner); - return T_VAR_END; - } + STATE_POP(0); } YY_BREAK -/* - * Regular Expression - */ case 25: YY_RULE_SETUP -#line 278 "util_expr_scan.l" +#line 310 "util_expr_scan.l" { - regex_del = yytext[1]; - regex_ptr = regex_buf; - BEGIN(regex); + STR_APPEND(yytext[0]); } YY_BREAK +case YY_STATE_EOF(var): +case YY_STATE_EOF(vararg): +case YY_STATE_EOF(varext): +#line 314 "util_expr_scan.l" +{ + PERROR("Unterminated variable"); +} + YY_BREAK +/* + * Regular Expression + */ case 26: YY_RULE_SETUP -#line 283 "util_expr_scan.l" +#line 321 "util_expr_scan.l" { - regex_del = yytext[0]; - regex_ptr = regex_buf; - BEGIN(regex); + STATE_PUSH(regex, 1); + str_state = 'm'; + str_del = yytext[0]; + return T_REGEX; } YY_BREAK case 27: -/* rule 27 can match eol */ YY_RULE_SETUP -#line 288 "util_expr_scan.l" +#line 327 "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_state = yytext[0]; + str_del = yytext[1]; + return (str_state == 'm') ? T_REGEX : T_REGSUB; } YY_BREAK case 28: +/* rule 28 can match eol */ YY_RULE_SETUP -#line 299 "util_expr_scan.l" +#line 333 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX_I; + if (yytext[0] == str_del) { + STATE_POP(0); + STATE_PUSH(regflags, 0); + if (str_state != 'm') { + STATE_PUSH(regsub, 0); + } + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + return T_REG_MATCH; + } + STR_APPEND(yytext[0]); } YY_BREAK case 29: -/* rule 29 can match eol */ YY_RULE_SETUP -#line 304 "util_expr_scan.l" +#line 345 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; + if (yytext[0] == str_del) { + /* Back to regflags */ + STATE_POP(0); + } + else { + STR_APPEND(yytext[0]); + } } YY_BREAK -case YY_STATE_EOF(regex_flags): -#line 310 "util_expr_scan.l" +case YY_STATE_EOF(regsub): +#line 354 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); - BEGIN(INITIAL); - return T_REGEX; + PERROR("Unterminated regexp"); } YY_BREAK +case 30: +YY_RULE_SETUP +#line 357 "util_expr_scan.l" +{ + if (ap_strchr_c("ismg", yytext[0])) { + STR_APPEND(yytext[0]); + } + else if (apr_isalnum(yytext[0])) { + PERROR("Invalid regexp flag(s)"); + } + else { + yyless(0); + if (!STR_EMPTY()) { + yylval->cpVal = apr_pstrdup(yyextra->pool, STR_FINAL()); + } + else { + yylval->cpVal = NULL; + STATE_POP(1); + } + return T_REG_FLAGS; + } +} + YY_BREAK +case YY_STATE_EOF(regflags): +#line 376 "util_expr_scan.l" +{ + STATE_POP(1); + yylval->cpVal = NULL; + return T_REG_FLAGS; +} + YY_BREAK +case YY_STATE_EOF(regex): +#line 381 "util_expr_scan.l" +{ + STATE_POP(1); + if (YY_START != INITIAL) { + PERROR("Unterminated regexp"); + } + yylval->cpVal = NULL; + return T_REG_FLAGS; +} + YY_BREAK /* * Operators */ -case 30: +case 31: YY_RULE_SETUP -#line 319 "util_expr_scan.l" +#line 393 "util_expr_scan.l" { return T_OP_STR_EQ; } YY_BREAK -case 31: +case 32: YY_RULE_SETUP -#line 320 "util_expr_scan.l" +#line 394 "util_expr_scan.l" { return T_OP_STR_NE; } YY_BREAK -case 32: +case 33: YY_RULE_SETUP -#line 321 "util_expr_scan.l" +#line 395 "util_expr_scan.l" { return T_OP_STR_LT; } YY_BREAK -case 33: +case 34: YY_RULE_SETUP -#line 322 "util_expr_scan.l" +#line 396 "util_expr_scan.l" { return T_OP_STR_LE; } YY_BREAK -case 34: +case 35: YY_RULE_SETUP -#line 323 "util_expr_scan.l" +#line 397 "util_expr_scan.l" { return T_OP_STR_GT; } YY_BREAK -case 35: +case 36: YY_RULE_SETUP -#line 324 "util_expr_scan.l" +#line 398 "util_expr_scan.l" { return T_OP_STR_GE; } YY_BREAK -case 36: +case 37: YY_RULE_SETUP -#line 325 "util_expr_scan.l" +#line 399 "util_expr_scan.l" { return T_OP_REG; } YY_BREAK -case 37: +case 38: YY_RULE_SETUP -#line 326 "util_expr_scan.l" +#line 400 "util_expr_scan.l" { return T_OP_NRE; } YY_BREAK -case 38: -YY_RULE_SETUP -#line 327 "util_expr_scan.l" -{ return T_OP_AND; } - YY_BREAK case 39: YY_RULE_SETUP -#line 328 "util_expr_scan.l" +#line 401 "util_expr_scan.l" { return T_OP_AND; } YY_BREAK case 40: YY_RULE_SETUP -#line 329 "util_expr_scan.l" -{ return T_OP_OR; } +#line 402 "util_expr_scan.l" +{ return T_OP_AND; } YY_BREAK case 41: YY_RULE_SETUP -#line 330 "util_expr_scan.l" +#line 403 "util_expr_scan.l" { return T_OP_OR; } YY_BREAK case 42: YY_RULE_SETUP -#line 331 "util_expr_scan.l" -{ return T_OP_NOT; } +#line 404 "util_expr_scan.l" +{ return T_OP_OR; } YY_BREAK case 43: YY_RULE_SETUP -#line 332 "util_expr_scan.l" +#line 405 "util_expr_scan.l" { return T_OP_NOT; } YY_BREAK case 44: YY_RULE_SETUP -#line 333 "util_expr_scan.l" -{ return T_OP_CONCAT; } +#line 406 "util_expr_scan.l" +{ return T_OP_NOT; } YY_BREAK case 45: YY_RULE_SETUP -#line 334 "util_expr_scan.l" -{ return T_OP_IN; } +#line 407 "util_expr_scan.l" +{ return T_OP_CONCAT; } YY_BREAK case 46: YY_RULE_SETUP -#line 335 "util_expr_scan.l" -{ return T_OP_EQ; } +#line 408 "util_expr_scan.l" +{ return T_OP_IN; } YY_BREAK case 47: YY_RULE_SETUP -#line 336 "util_expr_scan.l" -{ return T_OP_NE; } +#line 409 "util_expr_scan.l" +{ return T_OP_EQ; } YY_BREAK case 48: YY_RULE_SETUP -#line 337 "util_expr_scan.l" -{ return T_OP_GE; } +#line 410 "util_expr_scan.l" +{ return T_OP_NE; } YY_BREAK case 49: YY_RULE_SETUP -#line 338 "util_expr_scan.l" -{ return T_OP_LE; } +#line 411 "util_expr_scan.l" +{ return T_OP_GE; } YY_BREAK case 50: YY_RULE_SETUP -#line 339 "util_expr_scan.l" -{ return T_OP_GT; } +#line 412 "util_expr_scan.l" +{ return T_OP_LE; } YY_BREAK case 51: YY_RULE_SETUP -#line 340 "util_expr_scan.l" -{ return T_OP_LT; } +#line 413 "util_expr_scan.l" +{ return T_OP_GT; } YY_BREAK -/* for compatibility with ssl_expr */ case 52: YY_RULE_SETUP -#line 343 "util_expr_scan.l" +#line 414 "util_expr_scan.l" { return T_OP_LT; } YY_BREAK +/* for compatibility with ssl_expr */ case 53: YY_RULE_SETUP -#line 344 "util_expr_scan.l" -{ return T_OP_LE; } +#line 417 "util_expr_scan.l" +{ return T_OP_LT; } YY_BREAK case 54: YY_RULE_SETUP -#line 345 "util_expr_scan.l" -{ return T_OP_GT; } +#line 418 "util_expr_scan.l" +{ return T_OP_LE; } YY_BREAK case 55: YY_RULE_SETUP -#line 346 "util_expr_scan.l" -{ return T_OP_GE; } +#line 419 "util_expr_scan.l" +{ return T_OP_GT; } YY_BREAK case 56: YY_RULE_SETUP -#line 347 "util_expr_scan.l" -{ return T_OP_NE; } +#line 420 "util_expr_scan.l" +{ return T_OP_GE; } YY_BREAK case 57: YY_RULE_SETUP -#line 348 "util_expr_scan.l" -{ return T_OP_EQ; } +#line 421 "util_expr_scan.l" +{ return T_OP_NE; } YY_BREAK case 58: YY_RULE_SETUP -#line 349 "util_expr_scan.l" -{ return T_OP_IN; } +#line 422 "util_expr_scan.l" +{ return T_OP_EQ; } YY_BREAK case 59: YY_RULE_SETUP -#line 351 "util_expr_scan.l" +#line 423 "util_expr_scan.l" +{ return T_OP_IN; } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 425 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_UNARY; + return T_OP_BINARY; } YY_BREAK -case 60: +case 61: YY_RULE_SETUP -#line 356 "util_expr_scan.l" +#line 430 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); - return T_OP_BINARY; + return T_OP_UNARY; } YY_BREAK +/* Split a string (or list) into a(nother) list */ +case 62: +YY_RULE_SETUP +#line 436 "util_expr_scan.l" +{ + STATE_PUSH(split, 0); + return T_OP_SPLIT; +} + YY_BREAK +case 63: +YY_RULE_SETUP +#line 440 "util_expr_scan.l" +{ + STATE_POP(0); + STATE_PUSH(regex, 1); + str_del = yytext[0]; + str_state = 'S'; +} + YY_BREAK +case 64: +YY_RULE_SETUP +#line 446 "util_expr_scan.l" +{ + PERROR("Expecting split regular expression"); +} + YY_BREAK +case YY_STATE_EOF(split): +#line 449 "util_expr_scan.l" +{ + PERROR("Unterminated split"); +} + YY_BREAK +/* Join a list into a string */ +case 65: +YY_RULE_SETUP +#line 454 "util_expr_scan.l" +{ + STATE_PUSH(join, 1); + return T_OP_JOIN; +} + YY_BREAK +case 66: +YY_RULE_SETUP +#line 458 "util_expr_scan.l" +{ + if (++str_state == 3) { + STATE_POP(1); + } + return yytext[0]; +} + YY_BREAK +case YY_STATE_EOF(join): +#line 464 "util_expr_scan.l" +{ + PERROR("Unterminated join"); +} + YY_BREAK /* * Specials */ -case 61: +case 67: YY_RULE_SETUP -#line 364 "util_expr_scan.l" +#line 471 "util_expr_scan.l" { return T_TRUE; } YY_BREAK -case 62: +case 68: YY_RULE_SETUP -#line 365 "util_expr_scan.l" +#line 472 "util_expr_scan.l" { return T_FALSE; } YY_BREAK /* * Digits */ -case 63: +case 69: YY_RULE_SETUP -#line 370 "util_expr_scan.l" +#line 477 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_DIGIT; @@ -1484,9 +1655,9 @@ YY_RULE_SETUP /* * Identifiers */ -case 64: +case 70: YY_RULE_SETUP -#line 378 "util_expr_scan.l" +#line 485 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; @@ -1495,9 +1666,9 @@ YY_RULE_SETUP /* * These are parts of the grammar and are returned as is */ -case 65: +case 71: YY_RULE_SETUP -#line 386 "util_expr_scan.l" +#line 493 "util_expr_scan.l" { return yytext[0]; } @@ -1505,23 +1676,22 @@ YY_RULE_SETUP /* * Anything else is an error */ -case 66: -/* rule 66 can match eol */ +case 72: +/* rule 72 can match eol */ YY_RULE_SETUP -#line 393 "util_expr_scan.l" +#line 500 "util_expr_scan.l" { char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]); PERROR(msg); } YY_BREAK -case 67: +case 73: YY_RULE_SETUP -#line 398 "util_expr_scan.l" +#line 505 "util_expr_scan.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1523 "util_expr_scan.c" +#line 1694 "util_expr_scan.c" case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(regex): yyterminate(); case YY_END_OF_BUFFER: @@ -1815,7 +1985,7 @@ 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 >= 159 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1844,11 +2014,11 @@ 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 >= 159 ) 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_is_jam = (yy_current_state == 158); return yy_is_jam ? 0 : yy_current_state; } @@ -2251,8 +2421,8 @@ YY_BUFFER_STATE ap_expr_yy_scan_string (yyconst ch /** Setup the input buffer state to scan the given bytes. The next call to ap_expr_yylex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ @@ -2661,7 +2831,7 @@ void ap_expr_yyfree (void * ptr , yyscan_t yyscann #define YYTABLES_NAME "yytables" -#line 398 "util_expr_scan.l" +#line 505 "util_expr_scan.l"
--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@xxxxxxxxxxxxxxxx For additional commands, e-mail: users-help@xxxxxxxxxxxxxxxx