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"
47 #define YY_INPUT(buf,result,max_size) \
49 if ((result = MIN(max_size, yyextra->inputbuf \
51 - yyextra->inputptr)) <= 0) \
56 memcpy(buf, yyextra->inputptr, result); \
57 yyextra->inputptr += result; \
61 #define YY_EXTRA_TYPE ap_expr_parse_ctx_t*
63 #define PERROR(msg) yyextra->error2 = msg ; return T_ERROR;
65 #define str_ptr (yyextra->scan_ptr)
66 #define str_buf (yyextra->scan_buf)
67 #define str_del (yyextra->scan_del)
74 char regex_buf[MAX_STRING_LEN];
75 char *regex_ptr = NULL;
76 char regex_del = '\0';
86 * strings ("..." and '...')
95 if (yytext[0] == str_del) {
96 if (YY_START == var) {
97 PERROR("Unterminated variable in string");
99 else if (str_ptr == str_buf) {
104 /* return what we have so far and scan delimiter again */
106 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
113 *str_ptr++ = yytext[0];
117 PERROR("Unterminated string or variable");
119 <str,var,vararg><<EOF>> {
120 PERROR("Unterminated string or variable");
122 <str,vararg>\\[0-7]{1,3} {
125 (void)sscanf(yytext+1, "%o", &result);
127 PERROR("Escape sequence out of bound");
133 <str,vararg>\\[0-9]+ {
134 PERROR("Bad escape sequence");
136 <str,vararg>\\n { *str_ptr++ = '\n'; }
137 <str,vararg>\\r { *str_ptr++ = '\r'; }
138 <str,vararg>\\t { *str_ptr++ = '\t'; }
139 <str,vararg>\\b { *str_ptr++ = '\b'; }
140 <str,vararg>\\f { *str_ptr++ = '\f'; }
141 <str,vararg>\\(.|\n) {
142 *str_ptr++ = yytext[1];
145 /* regexp backref inside string/arg */
146 <str,vararg>[$][0-9] {
147 if (str_ptr != str_buf) {
148 /* return what we have so far and scan '$x' again */
150 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
156 yylval->num = yytext[1] - '0';
157 return T_REGEX_BACKREF;
161 <str,vararg>[^\\\n"'%}$]+ {
167 /* variable inside string/arg */
169 if (str_ptr != str_buf) {
170 /* return what we have so far and scan '%{' again */
172 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
178 yy_push_state(var, yyscanner);
184 *str_ptr++ = yytext[0];
188 *str_ptr++ = yytext[0];
192 yy_push_state(var, yyscanner);
197 yylval->num = yytext[1] - '0';
198 return T_REGEX_BACKREF;
202 * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax
204 <var>[a-zA-Z][a-zA-Z0-9_]* {
205 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
210 yy_pop_state(yyscanner);
220 char *msg = apr_psprintf(yyextra->pool,
221 "Invalid character in variable name '%c'", yytext[0]);
226 if (str_ptr != str_buf) {
227 /* return what we have so far and scan '}' again */
229 yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf);
235 yy_pop_state(yyscanner);
243 "m"[/#$%^,;:_\?\|\^\-\!\.\'\"] {
244 regex_del = yytext[1];
245 regex_ptr = regex_buf;
249 regex_del = yytext[0];
250 regex_ptr = regex_buf;
254 if (yytext[0] == regex_del) {
259 *regex_ptr++ = yytext[0];
263 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
268 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
273 <regex_flags><<EOF>> {
274 yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf);
282 ==? { return T_OP_STR_EQ; }
283 "!=" { return T_OP_STR_NE; }
284 "<" { return T_OP_STR_LT; }
285 "<=" { return T_OP_STR_LE; }
286 ">" { return T_OP_STR_GT; }
287 ">=" { return T_OP_STR_GE; }
288 "=~" { return T_OP_REG; }
289 "!~" { return T_OP_NRE; }
290 "and" { return T_OP_AND; }
291 "&&" { return T_OP_AND; }
292 "or" { return T_OP_OR; }
293 "||" { return T_OP_OR; }
294 "not" { return T_OP_NOT; }
295 "!" { return T_OP_NOT; }
296 "." { return T_OP_CONCAT; }
297 "-in" { return T_OP_IN; }
298 "-eq" { return T_OP_EQ; }
299 "-ne" { return T_OP_NE; }
300 "-ge" { return T_OP_GE; }
301 "-le" { return T_OP_LE; }
302 "-gt" { return T_OP_GT; }
303 "-lt" { return T_OP_LT; }
305 /* for compatibility with ssl_expr */
306 "lt" { return T_OP_LT; }
307 "le" { return T_OP_LE; }
308 "gt" { return T_OP_GT; }
309 "ge" { return T_OP_GE; }
310 "ne" { return T_OP_NE; }
311 "eq" { return T_OP_EQ; }
312 "in" { return T_OP_IN; }
315 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
319 "-"[a-zA-Z_][a-zA-Z_0-9]+ {
320 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1);
327 "true" { return T_TRUE; }
328 "false" { return T_FALSE; }
334 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
341 [a-zA-Z][a-zA-Z0-9_]* {
342 yylval->cpVal = apr_pstrdup(yyextra->pool, yytext);
347 * These are parts of the grammar and are returned as is
354 * Anything else is an error
357 char *msg = apr_psprintf(yyextra->pool, "Parse error near '%c'", yytext[0]);