Manual bugfixes.
[dyninst.git] / dyner / src / cmdline.y
1 %{
2 #if defined(i386_unknown_nt4_0)
3 #include <malloc.h>
4 #include <string.h>
5 #endif
6
7 /*
8  * Yacc will define token IF, conflicting with dyn_regs.h 
9  * This undef is safe b/c yacc also creates an enum IF 
10  * which serves the same purpose.
11 */
12 #undef IF
13
14 #include "BPatch_thread.h"
15 #include "BPatch_image.h"
16 #include "BPatch_type.h"
17 #include "BPatch_snippet.h"
18 #include "breakpoint.h"
19
20 extern "C" {
21 void yyerror(char *s);
22 int yyparse(void);
23 }
24
25 class runtimeVar {                                                                                                                                                         
26   public:                                                                                                                                                                     
27    runtimeVar(BPatch_variableExpr *v, const char *n) {                                                                                                                     
28       var = v, name = strdup(n);                                                                                                                                          
29    }                                                                                                                                                                       
30    BPatch_variableExpr *var;                                                                                                                                               
31    char *name;                                                                                                                                                             
32    bool readValue(void *buf) { return var->readValue(buf); }                                                                                                               
33 };
34
35 extern BPatch_thread *appThread;
36 extern BPatch_process *appProc;
37 extern BPatch_image *appImage;
38
39 static BPatch_Vector<runtimeVar *> varList;
40
41 const bool verbose = true;
42
43 int yylex();
44
45 BPatch_snippet *parse_result;
46 parse_ret parse_type;
47
48 %}
49
50 %union {
51    int          ival;
52    long  lval;
53    double dval;
54    char         *sval;
55    
56    BPatch_snippet                       *snippet;
57    BPatch_boolExpr                      *boolExpr;
58    BPatch_Vector<BPatch_snippet *>      *snippetList;
59    BPatch_funcCallExpr                  *funcCall;
60    BPatch_variableExpr     *varExpr;
61 };
62
63
64 %token <sval> IDENTIFIER_T STRING_T
65 %token <ival> NUMBER_T
66 %token _ERROR_T IF_T ELSE_T
67 %token PLUSPLUS_T MINUSMINUS_T
68 %token TRUE FALSE
69
70 %left DOT_T DOLLAR_T
71 %left OR_T
72 %left AND_T
73 %left EQ_T NOT_EQ_T LESS_EQ_T GREATER_EQ_T
74 %left '+' '-'
75 %left '*' '/' '%'
76 %left COMMA_T
77 %left ASSIGN_T ADD_ASSIGN_T SUB_ASSIGN_T MUL_ASSIGN_T DIV_ASSIGN_T MOD_ASSIGN_T
78 %left SEMI_T
79 %left START_BLOCK_T END_BLOCK_T
80
81 %type <boolExpr> bool_expression bool_constant
82 %type <snippet> arith_expression  statement inc_decr_expr 
83 %type <snippet> param block
84 %type <snippetList> param_list statement_list
85 %type <funcCall> func_call
86 %type <varExpr> variable_expr
87
88
89 %%
90
91 start:
92     '(' bool_expression ')' 
93     {
94        if(verbose) printf(" <bool>\n");
95        parse_result = $2;
96        parse_type = parsed_bool;
97     }
98     | statement_list
99     { 
100        parse_result = new BPatch_sequence(*$1); 
101        parse_type = parsed_statement; 
102        delete $1;
103     }
104     ; 
105
106 statement_list: 
107     statement
108     { 
109        if(verbose) printf("\n");
110        $$ = new BPatch_Vector<BPatch_snippet *>; 
111        $$->push_back($1);
112     }
113     | statement_list statement
114     {
115        $1->push_back($2);
116        $$ = $1;
117     }
118     ;
119
120 statement:
121     // 1 + 2;
122     arith_expression SEMI_T
123     { 
124        $$ = $1; 
125     }
126   // if (x == y) {}
127     | IF_T '(' bool_expression ')' block 
128     {
129        if(verbose) printf(" if () ");
130        $$ = new BPatch_ifExpr(*$3, *$5);
131        delete $3;
132        delete $5;
133     }
134     // if (x == y) {} else {}
135     | IF_T '(' bool_expression ')' block ELSE_T block 
136     {
137        if(verbose) printf(" if () else ");
138        $$ = new BPatch_ifExpr(*$3, *$5, *$7);
139        delete $3;
140        delete $5;
141        delete $7;
142     }
143     ;
144
145 block: statement
146      // {stuff}
147      | START_BLOCK_T statement_list END_BLOCK_T
148      {
149         $$ = new BPatch_sequence(*$2);
150         delete $2;
151      }
152      ;
153
154
155 func_call: IDENTIFIER_T '(' param_list ')'
156            //funct(stuff,stuff)
157     { 
158        if(verbose) printf(" %s () ", $1);
159        BPatch_Vector<BPatch_function *>bpfv;
160        if (NULL == appImage->findFunction($1, bpfv) || !bpfv.size()) {
161           printf("unable to find function %s\n", $1);
162           free($1);
163           return 1;
164        }
165        if (bpfv.size() > 1) {
166 // make this non verbose -- have it return errors through proper channels or as part of generated code.
167           printf("found %d references to  %s\n", (int) bpfv.size(), $1);
168        }
169
170        BPatch_function *func = bpfv[0];
171         
172        if (!func) {
173           printf("unable to find function %s\n", $1);
174           free($1);
175           return 1;
176        }
177       
178        free($1);
179        $$ = new BPatch_funcCallExpr(*func, *$3); 
180        delete $3;
181     }
182     ;
183
184 param_list: 
185     //()
186     {
187        //No parameters, return an empty vector
188        $$ = new BPatch_Vector<BPatch_snippet *>;
189     }
190     //(stuff)
191     | param 
192     { 
193        $$ = new BPatch_Vector<BPatch_snippet *>; 
194        $$->push_back($1);
195     }
196     //(stuff,stuff)
197     | param_list COMMA_T param
198     {
199        if(verbose) printf(" , ");
200        $1->push_back($3); 
201        $$ = $1;
202     }
203     ;
204
205 param: arith_expression  //funct(2+5)
206     //funct("hi")
207     |  STRING_T { 
208        $$ = new BPatch_constExpr($1); 
209     }
210     ;
211
212 bool_constant: TRUE 
213     { 
214        $$ = new BPatch_boolExpr(BPatch_eq, BPatch_constExpr(0), BPatch_constExpr(0));
215     }
216     | FALSE
217     {
218        $$ = new BPatch_boolExpr(BPatch_ne, BPatch_constExpr(0), BPatch_constExpr(0));
219     }
220     ;
221
222 bool_expression: bool_constant
223     |arith_expression '<' arith_expression
224     {
225        if(verbose) printf(" < ");
226        $$ = new BPatch_boolExpr(BPatch_lt, *$1, *$3);
227        delete $1;
228        delete $3;
229     }
230     |            arith_expression '>' arith_expression {
231        $$ = new BPatch_boolExpr(BPatch_gt, *$1, *$3);
232        delete $1;
233        delete $3;
234     }
235     |            arith_expression EQ_T arith_expression {
236        $$ = new BPatch_boolExpr(BPatch_eq, *$1, *$3);
237        delete $1;
238        delete $3;
239     }
240     |            arith_expression LESS_EQ_T arith_expression {
241        $$ = new BPatch_boolExpr(BPatch_le, *$1, *$3);
242        delete $1;
243        delete $3;
244     }
245     |            arith_expression GREATER_EQ_T arith_expression {
246        $$ = new BPatch_boolExpr(BPatch_ge, *$1, *$3);
247        delete $1;
248        delete $3;
249     }
250     |            arith_expression NOT_EQ_T arith_expression {
251        $$ = new BPatch_boolExpr(BPatch_ne, *$1, *$3);
252        delete $1;
253        delete $3;
254     }
255     |            bool_expression AND_T bool_expression  {
256        $$ = new BPatch_boolExpr(BPatch_and, *$1, *$3);
257        delete $1;
258        delete $3;
259     }
260     |            bool_expression OR_T bool_expression  {
261        $$ = new BPatch_boolExpr(BPatch_or, *$1, *$3);
262        delete $1;
263        delete $3;
264     }
265     ;
266
267 variable_expr:
268     IDENTIFIER_T {
269        BPatch_variableExpr *var = findVariable($1);
270        if (var == NULL) {
271           fprintf(stderr, "Cannot find variable: %s\n", $1);
272           free($1);
273           return 1;
274           $$ = NULL;
275        }
276        free($1);
277        $$ = var;
278     }
279     | IDENTIFIER_T DOT_T IDENTIFIER_T {
280        bool foundField = false;
281        
282        BPatch_variableExpr *var = findVariable($1);
283        if (var == NULL) {
284           fprintf(stderr, "Cannot find variable: %s\n", $1);
285           free($1);
286           return 1;
287        }
288        
289        BPatch_Vector<BPatch_variableExpr *> *vars = var->getComponents();
290        if (!vars) {
291           fprintf(stderr, "is not an aggregate type: %s\n", $1);
292           free($1);
293           return 1;
294        }
295        for (unsigned int i=0; i < vars->size(); i++) {
296           if (!strcmp($3, (*vars)[i]->getName())) {
297              $$ = (*vars)[i];
298              foundField = true;
299           }
300        }
301        
302        if (!foundField) {
303           fprintf(stderr, "%s is not a field of %s\n", $3, $1);
304           free($1);
305           return 1;
306        }
307     }
308     ;
309        
310 arith_expression: variable_expr { $$ = (BPatch_snippet *)$1;}
311     |  NUMBER_T     { $$ = new BPatch_constExpr($1); }
312     |            arith_expression '*' arith_expression  {
313         $$ = new BPatch_arithExpr(BPatch_times, *$1, *$3);
314         delete $1;
315         delete $3;
316     }
317     |
318     func_call { $$ = $1; }
319     |
320     variable_expr ASSIGN_T arith_expression {
321             $$ = new BPatch_arithExpr(BPatch_assign, *$1, *$3);
322             delete $1;
323             delete $3;
324     }
325     | variable_expr ADD_ASSIGN_T arith_expression
326     {
327        if(verbose) printf(" += ");
328        $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_plus, *$1, *$3));
329        delete $1;
330        delete $3;
331     }
332     | variable_expr SUB_ASSIGN_T arith_expression
333     {
334        if(verbose) printf(" -= ");
335        $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_minus, *$1, *$3));
336        delete $1;
337        delete $3;
338     }
339     | variable_expr MUL_ASSIGN_T arith_expression
340     {
341        if(verbose) printf(" *= ");
342        $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_times, *$1, *$3));
343        delete $1;
344        delete $3;
345     }
346     | variable_expr DIV_ASSIGN_T arith_expression
347     {
348        if(verbose) printf(" /= ");
349        $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_divide, *$1, *$3));
350        delete $1;
351        delete $3;
352     }
353     | variable_expr MOD_ASSIGN_T arith_expression
354     {
355        if(verbose) printf(" %%= ");
356        $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_minus, *$1, BPatch_arithExpr(BPatch_times, BPatch_arithExpr(BPatch_divide, *$1, *$3), *$3)));
357        delete $1;
358        delete $3;
359     }
360
361     |   arith_expression '/' arith_expression 
362     {
363        if(verbose) printf(" / ");
364        $$ = new BPatch_arithExpr(BPatch_divide, *$1, *$3);
365        delete $1;
366        delete $3;
367     }
368     | arith_expression '%' arith_expression
369     {
370        if(verbose) printf(" %% ");
371        $$ = new BPatch_arithExpr(BPatch_minus, *$1, BPatch_arithExpr(BPatch_times, BPatch_arithExpr(BPatch_divide, *$1, *$3), *$3));
372        delete $1;
373        delete $3;
374     }
375     |   arith_expression '+' arith_expression 
376     {
377        if(verbose) printf(" + ");
378        $$ = new BPatch_arithExpr(BPatch_plus, *$1, *$3);
379        delete $1;
380        delete $3;
381     }
382     |   arith_expression '-' arith_expression 
383     {
384        if(verbose) printf(" - ");
385        $$ = new BPatch_arithExpr(BPatch_minus, *$1, *$3);
386        delete $1;
387        delete $3;
388     }
389     |   '(' arith_expression ')'  {$$ = $2;}
390     | inc_decr_expr {$$ = $1;}
391     ;
392
393 inc_decr_expr:
394     variable_expr PLUSPLUS_T 
395     {
396        if(verbose) printf(" <++ ");
397        BPatch_arithExpr addOne = BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_plus, *$1, BPatch_constExpr(1)));
398        $$ = new BPatch_arithExpr(BPatch_seq, (BPatch_snippet &)addOne, BPatch_arithExpr(BPatch_minus, *$1, BPatch_constExpr(1)));
399     }
400     | PLUSPLUS_T variable_expr 
401     {
402        if(verbose) printf(" ++> ");
403        BPatch_arithExpr addOne = BPatch_arithExpr(BPatch_assign, *$2, BPatch_arithExpr(BPatch_plus, *$2, BPatch_constExpr(1)));
404        $$ = new BPatch_arithExpr(BPatch_seq, (BPatch_snippet &)addOne, *$2);
405     }
406     | variable_expr MINUSMINUS_T
407     {
408        if(verbose) printf(" -- ");
409        BPatch_arithExpr subOne = BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_minus, *$1, BPatch_constExpr(1)));
410        $$ = new BPatch_arithExpr(BPatch_seq, (BPatch_snippet &)subOne, BPatch_arithExpr(BPatch_plus, *$1, BPatch_constExpr(1)));
411     }
412     | MINUSMINUS_T variable_expr
413     {
414        if(verbose) printf(" -- ");
415        BPatch_arithExpr subOne = BPatch_arithExpr(BPatch_assign, *$2, BPatch_arithExpr(BPatch_minus, *$2, BPatch_constExpr(1)));
416        $$ = new BPatch_arithExpr(BPatch_seq, (BPatch_snippet &)subOne, *$2);
417     }
418     ;
419
420 %%
421
422
423 #if 0 // For testing the parser independently
424 extern "C" void set_lex_input(char *str);
425
426 main(int argc, char *argv[])
427 {
428     int ret;
429
430     char str[512];
431     printf("here> ");
432     gets(str);
433
434     set_lex_input(str);
435
436     ret = yyparse();
437
438     printf("Returned: %d\n", ret);
439 }
440 #endif
441
442
443
444 void yyerror(char *s)
445 {
446    fflush(stderr);
447     fprintf(stderr, "Error on command line: %s\n",s);
448 }