Fix subclassing to support nested messages.
[wine] / tools / widl / parser.y
1 %{
2 /*
3  * IDL Compiler
4  *
5  * Copyright 2002 Ove Kaaven
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
30 #ifdef HAVE_ALLOCA_H
31 #include <alloca.h>
32 #endif
33
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38 #include "proxy.h"
39 #include "typelib.h"
40
41 #if defined(YYBYACC)
42         /* Berkeley yacc (byacc) doesn't seem to know about these */
43         /* Some *BSD supplied versions do define these though */
44 # ifndef YYEMPTY
45 #  define YYEMPTY       (-1)    /* Empty lookahead value of yychar */
46 # endif
47 # ifndef YYLEX
48 #  define YYLEX         yylex()
49 # endif
50
51 #elif defined(YYBISON)
52         /* Bison was used for original development */
53         /* #define YYEMPTY -2 */
54         /* #define YYLEX   yylex() */
55
56 #else
57         /* No yacc we know yet */
58 # if !defined(YYEMPTY) || !defined(YYLEX)
59 #  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
60 # elif defined(__GNUC__)        /* gcc defines the #warning directive */
61 #  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
62   /* #else we just take a chance that it works... */
63 # endif
64 #endif
65
66 static attr_t *make_attr(enum attr_type type);
67 static attr_t *make_attrv(enum attr_type type, DWORD val);
68 static attr_t *make_attrp(enum attr_type type, void *val);
69 static expr_t *make_expr(enum expr_type type);
70 static expr_t *make_exprl(enum expr_type type, long val);
71 static expr_t *make_exprs(enum expr_type type, char *val);
72 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr);
73 static expr_t *make_expr1(enum expr_type type, expr_t *expr);
74 static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
75 static type_t *make_type(BYTE type, type_t *ref);
76 static typeref_t *make_tref(char *name, type_t *ref);
77 static typeref_t *uniq_tref(typeref_t *ref);
78 static type_t *type_ref(typeref_t *ref);
79 static void set_type(var_t *v, typeref_t *ref, expr_t *arr);
80 static ifref_t *make_ifref(type_t *iface);
81 static var_t *make_var(char *name);
82 static func_t *make_func(var_t *def, var_t *args);
83 static class_t *make_class(char *name);
84
85 static type_t *reg_type(type_t *type, char *name, int t);
86 static type_t *reg_types(type_t *type, var_t *names, int t);
87 static type_t *find_type(char *name, int t);
88 static type_t *find_type2(char *name, int t);
89 static type_t *get_type(BYTE type, char *name, int t);
90 static type_t *get_typev(BYTE type, var_t *name, int t);
91
92 static var_t *reg_const(var_t *var);
93 static var_t *find_const(char *name, int f);
94
95 #define tsENUM   1
96 #define tsSTRUCT 2
97 #define tsUNION  3
98
99 static type_t std_bool = { "boolean" };
100 static type_t std_int = { "int" };
101 static type_t std_int64 = { "__int64" };
102 static type_t std_uhyper = { "MIDL_uhyper" };
103
104 %}
105 %union {
106         attr_t *attr;
107         expr_t *expr;
108         type_t *type;
109         typeref_t *tref;
110         var_t *var;
111         func_t *func;
112         ifref_t *ifref;
113         class_t *clas;
114         char *str;
115         UUID *uuid;
116         unsigned int num;
117 }
118
119 %token <str> aIDENTIFIER
120 %token <str> aKNOWNTYPE
121 %token <num> aNUM aHEXNUM
122 %token <str> aSTRING
123 %token <uuid> aUUID
124 %token aEOF
125 %token SHL SHR
126 %token tAGGREGATABLE tALLOCATE tAPPOBJECT tARRAYS tASYNC tASYNCUUID
127 %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
128 %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
129 %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
130 %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
131 %token tDEFAULT
132 %token tDISPINTERFACE
133 %token tDLLNAME tDOUBLE tDUAL
134 %token tENTRY tENUM tERRORSTATUST
135 %token tEXTERN
136 %token tFLOAT
137 %token tHANDLET
138 %token tHELPSTRING
139 %token tHYPER tID tIDEMPOTENT
140 %token tIIDIS
141 %token tIMPORT tIMPORTLIB
142 %token tIN tINCLUDE tINLINE
143 %token tINPUTSYNC
144 %token tINT tINT64
145 %token tINTERFACE
146 %token tLENGTHIS tLIBRARY
147 %token tLOCAL
148 %token tLONG
149 %token tMETHODS
150 %token tMODULE
151 %token tOBJECT tODL tOLEAUTOMATION
152 %token tOUT
153 %token tPOINTERDEFAULT
154 %token tPROPERTIES
155 %token tPUBLIC
156 %token tREADONLY tREF
157 %token tRETVAL
158 %token tSHORT
159 %token tSIGNED
160 %token tSIZEIS tSIZEOF
161 %token tSOURCE
162 %token tSTDCALL
163 %token tSTRING tSTRUCT
164 %token tSWITCH tSWITCHIS tSWITCHTYPE
165 %token tTYPEDEF
166 %token tUNION
167 %token tUNIQUE
168 %token tUNSIGNED
169 %token tUUID
170 %token tV1ENUM
171 %token tVERSION
172 %token tVOID
173 %token tWCHAR tWIREMARSHAL
174
175 /* used in attr_t */
176 %token tPOINTERTYPE
177
178 %type <attr> m_attributes attributes attrib_list attribute
179 %type <expr> m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const
180 %type <expr> array array_list
181 %type <type> inherit interface interfacehdr interfacedef interfacedec
182 %type <type> dispinterface dispinterfacehdr dispinterfacedef
183 %type <type> module modulehdr moduledef
184 %type <type> base_type int_std
185 %type <type> enumdef structdef typedef uniondef
186 %type <ifref> gbl_statements coclass_ints coclass_int
187 %type <tref> type
188 %type <var> m_args no_args args arg
189 %type <var> fields field s_field cases case enums enum_list enum constdef externdef
190 %type <var> m_ident t_ident ident p_ident pident pident_list
191 %type <var> dispint_props
192 %type <func> funcdef int_statements
193 %type <func> dispint_meths
194 %type <clas> coclass coclasshdr coclassdef
195 %type <num> pointer_type version
196 %type <str> libraryhdr
197
198 %left ','
199 %left '|'
200 %left '&'
201 %left '-' '+'
202 %left '*' '/'
203 %left SHL SHR
204 %right '~'
205 %right CAST
206 %right PPTR
207 %right NEG
208
209 %%
210
211 input:    gbl_statements                        { write_proxies($1); }
212         ;
213
214 gbl_statements:                                 { $$ = NULL; }
215         | gbl_statements interfacedec           { $$ = $1; }
216         | gbl_statements interfacedef           { $$ = make_ifref($2); LINK($$, $1); }
217         | gbl_statements coclassdef             { $$ = $1; add_coclass($2); }
218         | gbl_statements moduledef              { $$ = $1; add_module($2); }
219         | gbl_statements librarydef             { $$ = $1; }
220         | gbl_statements statement              { $$ = $1; }
221         ;
222
223 imp_statements:                                 {}
224         | imp_statements interfacedec           { if (!parse_only) add_interface($2); }
225         | imp_statements interfacedef           { if (!parse_only) add_interface($2); }
226         | imp_statements coclassdef             { if (!parse_only) add_coclass($2); }
227         | imp_statements moduledef              { if (!parse_only) add_module($2); }
228         | imp_statements statement              {}
229         ;
230
231 int_statements:                                 { $$ = NULL; }
232         | int_statements funcdef ';'            { $$ = $2; LINK($$, $1); }
233         | int_statements statement              { $$ = $1; }
234         ;
235
236 statement: ';'                                  {}
237         | constdef ';'                          { if (!parse_only) { write_constdef($1); } }
238         | cppquote                              {}
239         | enumdef ';'                           { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
240         | externdef ';'                         { if (!parse_only) { write_externdef($1); } }
241         | import                                {}
242         | structdef ';'                         { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
243         | typedef ';'                           {}
244         | uniondef ';'                          { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
245         ;
246
247 cppquote: tCPPQUOTE '(' aSTRING ')'             { if (!parse_only) fprintf(header, "%s\n", $3); }
248         ;
249 import_start: tIMPORT aSTRING ';'               { assert(yychar == YYEMPTY);
250                                                   if (!do_import($2)) yychar = aEOF; }
251         ;
252 import:   import_start imp_statements aEOF      {}
253         ;
254
255 libraryhdr: tLIBRARY aIDENTIFIER                { $$ = $2; }
256         ;
257 library_start: attributes libraryhdr '{'        { start_typelib($2, $1); }
258         ;
259 librarydef: library_start imp_statements '}'    { end_typelib(); }
260         ;
261
262 m_args:                                         { $$ = NULL; }
263         | args
264         ;
265
266 no_args:  tVOID                                 { $$ = NULL; }
267         ;
268
269 args:     arg
270         | args ',' arg                          { LINK($3, $1); $$ = $3; }
271         | no_args
272         ;
273
274 /* split into two rules to get bison to resolve a tVOID conflict */
275 arg:      attributes type pident array          { $$ = $3;
276                                                   set_type($$, $2, $4);
277                                                   $$->attrs = $1;
278                                                 }
279         | type pident array                     { $$ = $2;
280                                                   set_type($$, $1, $3);
281                                                 }
282         | attributes type pident '(' m_args ')' { $$ = $3;
283                                                   $$->ptr_level--;
284                                                   set_type($$, $2, NULL);
285                                                   $$->attrs = $1;
286                                                   $$->args = $5;
287                                                 }
288         | type pident '(' m_args ')'            { $$ = $2;
289                                                   $$->ptr_level--;
290                                                   set_type($$, $1, NULL);
291                                                   $$->args = $4;
292                                                 }
293         ;
294
295 array:                                          { $$ = NULL; }
296         | '[' array_list ']'                    { $$ = $2; }
297         | '[' '*' ']'                           { $$ = make_expr(EXPR_VOID); }
298         ;
299
300 array_list: m_expr /* size of first dimension is optional */
301         | array_list ',' expr                   { LINK($3, $1); $$ = $3; }
302         | array_list ']' '[' expr               { LINK($4, $1); $$ = $4; }
303         ;
304
305 m_attributes:                                   { $$ = NULL; }
306         | attributes
307         ;
308
309 attributes:
310           '[' attrib_list ']'                   { $$ = $2; }
311         ;
312
313 attrib_list: attribute
314         | attrib_list ',' attribute             { LINK($3, $1); $$ = $3; }
315         | attrib_list ']' '[' attribute         { LINK($4, $1); $$ = $4; }
316         ;
317
318 attribute:
319           tASYNC                                { $$ = make_attr(ATTR_ASYNC); }
320         | tCALLAS '(' ident ')'                 { $$ = make_attrp(ATTR_CALLAS, $3); }
321         | tCASE '(' expr_list_const ')'         { $$ = make_attrp(ATTR_CASE, $3); }
322         | tCONTEXTHANDLE                        { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
323         | tCONTEXTHANDLENOSERIALIZE             { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
324         | tCONTEXTHANDLESERIALIZE               { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
325         | tDEFAULT                              { $$ = make_attr(ATTR_DEFAULT); }
326         | tDLLNAME '(' aSTRING ')'              { $$ = make_attrp(ATTR_DLLNAME, $3); }
327         | tDUAL                                 { $$ = make_attr(ATTR_DUAL); }
328         | tENTRY '(' aSTRING ')'                { $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
329         | tENTRY '(' expr_const ')'             { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
330         | tHELPSTRING '(' aSTRING ')'           { $$ = make_attrp(ATTR_HELPSTRING, $3); }
331         | tID '(' expr_const ')'                { $$ = make_attrp(ATTR_ID, $3); }
332         | tIDEMPOTENT                           { $$ = make_attr(ATTR_IDEMPOTENT); }
333         | tIIDIS '(' ident ')'                  { $$ = make_attrp(ATTR_IIDIS, $3); }
334         | tIN                                   { $$ = make_attr(ATTR_IN); }
335         | tINPUTSYNC                            { $$ = make_attr(ATTR_INPUTSYNC); }
336         | tLENGTHIS '(' m_exprs ')'             { $$ = make_attrp(ATTR_LENGTHIS, $3); }
337         | tLOCAL                                { $$ = make_attr(ATTR_LOCAL); }
338         | tOBJECT                               { $$ = make_attr(ATTR_OBJECT); }
339         | tODL                                  { $$ = make_attr(ATTR_ODL); }
340         | tOLEAUTOMATION                        { $$ = make_attr(ATTR_OLEAUTOMATION); }
341         | tOUT                                  { $$ = make_attr(ATTR_OUT); }
342         | tPOINTERDEFAULT '(' pointer_type ')'  { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
343         | tPUBLIC                               { $$ = make_attr(ATTR_PUBLIC); }
344         | tREADONLY                             { $$ = make_attr(ATTR_READONLY); }
345         | tRETVAL                               { $$ = make_attr(ATTR_RETVAL); }
346         | tSIZEIS '(' m_exprs ')'               { $$ = make_attrp(ATTR_SIZEIS, $3); }
347         | tSOURCE                               { $$ = make_attr(ATTR_SOURCE); }
348         | tSTRING                               { $$ = make_attr(ATTR_STRING); }
349         | tSWITCHIS '(' expr ')'                { $$ = make_attrp(ATTR_SWITCHIS, $3); }
350         | tSWITCHTYPE '(' type ')'              { $$ = make_attrp(ATTR_SWITCHTYPE, type_ref($3)); }
351         | tUUID '(' aUUID ')'                   { $$ = make_attrp(ATTR_UUID, $3); }
352         | tV1ENUM                               { $$ = make_attr(ATTR_V1ENUM); }
353         | tVERSION '(' version ')'              { $$ = make_attrv(ATTR_VERSION, $3); }
354         | tWIREMARSHAL '(' type ')'             { $$ = make_attrp(ATTR_WIREMARSHAL, type_ref($3)); }
355         | pointer_type                          { $$ = make_attrv(ATTR_POINTERTYPE, $1); }
356         ;
357
358 callconv:
359         | tSTDCALL
360         ;
361
362 cases:                                          { $$ = NULL; }
363         | cases case                            { if ($2) { LINK($2, $1); $$ = $2; }
364                                                   else { $$ = $1; }
365                                                 }
366         ;
367
368 case:     tCASE expr ':' field                  { attr_t *a = make_attrp(ATTR_CASE, $2);
369                                                   $$ = $4; if (!$$) $$ = make_var(NULL);
370                                                   LINK(a, $$->attrs); $$->attrs = a;
371                                                 }
372         | tDEFAULT ':' field                    { attr_t *a = make_attr(ATTR_DEFAULT);
373                                                   $$ = $3; if (!$$) $$ = make_var(NULL);
374                                                   LINK(a, $$->attrs); $$->attrs = a;
375                                                 }
376         ;
377
378 constdef: tCONST type ident '=' expr_const      { $$ = reg_const($3);
379                                                   set_type($$, $2, NULL);
380                                                   $$->eval = $5;
381                                                   $$->lval = $5->cval;
382                                                 }
383         ;
384
385 enums:                                          { $$ = NULL; }
386         | enum_list ','                         { $$ = $1; }
387         | enum_list
388         ;
389
390 enum_list: enum
391         | enum_list ',' enum                    { LINK($3, $1); $$ = $3;
392                                                   if ($1 && !$3->eval)
393                                                     $3->lval = $1->lval + 1;
394                                                 }
395         ;
396
397 enum:     ident '=' expr_const                  { $$ = reg_const($1);
398                                                   $$->eval = $3;
399                                                   $$->lval = $3->cval;
400                                                 }
401         | ident                                 { $$ = reg_const($1);
402                                                   $$->lval = 0; /* default for first enum entry */
403                                                 }
404         ;
405
406 enumdef: tENUM t_ident '{' enums '}'            { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
407                                                   $$->fields = $4;
408                                                   $$->defined = TRUE;
409                                                 }
410         ;
411
412 m_exprs:  m_expr
413         | m_exprs ',' m_expr                    { LINK($3, $1); $$ = $3; }
414         ;
415
416 /*
417 exprs:                                          { $$ = make_expr(EXPR_VOID); }
418         | expr_list
419         ;
420
421 expr_list: expr
422         | expr_list ',' expr                    { LINK($3, $1); $$ = $3; }
423         ;
424 */
425
426 m_expr:                                         { $$ = make_expr(EXPR_VOID); }
427         | expr
428         ;
429
430 expr:     aNUM                                  { $$ = make_exprl(EXPR_NUM, $1); }
431         | aHEXNUM                               { $$ = make_exprl(EXPR_HEXNUM, $1); }
432         | aIDENTIFIER                           { $$ = make_exprs(EXPR_IDENTIFIER, $1); }
433         | expr '|' expr                         { $$ = make_expr2(EXPR_OR , $1, $3); }
434         | expr '&' expr                         { $$ = make_expr2(EXPR_AND, $1, $3); }
435         | expr '+' expr                         { $$ = make_expr2(EXPR_ADD, $1, $3); }
436         | expr '-' expr                         { $$ = make_expr2(EXPR_SUB, $1, $3); }
437         | expr '*' expr                         { $$ = make_expr2(EXPR_MUL, $1, $3); }
438         | expr '/' expr                         { $$ = make_expr2(EXPR_DIV, $1, $3); }
439         | expr SHL expr                         { $$ = make_expr2(EXPR_SHL, $1, $3); }
440         | expr SHR expr                         { $$ = make_expr2(EXPR_SHR, $1, $3); }
441         | '~' expr                              { $$ = make_expr1(EXPR_NOT, $2); }
442         | '-' expr %prec NEG                    { $$ = make_expr1(EXPR_NEG, $2); }
443         | '*' expr %prec PPTR                   { $$ = make_expr1(EXPR_PPTR, $2); }
444         | '(' type ')' expr %prec CAST          { $$ = make_exprt(EXPR_CAST, $2, $4); }
445         | tSIZEOF '(' type ')'                  { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
446         | '(' expr ')'                          { $$ = $2; }
447         ;
448
449 expr_list_const: expr_const
450         | expr_list_const ',' expr_const        { LINK($3, $1); $$ = $3; }
451         ;
452
453 expr_const: expr                                { $$ = $1;
454                                                   if (!$$->is_const) yyerror("expression is not constant\n");
455                                                 }
456         ;
457
458 externdef: tEXTERN tCONST type ident            { $$ = $4;
459                                                   set_type($$, $3, NULL);
460                                                 }
461         ;
462
463 fields:                                         { $$ = NULL; }
464         | fields field                          { if ($2) { LINK($2, $1); $$ = $2; }
465                                                   else { $$ = $1; }
466                                                 }
467         ;
468
469 field:    s_field ';'                           { $$ = $1; }
470         | m_attributes uniondef ';'             { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
471         | attributes ';'                        { $$ = make_var(NULL); $$->attrs = $1; }
472         | ';'                                   { $$ = NULL; }
473         ;
474
475 s_field:  m_attributes type pident array        { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; }
476         ;
477
478 funcdef:
479           m_attributes type callconv pident
480           '(' m_args ')'                        { set_type($4, $2, NULL);
481                                                   $4->attrs = $1;
482                                                   $$ = make_func($4, $6);
483                                                 }
484         ;
485
486 m_ident:                                        { $$ = NULL; }
487         | ident
488         ;
489
490 t_ident:                                        { $$ = NULL; }
491         | aIDENTIFIER                           { $$ = make_var($1); }
492         | aKNOWNTYPE                            { $$ = make_var($1); }
493         ;
494
495 ident:    aIDENTIFIER                           { $$ = make_var($1); }
496 /* some "reserved words" used in attributes are also used as field names in some MS IDL files */
497         | tID                                   { $$ = make_var($<str>1); }
498         | tRETVAL                               { $$ = make_var($<str>1); }
499         | tVERSION                              { $$ = make_var($<str>1); }
500         ;
501
502 base_type: tBYTE                                { $$ = make_type(RPC_FC_BYTE, NULL); }
503         | tWCHAR                                { $$ = make_type(RPC_FC_WCHAR, NULL); }
504         | int_std
505         | tSIGNED int_std                       { $$ = $2; $$->sign = 1; }
506         | tUNSIGNED int_std                     { $$ = $2; $$->sign = -1;
507                                                   switch ($$->type) {
508                                                   case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
509                                                   case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
510                                                   case RPC_FC_LONG:  $$->type = RPC_FC_ULONG;  break;
511                                                   case RPC_FC_HYPER:
512                                                     if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
513                                                     break;
514                                                   default: break;
515                                                   }
516                                                 }
517         | tFLOAT                                { $$ = make_type(RPC_FC_FLOAT, NULL); }
518         | tDOUBLE                               { $$ = make_type(RPC_FC_DOUBLE, NULL); }
519         | tBOOLEAN                              { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
520         | tERRORSTATUST                         { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
521         | tHANDLET                              { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
522         ;
523
524 m_int:
525         | tINT
526         ;
527
528 int_std:  tINT                                  { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
529         | tSHORT m_int                          { $$ = make_type(RPC_FC_SHORT, NULL); }
530         | tLONG m_int                           { $$ = make_type(RPC_FC_LONG, NULL); }
531         | tHYPER m_int                          { $$ = make_type(RPC_FC_HYPER, NULL); }
532         | tINT64                                { $$ = make_type(RPC_FC_HYPER, &std_int64); }
533         | tCHAR                                 { $$ = make_type(RPC_FC_CHAR, NULL); }
534         ;
535
536 coclass:  tCOCLASS aIDENTIFIER                  { $$ = make_class($2); }
537         | tCOCLASS aKNOWNTYPE                   { $$ = make_class($2); }
538         ;
539
540 coclasshdr: attributes coclass                  { $$ = $2;
541                                                   $$->attrs = $1;
542                                                 }
543         ;
544
545 coclassdef: coclasshdr '{' coclass_ints '}'     { $$ = $1;
546                                                   $$->ifaces = $3;
547                                                 }
548         ;
549
550 coclass_ints:                                   { $$ = NULL; }
551         | coclass_ints coclass_int              { LINK($2, $1); $$ = $2; }
552         ;
553
554 coclass_int:
555           m_attributes interfacedec             { $$ = make_ifref($2); $$->attrs = $1; }
556         ;
557
558 dispinterface: tDISPINTERFACE aIDENTIFIER       { $$ = get_type(0, $2, 0); }
559         |      tDISPINTERFACE aKNOWNTYPE        { $$ = get_type(0, $2, 0); }
560         ;
561
562 dispinterfacehdr: attributes dispinterface      { $$ = $2;
563                                                   if ($$->defined) yyerror("multiple definition error\n");
564                                                   $$->attrs = $1;
565                                                 /*  $$->attrs = make_attr(ATTR_DISPINTERFACE); */
566                                                 /*  LINK($$->attrs, $1); */
567                                                   $$->ref = find_type("IDispatch", 0);
568                                                   if (!$$->ref) yyerror("IDispatch is undefined\n");
569                                                   $$->defined = TRUE;
570                                                   if (!parse_only) write_forward($$);
571                                                 }
572         ;
573
574 dispint_props: tPROPERTIES ':'                  { $$ = NULL; }
575         | dispint_props s_field ';'             { LINK($2, $1); $$ = $2; }
576         ;
577
578 dispint_meths: tMETHODS ':'                     { $$ = NULL; }
579         | dispint_meths funcdef ';'             { LINK($2, $1); $$ = $2; }
580         ;
581
582 dispinterfacedef: dispinterfacehdr '{'
583           dispint_props
584           dispint_meths
585           '}'                                   { $$ = $1;
586                                                   $$->fields = $3;
587                                                   $$->funcs = $4;
588                                                   if (!parse_only) write_interface($$);
589                                                 }
590 /* FIXME: not sure how to handle this yet
591         | dispinterfacehdr '{' interface '}'    { $$ = $1;
592                                                   if (!parse_only) write_interface($$);
593                                                 }
594 */
595         ;
596
597 inherit:                                        { $$ = NULL; }
598         | ':' aKNOWNTYPE                        { $$ = find_type2($2, 0); }
599         ;
600
601 interface: tINTERFACE aIDENTIFIER               { $$ = get_type(RPC_FC_IP, $2, 0); }
602         |  tINTERFACE aKNOWNTYPE                { $$ = get_type(RPC_FC_IP, $2, 0); }
603         ;
604
605 interfacehdr: attributes interface              { $$ = $2;
606                                                   if ($$->defined) yyerror("multiple definition error\n");
607                                                   $$->attrs = $1;
608                                                   $$->defined = TRUE;
609                                                   if (!parse_only) write_forward($$);
610                                                 }
611         ;
612
613 interfacedef: interfacehdr inherit
614           '{' int_statements '}'                { $$ = $1;
615                                                   $$->ref = $2;
616                                                   $$->funcs = $4;
617                                                   if (!parse_only) write_interface($$);
618                                                 }
619 /* MIDL is able to import the definition of a base class from inside the
620  * definition of a derived class, I'll try to support it with this rule */
621         | interfacehdr ':' aIDENTIFIER
622           '{' import int_statements '}'         { $$ = $1;
623                                                   $$->ref = find_type2($3, 0);
624                                                   if (!$$->ref) yyerror("base class %s not found in import\n", $3);
625                                                   $$->funcs = $6;
626                                                   if (!parse_only) write_interface($$);
627                                                 }
628         | dispinterfacedef                      { $$ = $1; }
629         ;
630
631 interfacedec:
632           interface ';'                         { $$ = $1; if (!parse_only) write_forward($$); }
633         | dispinterface ';'                     { $$ = $1; if (!parse_only) write_forward($$); }
634         ;
635
636 module:   tMODULE aIDENTIFIER                   { $$ = make_type(0, NULL); $$->name = $2; }
637         | tMODULE aKNOWNTYPE                    { $$ = make_type(0, NULL); $$->name = $2; }
638         ;
639
640 modulehdr: attributes module                    { $$ = $2;
641                                                   $$->attrs = $1;
642                                                 }
643         ;
644
645 moduledef: modulehdr '{' int_statements '}'     { $$ = $1;
646                                                   $$->funcs = $3;
647                                                   /* FIXME: if (!parse_only) write_module($$); */
648                                                 }
649         ;
650
651 p_ident:  '*' pident %prec PPTR                 { $$ = $2; $$->ptr_level++; }
652         | tCONST p_ident                        { $$ = $2; /* FIXME */ }
653         ;
654
655 pident:   ident
656         | p_ident
657         | '(' pident ')'                        { $$ = $2; }
658         ;
659
660 pident_list:
661           pident
662         | pident_list ',' pident                { LINK($3, $1); $$ = $3; }
663         ;
664
665 pointer_type:
666           tREF                                  { $$ = RPC_FC_RP; }
667         | tUNIQUE                               { $$ = RPC_FC_UP; }
668         ;
669
670 structdef: tSTRUCT t_ident '{' fields '}'       { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
671                                                   $$->fields = $4;
672                                                   $$->defined = TRUE;
673                                                 }
674         ;
675
676 type:     tVOID                                 { $$ = make_tref(NULL, make_type(0, NULL)); }
677         | aKNOWNTYPE                            { $$ = make_tref($1, find_type($1, 0)); }
678         | base_type                             { $$ = make_tref(NULL, $1); }
679         | tCONST type                           { $$ = uniq_tref($2); $$->ref->is_const = TRUE; }
680         | enumdef                               { $$ = make_tref(NULL, $1); }
681         | tENUM aIDENTIFIER                     { $$ = make_tref(NULL, find_type2($2, tsENUM)); }
682         | structdef                             { $$ = make_tref(NULL, $1); }
683         | tSTRUCT aIDENTIFIER                   { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); }
684         | uniondef                              { $$ = make_tref(NULL, $1); }
685         | tUNION aIDENTIFIER                    { $$ = make_tref(NULL, find_type2($2, tsUNION)); }
686         ;
687
688 typedef: tTYPEDEF m_attributes type pident_list { typeref_t *tref = uniq_tref($3);
689                                                   $4->tname = tref->name;
690                                                   tref->name = NULL;
691                                                   $$ = type_ref(tref);
692                                                   $$->attrs = $2;
693                                                   if (!parse_only) write_typedef($$, $4);
694                                                   reg_types($$, $4, 0);
695                                                 }
696         ;
697
698 uniondef: tUNION t_ident '{' fields '}'         { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
699                                                   $$->fields = $4;
700                                                   $$->defined = TRUE;
701                                                 }
702         | tUNION t_ident
703           tSWITCH '(' s_field ')'
704           m_ident '{' cases '}'                 { var_t *u = $7;
705                                                   $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
706                                                   if (!u) u = make_var("tagged_union");
707                                                   u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
708                                                   u->type->fields = $9;
709                                                   u->type->defined = TRUE;
710                                                   LINK(u, $5); $$->fields = u;
711                                                   $$->defined = TRUE;
712                                                 }
713         ;
714
715 version:
716           aNUM                                  { $$ = MAKELONG($1, 0); }
717         | aNUM '.' aNUM                         { $$ = MAKELONG($1, $3); }
718         ;
719
720 %%
721
722 static attr_t *make_attr(enum attr_type type)
723 {
724   attr_t *a = xmalloc(sizeof(attr_t));
725   a->type = type;
726   a->u.ival = 0;
727   INIT_LINK(a);
728   return a;
729 }
730
731 static attr_t *make_attrv(enum attr_type type, DWORD val)
732 {
733   attr_t *a = xmalloc(sizeof(attr_t));
734   a->type = type;
735   a->u.ival = val;
736   INIT_LINK(a);
737   return a;
738 }
739
740 static attr_t *make_attrp(enum attr_type type, void *val)
741 {
742   attr_t *a = xmalloc(sizeof(attr_t));
743   a->type = type;
744   a->u.pval = val;
745   INIT_LINK(a);
746   return a;
747 }
748
749 static expr_t *make_expr(enum expr_type type)
750 {
751   expr_t *e = xmalloc(sizeof(expr_t));
752   e->type = type;
753   e->ref = NULL;
754   e->u.lval = 0;
755   e->is_const = FALSE;
756   INIT_LINK(e);
757   return e;
758 }
759
760 static expr_t *make_exprl(enum expr_type type, long val)
761 {
762   expr_t *e = xmalloc(sizeof(expr_t));
763   e->type = type;
764   e->ref = NULL;
765   e->u.lval = val;
766   e->is_const = FALSE;
767   INIT_LINK(e);
768   /* check for numeric constant */
769   if (type == EXPR_NUM || type == EXPR_HEXNUM) {
770     e->is_const = TRUE;
771     e->cval = val;
772   }
773   return e;
774 }
775
776 static expr_t *make_exprs(enum expr_type type, char *val)
777 {
778   expr_t *e;
779   e = xmalloc(sizeof(expr_t));
780   e->type = type;
781   e->ref = NULL;
782   e->u.sval = val;
783   e->is_const = FALSE;
784   INIT_LINK(e);
785   /* check for predefined constants */
786   if (type == EXPR_IDENTIFIER) {
787     var_t *c = find_const(val, 0);
788     if (c) {
789       e->u.sval = c->name;
790       free(val);
791       e->is_const = TRUE;
792       e->cval = c->lval;
793     }
794   }
795   return e;
796 }
797
798 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr)
799 {
800   expr_t *e;
801   e = xmalloc(sizeof(expr_t));
802   e->type = type;
803   e->ref = expr;
804   e->u.tref = tref;
805   e->is_const = FALSE;
806   INIT_LINK(e);
807   /* check for cast of constant expression */
808   if (type == EXPR_CAST && expr->is_const) {
809     e->is_const = TRUE;
810     e->cval = expr->cval;
811   }
812   return e;
813 }
814
815 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
816 {
817   expr_t *e;
818   e = xmalloc(sizeof(expr_t));
819   e->type = type;
820   e->ref = expr;
821   e->u.lval = 0;
822   e->is_const = FALSE;
823   INIT_LINK(e);
824   /* check for compile-time optimization */
825   if (expr->is_const) {
826     e->is_const = TRUE;
827     switch (type) {
828     case EXPR_NEG:
829       e->cval = -expr->cval;
830       break;
831     case EXPR_NOT:
832       e->cval = ~expr->cval;
833       break;
834     default:
835       e->is_const = FALSE;
836       break;
837     }
838   }
839   return e;
840 }
841
842 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
843 {
844   expr_t *e;
845   e = xmalloc(sizeof(expr_t));
846   e->type = type;
847   e->ref = expr1;
848   e->u.ext = expr2;
849   e->is_const = FALSE;
850   INIT_LINK(e);
851   /* check for compile-time optimization */
852   if (expr1->is_const && expr2->is_const) {
853     e->is_const = TRUE;
854     switch (type) {
855     case EXPR_ADD:
856       e->cval = expr1->cval + expr2->cval;
857       break;
858     case EXPR_SUB:
859       e->cval = expr1->cval - expr2->cval;
860       break;
861     case EXPR_MUL:
862       e->cval = expr1->cval * expr2->cval;
863       break;
864     case EXPR_DIV:
865       e->cval = expr1->cval / expr2->cval;
866       break;
867     case EXPR_OR:
868       e->cval = expr1->cval | expr2->cval;
869       break;
870     case EXPR_AND:
871       e->cval = expr1->cval & expr2->cval;
872       break;
873     case EXPR_SHL:
874       e->cval = expr1->cval << expr2->cval;
875       break;
876     case EXPR_SHR:
877       e->cval = expr1->cval >> expr2->cval;
878       break;
879     default:
880       e->is_const = FALSE;
881       break;
882     }
883   }
884   return e;
885 }
886
887 static type_t *make_type(BYTE type, type_t *ref)
888 {
889   type_t *t = xmalloc(sizeof(type_t));
890   t->name = NULL;
891   t->type = type;
892   t->ref = ref;
893   t->rname = NULL;
894   t->attrs = NULL;
895   t->funcs = NULL;
896   t->fields = NULL;
897   t->ignore = parse_only;
898   t->is_const = FALSE;
899   t->sign = 0;
900   t->defined = FALSE;
901   t->written = FALSE;
902   INIT_LINK(t);
903   return t;
904 }
905
906 static typeref_t *make_tref(char *name, type_t *ref)
907 {
908   typeref_t *t = xmalloc(sizeof(typeref_t));
909   t->name = name;
910   t->ref = ref;
911   t->uniq = ref ? 0 : 1;
912   return t;
913 }
914
915 static typeref_t *uniq_tref(typeref_t *ref)
916 {
917   typeref_t *t = ref;
918   type_t *tp;
919   if (t->uniq) return t;
920   tp = make_type(0, t->ref);
921   tp->name = t->name;
922   t->name = NULL;
923   t->ref = tp;
924   t->uniq = 1;
925   return t;
926 }
927
928 static type_t *type_ref(typeref_t *ref)
929 {
930   type_t *t = ref->ref;
931   if (ref->name) free(ref->name);
932   free(ref);
933   return t;
934 }
935
936 static void set_type(var_t *v, typeref_t *ref, expr_t *arr)
937 {
938   v->type = ref->ref;
939   v->tname = ref->name;
940   ref->name = NULL;
941   free(ref);
942   v->array = arr;
943 }
944
945 static ifref_t *make_ifref(type_t *iface)
946 {
947   ifref_t *l = xmalloc(sizeof(ifref_t));
948   l->iface = iface;
949   l->attrs = NULL;
950   INIT_LINK(l);
951   return l;
952 }
953
954 static var_t *make_var(char *name)
955 {
956   var_t *v = xmalloc(sizeof(var_t));
957   v->name = name;
958   v->ptr_level = 0;
959   v->type = NULL;
960   v->tname = NULL;
961   v->attrs = NULL;
962   v->array = NULL;
963   v->eval = NULL;
964   v->lval = 0;
965   INIT_LINK(v);
966   return v;
967 }
968
969 static func_t *make_func(var_t *def, var_t *args)
970 {
971   func_t *f = xmalloc(sizeof(func_t));
972   f->def = def;
973   f->args = args;
974   f->ignore = parse_only;
975   f->idx = -1;
976   INIT_LINK(f);
977   return f;
978 }
979
980 static class_t *make_class(char *name)
981 {
982   class_t *c = xmalloc(sizeof(class_t));
983   c->name = name;
984   c->attrs = NULL;
985   c->ifaces = NULL;
986   INIT_LINK(c);
987   return c;
988 }
989
990 #define HASHMAX 64
991
992 static int hash_ident(const char *name)
993 {
994   const char *p = name;
995   int sum = 0;
996   /* a simple sum hash is probably good enough */
997   while (*p) {
998     sum += *p;
999     p++;
1000   }
1001   return sum & (HASHMAX-1);
1002 }
1003
1004 /***** type repository *****/
1005
1006 struct rtype {
1007   char *name;
1008   type_t *type;
1009   int t;
1010   struct rtype *next;
1011 };
1012
1013 struct rtype *type_hash[HASHMAX];
1014
1015 static type_t *reg_type(type_t *type, char *name, int t)
1016 {
1017   struct rtype *nt;
1018   int hash;
1019   if (!name) {
1020     yyerror("registering named type without name\n");
1021     return type;
1022   }
1023   hash = hash_ident(name);
1024   nt = xmalloc(sizeof(struct rtype));
1025   nt->name = name;
1026   nt->type = type;
1027   nt->t = t;
1028   nt->next = type_hash[hash];
1029   type_hash[hash] = nt;
1030   return type;
1031 }
1032
1033 static type_t *reg_types(type_t *type, var_t *names, int t)
1034 {
1035   type_t *ptr = type;
1036   int ptrc = 0;
1037
1038   while (names) {
1039     var_t *next = NEXT_LINK(names);
1040     if (names->name) {
1041       type_t *cur = ptr;
1042       int cptr = names->ptr_level;
1043       if (cptr > ptrc) {
1044         while (cptr > ptrc) {
1045           cur = ptr = make_type(RPC_FC_FP, cur); /* FIXME: pointer type from attrs? */
1046           ptrc++;
1047         }
1048       } else {
1049         while (cptr < ptrc) {
1050           cur = cur->ref;
1051           cptr++;
1052         }
1053       }
1054       reg_type(cur, names->name, t);
1055     }
1056     free(names);
1057     names = next;
1058   }
1059   return type;
1060 }
1061
1062 static type_t *find_type(char *name, int t)
1063 {
1064   struct rtype *cur = type_hash[hash_ident(name)];
1065   while (cur && (cur->t != t || strcmp(cur->name, name)))
1066     cur = cur->next;
1067   if (!cur) {
1068     yyerror("type %s not found\n", name);
1069     return NULL;
1070   }
1071   return cur->type;
1072 }
1073
1074 static type_t *find_type2(char *name, int t)
1075 {
1076   type_t *tp = find_type(name, t);
1077   free(name);
1078   return tp;
1079 }
1080
1081 int is_type(const char *name)
1082 {
1083   struct rtype *cur = type_hash[hash_ident(name)];
1084   while (cur && (cur->t || strcmp(cur->name, name)))
1085     cur = cur->next;
1086   if (cur) return TRUE;
1087   return FALSE;
1088 }
1089
1090 static type_t *get_type(BYTE type, char *name, int t)
1091 {
1092   struct rtype *cur = NULL;
1093   type_t *tp;
1094   if (name) {
1095     cur = type_hash[hash_ident(name)];
1096     while (cur && (cur->t != t || strcmp(cur->name, name)))
1097       cur = cur->next;
1098   }
1099   if (cur) {
1100     free(name);
1101     return cur->type;
1102   }
1103   tp = make_type(type, NULL);
1104   tp->name = name;
1105   if (!name) return tp;
1106   return reg_type(tp, name, t);
1107 }
1108
1109 static type_t *get_typev(BYTE type, var_t *name, int t)
1110 {
1111   char *sname = NULL;
1112   if (name) {
1113     sname = name->name;
1114     free(name);
1115   }
1116   return get_type(type, sname, t);
1117 }
1118
1119 /***** constant repository *****/
1120
1121 struct rconst {
1122   char *name;
1123   var_t *var;
1124   struct rconst *next;
1125 };
1126
1127 struct rconst *const_hash[HASHMAX];
1128
1129 static var_t *reg_const(var_t *var)
1130 {
1131   struct rconst *nc;
1132   int hash;
1133   if (!var->name) {
1134     yyerror("registering constant without name\n");
1135     return var;
1136   }
1137   hash = hash_ident(var->name);
1138   nc = xmalloc(sizeof(struct rconst));
1139   nc->name = var->name;
1140   nc->var = var;
1141   nc->next = const_hash[hash];
1142   const_hash[hash] = nc;
1143   return var;
1144 }
1145
1146 static var_t *find_const(char *name, int f)
1147 {
1148   struct rconst *cur = const_hash[hash_ident(name)];
1149   while (cur && strcmp(cur->name, name))
1150     cur = cur->next;
1151   if (!cur) {
1152     if (f) yyerror("constant %s not found\n", name);
1153     return NULL;
1154   }
1155   return cur->var;
1156 }