New igen features: error checking, synchronous upcalls.
[dyninst.git] / igen / src / parser.y
1 %{
2 #include <string.h>
3 extern int generatePVM;
4 extern int generateXDR;
5 #include "parse.h"
6
7 #define YYSTYPE union parseStack
8
9 int firstTag;
10 extern int yylex();
11 extern int emitHeader;
12 extern int generateTHREAD;
13 extern char *serverTypeName;
14 extern void *yyerror(char*);
15 extern List <typeDefn *> types;
16 extern typeDefn *foundType;
17 extern interfaceSpec *currentInterface;
18 %}
19
20 %token tIDENT tCOMMA tARRAY tSTAR tNAME tBASE tINT tUPCALL tASYNC
21 %token tLPAREN tRPAREN tSEMI tLBLOCK tRBLOCK tCMEMBER tSMEMBER
22 %token tTYPEDEF tSTRUCT tVERSION tVIRTUAL
23 %%
24
25 completeDefinition: parsableUnitList ;
26
27 parsableUnitList: 
28                 | parsableUnit { extern int parsing; parsing = 0; }parsableUnitList;
29
30 parsableUnit: interfaceSpec 
31             | typeSpec;
32
33 interfacePreamble: interfaceName tLBLOCK interfaceBase interfaceVersion {
34     interfaceSpec *is;
35
36     is = new interfaceSpec($1.cp, $4.i, $3.i);
37     currentInterface = $$.spec = is;
38
39
40 interfaceSpec: interfacePreamble definitionList tRBLOCK tSEMI {
41     $1.spec->genClass();
42 }
43
44 interfaceName: tIDENT { $$.cp = $1.cp; };
45
46 interfaceBase: tBASE tINT tSEMI { $$.i = $2.i; };
47
48 interfaceVersion: tVERSION tINT tSEMI { $$.i = $2.i; };
49
50 definitionList:
51               | definitionList definition
52               ;
53
54 optUpcall:
55                         { $$.fd.uc = syncCall; $$.fd.virtual_f = 0; }
56              | tVIRTUAL { $$.fd.uc = asyncCall; $$.fd.virtual_f = 1;}
57              | tASYNC    { $$.fd.uc = asyncCall; $$.fd.virtual_f = 0;}
58              | tVIRTUAL tASYNC { $$.fd.uc = asyncCall; $$.fd.virtual_f = 1;}
59              | tUPCALL { $$.fd.uc = syncUpcall; $$.fd.virtual_f = 0; }
60              | tVIRTUAL tUPCALL {$$.fd.uc = syncUpcall; $$.fd.virtual_f = 1; }
61              | tUPCALL tASYNC { $$.fd.uc = asyncUpcall; $$.fd.virtual_f = 0;}
62              | tVIRTUAL tUPCALL tASYNC { $$.fd.uc = asyncUpcall; $$.fd.virtual_f = 1;}
63
64 definition: optUpcall typeName pointers tIDENT tLPAREN arglist tRPAREN tSEMI {
65         char *retType;
66         remoteFunc *tf;
67         List <char *> cl;
68         List <argument *> lp, args;
69
70         /* reverse arg list */
71         for (lp = *$6.args; *lp; lp++) {
72             args.add(*lp);
73         }
74
75         retType = (char *) 
76           malloc(strlen($2.td.cp) + 1 + ($3.cl ? $3.cl->count() : 0));
77         strcpy(retType, $2.cp);
78
79         for (cl = *$3.cl; *cl; cl++) strcat(retType, "*");
80
81         tf = new remoteFunc(currentInterface, $3.cl, $4.cp, retType, 
82             args, $1.fd.uc, $1.fd.virtual_f, $2.td.structs);
83         currentInterface->newMethod(tf);
84
85         if (emitHeader) {
86             tf->genHeader();
87         }
88       }
89          | tCMEMBER tIDENT pointers tIDENT tSEMI {
90            addCMember ($2.cp, $4.cp, $3.cl); }
91          |  tSMEMBER typeName pointers tIDENT tSEMI {
92            addSMember ($2.cp, $4.cp, $3.cl);}
93
94
95 typeSpec: tTYPEDEF tSTRUCT tLBLOCK fieldDeclList tRBLOCK tIDENT tSEMI {
96            typeDefn *s;
97            List<field *> lp, fields;
98
99            /* reverse field list */
100            for (lp = *$4.fields; *lp; lp++) {
101                 fields.add(*lp);
102            }
103            s = new typeDefn($6.cp, fields);
104            s->genHeader();
105        }
106    ;
107
108 fieldDeclList:  { $$.fields = new List<field*>; }
109         | fieldDeclList fieldDecl { $1.fields->add($2.fld); }
110         ;
111
112 // note - $$.td.mallocs will not have any effect for thread code
113 // td.mallocs -> type will malloc memory
114 // td.struct -> type is a struct
115 typeName: tIDENT {
116                 if (!(foundType = types.find($1.cp)) && !generateTHREAD) {
117                     char str[80];
118                     sprintf(str, "unknown type %s", $1.cp);
119                     yyerror(str);
120                 }
121                 $$.td.cp = $1.cp;
122                 $$.td.structs = 0;
123                 $$.td.mallocs = 0;
124                 if (generateTHREAD || (!strcmp("String", $1.cp)))
125                   $$.td.mallocs = 1;
126                 else if (foundType->userDefined == TRUE)
127                   {
128                     $$.td.mallocs = 1;
129                     $$.td.structs = 1;
130                   }
131         }
132         | tARRAY tIDENT {
133                 extern char *findAndAddArrayType(char*);
134
135                 if (!types.find($2.cp) && !generateTHREAD) {
136                     char str[80];
137                     sprintf(str, "unknown type %s", $2.cp);
138                     yyerror(str);
139                 }
140                 $$.td.cp = findAndAddArrayType($2.cp);
141                 $$.td.mallocs = 1;
142                 $$.td.structs = 1;
143         }
144         ;
145
146 fieldDecl: typeName tIDENT tSEMI { 
147                 $$.fld = new field($1.td.cp, $2.cp);
148          }
149          ;
150
151 pointers:                { $$.cl = new List<char*>; }
152         | pointers tSTAR { $1.cl->add("*"); $$.cl = $1.cl; }
153         ;
154
155 argument: typeName pointers tIDENT {
156             $$.arg = new argument($1.td.cp, $3.cp, $2.cl, $1.td.mallocs);
157         }
158         | typeName pointers {
159             $$.arg = new argument($1.td.cp,currentInterface->genVariable(), $2.cl, $1.td.mallocs);
160         }
161         ;
162
163 nonEmptyArg: argument   {    
164                 $$.args = new(List<argument*>);
165                 $$.args->add($1.arg);
166             }
167            | nonEmptyArg tCOMMA argument {
168                $1.args->add($3.arg);
169            }
170            ;
171
172 arglist:                { $$.args = new(List<argument*>); }
173        | nonEmptyArg    { $$.args = $1.args; }
174        ;