diff options
author | Stefan Fritsch <sf@apache.org> | 2010-11-06 15:31:16 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2010-11-06 15:31:16 +0100 |
commit | 35cdba6976ca6f8a9bde73267340c40d7ae6d496 (patch) | |
tree | cc1609882f476369e5edea4aef79a868fef4f7fd /server/util_expr_scan.l | |
parent | Put the expression parser back into mod_include (diff) | |
download | apache2-35cdba6976ca6f8a9bde73267340c40d7ae6d496.tar.xz apache2-35cdba6976ca6f8a9bde73267340c40d7ae6d496.zip |
Replace ap_expr with a parser derived from mod_ssl's parser. Make mod_ssl use
the new parser. Rework ap_expr's public interface and provide hooks for modules
to add variables and functions.
The Netware and Windows build files still need to be adjusted
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1032073 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/util_expr_scan.l')
-rw-r--r-- | server/util_expr_scan.l | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/server/util_expr_scan.l b/server/util_expr_scan.l new file mode 100644 index 0000000000..d2840a00b4 --- /dev/null +++ b/server/util_expr_scan.l @@ -0,0 +1,344 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ap_expr_scan.l, based on ssl_expr_scan.l from mod_ssl + */ + +/* _________________________________________________________________ +** +** Expression Scanner +** _________________________________________________________________ +*/ + +%pointer +%option batch +%option never-interactive +%option nodefault +%option noyywrap +%option reentrant +%option bison-bridge +%option warn +%option noinput nounput +%option stack +%x str +%x var +%x vararg +%x regex regex_flags + +%{ +#include "util_expr_private.h" +#include "util_expr_parse.h" + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +{ \ + if ((result = MIN(max_size, yyextra->inputbuf \ + + yyextra->inputlen \ + - yyextra->inputptr)) <= 0) \ + { \ + result = YY_NULL; \ + } \ + else { \ + memcpy(buf, yyextra->inputptr, result); \ + yyextra->inputptr += result; \ + } \ +} + +#define YY_EXTRA_TYPE ap_expr_parse_ctx* + +#define PERROR(msg) yyextra->error2 = msg ; return ERROR; + +#define str_ptr (yyextra->scan_ptr) +#define str_buf (yyextra->scan_buf) +#define str_del (yyextra->scan_del) + +%} + + +%% + + char regex_buf[MAX_STRING_LEN]; + char *regex_ptr = NULL; + char regex_del = '\0'; + + /* + * Whitespaces + */ +[ \t\n]+ { + /* NOP */ +} + + /* + * strings ("..." and '...') + */ +["'] { + str_ptr = str_buf; + str_del = yytext[0]; + BEGIN(str); + return T_STR_BEGIN; +} +<str>["'] { + if (yytext[0] == str_del) { + if (YY_START == var) { + PERROR("Unterminated variable in string"); + } + else if (str_ptr == str_buf) { + BEGIN(INITIAL); + return T_STR_END; + } + else { + /* return what we have so far and scan delimiter again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + } + else { + *str_ptr++ = yytext[0]; + } +} +<str,var,vararg>\n { + PERROR("Unterminated string or variable"); +} +<str,var,vararg><<EOF>> { + PERROR("Unterminated string or variable"); +} +<str,vararg>\\[0-7]{1,3} { + int result; + + (void)sscanf(yytext+1, "%o", &result); + if (result > 0xff) { + PERROR("Escape sequence out of bound"); + } + else { + *str_ptr++ = result; + } +} +<str,vararg>\\[0-9]+ { + PERROR("Bad escape sequence"); +} +<str,vararg>\\n { *str_ptr++ = '\n'; } +<str,vararg>\\r { *str_ptr++ = '\r'; } +<str,vararg>\\t { *str_ptr++ = '\t'; } +<str,vararg>\\b { *str_ptr++ = '\b'; } +<str,vararg>\\f { *str_ptr++ = '\f'; } +<str,vararg>\\(.|\n) { + *str_ptr++ = yytext[1]; +} + +<str,vararg>[^\\\n"'%}]+ { + char *cp = yytext; + while (*cp != '\0') + *str_ptr++ = *cp++; +} + + /* variable inside string */ +<str>%\{ { + if (str_ptr != str_buf) { + /* return what we have so far and scan '%{' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + else { + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; + } +} + +<vararg>% { + *str_ptr++ = yytext[0]; +} + +<str>[%}] { + *str_ptr++ = yytext[0]; +} + +%\{ { + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; +} + + /* + * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax + */ +<var>[a-zA-Z][a-zA-Z0-9_]* { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; +} + +<var>\} { + yy_pop_state(yyscanner); + return T_VAR_END; +} + +<var>: { + BEGIN(vararg); + return yytext[0]; +} + +<var>.|\n { + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, + "Invalid character in variable name '%s'", c); + PERROR(msg); +} + +<vararg>\} { + if (str_ptr != str_buf) { + /* return what we have so far and scan '}' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + str_ptr = str_buf; + yyless(0); + return T_STRING; + } + else { + yy_pop_state(yyscanner); + return T_VAR_END; + } +} + + /* + * Regular Expression + */ +"m"[/#$%^,;:_\?\|\^\-\!\.\'\"] { + regex_del = yytext[1]; + regex_ptr = regex_buf; + BEGIN(regex); +} +"/" { + regex_del = yytext[0]; + regex_ptr = regex_buf; + BEGIN(regex); +} +<regex>.|\n { + if (yytext[0] == regex_del) { + *regex_ptr = '\0'; + BEGIN(regex_flags); + } + else { + *regex_ptr++ = yytext[0]; + } +} +<regex_flags>i { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX_I; +} +<regex_flags>.|\n { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + yyless(0); + BEGIN(INITIAL); + return T_REGEX; +} +<regex_flags><<EOF>> { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX; +} + + /* + * Operators + */ +==? { return T_OP_STR_EQ; } +"!=" { return T_OP_STR_NE; } +"<" { return T_OP_STR_LT; } +"<=" { return T_OP_STR_LE; } +">" { return T_OP_STR_GT; } +">=" { return T_OP_STR_GE; } +"=~" { return T_OP_REG; } +"!~" { return T_OP_NRE; } +"and" { return T_OP_AND; } +"&&" { return T_OP_AND; } +"or" { return T_OP_OR; } +"||" { return T_OP_OR; } +"not" { return T_OP_NOT; } +"!" { return T_OP_NOT; } +"." { return T_OP_CONCAT; } +"-in" { return T_OP_IN; } +"-eq" { return T_OP_EQ; } +"-ne" { return T_OP_NE; } +"-ge" { return T_OP_GE; } +"-le" { return T_OP_LE; } +"-gt" { return T_OP_GT; } +"-lt" { return T_OP_LT; } + + /* for compatibility with ssl_expr */ +"lt" { return T_OP_LT; } +"le" { return T_OP_LE; } +"gt" { return T_OP_GT; } +"ge" { return T_OP_GE; } +"ne" { return T_OP_NE; } +"eq" { return T_OP_EQ; } +"in" { return T_OP_IN; } + +"-"[a-zA-Z_] { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_UNARY; +} + +"-"[a-zA-Z_][a-zA-Z_0-9] { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_BINARY; +} + + /* + * Specials + */ +"true" { return T_TRUE; } +"false" { return T_FALSE; } + + /* + * Digits + */ +-?[0-9]+ { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_DIGIT; +} + + /* + * Identifiers + */ +[a-zA-Z][a-zA-Z0-9_]* { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; +} + + /* + * These are parts of the grammar and are returned as is + */ +[(){},:] { + return yytext[0]; +} + + /* + * Anything else is an error + */ +.|\n { + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, "Parse error near '%s'", c); + PERROR(msg); +} + +%% + + |