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