Fixed unhelpful coredump when parsing (invalid) command-line arguments,
[dyninst.git] / igen / src / parser.y
1 %{
2 /*
3  * Copyright (c) 1996 Barton P. Miller
4  * 
5  * We provide the Paradyn Parallel Performance Tools (below
6  * described as Paradyn") on an AS IS basis, and do not warrant its
7  * validity or performance.  We reserve the right to update, modify,
8  * or discontinue this software at any time.  We shall have no
9  * obligation to supply such updates or modifications or any other
10  * form of support to you.
11  * 
12  * This license is for research uses.  For such uses, there is no
13  * charge. We define "research use" to mean you may freely use it
14  * inside your organization for whatever purposes you see fit. But you
15  * may not re-distribute Paradyn or parts of Paradyn, in any form
16  * source or binary (including derivatives), electronic or otherwise,
17  * to any other organization or entity without our permission.
18  * 
19  * (for other uses, please contact us at paradyn@cs.wisc.edu)
20  * 
21  * All warranties, including without limitation, any warranty of
22  * merchantability or fitness for a particular purpose, are hereby
23  * excluded.
24  * 
25  * By your use of Paradyn, you understand and agree that we (or any
26  * other person or entity with proprietary rights in Paradyn) are
27  * under no obligation to provide either maintenance services,
28  * update services, notices of latent defects, or correction of
29  * defects for Paradyn.
30  * 
31  * Even if advised of the possibility of such damages, under no
32  * circumstances shall we (or any other person or entity with
33  * proprietary rights in the software licensed hereunder) be liable
34  * to you or any third party for direct, indirect, or consequential
35  * damages of any character regardless of type of action, including,
36  * without limitation, loss of profits, loss of use, loss of good
37  * will, or computer failure or malfunction.  You agree to indemnify
38  * us (and any other person or entity with proprietary rights in the
39  * software licensed hereunder) for any and all liability it may
40  * incur to third parties resulting from your use of Paradyn.
41  */
42
43
44 extern int ignoring;
45 #include "parse.h"
46
47 #define YYSTYPE union parse_stack
48
49 extern int parsing;
50 extern int yylex();
51 extern void yyerror(char*);
52
53 %}
54
55 %token tIDENT tCOMMA tSTAR tNAME tBASE tUNS tUPCALL tASYNC
56 %token tLPAREN tRPAREN tSEMI tLBLOCK tRBLOCK 
57 %token tTYPEDEF tSTRUCT tVERSION tVIRTUAL
58 %token tCLASS tCOLON tCIGNORE tSIGNORE tLINE tCONST tIGNORE
59 %token tANGLE_L tANGLE_R tFREE tREF tABSTRACT tFORWARD
60 %%
61
62 completeDefinition: parsableUnitList { return 0;}
63 | error {
64   char str[80];
65   sprintf(str, "Sorry, unrecoverable error, exiting\n\n");
66   yyerror(str);
67   exit(0);
68 };
69
70 parsableUnitList: 
71 | parsableUnitList parsableUnit { parsing = 0; };
72
73 parsableUnit: interface_spec 
74             | typeSpec;
75
76 interfacePreamble: interfaceName tLBLOCK interfaceBase interfaceVersion {
77   interface_spec *is;
78
79   is = new interface_spec($1.cp, $3.u, $4.u);
80   delete ($1.cp);
81   Options::current_interface = $$.spec = is;
82
83
84 interface_spec: interfacePreamble definitionList tRBLOCK tSEMI { } ;
85
86 interfaceName: tIDENT { $$.cp = $1.cp; };
87
88 interfaceBase: tBASE tUNS tSEMI { $$.u = $2.u; };
89
90 interfaceVersion: tVERSION tUNS tSEMI { $$.u = $2.u; };
91
92 forward_spec: tFORWARD tIDENT tSEMI {
93   Options::forward_decls += *$2.cp; delete $2.cp;
94 };
95
96 definitionList:
97               | definitionList definition
98               ;
99
100 optUpcall:   { $$.fd.call = remote_func::sync_call; $$.fd.is_virtual = false; }
101      | tVIRTUAL { $$.fd.call = remote_func::async_call; $$.fd.is_virtual = true;}
102      | tASYNC    { $$.fd.call = remote_func::async_call; $$.fd.is_virtual = false;}
103      | tVIRTUAL tASYNC { $$.fd.call = remote_func::async_call; $$.fd.is_virtual = true;}
104      | tUPCALL tASYNC { $$.fd.call = remote_func::async_upcall; $$.fd.is_virtual = false;}
105      | tVIRTUAL tUPCALL tASYNC { $$.fd.call = remote_func::async_upcall;
106                                  $$.fd.is_virtual = true;};
107
108 optFree:        { $$.b = false;}
109         | tFREE { $$.b = true;}
110
111 optRef:         { $$.b = false;}
112         | tREF  { $$.b = true;};
113
114 definition: optFree optUpcall optConst typeName pointers optRef tIDENT tLPAREN arglist tRPAREN tSEMI {
115   arg a($4.cp, $5.u, $3.b, NULL, $6.b);
116   if ($5.u && $6.b) {
117     char msg[80];
118     sprintf(msg, "Cannot use a reference with pointers, goodbye\n");
119     yyerror(msg);
120     exit(0);
121   }
122   if (!Options::current_interface->new_remote_func($7.cp, $9.arg_vector,
123                                                    $2.fd.call, $2.fd.is_virtual,
124                                                    a, $1.b))
125     abort();
126   delete ($7.cp); delete ($4.cp); delete ($9.arg_vector);
127
128 } | tCIGNORE {
129  Options::current_interface->ignore(false, $1.charp);
130 } | tSIGNORE {
131  Options::current_interface->ignore(true, $1.charp);
132 };
133
134 optIgnore: tIGNORE { $$.cp = new string($1.charp);}
135            |        { $$.cp = new string((char*)NULL); };
136
137 optAbstract:      { $$.b = false; }
138            | tABSTRACT { $$.b = true; };
139
140 classOrStruct: optAbstract tCLASS { $$.class_data.b = true; $$.class_data.abs = $1.b;}
141              | tSTRUCT { $$.class_data.b = false; $$.class_data.abs = false;};
142
143 typeSpec: classOrStruct tIDENT optDerived
144                         tLBLOCK fieldDeclList optIgnore tRBLOCK tSEMI {
145    // remove ignore tokens -- later
146    // is derived? -- later
147    if (($1.class_data.b || $3.derived.is_derived) &&
148        Options::ml->address_space() == message_layer::AS_one) {
149      char str[80];
150      sprintf(str, "Not supported for single address spaces, you should not be doing this, goodbye!\n");
151      yyerror(str);
152      exit(0);
153    }
154    if (Options::types_defined(*$2.cp)) {
155      char str[80];
156      
157      sprintf(str, "Duplicate type %s, exiting", ($2.cp)->string_of());
158      yyerror(str);
159      exit(0);
160    }
161
162    // FREE ALL MEMORY
163
164    $$.cp = new string(Options::allocate_type(*$2.cp, $1.class_data.b, $1.class_data.abs,
165                                              $3.derived.is_derived,
166                                              *($3.derived.name),
167                                              type_defn::TYPE_COMPLEX, true, false,
168                                              $5.arg_vector, *$6.cp));
169    delete ($2.cp); delete($3.derived.name); delete ($5.arg_vector); delete($6.cp);
170    parsing = 0;
171  }; 
172
173 optDerived: {$$.derived.is_derived = false; $$.derived.name = new string;}
174           | tCOLON tIDENT {$$.derived.is_derived=true; $$.derived.name = $2.cp;};
175
176 fieldDeclList:  { $$.arg_vector = new vector<arg*>; }
177 | fieldDeclList fieldDecl {
178   (*$1.arg_vector)+= $2.args;
179 };
180
181 fieldDecl: optConst typeName pointers tIDENT tSEMI {
182   $$.args = new arg($2.cp, $3.u, $1.b, $4.cp, false);
183   delete($2.cp); delete($4.cp);
184 };
185
186 typeName: tIDENT {
187
188   if (!Options::types_defined(*$1.cp)) {
189     char str[80];
190
191     bool in_lib = false;
192     bool is_forward = false;
193
194     unsigned fsize = Options::forward_decls.size();
195     for (unsigned u=0; u<fsize; u++) 
196       if (Options::forward_decls[u] == *$1.cp) {
197         is_forward = true; break;
198       }
199
200     if (Options::current_interface->are_bundlers_generated()) {
201       if (!is_forward) {
202         sprintf(str, "unknown type %s, exiting", ($1.cp)->string_of());
203         yyerror(str);
204         exit(0);
205       }
206     } else
207       in_lib = true;
208
209     if (!is_forward)
210       $$.cp = new string(Options::allocate_type(*$1.cp, false, false,
211                                                 false, "",
212                                                 type_defn::TYPE_COMPLEX, true, in_lib));
213     else
214       $$.cp = new string(Options::type_prefix() + *$1.cp);
215
216     delete ($1.cp);
217   } else
218     $$.cp = new string(Options::get_type(*$1.cp));
219 } | tIDENT tCOLON tCOLON tIDENT {
220   string tname = *$1.cp + "::" + *$4.cp;
221   if (!Options::types_defined(tname)) {
222     char str[80];
223
224     bool in_lib = false;
225     if (Options::current_interface->are_bundlers_generated()) {
226       sprintf(str, "unknown type %s, exiting", tname.string_of());
227       yyerror(str);
228       exit(0);
229     } else
230       in_lib = true;
231
232     $$.cp = new string(Options::allocate_type(tname, false, false, false, "",
233                                               type_defn::TYPE_COMPLEX, true, in_lib));
234   } else
235     $$.cp = new string(Options::get_type(tname));
236 } | tIDENT tANGLE_L typeName pointers tANGLE_R {
237   char str[80];
238   unsigned stl_index;
239   bool in_lib = false;
240   if (Options::current_interface->are_bundlers_generated()) {
241     bool found = false;
242     for (stl_index=0; stl_index<Options::stl_types.size(); stl_index++)
243       if (Options::stl_types[stl_index].name == *$1.cp) {
244         found = true;
245         break;
246       }
247     if (!found) {
248       sprintf(str, "unknown type %s, exiting", ($1.cp)->string_of());
249       yyerror(str);
250       exit(0);
251     }
252   }
253   Options::el_data el_data;
254   el_data.type = *$3.cp; el_data.stars = $4.u;
255   el_data.name = el_data.type + Options::make_ptrs($4.u);
256
257   in_lib = false;
258   if (Options::current_interface->are_bundlers_generated()) {
259     bool element_found = false;
260     for (unsigned z=0; z<Options::stl_types[stl_index].elements.size(); z++) {
261       if (Options::stl_types[stl_index].elements[z].name == el_data.name)
262         element_found = true;
263     }
264     if (!element_found)
265       Options::stl_types[stl_index].elements += el_data;
266   } else
267     in_lib = true;
268
269   string tname = string(*$1.cp) + "<" + el_data.name + ">";
270   Options::stl_seen = true;
271   if (!Options::types_defined(tname)) {
272     $$.cp = new string(Options::allocate_stl_type(*$1.cp, *$3.cp, $4.u, in_lib));
273     delete ($1.cp); delete ($3.cp);
274   } else
275     $$.cp = new string(tname);
276 };
277
278 optConst:  { $$.b = false; }
279         |  tCONST { $$.b = true;};
280
281 pointers:                { $$.u = 0; }
282         | tSTAR pointers { $$.u = $2.u + 1; };
283
284 // when is it ok to use pointers?
285 // if thread code is generated, it is always ok
286 // if xdr/pvm code is generated, pointers can be used for:
287 //       structs
288 //       classes
289 // ...but only 1 level of indirection
290 //
291
292 funcArg: optConst typeName pointers {
293             $$.args = new arg($2.cp, $3.u, $1.b, NULL, false);
294             delete ($2.cp);
295           } | optConst typeName pointers tIDENT {
296             // this may exit
297             $$.args = new arg($2.cp, $3.u, $1.b, $4.cp, false);
298             delete ($2.cp); delete($4.cp);
299           } | optConst typeName tREF tIDENT {
300             $$.args = new arg($2.cp, 0, $1.b, $4.cp, true);
301             delete ($2.cp); delete ($4.cp);
302           } | optConst typeName tREF {
303             $$.args = new arg($2.cp, 0, $1.b, NULL, true);
304             delete ($2.cp);
305           };
306
307 nonEmptyArg: funcArg {    
308   $$.arg_vector = new vector<arg*>;
309   (*$$.arg_vector)+= $1.args;
310 }
311 | nonEmptyArg tCOMMA funcArg {
312   (*$1.arg_vector)+= $3.args;
313 };
314
315 arglist:                { $$.arg_vector = new vector<arg*>; }
316 | nonEmptyArg   {
317   $$.arg_vector = $1.arg_vector;
318 };