httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s.@apache.org
Subject svn commit: r1037504 - in /httpd/httpd/trunk: include/ modules/aaa/ server/
Date Sun, 21 Nov 2010 17:22:27 GMT
Author: sf
Date: Sun Nov 21 17:22:26 2010
New Revision: 1037504

URL: http://svn.apache.org/viewvc?rev=1037504&view=rev
Log:
ap_expr related fixes/enhancements:
- implement regex backreferences and make them available for setting 
  envvars in SetEnvIfExpr
- implement nested function calls in %-syntax: %{func1:%{func2:arg}} 
- actually implement evaluation of concatenation operator (oops...)
- Fix <If ... > treating an internal error as success

Modified:
    httpd/httpd/trunk/include/ap_expr.h
    httpd/httpd/trunk/modules/aaa/mod_authz_core.c
    httpd/httpd/trunk/server/request.c
    httpd/httpd/trunk/server/util_expr_eval.c
    httpd/httpd/trunk/server/util_expr_parse.c
    httpd/httpd/trunk/server/util_expr_parse.h
    httpd/httpd/trunk/server/util_expr_parse.y
    httpd/httpd/trunk/server/util_expr_private.h
    httpd/httpd/trunk/server/util_expr_scan.c
    httpd/httpd/trunk/server/util_expr_scan.l

Modified: httpd/httpd/trunk/include/ap_expr.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_expr.h?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_expr.h (original)
+++ httpd/httpd/trunk/include/ap_expr.h Sun Nov 21 17:22:26 2010
@@ -55,12 +55,31 @@ typedef struct {
  * Evaluate a parse tree
  * @param r The current request
  * @param expr The expression to be evaluated
- * @param err A more detailed error string
+ * @param err Where an error message should be stored
  * @return > 0 if expression evaluates to true, == 0 if false, < 0 on error
+ * @note err will be set to NULL on success, or to an error message on error
  */
 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *expr,
                              const char **err);
 
+/**
+ * Evaluate a parse tree, with regexp backreferences
+ * @param r The current request
+ * @param expr The expression to be evaluated
+ * @param nmatch size of the regex match vector pmatch
+ * @param pmatch information about regex matches
+ * @param source the string that pmatch applies to
+ * @param err Where an error message should be stored
+ * @return > 0 if expression evaluates to true, == 0 if false, < 0 on error
+ * @note err will be set to NULL on success, or to an error message on error
+ * @note nmatch/pmatch/source can be used both to make previous matches
+ *       available to ap_expr_exec_re and to use ap_expr_exec_re's matches
+ *       later on.
+ */
+AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *expr,
+                                apr_size_t nmatch, ap_regmatch_t *pmatch,
+                                const char **source, const char **err);
+
 /** Context used during evaluation of a parse tree, created by ap_expr_exec */
 typedef struct {
     /** the current request */
@@ -75,6 +94,12 @@ typedef struct {
     const char **err;
     /** ap_expr_info_t for the expression */
     const ap_expr_info_t *info;
+    /** regex match information for back references */
+    ap_regmatch_t *re_pmatch;
+    /** size of the vector pointed to by re_pmatch */
+    apr_size_t re_nmatch;
+    /** the string corresponding to the re_pmatch*/
+    const char **re_source;
 } ap_expr_eval_ctx;
 
 

Modified: httpd/httpd/trunk/modules/aaa/mod_authz_core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authz_core.c?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authz_core.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authz_core.c Sun Nov 21 17:22:26 2010
@@ -992,7 +992,7 @@ static authz_status expr_check_authoriza
     const ap_expr_info_t *expr = parsed_require_line;
     int rc = ap_expr_exec(r, expr, &err);
 
-    if (err || !rc)
+    if (rc <= 0)
 	    /* XXX: real error handling? */
         return AUTHZ_DENIED;
     else

Modified: httpd/httpd/trunk/server/request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/request.c?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/request.c (original)
+++ httpd/httpd/trunk/server/request.c Sun Nov 21 17:22:26 2010
@@ -1535,7 +1535,7 @@ AP_DECLARE(int) ap_file_walk(request_rec
 
             if (entry_core->condition) {
                 /* XXX: error handling */
-                if (!ap_expr_exec(r, entry_core->condition, &err)) {
+                if (ap_expr_exec(r, entry_core->condition, &err) <= 0) {
                     continue;
                 }
             }

Modified: httpd/httpd/trunk/server/util_expr_eval.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_eval.c?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_eval.c (original)
+++ httpd/httpd/trunk/server/util_expr_eval.c Sun Nov 21 17:22:26 2010
@@ -38,12 +38,12 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lo
 
 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info,
                                             const ap_expr *args);
+static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx *ctx, int n);
 static const char *ap_expr_eval_var(ap_expr_eval_ctx *ctx,
                                     const ap_expr_var_func_t *func,
                                     const void *data);
 
 /* define AP_EXPR_DEBUG to log the parse tree when parsing an expression */
-/*#define AP_EXPR_DEBUG */ 
 #ifdef AP_EXPR_DEBUG
 static void expr_dump_tree(const ap_expr *e, const server_rec *s, int loglevel, int indent);
 #endif
@@ -61,14 +61,30 @@ static const char *ap_expr_eval_word(ap_
         case op_Var:
             result = ap_expr_eval_var(ctx, node->node_arg1, node->node_arg2);
             break;
+        case op_Concat: {
+            const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
+            const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
+            if (!*s1)
+                result = s2;
+            else if (!*s2)
+                result = s1;
+            else
+                result = apr_pstrcat(ctx->p, s1, s2, NULL);
+            break;
+        }
         case op_StringFuncCall: {
             const ap_expr *info = node->node_arg1;
             const ap_expr *args = node->node_arg2;
             result = ap_expr_eval_string_func(ctx, info, args);
             break;
         }
+        case op_RegexBackref: {
+            const int *np = node->node_arg1;
+            result = ap_expr_eval_re_backref(ctx, *np);
+            break;
+        }
         default:
-            *ctx->err = "Internal evaluation error: Unknown expression node";
+            *ctx->err = "Internal evaluation error: Unknown word expression node";
             break;
     }
     if (!result)
@@ -85,6 +101,21 @@ static const char *ap_expr_eval_var(ap_e
     return (*func)(ctx, data);
 }
 
+static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx *ctx, int n)
+{
+    int len;
+
+    if (!ctx->re_pmatch || !ctx->re_source || *ctx->re_source == '\0' ||
+        ctx->re_nmatch < n + 1)
+        return "";
+
+    len = ctx->re_pmatch[n].rm_eo - ctx->re_pmatch[n].rm_so;
+    if (len == 0)
+        return "";
+
+    return apr_pstrndup(ctx->p, *ctx->re_source + ctx->re_pmatch[n].rm_so, len);
+}
+
 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info,
                                             const ap_expr *arg)
 {
@@ -206,32 +237,39 @@ static int ap_expr_eval_comp(ap_expr_eva
             }
             return 0;
         }
-        case op_REG: {
-            const ap_expr *e1;
-            const ap_expr *e2;
-            const char *word;
-            const ap_regex_t *regex;
-
-            e1 = node->node_arg1;
-            e2 = node->node_arg2;
-            word = ap_expr_eval_word(ctx, e1);
-            regex = e2->node_arg1;
-            return (ap_regexec(regex, word, 0, NULL, 0) == 0);
-        }
+        case op_REG:
         case op_NRE: {
             const ap_expr *e1;
             const ap_expr *e2;
             const char *word;
             const ap_regex_t *regex;
+            int result;
 
             e1 = node->node_arg1;
             e2 = node->node_arg2;
             word = ap_expr_eval_word(ctx, e1);
             regex = e2->node_arg1;
-            return !(ap_regexec(regex, word, 0, NULL, 0) == 0);
+
+            /*
+             * $0 ... $9 may contain stuff the user wants to keep. Therefore
+             * we only set them if there are capturing parens in the regex.
+             */
+            if (regex->re_nsub > 0) {
+                result = (0 == ap_regexec(regex, word, ctx->re_nmatch,
+                                          ctx->re_pmatch, 0));
+                *ctx->re_source = result ? word : NULL;
+            }
+            else {
+                result = (0 == ap_regexec(regex, word, 0, NULL, 0));
+            }
+
+            if (node->node_op == op_REG)
+                return result;
+            else
+                return !result;
         }
         default: {
-            *ctx->err = "Internal evaluation error: Unknown expression node";
+            *ctx->err = "Internal evaluation error: Unknown comp expression node";
             return -1;
         }
     }
@@ -468,6 +506,8 @@ ap_expr *ap_expr_var_make(const char *na
     ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2)
 #define DUMP_P(op, p1)                                                      \
     ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1);
+#define DUMP_IP(op, p1)                                                      \
+    ap_log_error(MARK,"%*s%s: %d", indent, " ", op, *(int *)p1);
 #define DUMP_S(op, s1)                                                      \
     ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1)
 
@@ -604,6 +644,10 @@ static void expr_dump_tree(const ap_expr
     case op_Regex:
         DUMP_P("op_Regex", e->node_arg1);
         break;
+    /* arg1: pointer to int */
+    case op_RegexBackref:
+        DUMP_IP("op_RegexBackref", e->node_arg1);
+        break;
     default:
         ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
         break;
@@ -687,9 +731,15 @@ static int ap_expr_eval(ap_expr_eval_ctx
     }
 }
 
