make app_queue 1.2 jump compliant (issue #5580)
[asterisk/asterisk.git] / ast_expr2.fl
1 %{
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <locale.h>
7 #include <ctype.h>
8 #if !defined(SOLARIS) && !defined(__CYGWIN__)
9 #include <err.h>
10 #else
11 #define quad_t int64_t
12 #endif
13 #include <errno.h>
14 #include <regex.h>
15 #include <limits.h>
16 #include <asterisk/ast_expr.h>
17 #include <asterisk/logger.h>
18 #include <asterisk/strings.h>
19
20 enum valtype {
21         AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
22 } ;
23
24 struct val {
25         enum valtype type;
26         union {
27                 char *s;
28                 quad_t i;
29         } u;
30 } ;
31
32 #include "ast_expr2.h" /* the o/p of the bison on ast_expr2.y */
33
34 #define SET_COLUMNS yylloc_param->first_column = (int)(yyg->yytext_r - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);yylloc_param->last_column = yylloc_param->last_column + yyleng - 1; yylloc_param->first_line = yylloc_param->last_line = 1
35 #define SET_STRING yylval_param->val = (struct val *)calloc(sizeof(struct val),1); yylval_param->val->type = AST_EXPR_string; yylval_param->val->u.s = strdup(yytext);
36 #define SET_NUMERIC_STRING yylval_param->val = (struct val *)calloc(sizeof(struct val),1); yylval_param->val->type = AST_EXPR_numeric_string; yylval_param->val->u.s = strdup(yytext);
37
38 struct parse_io
39 {
40         char *string;
41         struct val *val;
42         yyscan_t scanner;
43 };
44  
45 void ast_yyset_column(int column_no, yyscan_t yyscanner);
46 int ast_yyget_column(yyscan_t yyscanner);
47
48 %}
49
50 %option prefix="ast_yy"
51 %option batch
52 %option outfile="ast_expr2f.c"
53 %option reentrant
54 %option bison-bridge
55 %option bison-locations
56 %option noyywrap
57
58 %%
59
60 \|      { SET_COLUMNS; SET_STRING; return TOK_OR;}
61 \&      { SET_COLUMNS; SET_STRING; return TOK_AND;}
62 \=      { SET_COLUMNS; SET_STRING; return TOK_EQ;}
63 \>      { SET_COLUMNS; SET_STRING; return TOK_GT;}
64 \<      { SET_COLUMNS; SET_STRING; return TOK_LT;}
65 \>\=    { SET_COLUMNS; SET_STRING; return TOK_GE;}
66 \<\=    { SET_COLUMNS; SET_STRING; return TOK_LE;}
67 \!\=    { SET_COLUMNS; SET_STRING; return TOK_NE;}
68 \+      { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
69 \-      { SET_COLUMNS; SET_STRING; return TOK_MINUS;}
70 \*      { SET_COLUMNS; SET_STRING; return TOK_MULT;}
71 \/      { SET_COLUMNS; SET_STRING; return TOK_DIV;}
72 \%      { SET_COLUMNS; SET_STRING; return TOK_MOD;}
73 \?      { SET_COLUMNS; SET_STRING; return TOK_COND;}
74 \:      { SET_COLUMNS; SET_STRING; return TOK_COLON;}
75 \:\:    { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
76 \(      { SET_COLUMNS; SET_STRING; return TOK_LP;}
77 \)      { SET_COLUMNS; SET_STRING; return TOK_RP;}
78
79 [       \r]             {}
80 \"[^"]*\"   {SET_COLUMNS; SET_STRING; return TOKEN;}
81
82 [\n]    {/* what to do with eol */}
83 [0-9]+          {   SET_COLUMNS;  /* the original behavior of the expression parser was to bring in numbers as a numeric string */
84                                 SET_NUMERIC_STRING;
85                                 return TOKEN;}
86 [a-zA-Z0-9,.';{}\\_^%$#@!]+     {SET_COLUMNS; SET_STRING; return TOKEN;}
87
88 %%
89
90 /* I'm putting the interface routine to the whole parse here in the flexer input file
91    mainly because of all the flexer initialization that has to be done. Shouldn't matter
92    where it is, as long as it's somewhere. I didn't want to define a prototype for the
93    ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
94         UGH! that would be inappropriate. */
95
96 int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
97 int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
98
99 int ast_expr(char *expr, char *buf, int length)
100 {
101         struct parse_io *io;
102         
103         io = calloc(sizeof(struct parse_io),1);
104         io->string = expr;  /* to pass to the error routine */
105         
106         ast_yylex_init(&io->scanner);
107         
108         ast_yy_scan_string(expr, io->scanner);
109         
110         ast_yyparse ((void *) io);
111
112         ast_yylex_destroy(io->scanner);
113
114         if (io->val == NULL) {
115                 if (length > 1) {
116                         strcpy(buf, "0");
117                         return 1;
118                 }
119         } else {
120                 if (io->val->type == AST_EXPR_integer) {
121                         int res_length;
122
123                         res_length = snprintf(buf, length, "%ld", (long int) io->val->u.i);
124                         return res_length <= length ? res_length : length;
125                 } else {
126 #ifdef STANDALONE
127                         strncpy(buf, io->val->u.s, length - 1);
128 #else /* !STANDALONE */
129                         ast_copy_string(buf, io->val->u.s, length);
130 #endif /* STANDALONE */
131                         return strlen(buf);
132                 }
133                 free(io->val);
134         }
135         free(io);
136         return 0;
137 }
138
139 int ast_yyerror (const char *s,  yyltype *loc, struct parse_io *parseio )
140 {       
141         struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner);
142         char spacebuf[8000]; /* best safe than sorry */
143         char spacebuf2[8000]; /* best safe than sorry */
144         int i=0;
145         spacebuf[0] = 0;
146         
147 #ifdef WHEN_LOC_MEANS_SOMETHING
148         if( loc->first_column > 7990 ) /* if things get out of whack, why crash? */
149                 loc->first_column = 7990;
150         if( loc->last_column > 7990 )
151                 loc->last_column = 7990;
152         for(i=0;i<loc->first_column;i++) spacebuf[i] = ' ';
153         for(   ;i<loc->last_column;i++) spacebuf[i] = '^';
154         spacebuf[i] = 0;
155 #endif
156         for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' ';  /* uh... assuming yyg is defined, then I can use the yycolumn macro,
157                                                                                                         which is the same thing as... get this:
158                                                                                                         yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column
159                                                                                                         I was tempted to just use yy_buf_pos in the STATE, but..., well:
160                                                                                                                 a. the yy_buf_pos is the current position in the buffer, which
161                                                                                                                         may not relate to the entire string/buffer because of the
162                                                                                                                         buffering.
163                                                                                                                 b. but, analysis of the situation is that when you use the
164                                                                                                                         yy_scan_string func, it creates a single buffer the size of
165                                                                                                                         string, so the two would be the same... 
166                                                                                                         so, in the end, the yycolumn macro is available, shorter, therefore easier. */
167         spacebuf2[i++]='^';
168         spacebuf2[i]= 0;
169
170 #ifdef STANDALONE3
171         /* easier to read in the standalone version */
172         printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",  
173                         s, parseio->string,spacebuf2);
174 #else
175         ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",  
176                         s, parseio->string,spacebuf2);
177 #endif
178 #ifndef STANDALONE
179         ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables in the asterisk source.\n");
180 #endif
181         return(0);
182 }