Blame server/util_expr_scan.l

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
 *  ap_expr_scan.l, based on ssl_expr_scan.l from mod_ssl
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
/*  _________________________________________________________________
Packit 90a5c9
**
Packit 90a5c9
**  Expression Scanner
Packit 90a5c9
**  _________________________________________________________________
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
%pointer
Packit 90a5c9
%option batch
Packit 90a5c9
%option never-interactive
Packit 90a5c9
%option nodefault
Packit 90a5c9
%option noyywrap
Packit 90a5c9
%option reentrant
Packit 90a5c9
%option bison-bridge
Packit 90a5c9
%option warn
Packit 90a5c9
%option noinput nounput noyy_top_state
Packit 90a5c9
%option stack
Packit 90a5c9
%x str
Packit 90a5c9
%x var
Packit 90a5c9
%x vararg
Packit 90a5c9
%x regex regex_flags
Packit 90a5c9
Packit 90a5c9
%{
Packit 90a5c9
#include "util_expr_private.h"
Packit 90a5c9
#include "util_expr_parse.h"
Packit 90a5c9
Packit 90a5c9
#undef  YY_INPUT
Packit 90a5c9
#define YY_INPUT(buf,result,max_size)                       \
Packit 90a5c9
{                                                           \
Packit 90a5c9
    if ((result = MIN(max_size, yyextra->inputbuf           \
Packit 90a5c9
                              + yyextra->inputlen           \
Packit 90a5c9
                              - yyextra->inputptr)) <= 0)   \
Packit 90a5c9
    {                                                       \
Packit 90a5c9
        result = YY_NULL;                                   \
Packit 90a5c9
    }                                                       \
Packit 90a5c9
    else {                                                  \
Packit 90a5c9
        memcpy(buf, yyextra->inputptr, result);             \
Packit 90a5c9
        yyextra->inputptr += result;                        \
Packit 90a5c9
    }                                                       \
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
#define YY_EXTRA_TYPE ap_expr_parse_ctx_t*
Packit 90a5c9
Packit 90a5c9
#define PERROR(msg) do { yyextra->error2 = msg ; return T_ERROR; } while (0)
Packit 90a5c9
Packit 90a5c9
#define str_ptr     (yyextra->scan_ptr)
Packit 90a5c9
#define str_buf     (yyextra->scan_buf)
Packit 90a5c9
#define str_del     (yyextra->scan_del)
Packit 90a5c9
Packit 90a5c9
#define STR_APPEND(c) do {                          \
Packit 90a5c9
        *str_ptr++ = (c);                           \
Packit 90a5c9
        if (str_ptr >= str_buf + sizeof(str_buf))   \
Packit 90a5c9
            PERROR("String too long");              \
Packit 90a5c9
    } while (0)
Packit 90a5c9
Packit 90a5c9
%}
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
%%
Packit 90a5c9
Packit 90a5c9
  char  regex_buf[MAX_STRING_LEN];
Packit 90a5c9
  char *regex_ptr = NULL;
Packit 90a5c9
  char  regex_del = '\0';
Packit 90a5c9
Packit 90a5c9
%{
Packit 90a5c9
 /*
Packit 90a5c9
  * Set initial state for string expressions
Packit 90a5c9
  */
Packit 90a5c9
  if (yyextra->at_start) {
Packit 90a5c9
    yyextra->at_start = 0;
Packit 90a5c9
    if (yyextra->flags & AP_EXPR_FLAG_STRING_RESULT) {
Packit 90a5c9
        BEGIN(str);
Packit 90a5c9
        return T_EXPR_STRING;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        return T_EXPR_BOOL;
Packit 90a5c9
    }
Packit 90a5c9
  }
Packit 90a5c9
%}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Whitespaces
Packit 90a5c9
  */