-
 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info, const char **err)
 {
+    return ap_expr_exec_re(r, info, 0, NULL, NULL, err);
+}
+
+AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
+                                apr_size_t nmatch, ap_regmatch_t *pmatch,
+                                const char **source, const char **err)
+{
     ap_expr_eval_ctx ctx;
     int rc;
     ctx.r = r;
@@ -698,6 +748,22 @@ AP_DECLARE(int) ap_expr_exec(request_rec
     ctx.p = r->pool;
     ctx.err  = err;
     ctx.info = info;
+    ctx.re_nmatch = nmatch;
+    ctx.re_pmatch = pmatch;
+    ctx.re_source = source;
+    ap_regmatch_t tmp_pmatch[10];
+    const char *tmp_source;
+
+    if (!pmatch) {
+        ctx.re_nmatch = 10;
+        ctx.re_pmatch = tmp_pmatch;
+        ctx.re_source = &tmp_source;
+        tmp_source = NULL;
+    }
+    else {
+        AP_DEBUG_ASSERT(source != NULL);
+        AP_DEBUG_ASSERT(nmatch > 0);
+    }
 
     *err = NULL;
     rc = ap_expr_eval(&ctx, info->root_node);

Modified: httpd/httpd/trunk/server/util_expr_parse.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_parse.c?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_parse.c (original)
+++ httpd/httpd/trunk/server/util_expr_parse.c Sun Nov 21 17:22:26 2010
@@ -117,31 +117,32 @@
      T_STRING = 263,
      T_REGEX = 264,
      T_REGEX_I = 265,
-     T_OP_UNARY = 266,
-     T_OP_BINARY = 267,
-     T_STR_BEGIN = 268,
-     T_STR_END = 269,
-     T_VAR_BEGIN = 270,
-     T_VAR_END = 271,
-     T_OP_EQ = 272,
-     T_OP_NE = 273,
-     T_OP_LT = 274,
-     T_OP_LE = 275,
-     T_OP_GT = 276,
-     T_OP_GE = 277,
-     T_OP_REG = 278,
-     T_OP_NRE = 279,
-     T_OP_IN = 280,
-     T_OP_STR_EQ = 281,
-     T_OP_STR_NE = 282,
-     T_OP_STR_LT = 283,
-     T_OP_STR_LE = 284,
-     T_OP_STR_GT = 285,
-     T_OP_STR_GE = 286,
-     T_OP_CONCAT = 287,
-     T_OP_OR = 288,
-     T_OP_AND = 289,
-     T_OP_NOT = 290
+     T_REGEX_BACKREF = 266,
+     T_OP_UNARY = 267,
+     T_OP_BINARY = 268,
+     T_STR_BEGIN = 269,
+     T_STR_END = 270,
+     T_VAR_BEGIN = 271,
+     T_VAR_END = 272,
+     T_OP_EQ = 273,
+     T_OP_NE = 274,
+     T_OP_LT = 275,
+     T_OP_LE = 276,
+     T_OP_GT = 277,
+     T_OP_GE = 278,
+     T_OP_REG = 279,
+     T_OP_NRE = 280,
+     T_OP_IN = 281,
+     T_OP_STR_EQ = 282,
+     T_OP_STR_NE = 283,
+     T_OP_STR_LT = 284,
+     T_OP_STR_LE = 285,
+     T_OP_STR_GT = 286,
+     T_OP_STR_GE = 287,
+     T_OP_CONCAT = 288,
+     T_OP_OR = 289,
+     T_OP_AND = 290,
+     T_OP_NOT = 291
    };
 #endif
 
@@ -156,11 +157,12 @@ typedef union YYSTYPE
 
     char    *cpVal;
     ap_expr *exVal;
+    int      num;
 
 
 
 /* Line 214 of yacc.c  */
-#line 164 "util_expr_parse.c"
+#line 166 "util_expr_parse.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -171,7 +173,7 @@ typedef union YYSTYPE
 /* Copy the second part of user declarations.  */
 
 /* Line 264 of yacc.c  */
-#line 96 "util_expr_parse.y"
+#line 99 "util_expr_parse.y"
 
 #include "util_expr_private.h"
 #define yyscanner ctx->scanner
@@ -180,7 +182,7 @@ int ap_expr_yylex(YYSTYPE *lvalp, void *
 
 
 /* Line 264 of yacc.c  */
-#line 184 "util_expr_parse.c"
+#line 186 "util_expr_parse.c"
 
 #ifdef short
 # undef short
@@ -393,22 +395,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  27
+#define YYFINAL  30
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   117
+#define YYLAST   122
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  42
+#define YYNTOKENS  43
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  13
+#define YYNNTS  14
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  47
+#define YYNRULES  50
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  88
+#define YYNSTATES  91
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   290
+#define YYMAXUTOK   291
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -420,15 +422,15 @@ static const yytype_uint8 yytranslate[] 
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      36,    37,     2,     2,    40,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    41,     2,
+      37,    38,     2,     2,    41,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    42,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    38,     2,    39,     2,     2,     2,     2,
+       2,     2,     2,    39,     2,    40,     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,
@@ -445,7 +447,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
+      35,    36
 };
 
 #if YYDEBUG
@@ -456,39 +458,42 @@ static const yytype_uint8 yyprhs[] =
        0,     0,     3,     5,     7,     9,    11,    14,    18,    22,
       24,    27,    31,    35,    39,    43,    47,    51,    55,    59,
       63,    67,    71,    75,    79,    83,    87,    91,    95,    97,
-     101,   103,   107,   110,   112,   114,   116,   120,   126,   128,
-     132,   134,   136,   140,   143,   145,   147,   152
+     101,   103,   107,   110,   112,   114,   116,   118,   122,   128,
+     130,   134,   136,   138,   140,   144,   147,   149,   151,   153,
+     158
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      43,     0,    -1,    44,    -1,     5,    -1,     3,    -1,     4,
-      -1,    35,    44,    -1,    44,    33,    44,    -1,    44,    34,
-      44,    -1,    45,    -1,    11,    51,    -1,    36,    44,    37,
-      -1,    51,    17,    51,    -1,    51,    18,    51,    -1,    51,
-      19,    51,    -1,    51,    20,    51,    -1,    51,    21,    51,
-      -1,    51,    22,    51,    -1,    51,    26,    51,    -1,    51,
-      27,    51,    -1,    51,    28,    51,    -1,    51,    29,    51,
-      -1,    51,    30,    51,    -1,    51,    31,    51,    -1,    51,
-      25,    46,    -1,    51,    23,    52,    -1,    51,    24,    52,
-      -1,    51,    12,    51,    -1,    53,    -1,    38,    47,    39,
-      -1,    51,    -1,    47,    40,    51,    -1,    48,    49,    -1,
-      49,    -1,     8,    -1,    50,    -1,    15,     7,    16,    -1,
-      15,     7,    41,    48,    16,    -1,     6,    -1,    51,    32,
-      51,    -1,    50,    -1,    54,    -1,    13,    48,    14,    -1,
-      13,    14,    -1,     9,    -1,    10,    -1,     7,    36,    51,
-      37,    -1,     7,    36,    51,    37,    -1
+      44,     0,    -1,    45,    -1,     5,    -1,     3,    -1,     4,
+      -1,    36,    45,    -1,    45,    34,    45,    -1,    45,    35,
+      45,    -1,    46,    -1,    12,    52,    -1,    37,    45,    38,
+      -1,    52,    18,    52,    -1,    52,    19,    52,    -1,    52,
+      20,    52,    -1,    52,    21,    52,    -1,    52,    22,    52,
+      -1,    52,    23,    52,    -1,    52,    27,    52,    -1,    52,
+      28,    52,    -1,    52,    29,    52,    -1,    52,    30,    52,
+      -1,    52,    31,    52,    -1,    52,    32,    52,    -1,    52,
+      26,    47,    -1,    52,    24,    53,    -1,    52,    25,    53,
+      -1,    52,    13,    52,    -1,    55,    -1,    39,    48,    40,
+      -1,    52,    -1,    48,    41,    52,    -1,    49,    50,    -1,
+      50,    -1,     8,    -1,    51,    -1,    54,    -1,    16,     7,
+      17,    -1,    16,     7,    42,    49,    17,    -1,     6,    -1,
+      52,    33,    52,    -1,    51,    -1,    54,    -1,    56,    -1,
+      14,    49,    15,    -1,    14,    15,    -1,     9,    -1,    10,
+      -1,    11,    -1,     7,    37,    52,    38,    -1,     7,    37,
+      52,    38,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,   106,   106,   107,   110,   111,   112,   113,   114,   115,
-     116,   117,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   138,   139,
-     142,   143,   146,   147,   151,   152,   155,   156,   159,   160,
-     161,   162,   163,   164,   167,   176,   187,   190
+       0,   109,   109,   110,   113,   114,   115,   116,   117,   118,
+     119,   120,   123,   124,   125,   126,   127,   128,   129,   130,
+     131,   132,   133,   134,   135,   136,   137,   138,   141,   142,
+     145,   146,   149,   150,   153,   154,   155,   158,   159,   162,
+     163,   164,   165,   166,   167,   168,   171,   180,   191,   198,
+     201
 };
 #endif
 
