widl: Allow trailing commas in attribute lists.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "windef.h"
35
36 #include "widl.h"
37 #include "utils.h"
38 #include "parser.h"
39 #include "header.h"
40 #include "typelib.h"
41
42 #if defined(YYBYACC)
43         /* Berkeley yacc (byacc) doesn't seem to know about these */
44         /* Some *BSD supplied versions do define these though */
45 # ifndef YYEMPTY
46 #  define YYEMPTY       (-1)    /* Empty lookahead value of yychar */
47 # endif
48 # ifndef YYLEX
49 #  define YYLEX         yylex()
50 # endif
51
52 #elif defined(YYBISON)
53         /* Bison was used for original development */
54         /* #define YYEMPTY -2 */
55         /* #define YYLEX   yylex() */
56
57 #else
58         /* No yacc we know yet */
59 # if !defined(YYEMPTY) || !defined(YYLEX)
60 #  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
61 # elif defined(__GNUC__)        /* gcc defines the #warning directive */
62 #  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
63   /* #else we just take a chance that it works... */
64 # endif
65 #endif
66
67 static attr_t *make_attr(enum attr_type type);
68 static attr_t *make_attrv(enum attr_type type, unsigned long val);
69 static attr_t *make_attrp(enum attr_type type, void *val);
70 static expr_t *make_expr(enum expr_type type);
71 static expr_t *make_exprl(enum expr_type type, long val);
72 static expr_t *make_exprs(enum expr_type type, char *val);
73 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr);
74 static expr_t *make_expr1(enum expr_type type, expr_t *expr);
75 static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
76 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3);
77 static type_t *make_type(unsigned char type, type_t *ref);
78 static typeref_t *make_tref(char *name, type_t *ref);
79 static typeref_t *uniq_tref(typeref_t *ref);
80 static type_t *type_ref(typeref_t *ref);
81 static void set_type(var_t *v, typeref_t *ref, expr_t *arr);
82 static ifref_t *make_ifref(type_t *iface);
83 static var_t *make_var(char *name);
84 static func_t *make_func(var_t *def, var_t *args);
85 static class_t *make_class(char *name);
86 static type_t *make_safearray(void);
87
88 static type_t *reg_type(type_t *type, const char *name, int t);
89 static type_t *reg_types(type_t *type, var_t *names, int t);
90 static type_t *find_type(const char *name, int t);
91 static type_t *find_type2(char *name, int t);
92 static type_t *get_type(unsigned char type, char *name, int t);
93 static type_t *get_typev(unsigned char type, var_t *name, int t);
94 static int get_struct_type(var_t *fields);
95
96 static var_t *reg_const(var_t *var);
97 static var_t *find_const(char *name, int f);
98
99 #define tsENUM   1
100 #define tsSTRUCT 2
101 #define tsUNION  3
102
103 static type_t std_bool = { "boolean" };
104 static type_t std_int = { "int" };
105 static type_t std_int64 = { "__int64" };
106 static type_t std_uhyper = { "MIDL_uhyper" };
107
108 %}
109 %union {
110         attr_t *attr;
111         expr_t *expr;
112         type_t *type;
113         typeref_t *tref;
114         var_t *var;
115         func_t *func;
116         ifref_t *ifref;
117         class_t *clas;
118         char *str;
119         UUID *uuid;
120         unsigned int num;
121 }
122
123 %token <str> aIDENTIFIER
124 %token <str> aKNOWNTYPE
125 %token <num> aNUM aHEXNUM
126 %token <str> aSTRING
127 %token <uuid> aUUID
128 %token aEOF
129 %token SHL SHR
130 %token tAGGREGATABLE tALLOCATE tAPPOBJECT tASYNC tASYNCUUID
131 %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
132 %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
133 %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
134 %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
135 %token tDEFAULT
136 %token tDEFAULTCOLLELEM
137 %token tDEFAULTVALUE
138 %token tDEFAULTVTABLE
139 %token tDISPLAYBIND
140 %token tDISPINTERFACE
141 %token tDLLNAME tDOUBLE tDUAL
142 %token tENDPOINT
143 %token tENTRY tENUM tERRORSTATUST
144 %token tEXPLICITHANDLE tEXTERN
145 %token tFALSE
146 %token tFLOAT
147 %token tHANDLE
148 %token tHANDLET
149 %token tHELPCONTEXT tHELPFILE
150 %token tHELPSTRING tHELPSTRINGCONTEXT tHELPSTRINGDLL
151 %token tHIDDEN
152 %token tHYPER tID tIDEMPOTENT
153 %token tIIDIS
154 %token tIMMEDIATEBIND
155 %token tIMPLICITHANDLE
156 %token tIMPORT tIMPORTLIB
157 %token tIN tINLINE
158 %token tINPUTSYNC
159 %token tINT tINT64
160 %token tINTERFACE
161 %token tLCID
162 %token tLENGTHIS tLIBRARY
163 %token tLOCAL
164 %token tLONG
165 %token tMETHODS
166 %token tMODULE
167 %token tNONBROWSABLE
168 %token tNONCREATABLE
169 %token tNONEXTENSIBLE
170 %token tOBJECT tODL tOLEAUTOMATION
171 %token tOPTIONAL
172 %token tOUT
173 %token tPOINTERDEFAULT
174 %token tPROPERTIES
175 %token tPROPGET tPROPPUT tPROPPUTREF
176 %token tPTR
177 %token tPUBLIC
178 %token tRANGE
179 %token tREADONLY tREF
180 %token tREQUESTEDIT
181 %token tRESTRICTED
182 %token tRETVAL
183 %token tSAFEARRAY
184 %token tSHORT
185 %token tSIGNED
186 %token tSINGLE
187 %token tSIZEIS tSIZEOF
188 %token tSMALL
189 %token tSOURCE
190 %token tSTDCALL
191 %token tSTRING tSTRUCT
192 %token tSWITCH tSWITCHIS tSWITCHTYPE
193 %token tTRANSMITAS
194 %token tTRUE
195 %token tTYPEDEF
196 %token tUNION
197 %token tUNIQUE
198 %token tUNSIGNED
199 %token tUUID
200 %token tV1ENUM
201 %token tVARARG
202 %token tVERSION
203 %token tVOID
204 %token tWCHAR tWIREMARSHAL
205
206 %type <attr> m_attributes attributes attrib_list attribute
207 %type <expr> m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const
208 %type <expr> array array_list
209 %type <type> inherit interface interfacehdr interfacedef interfacedec
210 %type <type> dispinterface dispinterfacehdr dispinterfacedef
211 %type <type> module modulehdr moduledef
212 %type <type> base_type int_std
213 %type <type> enumdef structdef typedef uniondef
214 %type <ifref> gbl_statements coclass_ints coclass_int
215 %type <tref> type
216 %type <var> m_args no_args args arg
217 %type <var> fields field s_field cases case enums enum_list enum constdef externdef
218 %type <var> m_ident t_ident ident p_ident pident pident_list
219 %type <var> dispint_props
220 %type <func> funcdef int_statements
221 %type <func> dispint_meths
222 %type <clas> coclass coclasshdr coclassdef
223 %type <num> pointer_type version
224 %type <str> libraryhdr
225
226 %left ','
227 %right '?' ':'
228 %left '|'
229 %left '&'
230 %left '-' '+'
231 %left '*' '/'
232 %left SHL SHR
233 %right '~'
234 %right CAST
235 %right PPTR
236 %right NEG
237
238 %%
239
240 input:   gbl_statements                        { write_proxies($1); write_client($1); write_server($1); }
241         ;
242
243 gbl_statements:                                 { $$ = NULL; }
244         | gbl_statements interfacedec           { $$ = $1; }
245         | gbl_statements interfacedef           { $$ = make_ifref($2); LINK($$, $1); }
246         | gbl_statements coclass ';'    { $$ = $1; if (!parse_only && do_header) write_coclass_forward($2); }
247         | gbl_statements coclassdef             { $$ = $1; add_coclass($2); }
248         | gbl_statements moduledef              { $$ = $1; add_module($2); }
249         | gbl_statements librarydef             { $$ = $1; }
250         | gbl_statements statement              { $$ = $1; }
251         ;
252
253 imp_statements:                                 {}
254         | imp_statements interfacedec           { if (!parse_only) add_interface($2); }
255         | imp_statements interfacedef           { if (!parse_only) add_interface($2); }
256         | imp_statements coclass ';'    { reg_type(NULL, $2->name, 0); if (!parse_only && do_header) write_coclass_forward($2); }
257         | imp_statements coclassdef             { if (!parse_only) add_coclass($2); }
258         | imp_statements moduledef              { if (!parse_only) add_module($2); }
259         | imp_statements statement              {}
260         | imp_statements importlib              {}
261         ;
262
263 int_statements:                                 { $$ = NULL; }
264         | int_statements funcdef ';'            { $$ = $2; LINK($$, $1); }
265         | int_statements statement              { $$ = $1; }
266         ;
267
268 statement: ';'                                  {}
269         | constdef ';'                          { if (!parse_only && do_header) { write_constdef($1); } }
270         | cppquote                              {}
271         | enumdef ';'                           { if (!parse_only && do_header) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
272         | externdef ';'                         { if (!parse_only && do_header) { write_externdef($1); } }
273         | import                                {}
274         | structdef ';'                         { if (!parse_only && do_header) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
275         | typedef ';'                           {}
276         | uniondef ';'                          { if (!parse_only && do_header) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
277         ;
278
279 cppquote: tCPPQUOTE '(' aSTRING ')'             { if (!parse_only && do_header) fprintf(header, "%s\n", $3); }
280         ;
281 import_start: tIMPORT aSTRING ';'               { assert(yychar == YYEMPTY);
282                                                   if (!do_import($2)) yychar = aEOF; }
283         ;
284 import:   import_start imp_statements aEOF      {}
285         ;
286
287 importlib: tIMPORTLIB '(' aSTRING ')'           { if(!parse_only) add_importlib($3); }
288         ;
289
290 libraryhdr: tLIBRARY aIDENTIFIER                { $$ = $2; }
291         ;
292 library_start: attributes libraryhdr '{'        { start_typelib($2, $1);
293                                                   if (!parse_only && do_header) write_library($2, $1); }
294         ;
295 librarydef: library_start imp_statements '}'    { end_typelib(); }
296         ;
297
298 m_args:                                         { $$ = NULL; }
299         | args
300         ;
301
302 no_args:  tVOID                                 { $$ = NULL; }
303         ;
304
305 args:     arg
306         | args ',' arg                          { LINK($3, $1); $$ = $3; }
307         | no_args
308         ;
309
310 /* split into two rules to get bison to resolve a tVOID conflict */
311 arg:      attributes type pident array          { $$ = $3;
312                                                   set_type($$, $2, $4);
313                                                   $$->attrs = $1;
314                                                 }
315         | type pident array                     { $$ = $2;
316                                                   set_type($$, $1, $3);
317                                                 }
318         | attributes type pident '(' m_args ')' { $$ = $3;
319                                                   $$->ptr_level--;
320                                                   set_type($$, $2, NULL);
321                                                   $$->attrs = $1;
322                                                   $$->args = $5;
323                                                 }
324         | type pident '(' m_args ')'            { $$ = $2;
325                                                   $$->ptr_level--;
326                                                   set_type($$, $1, NULL);
327                                                   $$->args = $4;
328                                                 }
329         ;
330
331 array:                                          { $$ = NULL; }
332         | '[' array_list ']'                    { $$ = $2; }
333         | '[' '*' ']'                           { $$ = make_expr(EXPR_VOID); }
334         ;
335
336 array_list: m_expr /* size of first dimension is optional */
337         | array_list ',' expr                   { LINK($3, $1); $$ = $3; }
338         | array_list ']' '[' expr               { LINK($4, $1); $$ = $4; }
339         ;
340
341 m_attributes:                                   { $$ = NULL; }
342         | attributes
343         ;
344
345 attributes:
346           '[' attrib_list ']'                   { $$ = $2;
347                                                   if (!$$)
348                                                     yyerror("empty attribute lists unsupported");
349                                                 }
350         ;
351
352 attrib_list: attribute
353         | attrib_list ',' attribute             { if ($3) { LINK($3, $1); $$ = $3; }
354                                                   else { $$ = $1; }
355                                                 }
356         | attrib_list ']' '[' attribute         { if ($4) { LINK($4, $1); $$ = $4; }
357                                                   else { $$ = $1; }
358                                                 }
359         ;
360
361 attribute:                                      { $$ = NULL; }
362         | tAGGREGATABLE                         { $$ = make_attr(ATTR_AGGREGATABLE); }
363         | tAPPOBJECT                            { $$ = make_attr(ATTR_APPOBJECT); }
364         | tASYNC                                { $$ = make_attr(ATTR_ASYNC); }
365         | tAUTOHANDLE                           { $$ = make_attr(ATTR_AUTO_HANDLE); }
366         | tBINDABLE                             { $$ = make_attr(ATTR_BINDABLE); }
367         | tCALLAS '(' ident ')'                 { $$ = make_attrp(ATTR_CALLAS, $3); }
368         | tCASE '(' expr_list_const ')'         { $$ = make_attrp(ATTR_CASE, $3); }
369         | tCONTEXTHANDLE                        { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
370         | tCONTEXTHANDLENOSERIALIZE             { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
371         | tCONTEXTHANDLESERIALIZE               { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
372         | tCONTROL                              { $$ = make_attr(ATTR_CONTROL); }
373         | tDEFAULT                              { $$ = make_attr(ATTR_DEFAULT); }
374         | tDEFAULTCOLLELEM                      { $$ = make_attr(ATTR_DEFAULTCOLLELEM); }
375         | tDEFAULTVALUE '(' expr_const ')'      { $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); }
376         | tDEFAULTVALUE '(' aSTRING ')'         { $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); }
377         | tDEFAULTVTABLE                        { $$ = make_attr(ATTR_DEFAULTVTABLE); }
378         | tDISPLAYBIND                          { $$ = make_attr(ATTR_DISPLAYBIND); }
379         | tDLLNAME '(' aSTRING ')'              { $$ = make_attrp(ATTR_DLLNAME, $3); }
380         | tDUAL                                 { $$ = make_attr(ATTR_DUAL); }
381         | tENDPOINT '(' aSTRING ')'             { $$ = make_attrp(ATTR_ENDPOINT, $3); }
382         | tENTRY '(' aSTRING ')'                { $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
383         | tENTRY '(' expr_const ')'             { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
384         | tEXPLICITHANDLE                       { $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
385         | tHANDLE                               { $$ = make_attr(ATTR_HANDLE); }
386         | tHELPCONTEXT '(' expr_const ')'       { $$ = make_attrp(ATTR_HELPCONTEXT, $3); }
387         | tHELPFILE '(' aSTRING ')'             { $$ = make_attrp(ATTR_HELPFILE, $3); }
388         | tHELPSTRING '(' aSTRING ')'           { $$ = make_attrp(ATTR_HELPSTRING, $3); }
389         | tHELPSTRINGCONTEXT '(' expr_const ')' { $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); }
390         | tHELPSTRINGDLL '(' aSTRING ')'        { $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); }
391         | tHIDDEN                               { $$ = make_attr(ATTR_HIDDEN); }
392         | tID '(' expr_const ')'                { $$ = make_attrp(ATTR_ID, $3); }
393         | tIDEMPOTENT                           { $$ = make_attr(ATTR_IDEMPOTENT); }
394         | tIIDIS '(' ident ')'                  { $$ = make_attrp(ATTR_IIDIS, $3); }
395         | tIMMEDIATEBIND                        { $$ = make_attr(ATTR_IMMEDIATEBIND); }
396         | tIMPLICITHANDLE '(' tHANDLET aIDENTIFIER ')'  { $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $4); }
397         | tIN                                   { $$ = make_attr(ATTR_IN); }
398         | tINPUTSYNC                            { $$ = make_attr(ATTR_INPUTSYNC); }
399         | tLENGTHIS '(' m_exprs ')'             { $$ = make_attrp(ATTR_LENGTHIS, $3); }
400         | tLOCAL                                { $$ = make_attr(ATTR_LOCAL); }
401         | tNONBROWSABLE                         { $$ = make_attr(ATTR_NONBROWSABLE); }
402         | tNONCREATABLE                         { $$ = make_attr(ATTR_NONCREATABLE); }
403         | tNONEXTENSIBLE                        { $$ = make_attr(ATTR_NONEXTENSIBLE); }
404         | tOBJECT                               { $$ = make_attr(ATTR_OBJECT); }
405         | tODL                                  { $$ = make_attr(ATTR_ODL); }
406         | tOLEAUTOMATION                        { $$ = make_attr(ATTR_OLEAUTOMATION); }
407         | tOPTIONAL                             { $$ = make_attr(ATTR_OPTIONAL); }
408         | tOUT                                  { $$ = make_attr(ATTR_OUT); }
409         | tPOINTERDEFAULT '(' pointer_type ')'  { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
410         | tPROPGET                              { $$ = make_attr(ATTR_PROPGET); }
411         | tPROPPUT                              { $$ = make_attr(ATTR_PROPPUT); }
412         | tPROPPUTREF                           { $$ = make_attr(ATTR_PROPPUTREF); }
413         | tPUBLIC                               { $$ = make_attr(ATTR_PUBLIC); }
414         | tRANGE '(' expr_const ',' expr_const ')' { LINK($5, $3); $$ = make_attrp(ATTR_RANGE, $5); }
415         | tREADONLY                             { $$ = make_attr(ATTR_READONLY); }
416         | tREQUESTEDIT                          { $$ = make_attr(ATTR_REQUESTEDIT); }
417         | tRESTRICTED                           { $$ = make_attr(ATTR_RESTRICTED); }
418         | tRETVAL                               { $$ = make_attr(ATTR_RETVAL); }
419         | tSIZEIS '(' m_exprs ')'               { $$ = make_attrp(ATTR_SIZEIS, $3); }
420         | tSOURCE                               { $$ = make_attr(ATTR_SOURCE); }
421         | tSTRING                               { $$ = make_attr(ATTR_STRING); }
422         | tSWITCHIS '(' expr ')'                { $$ = make_attrp(ATTR_SWITCHIS, $3); }
423         | tSWITCHTYPE '(' type ')'              { $$ = make_attrp(ATTR_SWITCHTYPE, type_ref($3)); }
424         | tTRANSMITAS '(' type ')'              { $$ = make_attrp(ATTR_TRANSMITAS, type_ref($3)); }
425         | tUUID '(' aUUID ')'                   { $$ = make_attrp(ATTR_UUID, $3); }
426         | tV1ENUM                               { $$ = make_attr(ATTR_V1ENUM); }
427         | tVARARG                               { $$ = make_attr(ATTR_VARARG); }
428         | tVERSION '(' version ')'              { $$ = make_attrv(ATTR_VERSION, $3); }
429         | tWIREMARSHAL '(' type ')'             { $$ = make_attrp(ATTR_WIREMARSHAL, type_ref($3)); }
430         | pointer_type                          { $$ = make_attrv(ATTR_POINTERTYPE, $1); }
431         ;
432
433 callconv:
434         | tSTDCALL
435         ;
436
437 cases:                                          { $$ = NULL; }
438         | cases case                            { if ($2) { LINK($2, $1); $$ = $2; }
439                                                   else { $$ = $1; }
440                                                 }
441         ;
442
443 case:     tCASE expr ':' field                  { attr_t *a = make_attrp(ATTR_CASE, $2);
444                                                   $$ = $4; if (!$$) $$ = make_var(NULL);
445                                                   LINK(a, $$->attrs); $$->attrs = a;
446                                                 }
447         | tDEFAULT ':' field                    { attr_t *a = make_attr(ATTR_DEFAULT);
448                                                   $$ = $3; if (!$$) $$ = make_var(NULL);
449                                                   LINK(a, $$->attrs); $$->attrs = a;
450                                                 }
451         ;
452
453 constdef: tCONST type ident '=' expr_const      { $$ = reg_const($3);
454                                                   set_type($$, $2, NULL);
455                                                   $$->eval = $5;
456                                                 }
457         ;
458
459 enums:                                          { $$ = NULL; }
460         | enum_list ','                         { $$ = $1; }
461         | enum_list
462         ;
463
464 enum_list: enum                                 { if (!$$->eval)
465                                                     $$->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */);
466                                                 }
467         | enum_list ',' enum                    { LINK($3, $1); $$ = $3;
468                                                   if (!$$->eval)
469                                                     $$->eval = make_exprl(EXPR_NUM, $1->eval->cval + 1);
470                                                 }
471         ;
472
473 enum:     ident '=' expr_const                  { $$ = reg_const($1);
474                                                   $$->eval = $3;
475                                                   $$->type = make_type(RPC_FC_LONG, &std_int);
476                                                 }
477         | ident                                 { $$ = reg_const($1);
478                                                   $$->type = make_type(RPC_FC_LONG, &std_int);
479                                                 }
480         ;
481
482 enumdef: tENUM t_ident '{' enums '}'            { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
483                                                   $$->fields = $4;
484                                                   $$->defined = TRUE;
485                                                   if(in_typelib)
486                                                       add_enum($$);
487                                                 }
488         ;
489
490 m_exprs:  m_expr
491         | m_exprs ',' m_expr                    { LINK($3, $1); $$ = $3; }
492         ;
493
494 /*
495 exprs:                                          { $$ = make_expr(EXPR_VOID); }
496         | expr_list
497         ;
498
499 expr_list: expr
500         | expr_list ',' expr                    { LINK($3, $1); $$ = $3; }
501         ;
502 */
503
504 m_expr:                                         { $$ = make_expr(EXPR_VOID); }
505         | expr
506         ;
507
508 expr:     aNUM                                  { $$ = make_exprl(EXPR_NUM, $1); }
509         | aHEXNUM                               { $$ = make_exprl(EXPR_HEXNUM, $1); }
510         | tFALSE                                { $$ = make_exprl(EXPR_TRUEFALSE, 0); }
511         | tTRUE                                 { $$ = make_exprl(EXPR_TRUEFALSE, 1); }
512         | aIDENTIFIER                           { $$ = make_exprs(EXPR_IDENTIFIER, $1); }
513         | expr '?' expr ':' expr                { $$ = make_expr3(EXPR_COND, $1, $3, $5); }
514         | expr '|' expr                         { $$ = make_expr2(EXPR_OR , $1, $3); }
515         | expr '&' expr                         { $$ = make_expr2(EXPR_AND, $1, $3); }
516         | expr '+' expr                         { $$ = make_expr2(EXPR_ADD, $1, $3); }
517         | expr '-' expr                         { $$ = make_expr2(EXPR_SUB, $1, $3); }
518         | expr '*' expr                         { $$ = make_expr2(EXPR_MUL, $1, $3); }
519         | expr '/' expr                         { $$ = make_expr2(EXPR_DIV, $1, $3); }
520         | expr SHL expr                         { $$ = make_expr2(EXPR_SHL, $1, $3); }
521         | expr SHR expr                         { $$ = make_expr2(EXPR_SHR, $1, $3); }
522         | '~' expr                              { $$ = make_expr1(EXPR_NOT, $2); }
523         | '-' expr %prec NEG                    { $$ = make_expr1(EXPR_NEG, $2); }
524         | '*' expr %prec PPTR                   { $$ = make_expr1(EXPR_PPTR, $2); }
525         | '(' type ')' expr %prec CAST          { $$ = make_exprt(EXPR_CAST, $2, $4); }
526         | tSIZEOF '(' type ')'                  { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
527         | '(' expr ')'                          { $$ = $2; }
528         ;
529
530 expr_list_const: expr_const
531         | expr_list_const ',' expr_const        { LINK($3, $1); $$ = $3; }
532         ;
533
534 expr_const: expr                                { $$ = $1;
535                                                   if (!$$->is_const)
536                                                       yyerror("expression is not constant");
537                                                 }
538         ;
539
540 externdef: tEXTERN tCONST type ident            { $$ = $4;
541                                                   set_type($$, $3, NULL);
542                                                 }
543         ;
544
545 fields:                                         { $$ = NULL; }
546         | fields field                          { if ($2) { LINK($2, $1); $$ = $2; }
547                                                   else { $$ = $1; }
548                                                 }
549         ;
550
551 field:    s_field ';'                           { $$ = $1; }
552         | m_attributes uniondef ';'             { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
553         | attributes ';'                        { $$ = make_var(NULL); $$->attrs = $1; }
554         | ';'                                   { $$ = NULL; }
555         ;
556
557 s_field:  m_attributes type pident array        { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; }
558         ;
559
560 funcdef:
561           m_attributes type callconv pident
562           '(' m_args ')'                        { set_type($4, $2, NULL);
563                                                   $4->attrs = $1;
564                                                   $$ = make_func($4, $6);
565                                                   if (is_attr($4->attrs, ATTR_IN)) {
566                                                     yyerror("inapplicable attribute [in] for function '%s'",$$->def->name);
567                                                   }
568                                                 }
569         ;
570
571 m_ident:                                        { $$ = NULL; }
572         | ident
573         ;
574
575 t_ident:                                        { $$ = NULL; }
576         | aIDENTIFIER                           { $$ = make_var($1); }
577         | aKNOWNTYPE                            { $$ = make_var($1); }
578         ;
579
580 ident:    aIDENTIFIER                           { $$ = make_var($1); }
581 /* some "reserved words" used in attributes are also used as field names in some MS IDL files */
582         | aKNOWNTYPE                            { $$ = make_var($<str>1); }
583         | tASYNC                                { $$ = make_var($<str>1); }
584         | tID                                   { $$ = make_var($<str>1); }
585         | tLCID                                 { $$ = make_var($<str>1); }
586         | tOBJECT                               { $$ = make_var($<str>1); }
587         | tRANGE                                { $$ = make_var($<str>1); }
588         | tRETVAL                               { $$ = make_var($<str>1); }
589         | tUUID                                 { $$ = make_var($<str>1); }
590         | tVERSION                              { $$ = make_var($<str>1); }
591         ;
592
593 base_type: tBYTE                                { $$ = make_type(RPC_FC_BYTE, NULL); }
594         | tWCHAR                                { $$ = make_type(RPC_FC_WCHAR, NULL); }
595         | int_std
596         | tSIGNED int_std                       { $$ = $2; $$->sign = 1; }
597         | tUNSIGNED int_std                     { $$ = $2; $$->sign = -1;
598                                                   switch ($$->type) {
599                                                   case RPC_FC_CHAR:  break;
600                                                   case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
601                                                   case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
602                                                   case RPC_FC_LONG:  $$->type = RPC_FC_ULONG;  break;
603                                                   case RPC_FC_HYPER:
604                                                     if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
605                                                     break;
606                                                   default: break;
607                                                   }
608                                                 }
609         | tUNSIGNED                             { $$ = make_type(RPC_FC_ULONG, &std_int); $$->sign = -1; }
610         | tFLOAT                                { $$ = make_type(RPC_FC_FLOAT, NULL); }
611         | tSINGLE                               { $$ = make_type(RPC_FC_FLOAT, NULL); }
612         | tDOUBLE                               { $$ = make_type(RPC_FC_DOUBLE, NULL); }
613         | tBOOLEAN                              { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
614         | tERRORSTATUST                         { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
615         | tHANDLET                              { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
616         ;
617
618 m_int:
619         | tINT
620         ;
621
622 int_std:  tINT                                  { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
623         | tSHORT m_int                          { $$ = make_type(RPC_FC_SHORT, NULL); }
624         | tSMALL                                { $$ = make_type(RPC_FC_SMALL, NULL); }
625         | tLONG m_int                           { $$ = make_type(RPC_FC_LONG, NULL); }
626         | tHYPER m_int                          { $$ = make_type(RPC_FC_HYPER, NULL); }
627         | tINT64                                { $$ = make_type(RPC_FC_HYPER, &std_int64); }
628         | tCHAR                                 { $$ = make_type(RPC_FC_CHAR, NULL); }
629         ;
630
631 coclass:  tCOCLASS aIDENTIFIER                  { $$ = make_class($2); }
632         | tCOCLASS aKNOWNTYPE                   { $$ = make_class($2); }
633         ;
634
635 coclasshdr: attributes coclass                  { $$ = $2;
636                                                   $$->attrs = $1;
637                                                   if (!parse_only && do_header)
638                                                     write_coclass($$);
639                                                 }
640         ;
641
642 coclassdef: coclasshdr '{' coclass_ints '}'     { $$ = $1;
643                                                   $$->ifaces = $3;
644                                                 }
645         ;
646
647 coclass_ints:                                   { $$ = NULL; }
648         | coclass_ints coclass_int              { LINK($2, $1); $$ = $2; }
649         ;
650
651 coclass_int:
652           m_attributes interfacedec             { $$ = make_ifref($2); $$->attrs = $1; }
653         ;
654
655 dispinterface: tDISPINTERFACE aIDENTIFIER       { $$ = get_type(0, $2, 0); }
656         |      tDISPINTERFACE aKNOWNTYPE        { $$ = get_type(0, $2, 0); }
657         ;
658
659 dispinterfacehdr: attributes dispinterface      { attr_t *attrs;
660                                                   $$ = $2;
661                                                   if ($$->defined) yyerror("multiple definition error");
662                                                   attrs = make_attr(ATTR_DISPINTERFACE);
663                                                   LINK(attrs, $1);
664                                                   $$->attrs = attrs;
665                                                   $$->ref = find_type("IDispatch", 0);
666                                                   if (!$$->ref) yyerror("IDispatch is undefined");
667                                                   $$->defined = TRUE;
668                                                   if (!parse_only && do_header) write_forward($$);
669                                                 }
670         ;
671
672 dispint_props: tPROPERTIES ':'                  { $$ = NULL; }
673         | dispint_props s_field ';'             { LINK($2, $1); $$ = $2; }
674         ;
675
676 dispint_meths: tMETHODS ':'                     { $$ = NULL; }
677         | dispint_meths funcdef ';'             { LINK($2, $1); $$ = $2; }
678         ;
679
680 dispinterfacedef: dispinterfacehdr '{'
681           dispint_props
682           dispint_meths
683           '}'                                   { $$ = $1;
684                                                   $$->fields = $3;
685                                                   $$->funcs = $4;
686                                                   if (!parse_only && do_header) write_dispinterface($$);
687                                                 }
688 /* FIXME: not sure how to handle this yet
689         | dispinterfacehdr '{' interface '}'    { $$ = $1;
690                                                   if (!parse_only && do_header) write_interface($$);
691                                                 }
692 */
693         ;
694
695 inherit:                                        { $$ = NULL; }
696         | ':' aKNOWNTYPE                        { $$ = find_type2($2, 0); }
697         ;
698
699 interface: tINTERFACE aIDENTIFIER               { $$ = get_type(RPC_FC_IP, $2, 0); }
700         |  tINTERFACE aKNOWNTYPE                { $$ = get_type(RPC_FC_IP, $2, 0); }
701         ;
702
703 interfacehdr: attributes interface              { $$ = $2;
704                                                   if ($$->defined) yyerror("multiple definition error");
705                                                   $$->attrs = $1;
706                                                   $$->defined = TRUE;
707                                                   if (!parse_only && do_header) write_forward($$);
708                                                 }
709         ;
710
711 interfacedef: interfacehdr inherit
712           '{' int_statements '}'                { $$ = $1;
713                                                   $$->ref = $2;
714                                                   $$->funcs = $4;
715                                                   if (!parse_only && do_header) write_interface($$);
716                                                 }
717 /* MIDL is able to import the definition of a base class from inside the
718  * definition of a derived class, I'll try to support it with this rule */
719         | interfacehdr ':' aIDENTIFIER
720           '{' import int_statements '}'         { $$ = $1;
721                                                   $$->ref = find_type2($3, 0);
722                                                   if (!$$->ref) yyerror("base class '%s' not found in import", $3);
723                                                   $$->funcs = $6;
724                                                   if (!parse_only && do_header) write_interface($$);
725                                                 }
726         | dispinterfacedef                      { $$ = $1; }
727         ;
728
729 interfacedec:
730           interface ';'                         { $$ = $1; if (!parse_only && do_header) write_forward($$); }
731         | dispinterface ';'                     { $$ = $1; if (!parse_only && do_header) write_forward($$); }
732         ;
733
734 module:   tMODULE aIDENTIFIER                   { $$ = make_type(0, NULL); $$->name = $2; }
735         | tMODULE aKNOWNTYPE                    { $$ = make_type(0, NULL); $$->name = $2; }
736         ;
737
738 modulehdr: attributes module                    { $$ = $2;
739                                                   $$->attrs = $1;
740                                                 }
741         ;
742
743 moduledef: modulehdr '{' int_statements '}'     { $$ = $1;
744                                                   $$->funcs = $3;
745                                                   /* FIXME: if (!parse_only && do_header) write_module($$); */
746                                                 }
747         ;
748
749 p_ident:  '*' pident %prec PPTR                 { $$ = $2; $$->ptr_level++; }
750         | tCONST p_ident                        { $$ = $2; /* FIXME */ }
751         ;
752
753 pident:   ident
754         | p_ident
755         | '(' pident ')'                        { $$ = $2; }
756         ;
757
758 pident_list:
759           pident
760         | pident_list ',' pident                { LINK($3, $1); $$ = $3; }
761         ;
762
763 pointer_type:
764           tREF                                  { $$ = RPC_FC_RP; }
765         | tUNIQUE                               { $$ = RPC_FC_UP; }
766         | tPTR                                  { $$ = RPC_FC_FP; }
767         ;
768
769 structdef: tSTRUCT t_ident '{' fields '}'       { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
770                                                   /* overwrite RPC_FC_STRUCT with a more exact type */
771                                                   $$->type = get_struct_type( $4 );
772                                                   $$->fields = $4;
773                                                   $$->defined = TRUE;
774                                                   if(in_typelib)
775                                                       add_struct($$);
776                                                 }
777         ;
778
779 type:     tVOID                                 { $$ = make_tref(NULL, make_type(0, NULL)); }
780         | aKNOWNTYPE                            { $$ = make_tref($1, find_type($1, 0)); }
781         | base_type                             { $$ = make_tref(NULL, $1); }
782         | tCONST type                           { $$ = uniq_tref($2); $$->ref->is_const = TRUE; }
783         | enumdef                               { $$ = make_tref(NULL, $1); }
784         | tENUM aIDENTIFIER                     { $$ = make_tref(NULL, find_type2($2, tsENUM)); }
785         | structdef                             { $$ = make_tref(NULL, $1); }
786         | tSTRUCT aIDENTIFIER                   { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); }
787         | uniondef                              { $$ = make_tref(NULL, $1); }
788         | tUNION aIDENTIFIER                    { $$ = make_tref(NULL, find_type2($2, tsUNION)); }
789         | tSAFEARRAY '(' type ')'               { $$ = make_tref(NULL, make_safearray()); }
790         ;
791
792 typedef: tTYPEDEF m_attributes type pident_list { typeref_t *tref = uniq_tref($3);
793                                                   $4->tname = tref->name;
794                                                   tref->name = NULL;
795                                                   $$ = type_ref(tref);
796                                                   $$->attrs = $2;
797                                                   if (!parse_only && do_header)
798                                                     write_typedef($$, $4);
799                                                   if (in_typelib && $$->attrs)
800                                                     add_typedef($$, $4);
801                                                   reg_types($$, $4, 0);
802                                                 }
803         ;
804
805 uniondef: tUNION t_ident '{' fields '}'         { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
806                                                   $$->fields = $4;
807                                                   $$->defined = TRUE;
808                                                 }
809         | tUNION t_ident
810           tSWITCH '(' s_field ')'
811           m_ident '{' cases '}'                 { var_t *u = $7;
812                                                   $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
813                                                   if (!u) u = make_var("tagged_union");
814                                                   u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
815                                                   u->type->fields = $9;
816                                                   u->type->defined = TRUE;
817                                                   LINK(u, $5); $$->fields = u;
818                                                   $$->defined = TRUE;
819                                                 }
820         ;
821
822 version:
823           aNUM                                  { $$ = MAKELONG($1, 0); }
824         | aNUM '.' aNUM                         { $$ = MAKELONG($1, $3); }
825         ;
826
827 %%
828
829 static attr_t *make_attr(enum attr_type type)
830 {
831   attr_t *a = xmalloc(sizeof(attr_t));
832   a->type = type;
833   a->u.ival = 0;
834   INIT_LINK(a);
835   return a;
836 }
837
838 static attr_t *make_attrv(enum attr_type type, unsigned long val)
839 {
840   attr_t *a = xmalloc(sizeof(attr_t));
841   a->type = type;
842   a->u.ival = val;
843   INIT_LINK(a);
844   return a;
845 }
846
847 static attr_t *make_attrp(enum attr_type type, void *val)
848 {
849   attr_t *a = xmalloc(sizeof(attr_t));
850   a->type = type;
851   a->u.pval = val;
852   INIT_LINK(a);
853   return a;
854 }
855
856 static expr_t *make_expr(enum expr_type type)
857 {
858   expr_t *e = xmalloc(sizeof(expr_t));
859   e->type = type;
860   e->ref = NULL;
861   e->u.lval = 0;
862   e->is_const = FALSE;
863   INIT_LINK(e);
864   return e;
865 }
866
867 static expr_t *make_exprl(enum expr_type type, long val)
868 {
869   expr_t *e = xmalloc(sizeof(expr_t));
870   e->type = type;
871   e->ref = NULL;
872   e->u.lval = val;
873   e->is_const = FALSE;
874   INIT_LINK(e);
875   /* check for numeric constant */
876   if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) {
877     /* make sure true/false value is valid */
878     assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
879     e->is_const = TRUE;
880     e->cval = val;
881   }
882   return e;
883 }
884
885 static expr_t *make_exprs(enum expr_type type, char *val)
886 {
887   expr_t *e;
888   e = xmalloc(sizeof(expr_t));
889   e->type = type;
890   e->ref = NULL;
891   e->u.sval = val;
892   e->is_const = FALSE;
893   INIT_LINK(e);
894   /* check for predefined constants */
895   if (type == EXPR_IDENTIFIER) {
896     var_t *c = find_const(val, 0);
897     if (c) {
898       e->u.sval = c->name;
899       free(val);
900       e->is_const = TRUE;
901       e->cval = c->eval->cval;
902     }
903   }
904   return e;
905 }
906
907 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr)
908 {
909   expr_t *e;
910   e = xmalloc(sizeof(expr_t));
911   e->type = type;
912   e->ref = expr;
913   e->u.tref = tref;
914   e->is_const = FALSE;
915   INIT_LINK(e);
916   /* check for cast of constant expression */
917   if (type == EXPR_SIZEOF) {
918     switch (tref->ref->type) {
919       case RPC_FC_BYTE:
920       case RPC_FC_CHAR:
921       case RPC_FC_SMALL:
922       case RPC_FC_USMALL:
923         e->is_const = TRUE;
924         e->cval = 1;
925         break;
926       case RPC_FC_WCHAR:
927       case RPC_FC_USHORT:
928       case RPC_FC_SHORT:
929         e->is_const = TRUE;
930         e->cval = 2;
931         break;
932       case RPC_FC_LONG:
933       case RPC_FC_ULONG:
934       case RPC_FC_FLOAT:
935       case RPC_FC_ERROR_STATUS_T:
936         e->is_const = TRUE;
937         e->cval = 4;
938         break;
939       case RPC_FC_HYPER:
940       case RPC_FC_DOUBLE:
941         e->is_const = TRUE;
942         e->cval = 8;
943         break;
944     }
945   }
946   if (type == EXPR_CAST && expr->is_const) {
947     e->is_const = TRUE;
948     e->cval = expr->cval;
949   }
950   return e;
951 }
952
953 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
954 {
955   expr_t *e;
956   e = xmalloc(sizeof(expr_t));
957   e->type = type;
958   e->ref = expr;
959   e->u.lval = 0;
960   e->is_const = FALSE;
961   INIT_LINK(e);
962   /* check for compile-time optimization */
963   if (expr->is_const) {
964     e->is_const = TRUE;
965     switch (type) {
966     case EXPR_NEG:
967       e->cval = -expr->cval;
968       break;
969     case EXPR_NOT:
970       e->cval = ~expr->cval;
971       break;
972     default:
973       e->is_const = FALSE;
974       break;
975     }
976   }
977   return e;
978 }
979
980 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
981 {
982   expr_t *e;
983   e = xmalloc(sizeof(expr_t));
984   e->type = type;
985   e->ref = expr1;
986   e->u.ext = expr2;
987   e->is_const = FALSE;
988   INIT_LINK(e);
989   /* check for compile-time optimization */
990   if (expr1->is_const && expr2->is_const) {
991     e->is_const = TRUE;
992     switch (type) {
993     case EXPR_ADD:
994       e->cval = expr1->cval + expr2->cval;
995       break;
996     case EXPR_SUB:
997       e->cval = expr1->cval - expr2->cval;
998       break;
999     case EXPR_MUL:
1000       e->cval = expr1->cval * expr2->cval;
1001       break;
1002     case EXPR_DIV:
1003       e->cval = expr1->cval / expr2->cval;
1004       break;
1005     case EXPR_OR:
1006       e->cval = expr1->cval | expr2->cval;
1007       break;
1008     case EXPR_AND:
1009       e->cval = expr1->cval & expr2->cval;
1010       break;
1011     case EXPR_SHL:
1012       e->cval = expr1->cval << expr2->cval;
1013       break;
1014     case EXPR_SHR:
1015       e->cval = expr1->cval >> expr2->cval;
1016       break;
1017     default:
1018       e->is_const = FALSE;
1019       break;
1020     }
1021   }
1022   return e;
1023 }
1024
1025 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
1026 {
1027   expr_t *e;
1028   e = xmalloc(sizeof(expr_t));
1029   e->type = type;
1030   e->ref = expr1;
1031   e->u.ext = expr2;
1032   e->ext2 = expr3;
1033   e->is_const = FALSE;
1034   INIT_LINK(e);
1035   /* check for compile-time optimization */
1036   if (expr1->is_const && expr2->is_const && expr3->is_const) {
1037     e->is_const = TRUE;
1038     switch (type) {
1039     case EXPR_COND:
1040       e->cval = expr1->cval ? expr2->cval : expr3->cval;
1041       break;
1042     default:
1043       e->is_const = FALSE;
1044       break;
1045     }
1046   }
1047   return e;
1048 }
1049
1050 static type_t *make_type(unsigned char type, type_t *ref)
1051 {
1052   type_t *t = xmalloc(sizeof(type_t));
1053   t->name = NULL;
1054   t->type = type;
1055   t->ref = ref;
1056   t->attrs = NULL;
1057   t->funcs = NULL;
1058   t->fields = NULL;
1059   t->ignore = parse_only;
1060   t->is_const = FALSE;
1061   t->sign = 0;
1062   t->defined = FALSE;
1063   t->written = FALSE;
1064   t->typelib_idx = -1;
1065   INIT_LINK(t);
1066   return t;
1067 }
1068
1069 static typeref_t *make_tref(char *name, type_t *ref)
1070 {
1071   typeref_t *t = xmalloc(sizeof(typeref_t));
1072   t->name = name;
1073   t->ref = ref;
1074   t->uniq = ref ? 0 : 1;
1075   return t;
1076 }
1077
1078 static typeref_t *uniq_tref(typeref_t *ref)
1079 {
1080   typeref_t *t = ref;
1081   type_t *tp;
1082   if (t->uniq) return t;
1083   tp = make_type(0, t->ref);
1084   tp->name = t->name;
1085   t->name = NULL;
1086   t->ref = tp;
1087   t->uniq = 1;
1088   return t;
1089 }
1090
1091 static type_t *type_ref(typeref_t *ref)
1092 {
1093   type_t *t = ref->ref;
1094   if (ref->name) free(ref->name);
1095   free(ref);
1096   return t;
1097 }
1098
1099 static void set_type(var_t *v, typeref_t *ref, expr_t *arr)
1100 {
1101   v->type = ref->ref;
1102   v->tname = ref->name;
1103   ref->name = NULL;
1104   free(ref);
1105   v->array = arr;
1106 }
1107
1108 static ifref_t *make_ifref(type_t *iface)
1109 {
1110   ifref_t *l = xmalloc(sizeof(ifref_t));
1111   l->iface = iface;
1112   l->attrs = NULL;
1113   INIT_LINK(l);
1114   return l;
1115 }
1116
1117 static var_t *make_var(char *name)
1118 {
1119   var_t *v = xmalloc(sizeof(var_t));
1120   v->name = name;
1121   v->ptr_level = 0;
1122   v->type = NULL;
1123   v->tname = NULL;
1124   v->attrs = NULL;
1125   v->array = NULL;
1126   v->eval = NULL;
1127   INIT_LINK(v);
1128   return v;
1129 }
1130
1131 static func_t *make_func(var_t *def, var_t *args)
1132 {
1133   func_t *f = xmalloc(sizeof(func_t));
1134   f->def = def;
1135   f->args = args;
1136   f->ignore = parse_only;
1137   f->idx = -1;
1138   INIT_LINK(f);
1139   return f;
1140 }
1141
1142 static class_t *make_class(char *name)
1143 {
1144   class_t *c = xmalloc(sizeof(class_t));
1145   c->name = name;
1146   c->attrs = NULL;
1147   c->ifaces = NULL;
1148   INIT_LINK(c);
1149   return c;
1150 }
1151
1152 static type_t *make_safearray(void)
1153 {
1154   return make_type(RPC_FC_FP, find_type("SAFEARRAY", 0));
1155 }
1156
1157 #define HASHMAX 64
1158
1159 static int hash_ident(const char *name)
1160 {
1161   const char *p = name;
1162   int sum = 0;
1163   /* a simple sum hash is probably good enough */
1164   while (*p) {
1165     sum += *p;
1166     p++;
1167   }
1168   return sum & (HASHMAX-1);
1169 }
1170
1171 /***** type repository *****/
1172
1173 struct rtype {
1174   const char *name;
1175   type_t *type;
1176   int t;
1177   struct rtype *next;
1178 };
1179
1180 struct rtype *type_hash[HASHMAX];
1181
1182 static type_t *reg_type(type_t *type, const char *name, int t)
1183 {
1184   struct rtype *nt;
1185   int hash;
1186   if (!name) {
1187     yyerror("registering named type without name");
1188     return type;
1189   }
1190   hash = hash_ident(name);
1191   nt = xmalloc(sizeof(struct rtype));
1192   nt->name = name;
1193   nt->type = type;
1194   nt->t = t;
1195   nt->next = type_hash[hash];
1196   type_hash[hash] = nt;
1197   return type;
1198 }
1199
1200 /* determine pointer type from attrs */
1201 static unsigned char get_pointer_type( type_t *type )
1202 {
1203   int t;
1204   if (is_attr( type->attrs, ATTR_STRING ))
1205   {
1206     type_t *t = type;
1207     while( t->type == 0 && t->ref )
1208       t = t->ref;
1209     switch( t->type )
1210     {
1211     case RPC_FC_CHAR:
1212       return RPC_FC_C_CSTRING;
1213     case RPC_FC_WCHAR:
1214       return RPC_FC_C_WSTRING;
1215     }
1216   }
1217   t = get_attrv( type->attrs, ATTR_POINTERTYPE );
1218   if (t) return t;
1219   return RPC_FC_FP;
1220 }
1221
1222 static type_t *reg_types(type_t *type, var_t *names, int t)
1223 {
1224   type_t *ptr = type;
1225   int ptrc = 0;
1226
1227   while (names) {
1228     var_t *next = NEXT_LINK(names);
1229     if (names->name) {
1230       type_t *cur = ptr;
1231       int cptr = names->ptr_level;
1232       if (cptr > ptrc) {
1233         while (cptr > ptrc) {
1234           int t = get_pointer_type( cur );
1235           cur = ptr = make_type(t, cur);
1236           ptrc++;
1237         }
1238       } else {
1239         while (cptr < ptrc) {
1240           cur = cur->ref;
1241           cptr++;
1242         }
1243       }
1244       reg_type(cur, names->name, t);
1245     }
1246     free(names);
1247     names = next;
1248   }
1249   return type;
1250 }
1251
1252 static type_t *find_type(const char *name, int t)
1253 {
1254   struct rtype *cur = type_hash[hash_ident(name)];
1255   while (cur && (cur->t != t || strcmp(cur->name, name)))
1256     cur = cur->next;
1257   if (!cur) {
1258     yyerror("type '%s' not found", name);
1259     return NULL;
1260   }
1261   return cur->type;
1262 }
1263
1264 static type_t *find_type2(char *name, int t)
1265 {
1266   type_t *tp = find_type(name, t);
1267   free(name);
1268   return tp;
1269 }
1270
1271 int is_type(const char *name)
1272 {
1273   struct rtype *cur = type_hash[hash_ident(name)];
1274   while (cur && (cur->t || strcmp(cur->name, name)))
1275     cur = cur->next;
1276   if (cur) return TRUE;
1277   return FALSE;
1278 }
1279
1280 static type_t *get_type(unsigned char type, char *name, int t)
1281 {
1282   struct rtype *cur = NULL;
1283   type_t *tp;
1284   if (name) {
1285     cur = type_hash[hash_ident(name)];
1286     while (cur && (cur->t != t || strcmp(cur->name, name)))
1287       cur = cur->next;
1288   }
1289   if (cur) {
1290     free(name);
1291     return cur->type;
1292   }
1293   tp = make_type(type, NULL);
1294   tp->name = name;
1295   if (!name) return tp;
1296   return reg_type(tp, name, t);
1297 }
1298
1299 static type_t *get_typev(unsigned char type, var_t *name, int t)
1300 {
1301   char *sname = NULL;
1302   if (name) {
1303     sname = name->name;
1304     free(name);
1305   }
1306   return get_type(type, sname, t);
1307 }
1308
1309 static int get_struct_type(var_t *field)
1310 {
1311   int has_pointer = 0;
1312   int has_conformance = 0;
1313   int has_variance = 0;
1314
1315   for (; field; field = NEXT_LINK(field))
1316   {
1317     type_t *t = field->type;
1318
1319     /* get the base type */
1320     while( (t->type == 0) && t->ref )
1321       t = t->ref;
1322
1323     if (field->ptr_level > 0)
1324     {
1325         has_pointer = 1;
1326         continue;
1327     }
1328
1329     if (is_string_type(field->attrs, 0, field->array))
1330     {
1331         has_conformance = 1;
1332         has_variance = 1;
1333         continue;
1334     }
1335
1336     if (is_array_type(field->attrs, 0, field->array))
1337     {
1338         if (field->array && !field->array->is_const)
1339         {
1340             has_conformance = 1;
1341             if (PREV_LINK(field))
1342                 yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1343                         field->name);
1344         }
1345         if (is_attr(field->attrs, ATTR_LENGTHIS))
1346             has_variance = 1;
1347     }
1348
1349     switch (t->type)
1350     {
1351     /*
1352      * RPC_FC_BYTE, RPC_FC_STRUCT, etc
1353      *  Simple types don't effect the type of struct.
1354      *  A struct containing a simple struct is still a simple struct.
1355      *  So long as we can block copy the data, we return RPC_FC_STRUCT.
1356      */
1357     case 0: /* void pointer */
1358     case RPC_FC_BYTE:
1359     case RPC_FC_CHAR:
1360     case RPC_FC_SMALL:
1361     case RPC_FC_USMALL:
1362     case RPC_FC_WCHAR:
1363     case RPC_FC_SHORT:
1364     case RPC_FC_USHORT:
1365     case RPC_FC_LONG:
1366     case RPC_FC_ULONG:
1367     case RPC_FC_INT3264:
1368     case RPC_FC_UINT3264:
1369     case RPC_FC_HYPER:
1370     case RPC_FC_FLOAT:
1371     case RPC_FC_DOUBLE:
1372     case RPC_FC_STRUCT:
1373     case RPC_FC_ENUM16:
1374     case RPC_FC_ENUM32:
1375       break;
1376
1377     case RPC_FC_UP:
1378     case RPC_FC_FP:
1379       has_pointer = 1;
1380       break;
1381     case RPC_FC_CARRAY:
1382       has_conformance = 1;
1383       if (PREV_LINK(field))
1384           yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1385                   field->name);
1386       break;
1387     case RPC_FC_C_CSTRING:
1388     case RPC_FC_C_WSTRING:
1389       has_conformance = 1;
1390       has_variance = 1;
1391       break;
1392
1393     /*
1394      * Propagate member attributes
1395      *  a struct should be at least as complex as its member
1396      */
1397     case RPC_FC_CVSTRUCT:
1398       has_conformance = 1;
1399       has_variance = 1;
1400       has_pointer = 1;
1401       break;
1402
1403     case RPC_FC_CPSTRUCT:
1404       has_conformance = 1;
1405       if (PREV_LINK(field))
1406           yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1407                   field->name);
1408       has_pointer = 1;
1409       break;
1410
1411     case RPC_FC_CSTRUCT:
1412       has_conformance = 1;
1413       if (PREV_LINK(field))
1414           yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1415                   field->name);
1416       break;
1417
1418     case RPC_FC_PSTRUCT:
1419       has_pointer = 1;
1420       break;
1421
1422     default:
1423       fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n",
1424               field->name, t->type);
1425       /* fallthru - treat it as complex */
1426
1427     /* as soon as we see one of these these members, it's bogus... */
1428     case RPC_FC_IP:
1429     case RPC_FC_ENCAPSULATED_UNION:
1430     case RPC_FC_NON_ENCAPSULATED_UNION:
1431     case RPC_FC_TRANSMIT_AS:
1432     case RPC_FC_REPRESENT_AS:
1433     case RPC_FC_PAD:
1434     case RPC_FC_EMBEDDED_COMPLEX:
1435     case RPC_FC_BOGUS_STRUCT:
1436       return RPC_FC_BOGUS_STRUCT;
1437     }
1438   }
1439
1440   if( has_variance )
1441     return RPC_FC_CVSTRUCT;
1442   if( has_conformance && has_pointer )
1443     return RPC_FC_CPSTRUCT;
1444   if( has_conformance )
1445     return RPC_FC_CSTRUCT;
1446   if( has_pointer )
1447     return RPC_FC_PSTRUCT;
1448   return RPC_FC_STRUCT;
1449 }
1450
1451 /***** constant repository *****/
1452
1453 struct rconst {
1454   char *name;
1455   var_t *var;
1456   struct rconst *next;
1457 };
1458
1459 struct rconst *const_hash[HASHMAX];
1460
1461 static var_t *reg_const(var_t *var)
1462 {
1463   struct rconst *nc;
1464   int hash;
1465   if (!var->name) {
1466     yyerror("registering constant without name");
1467     return var;
1468   }
1469   hash = hash_ident(var->name);
1470   nc = xmalloc(sizeof(struct rconst));
1471   nc->name = var->name;
1472   nc->var = var;
1473   nc->next = const_hash[hash];
1474   const_hash[hash] = nc;
1475   return var;
1476 }
1477
1478 static var_t *find_const(char *name, int f)
1479 {
1480   struct rconst *cur = const_hash[hash_ident(name)];
1481   while (cur && strcmp(cur->name, name))
1482     cur = cur->next;
1483   if (!cur) {
1484     if (f) yyerror("constant '%s' not found", name);
1485     return NULL;
1486   }
1487   return cur->var;
1488 }