1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * ap_expr_scan.l, based on ssl_expr_scan.l from mod_ssl
21 /* _________________________________________________________________
24 ** _________________________________________________________________
29 %option never-interactive
35 %option noinput nounput noyy_top_state
43 #include "util_expr_private.h"
44 #include "util_expr_parse.h"
45 #include "http_main.h"
49 #define YY_INPUT(buf,result,max_size) \
51 if ((result = MIN(max_size, yyextra->inputbuf \
53 - yyextra->inputptr)) <= 0) \
58 memcpy(buf, yyextra->inputptr, result); \
59 yyextra->inputptr += result; \
64 * XXX: It would be nice if we could recover somehow, e.g. via
65 * XXX: longjmp. It is not clear if the scanner is in any state
66 * XXX: to be cleaned up, though.
68 #define YY_FATAL_ERROR(msg) \
70 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, \
71 "expr parser fatal error (BUG?): " \
72 "%s, exiting", msg); \
76 #define YY_EXTRA_TYPE ap_expr_parse_ctx_t*
78 #define PERROR(msg) do { yyextra->error2 = msg ; return T_ERROR; } while (0)
80 #define str_ptr (yyextra->scan_ptr)
81 #define str_buf (yyextra->scan_buf)
82 #define str_del (yyextra->scan_del)
84 #define STR_APPEND(c) do { \
86 if (str_ptr >= str_buf + sizeof(str_buf)) \
87 PERROR("String too long"); \
95 char regex_buf[MAX_STRING_LEN];
96 char *regex_ptr = NULL;
97 char regex_del = '\0';
101 * Set initial state for string expressions
103 if (yyextra->at_start) {
104 yyextra->at_start = 0;
105 if (yyextra->flags & AP_EXPR_FLAG_STRING_RESULT) {
107 return T_EXPR_STRING;
123 * strings ("..." and '...')
132 if (yytext[0] == str_del) {
133 if (YY_START == var) {
134 PERROR("Unterminated variable in string");
136 else if (str_ptr == str_buf) {
141 /* return what we have so far and scan delimiter again */
143 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
150 STR_APPEND(yytext[0]);
154 PERROR("Unterminated string or variable");
156 <var,vararg><<EOF>> {
157 PERROR("Unterminated string or variable");
160 if (!(yyextra->flags & AP_EXPR_FLAG_STRING_RESULT)) {
161 PERROR("Unterminated string or variable");
165 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
172 <str,vararg>\\[0-7]{1,3} {
175 (void)sscanf(yytext+1, "%o", &result);
177 PERROR("Escape sequence out of bound");
183 <str,vararg>\\[0-9]+ {
184 PERROR("Bad escape sequence");
186 <str,vararg>\\n { STR_APPEND('\n'); }
187 <str,vararg>\\r { STR_APPEND('\r'); }
188 <str,vararg>\\t { STR_APPEND('\t'); }
189 <str,vararg>\\b { STR_APPEND('\b'); }
190 <str,vararg>\\f { STR_APPEND('\f'); }
191 <str,vararg>\\(.|\n) { STR_APPEND(yytext[1]); }
193 /* regexp backref inside string/arg */
194 <str,vararg>[$][0-9] {
195 if (str_ptr != str_buf) {
196 /* return what we have so far and scan '$x' again */
198 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
204 yylval->num = yytext[1] - '0';
205 return T_REGEX_BACKREF;
209 <str,vararg>[^\\\n"'%}$]+ {
211 while (*cp != '\0') {
217 /* variable inside string/arg */
219 if (str_ptr != str_buf) {
220 /* return what we have so far and scan '%{' again */
222 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
228 yy_push_state(var, yyscanner);
234 STR_APPEND(yytext[0]);
238 STR_APPEND(yytext[0]);
242 yy_push_state(var, yyscanner);
247 yylval->num = yytext[1] - '0';
248 return T_REGEX_BACKREF;
252 * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
254 <var>[a-ij-rs-zA-IJ-RS-Z][a-ij-rs-zA-IJ-RS-Z0-9_]* {
255 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
260 yy_pop_state(yyscanner);
270 char *msg = apr_psprintf(yyextra->pool,
271 "Invalid character in variable name '%c'", yytext[0]);
276 if (str_ptr != str_buf) {
277 /* return what we have so far and scan '}' again */
279 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
285 yy_pop_state(yyscanner);
293 "m"[/#$%^,;:_\?\|\^\-\!\.\'\"] {
294 regex_del = yytext[1];
295 regex_ptr = regex_buf;
299 regex_del = yytext[0];
300 regex_ptr = regex_buf;
304 if (yytext[0] == regex_del) {
309 *regex_ptr++ = yytext[0];
310 if (regex_ptr >= regex_buf + sizeof(regex_buf))
311 PERROR("Regexp too long");
315 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
320 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
325 <regex_flags><<EOF>> {
326 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
334 ==? { return T_OP_STR_EQ; }
335 "!=" { return T_OP_STR_NE; }
336 "<" { return T_OP_STR_LT; }
337 "<=" { return T_OP_STR_LE; }
338 ">" { return T_OP_STR_GT; }
339 ">=" { return T_OP_STR_GE; }
340 "=~" { return T_OP_REG; }
341 "!~" { return T_OP_NRE; }
342 "and" { return T_OP_AND; }
343 "&&" { return T_OP_AND; }
344 "or" { return T_OP_OR; }
345 "||" { return T_OP_OR; }
346 "not" { return T_OP_NOT; }
347 "!" { return T_OP_NOT; }
348 "." { return T_OP_CONCAT; }
349 "-in" { return T_OP_IN; }
350 "-eq" { return T_OP_EQ; }
351 "-ne" { return T_OP_NE; }
352 "-ge" { return T_OP_GE; }
353 "-le" { return T_OP_LE; }
354 "-gt" { return T_OP_GT; }
355 "-lt" { return T_OP_LT; }
357 /* for compatibility with ssl_expr */
358 "lt" { return T_OP_LT; }
359 "le" { return T_OP_LE; }
360 "gt" { return T_OP_GT; }
361 "ge" { return T_OP_GE; }
362 "ne" { return T_OP_NE; }
363 "eq" { return T_OP_EQ; }
364 "in" { return T_OP_IN; }
366 "-"[a-ij-rs-zA-IJ-RS-Z_] {
367 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
371 "-"[a-ij-rs-zA-IJ-RS-Z_][a-ij-rs-zA-IJ-RS-Z_0-9]+ {
372 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
379 "true" { return T_TRUE; }
380 "false" { return T_FALSE; }
386 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
393 [a-ij-rs-zA-IJ-RS-Z][a-ij-rs-zA-IJ-RS-Z0-9_]* {
394 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
399 * These are parts of the grammar and are returned as is
406 * Anything else is an error
409 char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);