@@ -498,14 +503,15 @@ static const yytype_uint8 yyrline[] =
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "T_TRUE", "T_FALSE", "ERROR", "T_DIGIT",
-  "T_ID", "T_STRING", "T_REGEX", "T_REGEX_I", "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", "lstfunccall", "strfunccall", 0
+  "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
 };
 #endif
 
@@ -517,19 +523,20 @@ 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,    40,    41,   123,   125,
-      44,    58
+     285,   286,   287,   288,   289,   290,   291,    40,    41,   123,
+     125,    44,    58
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    42,    43,    43,    44,    44,    44,    44,    44,    44,
-      44,    44,    45,    45,    45,    45,    45,    45,    45,    45,
-      45,    45,    45,    45,    45,    45,    45,    45,    46,    46,
-      47,    47,    48,    48,    49,    49,    50,    50,    51,    51,
-      51,    51,    51,    51,    52,    52,    53,    54
+       0,    43,    44,    44,    45,    45,    45,    45,    45,    45,
+      45,    45,    46,    46,    46,    46,    46,    46,    46,    46,
+      46,    46,    46,    46,    46,    46,    46,    46,    47,    47,
+      48,    48,    49,    49,    50,    50,    50,    51,    51,    52,
+      52,    52,    52,    52,    52,    52,    53,    53,    54,    55,
+      56
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -538,8 +545,9 @@ static const yytype_uint8 yyr2[] =
        0,     2,     1,     1,     1,     1,     2,     3,     3,     1,
        2,     3,     3,     3,     3,     3,     3,     3,     3,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     1,     3,
-       1,     3,     2,     1,     1,     1,     3,     5,     1,     3,
-       1,     1,     3,     2,     1,     1,     4,     4
+       1,     3,     2,     1,     1,     1,     1,     3,     5,     1,
+       3,     1,     1,     1,     3,     2,     1,     1,     1,     4,
+       4
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -547,22 +555,23 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     4,     5,     3,    38,     0,     0,     0,     0,     0,
-       0,     0,     2,     9,    40,     0,    41,     0,    10,    34,
-      43,     0,    33,    35,     0,     6,     0,     1,     0,     0,
+       0,     4,     5,     3,    39,     0,    48,     0,     0,     0,
+       0,     0,     0,     2,     9,    41,     0,    42,    43,     0,
+      10,    34,    45,     0,    33,    35,    36,     0,     6,     0,
+       1,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    42,    32,
-      36,     0,    11,     7,     8,    27,    12,    13,    14,    15,
-      16,    17,    44,    45,    25,    26,     0,     0,    24,    28,
-      18,    19,    20,    21,    22,    23,    39,    47,     0,     0,
-       0,    30,    37,     0,    29,     0,    46,    31
+       0,    44,    32,    37,     0,    11,     7,     8,    27,    12,
+      13,    14,    15,    16,    17,    46,    47,    25,    26,     0,
+       0,    24,    28,    18,    19,    20,    21,    22,    23,    40,
+      50,     0,     0,     0,    30,    38,     0,    29,     0,    49,
+      31
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,    11,    12,    13,    68,    80,    21,    22,    14,    15,
-      64,    69,    16
+      -1,    12,    13,    14,    71,    83,    23,    24,    15,    16,
+      67,    17,    72,    18
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -570,22 +579,23 @@ static const yytype_int8 yydefgoto[] =
 #define YYPACT_NINF -29
 static const yytype_int8 yypact[] =
 {
-      49,   -29,   -29,   -29,   -29,    12,     1,    35,    25,    65,
-      65,    57,   -15,   -29,   -29,    85,   -29,     1,    31,   -29,
-     -29,    51,   -29,   -29,   -10,   -29,    53,   -29,    65,    65,
-       1,     1,     1,     1,     1,     1,     1,    11,    11,    -5,
-       1,     1,     1,     1,     1,     1,     1,   -28,   -29,   -29,
-     -29,    36,   -29,    33,   -29,    31,    31,    31,    31,    31,
-      31,    31,   -29,   -29,   -29,   -29,    34,     1,   -29,   -29,
-      31,    31,    31,    31,    31,    31,   -29,   -29,    -3,     1,
-       6,    31,   -29,   -22,   -29,     1,   -29,    31
+      50,   -29,   -29,   -29,   -29,   -13,   -29,     9,    -6,    14,
+      85,    85,    48,   -28,   -29,   -29,    87,   -29,   -29,     9,
+      25,   -29,   -29,    36,   -29,   -29,   -29,    -9,   -29,    45,
+     -29,    85,    85,     9,     9,     9,     9,     9,     9,     9,
+      60,    60,     4,     9,     9,     9,     9,     9,     9,     9,
+     -16,   -29,   -29,   -29,    74,   -29,    43,   -29,    25,    25,
+      25,    25,    25,    25,    25,   -29,   -29,   -29,   -29,    23,
+       9,   -29,   -29,    25,    25,    25,    25,    25,    25,   -29,
+     -29,    57,     9,     5,    25,   -29,    34,   -29,     9,   -29,
+      25
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -29,   -29,    13,   -29,   -29,   -29,    24,   -20,    -4,    -6,
-      39,   -29,   -29
+     -29,   -29,     3,   -29,   -29,   -29,    17,   -22,    -5,    -7,
+      52,    -4,   -29,   -29
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -595,49 +605,52 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      18,    49,    66,    23,    46,    19,    50,     4,     5,    77,
-      46,    47,     8,    82,     7,    86,     8,    23,    28,    29,
-      62,    63,    25,    26,    55,    56,    57,    58,    59,    60,
-      61,    51,    24,    67,    70,    71,    72,    73,    74,    75,
-      76,    53,    54,    19,    19,    84,    85,    23,    17,    20,
-       8,     8,     1,     2,     3,     4,     5,    27,    49,    19,
-       6,    81,     7,    46,     8,    48,     8,    29,     1,     2,
-      79,     4,     5,    83,    23,    78,     6,    65,     7,    87,
-       8,     0,     0,     0,     9,    10,    28,    29,     0,     0,
-      52,     0,     0,     0,     0,     0,     0,    30,     0,     0,
-       9,    10,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46
+      20,    52,    21,    25,    26,     6,    31,    32,    53,    22,
+       9,    69,    50,    28,    29,     4,     5,    49,    25,    26,
+       6,    27,    80,     8,    19,     9,    58,    59,    60,    61,
+      62,    63,    64,    54,    56,    57,    73,    74,    75,    76,
+      77,    78,    79,    70,    21,    87,    88,     6,    30,    25,
+      26,    51,     9,     1,     2,     3,     4,     5,    49,    52,
+      82,     6,     7,    84,     8,    21,     9,    49,     6,    65,
+      66,    81,    89,     9,    85,    86,    25,    26,    32,    31,
+      32,    90,    21,    55,     0,     6,    10,    11,     1,     2,
+       9,     4,     5,    68,     0,     0,     6,     7,     0,     8,
+      33,     9,     0,     0,     0,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    10,    11
 };
 
 static const yytype_int8 yycheck[] =
 {
-       6,    21,     7,     7,    32,     8,    16,     6,     7,    37,
-      32,    17,    15,    16,    13,    37,    15,    21,    33,    34,
-       9,    10,     9,    10,    30,    31,    32,    33,    34,    35,
-      36,    41,     7,    38,    40,    41,    42,    43,    44,    45,
-      46,    28,    29,     8,     8,    39,    40,    51,    36,    14,
-      15,    15,     3,     4,     5,     6,     7,     0,    78,     8,
-      11,    67,    13,    32,    15,    14,    15,    34,     3,     4,
-      36,     6,     7,    79,    78,    51,    11,    38,    13,    85,
-      15,    -1,    -1,    -1,    35,    36,    33,    34,    -1,    -1,
-      37,    -1,    -1,    -1,    -1,    -1,    -1,    12,    -1,    -1,
-      35,    36,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32
+       7,    23,     8,     8,     8,    11,    34,    35,    17,    15,
+      16,     7,    19,    10,    11,     6,     7,    33,    23,    23,
+      11,     7,    38,    14,    37,    16,    33,    34,    35,    36,
+      37,    38,    39,    42,    31,    32,    43,    44,    45,    46,
+      47,    48,    49,    39,     8,    40,    41,    11,     0,    54,
+      54,    15,    16,     3,     4,     5,     6,     7,    33,    81,
+      37,    11,    12,    70,    14,     8,    16,    33,    11,     9,
+      10,    54,    38,    16,    17,    82,    81,    81,    35,    34,
+      35,    88,     8,    38,    -1,    11,    36,    37,     3,     4,
+      16,     6,     7,    41,    -1,    -1,    11,    12,    -1,    14,
+      13,    16,    -1,    -1,    -1,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    36,    37
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,     4,     5,     6,     7,    11,    13,    15,    35,
-      36,    43,    44,    45,    50,    51,    54,    36,    51,     8,
-      14,    48,    49,    50,     7,    44,    44,     0,    33,    34,
-      12,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    51,    14,    49,
-      16,    41,    37,    44,    44,    51,    51,    51,    51,    51,
-      51,    51,     9,    10,    52,    52,     7,    38,    46,    53,
-      51,    51,    51,    51,    51,    51,    51,    37,    48,    36,
-      47,    51,    16,    51,    39,    40,    37,    51
+       0,     3,     4,     5,     6,     7,    11,    12,    14,    16,
+      36,    37,    44,    45,    46,    51,    52,    54,    56,    37,
+      52,     8,    15,    49,    50,    51,    54,     7,    45,    45,
+       0,    34,    35,    13,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      52,    15,    50,    17,    42,    38,    45,    45,    52,    52,
+      52,    52,    52,    52,    52,     9,    10,    53,    53,     7,
+      39,    47,    55,    52,    52,    52,    52,    52,    52,    52,
+      38,    49,    37,    48,    52,    17,    52,    40,    41,    38,
+      52
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1456,238 +1469,238 @@ yyreduce:
         case 2:
 
 /* Line 1455 of yacc.c  */
-#line 106 "util_expr_parse.y"
+#line 109 "util_expr_parse.y"
     { ctx->expr = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 3:
 
 /* Line 1455 of yacc.c  */
-#line 107 "util_expr_parse.y"
+#line 110 "util_expr_parse.y"
     { YYABORT; ;}
     break;
 
   case 4:
 
 /* Line 1455 of yacc.c  */
-#line 110 "util_expr_parse.y"
+#line 113 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_True,        NULL, NULL, ctx); ;}
     break;
 
   case 5:
 
 /* Line 1455 of yacc.c  */
-#line 111 "util_expr_parse.y"
+#line 114 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_False,       NULL, NULL, ctx); ;}
     break;
 
   case 6:
 
 /* Line 1455 of yacc.c  */
-#line 112 "util_expr_parse.y"
+#line 115 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_Not,         (yyvsp[(2) - (2)].exVal),   NULL, ctx); ;}
     break;
 
   case 7:
 
 /* Line 1455 of yacc.c  */
-#line 113 "util_expr_parse.y"
+#line 116 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_Or,          (yyvsp[(1) - (3)].exVal),   (yyvsp[(3) - (3)].exVal),   ctx); ;}
     break;
 
   case 8:
 
 /* Line 1455 of yacc.c  */
-#line 114 "util_expr_parse.y"
+#line 117 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_And,         (yyvsp[(1) - (3)].exVal),   (yyvsp[(3) - (3)].exVal),   ctx); ;}
     break;
 
   case 9:
 
 /* Line 1455 of yacc.c  */
-#line 115 "util_expr_parse.y"
+#line 118 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_Comp,        (yyvsp[(1) - (1)].exVal),   NULL, ctx); ;}
     break;
 
   case 10:
 
 /* Line 1455 of yacc.c  */
-#line 116 "util_expr_parse.y"
+#line 119 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_unary_op_make(       (yyvsp[(1) - (2)].cpVal),   (yyvsp[(2) - (2)].exVal),   ctx); ;}
     break;
 
   case 11:
 
 /* Line 1455 of yacc.c  */
-#line 117 "util_expr_parse.y"
+#line 120 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;}
     break;
 
   case 12:
 
 /* Line 1455 of yacc.c  */
-#line 120 "util_expr_parse.y"
+#line 123 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_EQ,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 13:
 
 /* Line 1455 of yacc.c  */
-#line 121 "util_expr_parse.y"
+#line 124 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_NE,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 14:
 
 /* Line 1455 of yacc.c  */
-#line 122 "util_expr_parse.y"
+#line 125 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_LT,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 15:
 
 /* Line 1455 of yacc.c  */
-#line 123 "util_expr_parse.y"
+#line 126 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_LE,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 16:
 
 /* Line 1455 of yacc.c  */
-#line 124 "util_expr_parse.y"
+#line 127 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_GT,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 17:
 
 /* Line 1455 of yacc.c  */
-#line 125 "util_expr_parse.y"
+#line 128 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_GE,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 18:
 
 /* Line 1455 of yacc.c  */
-#line 126 "util_expr_parse.y"
+#line 129 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_EQ,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 19:
 
 /* Line 1455 of yacc.c  */
-#line 127 "util_expr_parse.y"
+#line 130 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_NE,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 20:
 
 /* Line 1455 of yacc.c  */
-#line 128 "util_expr_parse.y"
+#line 131 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_LT,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 21:
 
 /* Line 1455 of yacc.c  */
-#line 129 "util_expr_parse.y"
+#line 132 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_LE,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 22:
 
 /* Line 1455 of yacc.c  */
-#line 130 "util_expr_parse.y"
+#line 133 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_GT,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 23:
 
 /* Line 1455 of yacc.c  */
-#line 131 "util_expr_parse.y"
+#line 134 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_STR_GE,  (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 24:
 
 /* Line 1455 of yacc.c  */
-#line 132 "util_expr_parse.y"
+#line 135 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_IN,      (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 25:
 
 /* Line 1455 of yacc.c  */
-#line 133 "util_expr_parse.y"
+#line 136 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_REG,     (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 26:
 
 /* Line 1455 of yacc.c  */
-#line 134 "util_expr_parse.y"
+#line 137 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_NRE,     (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 27:
 
 /* Line 1455 of yacc.c  */
-#line 135 "util_expr_parse.y"
+#line 138 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_binary_op_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;}
     break;
 
   case 28:
 
 /* Line 1455 of yacc.c  */
-#line 138 "util_expr_parse.y"
+#line 141 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 29:
 
 /* Line 1455 of yacc.c  */
-#line 139 "util_expr_parse.y"
+#line 142 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;}
     break;
 
   case 30:
 
 /* Line 1455 of yacc.c  */
-#line 142 "util_expr_parse.y"
+#line 145 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); ;}
     break;
 
   case 31:
 
 /* Line 1455 of yacc.c  */
-#line 143 "util_expr_parse.y"
+#line 146 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(3) - (3)].exVal), (yyvsp[(1) - (3)].exVal),   ctx); ;}
     break;
 
   case 32:
 
 /* Line 1455 of yacc.c  */
-#line 146 "util_expr_parse.y"
+#line 149 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (2)].exVal), (yyvsp[(2) - (2)].exVal), ctx); ;}
     break;
 
   case 33:
 
 /* Line 1455 of yacc.c  */
-#line 147 "util_expr_parse.y"
+#line 150 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 34:
 
 /* Line 1455 of yacc.c  */
-#line 151 "util_expr_parse.y"
+#line 153 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx); ;}
     break;
 
   case 35:
 
 /* Line 1455 of yacc.c  */
-#line 152 "util_expr_parse.y"
+#line 154 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
@@ -1695,62 +1708,76 @@ yyreduce:
 
 /* Line 1455 of yacc.c  */
 #line 155 "util_expr_parse.y"
-    { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); ;}
+    { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 37:
 
 /* Line 1455 of yacc.c  */
-#line 156 "util_expr_parse.y"
-    { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); ;}
+#line 158 "util_expr_parse.y"
+    { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); ;}
     break;
 
   case 38:
 
 /* Line 1455 of yacc.c  */
 #line 159 "util_expr_parse.y"