Packit 90a5c9
[ \t\n]+ { 
Packit 90a5c9
    /* NOP */
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * strings ("..." and '...')
Packit 90a5c9
  */
Packit 90a5c9
["'] {
Packit 90a5c9
    str_ptr = str_buf;
Packit 90a5c9
    str_del = yytext[0];
Packit 90a5c9
    BEGIN(str);
Packit 90a5c9
    return T_STR_BEGIN;
Packit 90a5c9
}
Packit 90a5c9
<str>["'] {
Packit 90a5c9
    if (yytext[0] == str_del) {
Packit 90a5c9
        if (YY_START == var) {
Packit 90a5c9
            PERROR("Unterminated variable in string");
Packit 90a5c9
        }
Packit 90a5c9
        else if (str_ptr == str_buf) {
Packit 90a5c9
            BEGIN(INITIAL);
Packit 90a5c9
            return T_STR_END;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            /* return what we have so far and scan delimiter again */
Packit 90a5c9
            *str_ptr = '\0';
Packit 90a5c9
            yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
Packit 90a5c9
            yyless(0);
Packit 90a5c9
            str_ptr = str_buf;
Packit 90a5c9
            return T_STRING;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        STR_APPEND(yytext[0]);
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
<str,var,vararg>\n {
Packit 90a5c9
    PERROR("Unterminated string or variable");
Packit 90a5c9
}
Packit 90a5c9
<var,vararg><<EOF>> {
Packit 90a5c9
    PERROR("Unterminated string or variable");
Packit 90a5c9
}
Packit 90a5c9
<str><<EOF>> {
Packit 90a5c9
    if (!(yyextra->flags & AP_EXPR_FLAG_STRING_RESULT)) {
Packit 90a5c9
        PERROR("Unterminated string or variable");
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        *str_ptr = '\0';
Packit 90a5c9
        yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
Packit 90a5c9
        str_ptr = str_buf;
Packit 90a5c9
        BEGIN(INITIAL);
Packit 90a5c9
        return T_STRING;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
<str,vararg>\\[0-7]{1,3} {
Packit 90a5c9
    int result;
Packit 90a5c9
Packit 90a5c9
    (void)sscanf(yytext+1, "%o", &result);
Packit 90a5c9
    if (result > 0xff) {
Packit 90a5c9
        PERROR("Escape sequence out of bound");
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        STR_APPEND(result);
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
<str,vararg>\\[0-9]+ {
Packit 90a5c9
    PERROR("Bad escape sequence");
Packit 90a5c9
}
Packit 90a5c9
<str,vararg>\\n      { STR_APPEND('\n'); }
Packit 90a5c9
<str,vararg>\\r      { STR_APPEND('\r'); }
Packit 90a5c9
<str,vararg>\\t      { STR_APPEND('\t'); }
Packit 90a5c9
<str,vararg>\\b      { STR_APPEND('\b'); }
Packit 90a5c9
<str,vararg>\\f      { STR_APPEND('\f'); }
Packit 90a5c9
<str,vararg>\\(.|\n) { STR_APPEND(yytext[1]); }
Packit 90a5c9
Packit 90a5c9
 /* regexp backref inside string/arg */
Packit 90a5c9
<str,vararg>[$][0-9] {
Packit 90a5c9
    if (str_ptr != str_buf) {
Packit 90a5c9
        /* return what we have so far and scan '$x' again */
Packit 90a5c9
        *str_ptr = '\0';
Packit 90a5c9
        yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
Packit 90a5c9
        str_ptr = str_buf;
Packit 90a5c9
        yyless(0);
Packit 90a5c9
        return T_STRING;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        yylval->num = yytext[1] - '0';
Packit 90a5c9
        return T_REGEX_BACKREF;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
<str,vararg>[^\\\n"'%}$]+ {
Packit 90a5c9
    char *cp = yytext;
Packit 90a5c9
    while (*cp != '\0') {
Packit 90a5c9
        STR_APPEND(*cp);
Packit 90a5c9
        cp++;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /* variable inside string/arg */
Packit 90a5c9
<str,vararg>%\{ {
Packit 90a5c9
    if (str_ptr != str_buf) {
Packit 90a5c9
        /* return what we have so far and scan '%{' again */
Packit 90a5c9
        *str_ptr = '\0';
Packit 90a5c9
        yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
Packit 90a5c9
        yyless(0);
Packit 90a5c9
        str_ptr = str_buf;
Packit 90a5c9
        return T_STRING;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        yy_push_state(var, yyscanner);
Packit 90a5c9
        return T_VAR_BEGIN;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
<vararg>[%$] {
Packit 90a5c9
     STR_APPEND(yytext[0]);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
<str>[%}$] {
Packit 90a5c9
     STR_APPEND(yytext[0]);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
%\{ {
Packit 90a5c9
    yy_push_state(var, yyscanner);
Packit 90a5c9
    return T_VAR_BEGIN;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
[$][0-9] {
Packit 90a5c9
    yylval->num = yytext[1] - '0';
Packit 90a5c9
    return T_REGEX_BACKREF;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
Packit 90a5c9
  */
Packit 90a5c9
[a-zA-Z][a-zA-Z0-9_]* {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
Packit 90a5c9
    return T_ID;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
\} {
Packit 90a5c9
    yy_pop_state(yyscanner);
Packit 90a5c9
    return T_VAR_END;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
: {
Packit 90a5c9
    BEGIN(vararg);
Packit 90a5c9
    return yytext[0];
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
.|\n {
Packit 90a5c9
    char *msg = apr_psprintf(yyextra->pool,
Packit 90a5c9
                             "Invalid character in variable name '%c'", yytext[0]);
Packit 90a5c9
    PERROR(msg);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
<vararg>\} {
Packit 90a5c9
    if (str_ptr != str_buf) {
Packit 90a5c9
        /* return what we have so far and scan '}' again */
Packit 90a5c9
        *str_ptr = '\0';
Packit 90a5c9
        yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
Packit 90a5c9
        str_ptr = str_buf;
Packit 90a5c9
        yyless(0);
Packit 90a5c9
        return T_STRING;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        yy_pop_state(yyscanner);
Packit 90a5c9
        return T_VAR_END;
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Regular Expression
Packit 90a5c9
  */
Packit 90a5c9
"m"[/#$%^,;:_\?\|\^\-\!\.\'\"] {
Packit 90a5c9
    regex_del = yytext[1];
Packit 90a5c9
    regex_ptr = regex_buf;
Packit 90a5c9
    BEGIN(regex);
Packit 90a5c9
}
Packit 90a5c9
"/" {
Packit 90a5c9
    regex_del = yytext[0];
Packit 90a5c9
    regex_ptr = regex_buf;
Packit 90a5c9
    BEGIN(regex);
Packit 90a5c9
}
Packit 90a5c9
<regex>.|\n {
Packit 90a5c9
    if (yytext[0] == regex_del) {
Packit 90a5c9
        *regex_ptr = '\0';
Packit 90a5c9
        BEGIN(regex_flags);
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        *regex_ptr++ = yytext[0];
Packit 90a5c9
        if (regex_ptr >= regex_buf + sizeof(regex_buf))
Packit 90a5c9
            PERROR("Regexp too long");
Packit 90a5c9
    }
Packit 90a5c9
}
Packit 90a5c9
<regex_flags>i {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
Packit 90a5c9
    BEGIN(INITIAL);
Packit 90a5c9
    return T_REGEX_I;
Packit 90a5c9
}
Packit 90a5c9
<regex_flags>.|\n {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
Packit 90a5c9
    yyless(0);
Packit 90a5c9
    BEGIN(INITIAL);
Packit 90a5c9
    return T_REGEX;
Packit 90a5c9
}
Packit 90a5c9
<regex_flags><<EOF>> {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
Packit 90a5c9
    BEGIN(INITIAL);
Packit 90a5c9
    return T_REGEX;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Operators
Packit 90a5c9
  */
Packit 90a5c9
==?   { return T_OP_STR_EQ; }
Packit 90a5c9
"!="  { return T_OP_STR_NE; }
Packit 90a5c9
"<"   { return T_OP_STR_LT; }
Packit 90a5c9
"<="  { return T_OP_STR_LE; }
Packit 90a5c9
">"   { return T_OP_STR_GT; }
Packit 90a5c9
">="  { return T_OP_STR_GE; }
Packit 90a5c9
"=~"  { return T_OP_REG; }
Packit 90a5c9
"!~"  { return T_OP_NRE; }
Packit 90a5c9
"and" { return T_OP_AND; }
Packit 90a5c9
"&&"  { return T_OP_AND; }
Packit 90a5c9
"or"  { return T_OP_OR; }
Packit 90a5c9
"||"  { return T_OP_OR; }
Packit 90a5c9
"not" { return T_OP_NOT; }
Packit 90a5c9
"!"   { return T_OP_NOT; }
Packit 90a5c9
"."   { return T_OP_CONCAT; }
Packit 90a5c9
"-in"  { return T_OP_IN; }
Packit 90a5c9
"-eq"  { return T_OP_EQ; }
Packit 90a5c9
"-ne"  { return T_OP_NE; }
Packit 90a5c9
"-ge"  { return T_OP_GE; }
Packit 90a5c9
"-le"  { return T_OP_LE; }
Packit 90a5c9
"-gt"  { return T_OP_GT; }
Packit 90a5c9
"-lt"  { return T_OP_LT; }
Packit 90a5c9
Packit 90a5c9
 /* for compatibility with ssl_expr */
Packit 90a5c9
"lt"  { return T_OP_LT; }
Packit 90a5c9
"le"  { return T_OP_LE; }
Packit 90a5c9
"gt"  { return T_OP_GT; }
Packit 90a5c9
"ge"  { return T_OP_GE; }
Packit 90a5c9
"ne"  { return T_OP_NE; }
Packit 90a5c9
"eq"  { return T_OP_EQ; }
Packit 90a5c9
"in"  { return T_OP_IN; }
Packit 90a5c9
Packit 90a5c9
"-"[a-zA-Z_] {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
Packit 90a5c9
    return T_OP_UNARY;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
"-"[a-zA-Z_][a-zA-Z_0-9]+ {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
Packit 90a5c9
    return T_OP_BINARY;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Specials
Packit 90a5c9
  */
Packit 90a5c9
"true"  { return T_TRUE; }
Packit 90a5c9
"false" { return T_FALSE; }
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Digits
Packit 90a5c9
  */
Packit 90a5c9
-?[0-9]+ {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
Packit 90a5c9
    return T_DIGIT;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Identifiers
Packit 90a5c9
  */
Packit 90a5c9
[a-zA-Z][a-zA-Z0-9_]* {
Packit 90a5c9
    yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
Packit 90a5c9
    return T_ID;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * These are parts of the grammar and are returned as is
Packit 90a5c9
  */
Packit 90a5c9
[(){},:] {
Packit 90a5c9
    return yytext[0];
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
 /*
Packit 90a5c9
  * Anything else is an error
Packit 90a5c9
  */
Packit 90a5c9
.|\n {
Packit 90a5c9
    char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);
Packit 90a5c9
    PERROR(msg);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
%%
Packit 90a5c9
Packit 90a5c9