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