-    { (yyval.exVal) = ap_expr_make(op_Digit,  (yyvsp[(1) - (1)].cpVal), NULL, ctx); ;}
+    { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); ;}
     break;
 
   case 39:
 
 /* Line 1455 of yacc.c  */
-#line 160 "util_expr_parse.y"
-    { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal),   ctx); ;}
+#line 162 "util_expr_parse.y"
+    { (yyval.exVal) = ap_expr_make(op_Digit,  (yyvsp[(1) - (1)].cpVal), NULL, ctx); ;}
     break;
 
   case 40:
 
 /* Line 1455 of yacc.c  */
-#line 161 "util_expr_parse.y"
-    { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
+#line 163 "util_expr_parse.y"
+    { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal),   ctx); ;}
     break;
 
   case 41:
 
 /* Line 1455 of yacc.c  */
-#line 162 "util_expr_parse.y"
+#line 164 "util_expr_parse.y"
     { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 42:
 
 /* Line 1455 of yacc.c  */
-#line 163 "util_expr_parse.y"
-    { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;}
+#line 165 "util_expr_parse.y"
+    { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 43:
 
 /* Line 1455 of yacc.c  */
-#line 164 "util_expr_parse.y"
-    { (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); ;}
+#line 166 "util_expr_parse.y"
+    { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;}
     break;
 
   case 44:
 
 /* Line 1455 of yacc.c  */
 #line 167 "util_expr_parse.y"
+    { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;}
+    break;
+
+  case 45:
+
+/* Line 1455 of yacc.c  */
+#line 168 "util_expr_parse.y"
+    { (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); ;}
+    break;
+
+  case 46:
+
+/* Line 1455 of yacc.c  */
+#line 171 "util_expr_parse.y"
     {
                 ap_regex_t *regex;
                 if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal),
@@ -1762,10 +1789,10 @@ yyreduce:
             ;}
     break;
 
-  case 45:
+  case 47:
 
 /* Line 1455 of yacc.c  */
-#line 176 "util_expr_parse.y"
+#line 180 "util_expr_parse.y"
     {
                 ap_regex_t *regex;
                 if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal),
@@ -1777,24 +1804,35 @@ yyreduce:
             ;}
     break;
 
-  case 46:
+  case 48:
 
 /* Line 1455 of yacc.c  */
-#line 187 "util_expr_parse.y"
+#line 191 "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);
+            ;}
+    break;
+
+  case 49:
+
+/* Line 1455 of yacc.c  */
+#line 198 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); ;}
     break;
 
-  case 47:
+  case 50:
 
 /* Line 1455 of yacc.c  */
-#line 190 "util_expr_parse.y"
+#line 201 "util_expr_parse.y"
     { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); ;}
     break;
 
 
 
 /* Line 1455 of yacc.c  */
-#line 1798 "util_expr_parse.c"
+#line 1836 "util_expr_parse.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2006,7 +2044,7 @@ yyreturn:
 
 
 /* Line 1675 of yacc.c  */
-#line 193 "util_expr_parse.y"
+#line 204 "util_expr_parse.y"
 
 
 void yyerror(ap_expr_parse_ctx *ctx, char *s)

Modified: httpd/httpd/trunk/server/util_expr_parse.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_parse.h?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_parse.h (original)
+++ httpd/httpd/trunk/server/util_expr_parse.h Sun Nov 21 17:22:26 2010
@@ -47,31 +47,32 @@
      T_STRING = 263,
      T_REGEX = 264,
      T_REGEX_I = 265,
-     T_OP_UNARY = 266,
-     T_OP_BINARY = 267,
-     T_STR_BEGIN = 268,
-     T_STR_END = 269,
-     T_VAR_BEGIN = 270,
-     T_VAR_END = 271,
-     T_OP_EQ = 272,
-     T_OP_NE = 273,
-     T_OP_LT = 274,
-     T_OP_LE = 275,
-     T_OP_GT = 276,
-     T_OP_GE = 277,
-     T_OP_REG = 278,
-     T_OP_NRE = 279,
-     T_OP_IN = 280,
-     T_OP_STR_EQ = 281,
-     T_OP_STR_NE = 282,
-     T_OP_STR_LT = 283,
-     T_OP_STR_LE = 284,
-     T_OP_STR_GT = 285,
-     T_OP_STR_GE = 286,
-     T_OP_CONCAT = 287,
-     T_OP_OR = 288,
-     T_OP_AND = 289,
-     T_OP_NOT = 290
+     T_REGEX_BACKREF = 266,
+     T_OP_UNARY = 267,
+     T_OP_BINARY = 268,
+     T_STR_BEGIN = 269,
+     T_STR_END = 270,
+     T_VAR_BEGIN = 271,
+     T_VAR_END = 272,
+     T_OP_EQ = 273,
+     T_OP_NE = 274,
+     T_OP_LT = 275,
+     T_OP_LE = 276,
+     T_OP_GT = 277,
+     T_OP_GE = 278,
+     T_OP_REG = 279,
+     T_OP_NRE = 280,
+     T_OP_IN = 281,
+     T_OP_STR_EQ = 282,
+     T_OP_STR_NE = 283,
+     T_OP_STR_LT = 284,
+     T_OP_STR_LE = 285,
+     T_OP_STR_GT = 286,
+     T_OP_STR_GE = 287,
+     T_OP_CONCAT = 288,
+     T_OP_OR = 289,
+     T_OP_AND = 290,
+     T_OP_NOT = 291
    };
 #endif
 
@@ -86,11 +87,12 @@ typedef union YYSTYPE
 
     char    *cpVal;
     ap_expr *exVal;
+    int      num;
 
 
 
 /* Line 1676 of yacc.c  */
-#line 94 "util_expr_parse.h"
+#line 96 "util_expr_parse.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */

Modified: httpd/httpd/trunk/server/util_expr_parse.y
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_parse.y?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_parse.y (original)
+++ httpd/httpd/trunk/server/util_expr_parse.y Sun Nov 21 17:22:26 2010
@@ -35,6 +35,7 @@
 %union {
     char    *cpVal;
     ap_expr *exVal;
+    int      num;
 }
 
 %token  T_TRUE
@@ -47,6 +48,7 @@
 %token  <cpVal> T_STRING
 %token  <cpVal> T_REGEX
 %token  <cpVal> T_REGEX_I
+%token  <num>   T_REGEX_BACKREF
 %token  <cpVal> T_OP_UNARY
 %token  <cpVal> T_OP_BINARY
 
@@ -92,6 +94,7 @@
 %type   <exVal>   string
 %type   <exVal>   strpart
 %type   <exVal>   var
+%type   <exVal>   backref
 
 %{
 #include "util_expr_private.h"
@@ -147,9 +150,9 @@ string    : string strpart              
           | strpart                      { $$ = $1; }
           ;
 
-
 strpart   : T_STRING                     { $$ = ap_expr_make(op_String, $1, NULL, ctx); }
           | var                          { $$ = $1; }
+          | backref                      { $$ = $1; }
           ;
 
 var       : T_VAR_BEGIN T_ID T_VAR_END            { $$ = ap_expr_var_make($2, ctx); }
@@ -159,6 +162,7 @@ var       : T_VAR_BEGIN T_ID T_VAR_END  
 word      : T_DIGIT                      { $$ = ap_expr_make(op_Digit,  $1, NULL, ctx); }
           | word T_OP_CONCAT word        { $$ = ap_expr_make(op_Concat, $1, $3,   ctx); }
           | var                          { $$ = $1; }
+          | backref                      { $$ = $1; }
           | strfunccall                  { $$ = $1; }
           | T_STR_BEGIN string T_STR_END { $$ = $2; }
           | T_STR_BEGIN T_STR_END        { $$ = ap_expr_make(op_String, "", NULL, ctx); }
@@ -184,6 +188,13 @@ regex     : T_REGEX {
             }
           ;
 
+backref     : T_REGEX_BACKREF   {
+                int *n = apr_palloc(ctx->pool, sizeof(int));
+                *n = $1;
+                $$ = ap_expr_make(op_RegexBackref, n, NULL, ctx);
+            }
+            ;
+
 lstfunccall : T_ID '(' word ')' { $$ = ap_expr_list_func_make($1, $3, ctx); }
             ;
 

Modified: httpd/httpd/trunk/server/util_expr_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_private.h?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_private.h (original)
+++ httpd/httpd/trunk/server/util_expr_private.h Sun Nov 21 17:22:26 2010
@@ -44,7 +44,7 @@ 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_Digit, op_String, op_Regex, op_RegexBackref,
     op_Var,
     op_ListElement,
     /*

Modified: httpd/httpd/trunk/server/util_expr_scan.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_scan.c?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_scan.c (original)
+++ httpd/httpd/trunk/server/util_expr_scan.c Sun Nov 21 17:22:26 2010
@@ -358,8 +358,8 @@ static void yy_fatal_error (yyconst char
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 65
-#define YY_END_OF_BUFFER 66
+#define YY_NUM_RULES 67
+#define YY_END_OF_BUFFER 68
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -367,21 +367,22 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[119] =
+static yyconst flex_int16_t yy_accept[124] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   66,   64,    1,   41,    2,   64,   64,   63,
-       64,   42,   24,   61,   30,   28,   32,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   64,   13,
-        4,    3,   16,   65,   16,   21,    4,   20,   18,   19,
-       65,   15,   22,   25,   27,   26,    1,   29,   35,   17,
-       37,   61,   57,   57,   57,   57,   57,   57,   31,   28,
-       34,   33,   62,   62,   55,   62,   53,   52,   56,   51,
-       50,   23,   23,   54,   62,   38,   62,   39,   13,   14,
-       12,    5,    6,   10,   11,    7,    8,    9,   18,   58,
-
-       44,   46,   48,   43,   47,   49,   45,   36,   62,   40,
-       62,    5,    6,   62,   59,    5,   60,    0
+        0,    0,   68,   66,    1,   43,    2,   66,   66,   66,
+       65,   66,   44,   26,   63,   32,   30,   34,   64,   64,
+       64,   64,   64,   64,   64,   64,   64,   64,   64,   66,
+       14,    4,    3,   17,   17,   67,   17,   23,    4,   22,
+       20,   21,   67,   16,   16,   24,   27,   29,   28,    1,
+       31,   37,   19,   18,   39,   63,   59,   59,   59,   59,
+       59,   59,   33,   30,   36,   35,   64,   64,   57,   64,
+       55,   54,   58,   53,   52,   25,   25,   56,   64,   40,
+       64,   41,   14,   13,   15,   12,    5,    6,   10,   11,
+
+        7,    8,    9,   20,   60,   46,   48,   50,   45,   49,
+       51,   47,   38,   64,   42,   64,    5,    6,   64,   61,
+        5,   62,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -389,17 +390,17 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    5,    6,    6,    7,    8,    5,    9,
-        9,    1,    1,   10,   11,   12,   13,   14,   14,   14,
-       14,   14,   14,   14,   14,   15,   15,   16,    6,   17,
-       18,   19,    6,    1,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-        1,   21,    1,    6,   22,    1,   23,   24,   20,   25,
-
-       26,   27,   28,   20,   29,   20,   20,   30,   31,   32,
-       33,   20,   34,   35,   36,   37,   38,   20,   20,   20,
-       20,   20,   39,   40,   41,   42,    1,    1,    1,    1,
+        1,    2,    4,    5,    6,    7,    8,    9,    5,   10,
+       10,    1,    1,   11,   12,   13,   14,   15,   15,   15,
+       15,   15,   15,   15,   15,   16,   16,   17,    6,   18,
+       19,   20,    6,    1,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+        1,   22,    1,    6,   23,    1,   24,   25,   21,   26,
+
+       27,   28,   29,   21,   30,   21,   21,   31,   32,   33,
+       34,   21,   35,   36,   37,   38,   39,   21,   21,   21,
+       21,   21,   40,   41,   42,   43,    1,    1,    1,    1,
         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,
@@ -416,125 +417,129 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[43] =
+static yyconst flex_int32_t yy_meta[44] =
     {   0,
-        1,    1,    2,    1,    2,    1,    2,    1,    1,    1,
-        1,    1,    1,    3,    3,    1,    1,    1,    1,    3,
-        2,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    1,    1,
-        2,    1
+        1,    1,    2,    1,    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
     } ;
 
-static yyconst flex_int16_t yy_base[128] =
+static yyconst flex_int16_t yy_base[133] =
     {   0,
-        0,    0,   40,   41,   82,    0,  122,  123,    0,    0,
-      138,  133,  161,  260,   47,   33,  260,  121,  151,  260,
-      151,  260,  260,   38,  140,   36,  139,    0,  124,  121,
-      131,   29,  121,   30,  180,   31,  117,  116,  110,    0,
-      260,  260,  110,  207,  260,  260,  260,  260,    0,  260,
-      260,  260,  260,  260,  260,  260,   56,  260,  260,  260,
-      260,   54,    0,  114,   34,  115,   37,  120,  260,  260,
-      260,  260,    0,  120,    0,  112,    0,    0,    0,    0,
-        0,  260,    0,    0,  104,    0,  102,  260,    0,  260,
-      260,   58,   62,  260,  260,  260,  260,  260,    0,  260,
-
-      260,  260,  260,  260,  260,  260,  260,    0,  103,    0,
-      112,   65,  117,  111,    0,  119,    0,  260,  244,  247,
-      250,  133,  132,  253,  256,   67,   62
+        0,    0,   41,   47,   89,    0,  130,  136,    0,    0,
+      147,  146,  175,  275,   54,   28,  275,   43,  134,  164,
+      275,  164,  275,  275,   45,  152,   32,  151,    0,  136,
+      133,  143,   26,  133,   35,  194,   38,  129,  128,  122,
+        0,  275,  275,   51,  122,  221,  275,  275,  275,  275,
+        0,  275,  275,   61,  121,  275,  275,  275,  275,   76,
+      275,  275,  275,  275,  275,   65,    0,  125,   47,  126,
+      107,  130,  275,  275,  275,  275,    0,  130,    0,  124,
+        0,    0,    0,    0,    0,  275,    0,    0,  104,    0,
+      101,  275,    0,  275,  275,  275,   71,  131,  275,  275,
+
+      275,  275,  275,    0,  275,  275,  275,  275,  275,  275,
+      275,  275,    0,   99,    0,   61,  133,  135,   57,    0,
+      138,    0,  275,  259,  262,  265,   79,   67,  268,  271,
+       65,   42
     } ;
 
-static yyconst flex_int16_t yy_def[128] =
+static yyconst flex_int16_t yy_def[133] =
     {   0,
-      118,    1,  119,  119,  118,    5,  119,  119,  120,  120,
-      121,  121,  118,  118,  118,  118,  118,  118,  118,  118,
-      122,  118,  118,  118,  118,  118,  118,  123,  123,  123,
-      123,  123,  123,  123,  123,  123,  123,  123,  118,  124,
-      118,  118,  118,  125,  118,  118,  118,  118,  126,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  127,  127,  127,  127,  127,  127,  118,  118,
-      118,  118,  123,  123,  123,  123,  123,  123,  123,  123,
-      123,  118,  123,  123,  123,  123,  123,  118,  124,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  126,  118,
-
-      118,  118,  118,  118,  118,  118,  118,  123,  123,  123,
-      123,  118,  118,  123,  123,  118,  123,    0,  118,  118,
-      118,  118,  118,  118,  118,  118,  118
+      123,    1,  124,  124,  123,    5,  124,  124,  125,  125,
+      126,  126,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  127,  123,  123,  123,  123,  123,  123,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  123,
+      129,  123,  123,  123,  123,  130,  123,  123,  123,  123,
+      131,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  132,  132,  132,  132,
+      132,  132,  123,  123,  123,  123,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  123,  128,  128,  128,  128,
+      128,  123,  129,  123,  123,  123,  123,  123,  123,  123,
+
+      123,  123,  123,  131,  123,  123,  123,  123,  123,  123,
+      123,  123,  128,  128,  128,  128,  123,  123,  128,  128,
+      123,  128,    0,  123,  123,  123,  123,  123,  123,  123,
+      123,  123
     } ;
 
-static yyconst flex_int16_t yy_nxt[303] =
+static yyconst flex_int16_t yy_nxt[319] =
     {   0,
-       14,   15,   15,   16,   17,   14,   18,   19,   20,   20,
-       21,   22,   23,   24,   24,   20,   25,   26,   27,   28,
-       14,   14,   29,   28,   28,   30,   31,   32,   33,   34,
-       35,   36,   37,   28,   28,   28,   38,   28,   20,   39,
-       20,   14,   41,   41,   42,   42,   43,   43,   57,   57,
-       58,   62,   62,   70,   77,   80,   84,   57,   57,  102,
-       44,   44,  105,   85,  100,   78,   81,   62,   62,   99,
-      103,  112,  113,  106,   59,  113,  113,   71,  116,  113,
-       45,   45,   46,   46,   47,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   48,   46,   46,
-
-       46,   49,   46,   46,   49,   49,   49,   49,   49,   49,
-       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
-       46,   46,   50,   46,   41,   41,   51,   51,   52,   52,
-      113,  113,  113,  113,   73,   63,  117,  115,  114,  111,
-      110,  109,   44,   44,  108,  107,  104,  101,   90,   88,
-       87,   86,   79,   76,   75,   74,   72,   69,   61,   60,
-      118,   56,   53,   53,   62,   62,   56,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,   64,  118,   65,   66,
-       67,  118,   68,   82,   82,   82,   82,  118,  118,   82,
-       82,   82,   82,  118,  118,   82,  118,  118,  118,  118,
-
-      118,   83,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,   82,
-       92,   93,  118,  118,  118,  118,  118,  118,  118,  118,
-       94,  118,  118,   95,  118,  118,  118,  118,   96,  118,
-      118,   97,  118,   98,   40,   40,   40,   54,   54,   54,
-       55,   55,   55,   89,  118,   89,   91,   91,   91,   13,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
+       14,   15,   15,   16,   17,   14,   18,   19,   20,   21,
+       21,   22,   23,   24,   25,   25,   21,   26,   27,   28,
+       29,   14,   14,   30,   29,   29,   31,   32,   33,   34,
+       35,   36,   37,   38,   29,   29,   29,   39,   29,   21,
+       40,   21,   14,   42,  105,   43,   61,   44,   45,   42,
+       74,   43,   81,   44,   45,   60,   60,   63,   63,   66,
+       66,   84,   46,   82,   88,   94,   94,  104,   46,   77,
+       62,   89,   85,  107,   75,   94,   94,   60,   60,   66,
+       66,   67,   47,  122,  108,  117,  118,  120,   47,   48,
+       48,   49,   48,   48,   48,   48,   48,   48,   48,   48,
+
+       48,   48,   48,   48,   48,   50,   48,   48,   48,   51,
+       48,   48,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   48,   48,
+       52,   48,   42,  110,   53,  119,   54,   55,   42,  116,
+       53,  115,   54,   55,  111,  118,  118,  121,  118,  118,
+      118,   46,  118,  118,  114,  113,  112,   46,  109,  106,
+       95,   95,   92,   91,   90,   83,   80,   79,   78,   76,
+       73,   56,   65,   64,  123,   59,   59,   56,   66,   66,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+       68,  123,   69,   70,   71,  123,   72,   86,   86,   86,
+
+       86,   86,  123,  123,   86,   86,   86,   86,  123,  123,
+       86,  123,  123,  123,  123,  123,   87,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,   86,   97,   98,  123,  123,  123,
+      123,  123,  123,  123,  123,   99,  123,  123,  100,  123,
+      123,  123,  123,  101,  123,  123,  102,  123,  103,   41,
+       41,   41,   57,   57,   57,   58,   58,   58,   93,  123,
+       93,   96,   96,   96,   13,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
 
-      118,  118
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123
     } ;
 
-static yyconst flex_int16_t yy_chk[303] =
+static yyconst flex_int16_t yy_chk[319] =
     {   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,    3,    4,    3,    4,    3,    4,   15,   15,
-       16,   24,   24,   26,   32,   34,   36,   57,   57,   65,
-        3,    4,   67,   36,  127,   32,   34,   62,   62,  126,
-       65,   92,   92,   67,   16,   93,   93,   26,  112,  112,
-        3,    4,    5,    5,    5,    5,    5,    5,    5,    5,
+        1,    1,    1,    3,  132,    3,   16,    3,    3,    4,
+       27,    4,   33,    4,    4,   15,   15,   18,   18,   25,
+       25,   35,    3,   33,   37,   44,   44,  131,    4,  128,
+       16,   37,   35,   69,   27,   54,   54,   60,   60,   66,
+       66,  127,    3,  119,   69,   97,   97,  116,    4,    5,
         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
 
         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,    8,    7,    8,    7,    8,
-      113,  113,  116,  116,  123,  122,  114,  111,  109,   87,
-       85,   76,    7,    8,   74,   68,   66,   64,   43,   39,
-       38,   37,   33,   31,   30,   29,   27,   25,   19,   18,
-       13,   12,    7,    8,   21,   21,   11,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   21,    0,   21,   21,
-       21,    0,   21,   35,   35,   35,   35,    0,    0,   35,
-       35,   35,   35,    0,    0,   35,    0,    0,    0,    0,
-
-        0,   35,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   35,
-       44,   44,    0,    0,    0,    0,    0,    0,    0,    0,
-       44,    0,    0,   44,    0,    0,    0,    0,   44,    0,
-        0,   44,    0,   44,  119,  119,  119,  120,  120,  120,
-      121,  121,  121,  124,    0,  124,  125,  125,  125,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
-      118,  118,  118,  118,  118,  118,  118,  118,  118,  118,
+        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,
 
-      118,  118
+       36,   36,    0,    0,   36,   36,   36,   36,    0,    0,
+       36,    0,    0,    0,    0,    0,   36,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   36,   46,   46,    0,    0,    0,
+        0,    0,    0,    0,    0,   46,    0,    0,   46,    0,
+        0,    0,    0,   46,    0,    0,   46,    0,   46,  124,
+      124,  124,  125,  125,  125,  126,  126,  126,  129,    0,
+      129,  130,  130,  130,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+
+      123,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  123,  123,  123,  123,  123,  123,  123
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -600,7 +605,7 @@ static yyconst flex_int16_t yy_chk[303] 
 #define str_buf     (yyextra->scan_buf)
 #define str_del     (yyextra->scan_del)
 
-#line 604 "util_expr_scan.c"
+#line 609 "util_expr_scan.c"
 
 #define INITIAL 0
 #define str 1
@@ -855,7 +860,7 @@ YY_DECL
  /*
   * Whitespaces
   */
-#line 859 "util_expr_scan.c"
+#line 864 "util_expr_scan.c"
 
     yylval = yylval_param;
 
@@ -910,13 +915,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 >= 119 )
+				if ( yy_current_state >= 124 )
 					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 != 118 );
+		while ( yy_current_state != 123 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -1054,19 +1059,38 @@ YY_RULE_SETUP
     *str_ptr++ = yytext[1];
 }
 	YY_BREAK
+/* regexp backref inside string/arg */
 case 13:
 YY_RULE_SETUP
-#line 145 "util_expr_scan.l"
+#line 146 "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;
+    }
+}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 161 "util_expr_scan.l"
 {
     char *cp = yytext;
     while (*cp != '\0')
         *str_ptr++ = *cp++;
 }
 	YY_BREAK
-/* variable inside string */
-case 14:
+/* variable inside string/arg */
+case 15:
 YY_RULE_SETUP
-#line 152 "util_expr_scan.l"
+#line 168 "util_expr_scan.l"
 {
     if (str_ptr != str_buf) {
         /* return what we have so far and scan '%{' again */
@@ -1082,68 +1106,76 @@ YY_RULE_SETUP
     }
 }
 	YY_BREAK
-case 15:
+case 16:
 YY_RULE_SETUP
-#line 167 "util_expr_scan.l"
+#line 183 "util_expr_scan.l"
 {
      *str_ptr++ = yytext[0];
 }
 	YY_BREAK
-case 16:
+case 17:
 YY_RULE_SETUP
-#line 171 "util_expr_scan.l"
+#line 187 "util_expr_scan.l"
 {
      *str_ptr++ = yytext[0];
 }
 	YY_BREAK
-case 17:
+case 18:
 YY_RULE_SETUP
-#line 175 "util_expr_scan.l"
+#line 191 "util_expr_scan.l"
 {
     yy_push_state(var, yyscanner);
     return T_VAR_BEGIN;
 }
 	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 196 "util_expr_scan.l"
+{
+    yylval->num = yytext[1] - '0';
+    return T_REGEX_BACKREF;
+}
+	YY_BREAK
 /*
   * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
   */
-case 18:
+case 20:
 YY_RULE_SETUP
-#line 183 "util_expr_scan.l"
+#line 204 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
     return T_ID;
 }
 	YY_BREAK
-case 19:
+case 21:
 YY_RULE_SETUP
-#line 188 "util_expr_scan.l"
+#line 209 "util_expr_scan.l"
 {
     yy_pop_state(yyscanner);
     return T_VAR_END;
 }
 	YY_BREAK
-case 20:
+case 22:
 YY_RULE_SETUP
-#line 193 "util_expr_scan.l"
+#line 214 "util_expr_scan.l"
 {
     BEGIN(vararg);
     return yytext[0];
 }
 	YY_BREAK
-case 21:
-/* rule 21 can match eol */
+case 23:
+/* rule 23 can match eol */
 YY_RULE_SETUP
-#line 198 "util_expr_scan.l"
+#line 219 "util_expr_scan.l"
 {
     char *msg = apr_psprintf(yyextra->pool,
                              "Invalid character in variable name '%c'", yytext[0]);
     PERROR(msg);
 }
 	YY_BREAK
-case 22:
+case 24:
 YY_RULE_SETUP
-#line 204 "util_expr_scan.l"
+#line 225 "util_expr_scan.l"
 {
     if (str_ptr != str_buf) {
         /* return what we have so far and scan '}' again */
@@ -1162,28 +1194,28 @@ YY_RULE_SETUP
 /*
   * Regular Expression
   */
-case 23:
+case 25:
 YY_RULE_SETUP
-#line 222 "util_expr_scan.l"
+#line 243 "util_expr_scan.l"
 {
     regex_del = yytext[1];
     regex_ptr = regex_buf;
     BEGIN(regex);
 }
 	YY_BREAK
-case 24:
+case 26:
 YY_RULE_SETUP
-#line 227 "util_expr_scan.l"
+#line 248 "util_expr_scan.l"
 {
     regex_del = yytext[0];
     regex_ptr = regex_buf;
     BEGIN(regex);
 }
 	YY_BREAK
-case 25:
-/* rule 25 can match eol */
+case 27:
+/* rule 27 can match eol */
 YY_RULE_SETUP
-#line 232 "util_expr_scan.l"
+#line 253 "util_expr_scan.l"
 {
     if (yytext[0] == regex_del) {
         *regex_ptr = '\0';
@@ -1194,19 +1226,19 @@ YY_RULE_SETUP
     }
 }
 	YY_BREAK
-case 26:
+case 28:
 YY_RULE_SETUP
-#line 241 "util_expr_scan.l"
+#line 262 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
     BEGIN(INITIAL);
     return T_REGEX_I;
 }
 	YY_BREAK
-case 27:
-/* rule 27 can match eol */
+case 29:
+/* rule 29 can match eol */
 YY_RULE_SETUP
-#line 246 "util_expr_scan.l"
+#line 267 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
     yyless(0);
@@ -1215,7 +1247,7 @@ YY_RULE_SETUP
 }
 	YY_BREAK
 case YY_STATE_EOF(regex_flags):
-#line 252 "util_expr_scan.l"
+#line 273 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
     BEGIN(INITIAL);
@@ -1225,163 +1257,163 @@ case YY_STATE_EOF(regex_flags):
 /*
   * Operators
   */
-case 28:
+case 30:
 YY_RULE_SETUP
-#line 261 "util_expr_scan.l"
+#line 282 "util_expr_scan.l"
 { return T_OP_STR_EQ; }
 	YY_BREAK
-case 29:
+case 31:
 YY_RULE_SETUP
-#line 262 "util_expr_scan.l"
+#line 283 "util_expr_scan.l"
 { return T_OP_STR_NE; }
 	YY_BREAK
-case 30:
+case 32:
 YY_RULE_SETUP
-#line 263 "util_expr_scan.l"
+#line 284 "util_expr_scan.l"
 { return T_OP_STR_LT; }
 	YY_BREAK
-case 31:
+case 33:
 YY_RULE_SETUP
-#line 264 "util_expr_scan.l"
+#line 285 "util_expr_scan.l"
 { return T_OP_STR_LE; }
 	YY_BREAK
-case 32:
+case 34:
 YY_RULE_SETUP
-#line 265 "util_expr_scan.l"
+#line 286 "util_expr_scan.l"
 { return T_OP_STR_GT; }
 	YY_BREAK
-case 33:
+case 35:
 YY_RULE_SETUP
-#line 266 "util_expr_scan.l"
+#line 287 "util_expr_scan.l"
 { return T_OP_STR_GE; }
 	YY_BREAK
-case 34:
+case 36:
 YY_RULE_SETUP
-#line 267 "util_expr_scan.l"
+#line 288 "util_expr_scan.l"
 { return T_OP_REG; }
 	YY_BREAK
-case 35:
+case 37:
 YY_RULE_SETUP
-#line 268 "util_expr_scan.l"
+#line 289 "util_expr_scan.l"
 { return T_OP_NRE; }
 	YY_BREAK
-case 36:
+case 38:
 YY_RULE_SETUP
-#line 269 "util_expr_scan.l"
+#line 290 "util_expr_scan.l"
 { return T_OP_AND; }
 	YY_BREAK
-case 37:
+case 39:
 YY_RULE_SETUP
-#line 270 "util_expr_scan.l"
+#line 291 "util_expr_scan.l"
 { return T_OP_AND; }
 	YY_BREAK
-case 38:
+case 40:
 YY_RULE_SETUP
-#line 271 "util_expr_scan.l"
+#line 292 "util_expr_scan.l"
 { return T_OP_OR; }
 	YY_BREAK
-case 39:
+case 41:
 YY_RULE_SETUP
-#line 272 "util_expr_scan.l"
+#line 293 "util_expr_scan.l"
 { return T_OP_OR; }
 	YY_BREAK
-case 40:
+case 42:
 YY_RULE_SETUP
-#line 273 "util_expr_scan.l"
+#line 294 "util_expr_scan.l"
 { return T_OP_NOT; }
 	YY_BREAK
-case 41:
+case 43:
 YY_RULE_SETUP
-#line 274 "util_expr_scan.l"
+#line 295 "util_expr_scan.l"
 { return T_OP_NOT; }
 	YY_BREAK
-case 42:
+case 44:
 YY_RULE_SETUP
-#line 275 "util_expr_scan.l"
+#line 296 "util_expr_scan.l"
 { return T_OP_CONCAT; }
 	YY_BREAK
-case 43:
+case 45:
 YY_RULE_SETUP
-#line 276 "util_expr_scan.l"
+#line 297 "util_expr_scan.l"
 { return T_OP_IN; }
 	YY_BREAK
-case 44:
+case 46:
 YY_RULE_SETUP
-#line 277 "util_expr_scan.l"
+#line 298 "util_expr_scan.l"
 { return T_OP_EQ; }
 	YY_BREAK
-case 45:
+case 47:
 YY_RULE_SETUP
-#line 278 "util_expr_scan.l"
+#line 299 "util_expr_scan.l"
 { return T_OP_NE; }
 	YY_BREAK
-case 46:
+case 48:
 YY_RULE_SETUP
-#line 279 "util_expr_scan.l"
+#line 300 "util_expr_scan.l"
 { return T_OP_GE; }
 	YY_BREAK
-case 47:
+case 49:
 YY_RULE_SETUP
-#line 280 "util_expr_scan.l"
+#line 301 "util_expr_scan.l"
 { return T_OP_LE; }
 	YY_BREAK
-case 48:
+case 50:
 YY_RULE_SETUP
-#line 281 "util_expr_scan.l"
+#line 302 "util_expr_scan.l"
 { return T_OP_GT; }
 	YY_BREAK
-case 49:
+case 51:
 YY_RULE_SETUP
-#line 282 "util_expr_scan.l"
+#line 303 "util_expr_scan.l"
 { return T_OP_LT; }
 	YY_BREAK
 /* for compatibility with ssl_expr */
-case 50:
+case 52:
 YY_RULE_SETUP
-#line 285 "util_expr_scan.l"
+#line 306 "util_expr_scan.l"
 { return T_OP_LT; }
 	YY_BREAK
-case 51:
+case 53:
 YY_RULE_SETUP
-#line 286 "util_expr_scan.l"
+#line 307 "util_expr_scan.l"
 { return T_OP_LE; }
 	YY_BREAK
-case 52:
+case 54:
 YY_RULE_SETUP
-#line 287 "util_expr_scan.l"
+#line 308 "util_expr_scan.l"
 { return T_OP_GT; }
 	YY_BREAK
-case 53:
+case 55:
 YY_RULE_SETUP
-#line 288 "util_expr_scan.l"
+#line 309 "util_expr_scan.l"
 { return T_OP_GE; }
 	YY_BREAK
-case 54:
+case 56:
 YY_RULE_SETUP
-#line 289 "util_expr_scan.l"
+#line 310 "util_expr_scan.l"
 { return T_OP_NE; }
 	YY_BREAK
-case 55:
+case 57:
 YY_RULE_SETUP
-#line 290 "util_expr_scan.l"
+#line 311 "util_expr_scan.l"
 { return T_OP_EQ; }
 	YY_BREAK
-case 56:
+case 58:
 YY_RULE_SETUP
-#line 291 "util_expr_scan.l"
+#line 312 "util_expr_scan.l"
 { return T_OP_IN; }
 	YY_BREAK
-case 57:
+case 59:
 YY_RULE_SETUP
-#line 293 "util_expr_scan.l"
+#line 314 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
     return T_OP_UNARY;
 }
 	YY_BREAK
-case 58:
+case 60:
 YY_RULE_SETUP
-#line 298 "util_expr_scan.l"
+#line 319 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
     return T_OP_BINARY;
@@ -1390,22 +1422,22 @@ YY_RULE_SETUP
 /*
   * Specials
   */
-case 59:
+case 61:
 YY_RULE_SETUP
-#line 306 "util_expr_scan.l"
+#line 327 "util_expr_scan.l"
 { return T_TRUE; }
 	YY_BREAK
-case 60:
+case 62:
 YY_RULE_SETUP
-#line 307 "util_expr_scan.l"
+#line 328 "util_expr_scan.l"
 { return T_FALSE; }
 	YY_BREAK
 /*
   * Digits
   */
-case 61:
+case 63:
 YY_RULE_SETUP
-#line 312 "util_expr_scan.l"
+#line 333 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
     return T_DIGIT;
@@ -1414,9 +1446,9 @@ YY_RULE_SETUP
 /*
   * Identifiers
   */
-case 62:
+case 64:
 YY_RULE_SETUP
-#line 320 "util_expr_scan.l"
+#line 341 "util_expr_scan.l"
 {
     yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
     return T_ID;
@@ -1425,9 +1457,9 @@ YY_RULE_SETUP
 /*
   * These are parts of the grammar and are returned as is
   */
-case 63:
+case 65:
 YY_RULE_SETUP
-#line 328 "util_expr_scan.l"
+#line 349 "util_expr_scan.l"
 {
     return yytext[0];
 }
@@ -1435,21 +1467,21 @@ YY_RULE_SETUP
 /*
   * Anything else is an error
   */
-case 64:
-/* rule 64 can match eol */
+case 66:
+/* rule 66 can match eol */
 YY_RULE_SETUP
-#line 335 "util_expr_scan.l"
+#line 356 "util_expr_scan.l"
 {
     char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);
     PERROR(msg);
 }
 	YY_BREAK
-case 65:
+case 67:
 YY_RULE_SETUP
-#line 340 "util_expr_scan.l"
+#line 361 "util_expr_scan.l"
 YY_FATAL_ERROR( "flex scanner jammed" );
 	YY_BREAK
-#line 1453 "util_expr_scan.c"
+#line 1485 "util_expr_scan.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(regex):
 	yyterminate();
@@ -1745,7 +1777,7 @@ static int yy_get_next_buffer (yyscan_t 
 		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 >= 119 )
+			if ( yy_current_state >= 124 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1774,11 +1806,11 @@ static int yy_get_next_buffer (yyscan_t 
 	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 >= 119 )
+		if ( yy_current_state >= 124 )
 			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 == 118);
+	yy_is_jam = (yy_current_state == 123);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2610,7 +2642,7 @@ void ap_expr_yyfree (void * ptr , yyscan
 
 #define YYTABLES_NAME "yytables"
 
-#line 340 "util_expr_scan.l"
+#line 361 "util_expr_scan.l"
 
 
 

Modified: httpd/httpd/trunk/server/util_expr_scan.l
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_scan.l?rev=1037504&r1=1037503&r2=1037504&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_scan.l (original)
+++ httpd/httpd/trunk/server/util_expr_scan.l Sun Nov 21 17:22:26 2010
@@ -142,14 +142,30 @@
     *str_ptr++ = yytext[1];
 }
 
-<str,vararg>[^\\\n"'%}]+ {
+ /* regexp backref inside string/arg */
+<str,vararg>[$][0-9] {
+    if (str_ptr != str_buf) {
+        /* return what we have so far and scan '$x' again */
+        *str_ptr = '\0';
+        yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
+        str_ptr = str_buf;
+        yyless(0);
+        return T_STRING;
+    }
+    else {
+        yylval->num = yytext[1] - '0';
+        return T_REGEX_BACKREF;
+    }
+}
+
+<str,vararg>[^\\\n"'%}$]+ {
     char *cp = yytext;
     while (*cp != '\0')
         *str_ptr++ = *cp++;
 }
 
- /* variable inside string */
-<str>%\{ {
+ /* variable inside string/arg */
+<str,vararg>%\{ {
     if (str_ptr != str_buf) {
         /* return what we have so far and scan '%{' again */
         *str_ptr = '\0';
@@ -164,11 +180,11 @@
     }
 }
 
-<vararg>% {
+<vararg>[%$] {
      *str_ptr++ = yytext[0];
 }
 
-<str>[%}] {
+<str>[%}$] {
      *str_ptr++ = yytext[0];
 }
 
@@ -177,6 +193,11 @@
     return T_VAR_BEGIN;
 }
 
+[$][0-9] {
+    yylval->num = yytext[1] - '0';
+    return T_REGEX_BACKREF;
+}
+
  /*
   * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
   */



Mime
View raw message