widl: Fix the writing out of function pointers with more than one level of indirection.
[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 "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38 #include "typelib.h"
39 #include "typegen.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 unsigned char pointer_default = RPC_FC_UP;
67 static int is_object_interface = FALSE;
68
69 typedef struct list typelist_t;
70 struct typenode {
71   type_t *type;
72   struct list entry;
73 };
74
75 typelist_t incomplete_types = LIST_INIT(incomplete_types);
76
77 static void add_incomplete(type_t *t);
78 static void fix_incomplete(void);
79
80 static str_list_t *append_str(str_list_t *list, char *str);
81 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
82 static attr_t *make_attr(enum attr_type type);
83 static attr_t *make_attrv(enum attr_type type, unsigned long val);
84 static attr_t *make_attrp(enum attr_type type, void *val);
85 static expr_t *make_expr(enum expr_type type);
86 static expr_t *make_exprl(enum expr_type type, long val);
87 static expr_t *make_exprd(enum expr_type type, double val);
88 static expr_t *make_exprs(enum expr_type type, char *val);
89 static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr);
90 static expr_t *make_expr1(enum expr_type type, expr_t *expr);
91 static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
92 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3);
93 static type_t *make_type(unsigned char type, type_t *ref);
94 static expr_list_t *append_expr(expr_list_t *list, expr_t *expr);
95 static array_dims_t *append_array(array_dims_t *list, expr_t *expr);
96 static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_t *arr, int top);
97 static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
98 static ifref_t *make_ifref(type_t *iface);
99 static var_list_t *append_var(var_list_t *list, var_t *var);
100 static var_t *make_var(char *name);
101 static pident_list_t *append_pident(pident_list_t *list, pident_t *p);
102 static pident_t *make_pident(var_t *var);
103 static func_list_t *append_func(func_list_t *list, func_t *func);
104 static func_t *make_func(var_t *def, var_list_t *args);
105 static type_t *make_class(char *name);
106 static type_t *make_safearray(type_t *type);
107 static type_t *make_builtin(char *name);
108 static type_t *make_int(int sign);
109
110 static type_t *reg_type(type_t *type, const char *name, int t);
111 static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs);
112 static type_t *find_type(const char *name, int t);
113 static type_t *find_type2(char *name, int t);
114 static type_t *get_type(unsigned char type, char *name, int t);
115 static type_t *get_typev(unsigned char type, var_t *name, int t);
116 static int get_struct_type(var_list_t *fields);
117
118 static var_t *reg_const(var_t *var);
119 static var_t *find_const(char *name, int f);
120
121 static void write_libid(const char *name, const attr_list_t *attr);
122 static void write_clsid(type_t *cls);
123 static void write_diid(type_t *iface);
124 static void write_iid(type_t *iface);
125
126 static int compute_method_indexes(type_t *iface);
127 static char *gen_name(void);
128 static void process_typedefs(var_list_t *names);
129 static void check_arg(var_t *arg);
130 static void check_all_user_types(ifref_list_t *ifaces);
131
132 #define tsENUM   1
133 #define tsSTRUCT 2
134 #define tsUNION  3
135
136 %}
137 %union {
138         attr_t *attr;
139         attr_list_t *attr_list;
140         str_list_t *str_list;
141         expr_t *expr;
142         expr_list_t *expr_list;
143         array_dims_t *array_dims;
144         type_t *type;
145         var_t *var;
146         var_list_t *var_list;
147         pident_t *pident;
148         pident_list_t *pident_list;
149         func_t *func;
150         func_list_t *func_list;
151         ifref_t *ifref;
152         ifref_list_t *ifref_list;
153         char *str;
154         UUID *uuid;
155         unsigned int num;
156         double dbl;
157         interface_info_t ifinfo;
158 }
159
160 %token <str> aIDENTIFIER
161 %token <str> aKNOWNTYPE
162 %token <num> aNUM aHEXNUM
163 %token <dbl> aDOUBLE
164 %token <str> aSTRING
165 %token <uuid> aUUID
166 %token aEOF
167 %token SHL SHR
168 %token tAGGREGATABLE tALLOCATE tAPPOBJECT tASYNC tASYNCUUID
169 %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
170 %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
171 %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
172 %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
173 %token tDEFAULT
174 %token tDEFAULTCOLLELEM
175 %token tDEFAULTVALUE
176 %token tDEFAULTVTABLE
177 %token tDISPLAYBIND
178 %token tDISPINTERFACE
179 %token tDLLNAME tDOUBLE tDUAL
180 %token tENDPOINT
181 %token tENTRY tENUM tERRORSTATUST
182 %token tEXPLICITHANDLE tEXTERN
183 %token tFALSE
184 %token tFASTCALL
185 %token tFLOAT
186 %token tHANDLE
187 %token tHANDLET
188 %token tHELPCONTEXT tHELPFILE
189 %token tHELPSTRING tHELPSTRINGCONTEXT tHELPSTRINGDLL
190 %token tHIDDEN
191 %token tHYPER tID tIDEMPOTENT
192 %token tIIDIS
193 %token tIMMEDIATEBIND
194 %token tIMPLICITHANDLE
195 %token tIMPORT tIMPORTLIB
196 %token tIN tINLINE
197 %token tINPUTSYNC
198 %token tINT tINT64
199 %token tINTERFACE
200 %token tLCID
201 %token tLENGTHIS tLIBRARY
202 %token tLOCAL
203 %token tLONG
204 %token tMETHODS
205 %token tMODULE
206 %token tNONBROWSABLE
207 %token tNONCREATABLE
208 %token tNONEXTENSIBLE
209 %token tOBJECT tODL tOLEAUTOMATION
210 %token tOPTIONAL
211 %token tOUT
212 %token tPASCAL
213 %token tPOINTERDEFAULT
214 %token tPROPERTIES
215 %token tPROPGET tPROPPUT tPROPPUTREF
216 %token tPTR
217 %token tPUBLIC
218 %token tRANGE
219 %token tREADONLY tREF
220 %token tREQUESTEDIT
221 %token tRESTRICTED
222 %token tRETVAL
223 %token tSAFEARRAY
224 %token tSHORT
225 %token tSIGNED
226 %token tSINGLE
227 %token tSIZEIS tSIZEOF
228 %token tSMALL
229 %token tSOURCE
230 %token tSTDCALL
231 %token tSTRICTCONTEXTHANDLE
232 %token tSTRING tSTRUCT
233 %token tSWITCH tSWITCHIS tSWITCHTYPE
234 %token tTRANSMITAS
235 %token tTRUE
236 %token tTYPEDEF
237 %token tUNION
238 %token tUNIQUE
239 %token tUNSIGNED
240 %token tUUID
241 %token tV1ENUM
242 %token tVARARG
243 %token tVERSION
244 %token tVOID
245 %token tWCHAR tWIREMARSHAL
246
247 %type <attr> attribute
248 %type <attr_list> m_attributes attributes attrib_list
249 %type <str_list> str_list
250 %type <expr> m_expr expr expr_const
251 %type <expr_list> m_exprs /* exprs expr_list */ expr_list_const
252 %type <array_dims> array array_list
253 %type <ifinfo> interfacehdr
254 %type <type> inherit interface interfacedef interfacedec
255 %type <type> dispinterface dispinterfacehdr dispinterfacedef
256 %type <type> module modulehdr moduledef
257 %type <type> base_type int_std
258 %type <type> enumdef structdef uniondef
259 %type <type> type
260 %type <ifref> coclass_int
261 %type <ifref_list> gbl_statements coclass_ints
262 %type <var> arg field s_field case enum constdef externdef
263 %type <var_list> m_args no_args args fields cases enums enum_list dispint_props
264 %type <var> m_ident t_ident ident
265 %type <pident> pident func_ident direct_ident
266 %type <pident_list> pident_list
267 %type <func> funcdef
268 %type <func_list> int_statements dispint_meths
269 %type <type> coclass coclasshdr coclassdef
270 %type <num> pointer_type version
271 %type <str> libraryhdr callconv
272 %type <uuid> uuid_string
273 %type <num> import_start
274
275 %left ','
276 %right '?' ':'
277 %left '|'
278 %left '&'
279 %left '-' '+'
280 %left '*' '/'
281 %left SHL SHR
282 %right '~'
283 %right CAST
284 %right PPTR
285 %right NEG
286 %right ADDRESSOF
287
288 %%
289
290 input:   gbl_statements                         { fix_incomplete();
291                                                   check_all_user_types($1);
292                                                   write_proxies($1);
293                                                   write_client($1);
294                                                   write_server($1);
295                                                   write_dlldata($1);
296                                                 }
297         ;
298
299 gbl_statements:                                 { $$ = NULL; }
300         | gbl_statements interfacedec           { $$ = $1; }
301         | gbl_statements interfacedef           { $$ = append_ifref( $1, make_ifref($2) ); }
302         | gbl_statements coclass ';'            { $$ = $1;
303                                                   reg_type($2, $2->name, 0);
304                                                   if (!parse_only && do_header) write_coclass_forward($2);
305                                                 }
306         | gbl_statements coclassdef             { $$ = $1;
307                                                   add_typelib_entry($2);
308                                                   reg_type($2, $2->name, 0);
309                                                   if (!parse_only && do_header) write_coclass_forward($2);
310                                                 }
311         | gbl_statements moduledef              { $$ = $1; add_typelib_entry($2); }
312         | gbl_statements librarydef             { $$ = $1; }
313         | gbl_statements statement              { $$ = $1; }
314         ;
315
316 imp_statements:                                 {}
317         | imp_statements interfacedec           { if (!parse_only) add_typelib_entry($2); }
318         | imp_statements interfacedef           { if (!parse_only) add_typelib_entry($2); }
319         | imp_statements coclass ';'            { reg_type($2, $2->name, 0); if (!parse_only && do_header) write_coclass_forward($2); }
320         | imp_statements coclassdef             { if (!parse_only) add_typelib_entry($2);
321                                                   reg_type($2, $2->name, 0);
322                                                   if (!parse_only && do_header) write_coclass_forward($2);
323                                                 }
324         | imp_statements moduledef              { if (!parse_only) add_typelib_entry($2); }
325         | imp_statements statement              {}
326         | imp_statements importlib              {}
327         | imp_statements librarydef             {}
328         ;
329
330 int_statements:                                 { $$ = NULL; }
331         | int_statements funcdef ';'            { $$ = append_func( $1, $2 ); }
332         | int_statements statement              { $$ = $1; }
333         ;
334
335 semicolon_opt:
336         | ';'
337         ;
338
339 statement: constdef ';'                         { if (!parse_only && do_header) { write_constdef($1); } }
340         | cppquote                              {}
341         | enumdef ';'                           { if (!parse_only && do_header) {
342                                                     write_type_def_or_decl(header, $1, FALSE, NULL);
343                                                     fprintf(header, ";\n\n");
344                                                   }
345                                                 }
346         | externdef ';'                         { if (!parse_only && do_header) { write_externdef($1); } }
347         | import                                {}
348         | structdef ';'                         { if (!parse_only && do_header) {
349                                                     write_type_def_or_decl(header, $1, FALSE, NULL);
350                                                     fprintf(header, ";\n\n");
351                                                   }
352                                                 }
353         | typedef ';'                           {}
354         | uniondef ';'                          { if (!parse_only && do_header) {
355                                                     write_type_def_or_decl(header, $1, FALSE, NULL);
356                                                     fprintf(header, ";\n\n");
357                                                   }
358                                                 }
359         ;
360
361 cppquote: tCPPQUOTE '(' aSTRING ')'             { if (!parse_only && do_header) fprintf(header, "%s\n", $3); }
362         ;
363 import_start: tIMPORT aSTRING ';'               { assert(yychar == YYEMPTY);
364                                                   $$ = do_import($2);
365                                                   if (!$$) yychar = aEOF;
366                                                 }
367         ;
368
369 import: import_start imp_statements aEOF
370                                                 { if ($1) pop_import(); }
371         ;
372
373 importlib: tIMPORTLIB '(' aSTRING ')'
374            semicolon_opt                        { if(!parse_only) add_importlib($3); }
375         ;
376
377 libraryhdr: tLIBRARY aIDENTIFIER                { $$ = $2; }
378         ;
379 library_start: attributes libraryhdr '{'        { if (!parse_only) start_typelib($2, $1);
380                                                   if (!parse_only && do_header) write_library($2, $1);
381                                                   if (!parse_only && do_idfile) write_libid($2, $1);
382                                                 }
383         ;
384 librarydef: library_start imp_statements '}'
385             semicolon_opt                       { if (!parse_only) end_typelib(); }
386         ;
387
388 m_args:                                         { $$ = NULL; }
389         | args
390         ;
391
392 no_args:  tVOID                                 { $$ = NULL; }
393         ;
394
395 args:     arg                                   { check_arg($1); $$ = append_var( NULL, $1 ); }
396         | args ',' arg                          { check_arg($3); $$ = append_var( $1, $3); }
397         | no_args
398         ;
399
400 /* split into two rules to get bison to resolve a tVOID conflict */
401 arg:      attributes type pident array          { $$ = $3->var;
402                                                   $$->attrs = $1;
403                                                   set_type($$, $2, $3, $4, TRUE);
404                                                   free($3);
405                                                 }
406         | type pident array                     { $$ = $2->var;
407                                                   set_type($$, $1, $2, $3, TRUE);
408                                                   free($2);
409                                                 }
410         ;
411
412 array:                                          { $$ = NULL; }
413         | '[' array_list ']'                    { $$ = $2; }
414         | '[' '*' ']'                           { $$ = append_array( NULL, make_expr(EXPR_VOID) ); }
415         ;
416
417 array_list: m_expr /* size of first dimension is optional */ { $$ = append_array( NULL, $1 ); }
418         | array_list ',' expr                   { $$ = append_array( $1, $3 ); }
419         | array_list ']' '[' expr               { $$ = append_array( $1, $4 ); }
420         ;
421
422 m_attributes:                                   { $$ = NULL; }
423         | attributes
424         ;
425
426 attributes:
427           '[' attrib_list ']'                   { $$ = $2;
428                                                   if (!$$)
429                                                     error_loc("empty attribute lists unsupported\n");
430                                                 }
431         ;
432
433 attrib_list: attribute                          { $$ = append_attr( NULL, $1 ); }
434         | attrib_list ',' attribute             { $$ = append_attr( $1, $3 ); }
435         | attrib_list ']' '[' attribute         { $$ = append_attr( $1, $4 ); }
436         ;
437
438 str_list: aSTRING                               { $$ = append_str( NULL, $1 ); }
439         | str_list ',' aSTRING                  { $$ = append_str( $1, $3 ); }
440         ;
441
442 attribute:                                      { $$ = NULL; }
443         | tAGGREGATABLE                         { $$ = make_attr(ATTR_AGGREGATABLE); }
444         | tAPPOBJECT                            { $$ = make_attr(ATTR_APPOBJECT); }
445         | tASYNC                                { $$ = make_attr(ATTR_ASYNC); }
446         | tAUTOHANDLE                           { $$ = make_attr(ATTR_AUTO_HANDLE); }
447         | tBINDABLE                             { $$ = make_attr(ATTR_BINDABLE); }
448         | tCALLAS '(' ident ')'                 { $$ = make_attrp(ATTR_CALLAS, $3); }
449         | tCASE '(' expr_list_const ')'         { $$ = make_attrp(ATTR_CASE, $3); }
450         | tCONTEXTHANDLE                        { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
451         | tCONTEXTHANDLENOSERIALIZE             { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
452         | tCONTEXTHANDLESERIALIZE               { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
453         | tCONTROL                              { $$ = make_attr(ATTR_CONTROL); }
454         | tDEFAULT                              { $$ = make_attr(ATTR_DEFAULT); }
455         | tDEFAULTCOLLELEM                      { $$ = make_attr(ATTR_DEFAULTCOLLELEM); }
456         | tDEFAULTVALUE '(' expr_const ')'      { $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); }
457         | tDEFAULTVALUE '(' aSTRING ')'         { $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); }
458         | tDEFAULTVTABLE                        { $$ = make_attr(ATTR_DEFAULTVTABLE); }
459         | tDISPLAYBIND                          { $$ = make_attr(ATTR_DISPLAYBIND); }
460         | tDLLNAME '(' aSTRING ')'              { $$ = make_attrp(ATTR_DLLNAME, $3); }
461         | tDUAL                                 { $$ = make_attr(ATTR_DUAL); }
462         | tENDPOINT '(' str_list ')'            { $$ = make_attrp(ATTR_ENDPOINT, $3); }
463         | tENTRY '(' aSTRING ')'                { $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
464         | tENTRY '(' expr_const ')'             { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
465         | tEXPLICITHANDLE                       { $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
466         | tHANDLE                               { $$ = make_attr(ATTR_HANDLE); }
467         | tHELPCONTEXT '(' expr_const ')'       { $$ = make_attrp(ATTR_HELPCONTEXT, $3); }
468         | tHELPFILE '(' aSTRING ')'             { $$ = make_attrp(ATTR_HELPFILE, $3); }
469         | tHELPSTRING '(' aSTRING ')'           { $$ = make_attrp(ATTR_HELPSTRING, $3); }
470         | tHELPSTRINGCONTEXT '(' expr_const ')' { $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); }
471         | tHELPSTRINGDLL '(' aSTRING ')'        { $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); }
472         | tHIDDEN                               { $$ = make_attr(ATTR_HIDDEN); }
473         | tID '(' expr_const ')'                { $$ = make_attrp(ATTR_ID, $3); }
474         | tIDEMPOTENT                           { $$ = make_attr(ATTR_IDEMPOTENT); }
475         | tIIDIS '(' expr ')'                   { $$ = make_attrp(ATTR_IIDIS, $3); }
476         | tIMMEDIATEBIND                        { $$ = make_attr(ATTR_IMMEDIATEBIND); }
477         | tIMPLICITHANDLE '(' tHANDLET aIDENTIFIER ')'  { $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $4); }
478         | tIN                                   { $$ = make_attr(ATTR_IN); }
479         | tINPUTSYNC                            { $$ = make_attr(ATTR_INPUTSYNC); }
480         | tLENGTHIS '(' m_exprs ')'             { $$ = make_attrp(ATTR_LENGTHIS, $3); }
481         | tLOCAL                                { $$ = make_attr(ATTR_LOCAL); }
482         | tNONBROWSABLE                         { $$ = make_attr(ATTR_NONBROWSABLE); }
483         | tNONCREATABLE                         { $$ = make_attr(ATTR_NONCREATABLE); }
484         | tNONEXTENSIBLE                        { $$ = make_attr(ATTR_NONEXTENSIBLE); }
485         | tOBJECT                               { $$ = make_attr(ATTR_OBJECT); }
486         | tODL                                  { $$ = make_attr(ATTR_ODL); }
487         | tOLEAUTOMATION                        { $$ = make_attr(ATTR_OLEAUTOMATION); }
488         | tOPTIONAL                             { $$ = make_attr(ATTR_OPTIONAL); }
489         | tOUT                                  { $$ = make_attr(ATTR_OUT); }
490         | tPOINTERDEFAULT '(' pointer_type ')'  { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
491         | tPROPGET                              { $$ = make_attr(ATTR_PROPGET); }
492         | tPROPPUT                              { $$ = make_attr(ATTR_PROPPUT); }
493         | tPROPPUTREF                           { $$ = make_attr(ATTR_PROPPUTREF); }
494         | tPUBLIC                               { $$ = make_attr(ATTR_PUBLIC); }
495         | tRANGE '(' expr_const ',' expr_const ')' { expr_list_t *list = append_expr( NULL, $3 );
496                                                      list = append_expr( list, $5 );
497                                                      $$ = make_attrp(ATTR_RANGE, list); }
498         | tREADONLY                             { $$ = make_attr(ATTR_READONLY); }
499         | tREQUESTEDIT                          { $$ = make_attr(ATTR_REQUESTEDIT); }
500         | tRESTRICTED                           { $$ = make_attr(ATTR_RESTRICTED); }
501         | tRETVAL                               { $$ = make_attr(ATTR_RETVAL); }
502         | tSIZEIS '(' m_exprs ')'               { $$ = make_attrp(ATTR_SIZEIS, $3); }
503         | tSOURCE                               { $$ = make_attr(ATTR_SOURCE); }
504         | tSTRICTCONTEXTHANDLE                  { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); }
505         | tSTRING                               { $$ = make_attr(ATTR_STRING); }
506         | tSWITCHIS '(' expr ')'                { $$ = make_attrp(ATTR_SWITCHIS, $3); }
507         | tSWITCHTYPE '(' type ')'              { $$ = make_attrp(ATTR_SWITCHTYPE, $3); }
508         | tTRANSMITAS '(' type ')'              { $$ = make_attrp(ATTR_TRANSMITAS, $3); }
509         | tUUID '(' uuid_string ')'             { $$ = make_attrp(ATTR_UUID, $3); }
510         | tV1ENUM                               { $$ = make_attr(ATTR_V1ENUM); }
511         | tVARARG                               { $$ = make_attr(ATTR_VARARG); }
512         | tVERSION '(' version ')'              { $$ = make_attrv(ATTR_VERSION, $3); }
513         | tWIREMARSHAL '(' type ')'             { $$ = make_attrp(ATTR_WIREMARSHAL, $3); }
514         | pointer_type                          { $$ = make_attrv(ATTR_POINTERTYPE, $1); }
515         ;
516
517 uuid_string:
518           aUUID
519         | aSTRING                               { if (!is_valid_uuid($1))
520                                                     error_loc("invalid UUID: %s\n", $1);
521                                                   $$ = parse_uuid($1); }
522         ;
523
524 callconv: tCDECL                                { $$ = $<str>1; }
525         | tFASTCALL                             { $$ = $<str>1; }
526         | tPASCAL                               { $$ = $<str>1; }
527         | tSTDCALL                              { $$ = $<str>1; }
528         ;
529
530 cases:                                          { $$ = NULL; }
531         | cases case                            { $$ = append_var( $1, $2 ); }
532         ;
533
534 case:     tCASE expr ':' field                  { attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, $2 ));
535                                                   $$ = $4; if (!$$) $$ = make_var(NULL);
536                                                   $$->attrs = append_attr( $$->attrs, a );
537                                                 }
538         | tDEFAULT ':' field                    { attr_t *a = make_attr(ATTR_DEFAULT);
539                                                   $$ = $3; if (!$$) $$ = make_var(NULL);
540                                                   $$->attrs = append_attr( $$->attrs, a );
541                                                 }
542         ;
543
544 constdef: tCONST type ident '=' expr_const      { $$ = reg_const($3);
545                                                   set_type($$, $2, NULL, NULL, FALSE);
546                                                   $$->eval = $5;
547                                                 }
548         ;
549
550 enums:                                          { $$ = NULL; }
551         | enum_list ','                         { $$ = $1; }
552         | enum_list
553         ;
554
555 enum_list: enum                                 { if (!$1->eval)
556                                                     $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */);
557                                                   $$ = append_var( NULL, $1 );
558                                                 }
559         | enum_list ',' enum                    { if (!$3->eval)
560                                                   {
561                                                     var_t *last = LIST_ENTRY( list_tail($$), var_t, entry );
562                                                     $3->eval = make_exprl(EXPR_NUM, last->eval->cval + 1);
563                                                   }
564                                                   $$ = append_var( $1, $3 );
565                                                 }
566         ;
567
568 enum:     ident '=' expr_const                  { $$ = reg_const($1);
569                                                   $$->eval = $3;
570                                                   $$->type = make_int(0);
571                                                 }
572         | ident                                 { $$ = reg_const($1);
573                                                   $$->type = make_int(0);
574                                                 }
575         ;
576
577 enumdef: tENUM t_ident '{' enums '}'            { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
578                                                   $$->kind = TKIND_ENUM;
579                                                   $$->fields_or_args = $4;
580                                                   $$->defined = TRUE;
581                                                   if(in_typelib)
582                                                       add_typelib_entry($$);
583                                                 }
584         ;
585
586 m_exprs:  m_expr                                { $$ = append_expr( NULL, $1 ); }
587         | m_exprs ',' m_expr                    { $$ = append_expr( $1, $3 ); }
588         ;
589
590 /*
591 exprs:                                          { $$ = make_expr(EXPR_VOID); }
592         | expr_list
593         ;
594
595 expr_list: expr
596         | expr_list ',' expr                    { LINK($3, $1); $$ = $3; }
597         ;
598 */
599
600 m_expr:                                         { $$ = make_expr(EXPR_VOID); }
601         | expr
602         ;
603
604 expr:     aNUM                                  { $$ = make_exprl(EXPR_NUM, $1); }
605         | aHEXNUM                               { $$ = make_exprl(EXPR_HEXNUM, $1); }
606         | aDOUBLE                               { $$ = make_exprd(EXPR_DOUBLE, $1); }
607         | tFALSE                                { $$ = make_exprl(EXPR_TRUEFALSE, 0); }
608         | tTRUE                                 { $$ = make_exprl(EXPR_TRUEFALSE, 1); }
609         | aIDENTIFIER                           { $$ = make_exprs(EXPR_IDENTIFIER, $1); }
610         | expr '?' expr ':' expr                { $$ = make_expr3(EXPR_COND, $1, $3, $5); }
611         | expr '|' expr                         { $$ = make_expr2(EXPR_OR , $1, $3); }
612         | expr '&' expr                         { $$ = make_expr2(EXPR_AND, $1, $3); }
613         | expr '+' expr                         { $$ = make_expr2(EXPR_ADD, $1, $3); }
614         | expr '-' expr                         { $$ = make_expr2(EXPR_SUB, $1, $3); }
615         | expr '*' expr                         { $$ = make_expr2(EXPR_MUL, $1, $3); }
616         | expr '/' expr                         { $$ = make_expr2(EXPR_DIV, $1, $3); }
617         | expr SHL expr                         { $$ = make_expr2(EXPR_SHL, $1, $3); }
618         | expr SHR expr                         { $$ = make_expr2(EXPR_SHR, $1, $3); }
619         | '~' expr                              { $$ = make_expr1(EXPR_NOT, $2); }
620         | '-' expr %prec NEG                    { $$ = make_expr1(EXPR_NEG, $2); }
621         | '&' expr %prec ADDRESSOF      { $$ = make_expr1(EXPR_ADDRESSOF, $2); }
622         | '*' expr %prec PPTR                   { $$ = make_expr1(EXPR_PPTR, $2); }
623         | '(' type ')' expr %prec CAST          { $$ = make_exprt(EXPR_CAST, $2, $4); }
624         | tSIZEOF '(' type ')'                  { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
625         | '(' expr ')'                          { $$ = $2; }
626         ;
627
628 expr_list_const: expr_const                     { $$ = append_expr( NULL, $1 ); }
629         | expr_list_const ',' expr_const        { $$ = append_expr( $1, $3 ); }
630         ;
631
632 expr_const: expr                                { $$ = $1;
633                                                   if (!$$->is_const)
634                                                       error_loc("expression is not constant\n");
635                                                 }
636         ;
637
638 externdef: tEXTERN tCONST type ident            { $$ = $4;
639                                                   set_type($$, $3, NULL, NULL, FALSE);
640                                                 }
641         ;
642
643 fields:                                         { $$ = NULL; }
644         | fields field                          { $$ = append_var( $1, $2 ); }
645         ;
646
647 field:    s_field ';'                           { $$ = $1; }
648         | m_attributes uniondef ';'             { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
649         | attributes ';'                        { $$ = make_var(NULL); $$->attrs = $1; }
650         | ';'                                   { $$ = NULL; }
651         ;
652
653 s_field:  m_attributes type pident array        { $$ = $3->var;
654                                                   $$->attrs = $1;
655                                                   set_type($$, $2, $3, $4, FALSE);
656                                                   free($3);
657                                                 }
658         ;
659
660 funcdef:
661           m_attributes type pident              { var_t *v = $3->var;
662                                                   var_list_t *args = $3->args;
663                                                   v->attrs = $1;
664                                                   set_type(v, $2, $3, NULL, FALSE);
665                                                   free($3);
666                                                   $$ = make_func(v, args);
667                                                   if (is_attr(v->attrs, ATTR_IN)) {
668                                                     error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name);
669                                                   }
670                                                 }
671         ;
672
673 m_ident:                                        { $$ = NULL; }
674         | ident
675         ;
676
677 t_ident:                                        { $$ = NULL; }
678         | aIDENTIFIER                           { $$ = make_var($1); }
679         | aKNOWNTYPE                            { $$ = make_var($1); }
680         ;
681
682 ident:    aIDENTIFIER                           { $$ = make_var($1); }
683 /* some "reserved words" used in attributes are also used as field names in some MS IDL files */
684         | aKNOWNTYPE                            { $$ = make_var($<str>1); }
685         ;
686
687 base_type: tBYTE                                { $$ = make_builtin($<str>1); }
688         | tWCHAR                                { $$ = make_builtin($<str>1); }
689         | int_std
690         | tSIGNED int_std                       { $$ = $2; $$->sign = 1; }
691         | tUNSIGNED int_std                     { $$ = $2; $$->sign = -1;
692                                                   switch ($$->type) {
693                                                   case RPC_FC_CHAR:  break;
694                                                   case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
695                                                   case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
696                                                   case RPC_FC_LONG:  $$->type = RPC_FC_ULONG;  break;
697                                                   case RPC_FC_HYPER:
698                                                     if ($$->name[0] == 'h') /* hyper, as opposed to __int64 */
699                                                     {
700                                                       $$ = alias($$, "MIDL_uhyper");
701                                                       $$->sign = 0;
702                                                     }
703                                                     break;
704                                                   default: break;
705                                                   }
706                                                 }
707         | tUNSIGNED                             { $$ = make_int(-1); }
708         | tFLOAT                                { $$ = make_builtin($<str>1); }
709         | tSINGLE                               { $$ = duptype(find_type("float", 0), 1); }
710         | tDOUBLE                               { $$ = make_builtin($<str>1); }
711         | tBOOLEAN                              { $$ = make_builtin($<str>1); }
712         | tERRORSTATUST                         { $$ = make_builtin($<str>1); }
713         | tHANDLET                              { $$ = make_builtin($<str>1); }
714         ;
715
716 m_int:
717         | tINT
718         ;
719
720 int_std:  tINT                                  { $$ = make_builtin($<str>1); }
721         | tSHORT m_int                          { $$ = make_builtin($<str>1); }
722         | tSMALL                                { $$ = make_builtin($<str>1); }
723         | tLONG m_int                           { $$ = make_builtin($<str>1); }
724         | tHYPER m_int                          { $$ = make_builtin($<str>1); }
725         | tINT64                                { $$ = make_builtin($<str>1); }
726         | tCHAR                                 { $$ = make_builtin($<str>1); }
727         ;
728
729 coclass:  tCOCLASS aIDENTIFIER                  { $$ = make_class($2); }
730         | tCOCLASS aKNOWNTYPE                   { $$ = find_type($2, 0);
731                                                   if ($$->defined) error_loc("multiple definition error\n");
732                                                   if ($$->kind != TKIND_COCLASS) error_loc("%s was not declared a coclass\n", $2);
733                                                 }
734         ;
735
736 coclasshdr: attributes coclass                  { $$ = $2;
737                                                   $$->attrs = $1;
738                                                   if (!parse_only && do_header)
739                                                     write_coclass($$);
740                                                   if (!parse_only && do_idfile)
741                                                     write_clsid($$);
742                                                 }
743         ;
744
745 coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
746                                                 { $$ = $1;
747                                                   $$->ifaces = $3;
748                                                   $$->defined = TRUE;
749                                                 }
750         ;
751
752 coclass_ints:                                   { $$ = NULL; }
753         | coclass_ints coclass_int              { $$ = append_ifref( $1, $2 ); }
754         ;
755
756 coclass_int:
757           m_attributes interfacedec             { $$ = make_ifref($2); $$->attrs = $1; }
758         ;
759
760 dispinterface: tDISPINTERFACE aIDENTIFIER       { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; }
761         |      tDISPINTERFACE aKNOWNTYPE        { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; }
762         ;
763
764 dispinterfacehdr: attributes dispinterface      { attr_t *attrs;
765                                                   is_object_interface = TRUE;
766                                                   $$ = $2;
767                                                   if ($$->defined) error_loc("multiple definition error\n");
768                                                   attrs = make_attr(ATTR_DISPINTERFACE);
769                                                   $$->attrs = append_attr( $1, attrs );
770                                                   $$->ref = find_type("IDispatch", 0);
771                                                   if (!$$->ref) error_loc("IDispatch is undefined\n");
772                                                   $$->defined = TRUE;
773                                                   if (!parse_only && do_header) write_forward($$);
774                                                 }
775         ;
776
777 dispint_props: tPROPERTIES ':'                  { $$ = NULL; }
778         | dispint_props s_field ';'             { $$ = append_var( $1, $2 ); }
779         ;
780
781 dispint_meths: tMETHODS ':'                     { $$ = NULL; }
782         | dispint_meths funcdef ';'             { $$ = append_func( $1, $2 ); }
783         ;
784
785 dispinterfacedef: dispinterfacehdr '{'
786           dispint_props
787           dispint_meths
788           '}'                                   { $$ = $1;
789                                                   $$->fields_or_args = $3;
790                                                   $$->funcs = $4;
791                                                   if (!parse_only && do_header) write_dispinterface($$);
792                                                   if (!parse_only && do_idfile) write_diid($$);
793                                                 }
794         | dispinterfacehdr
795          '{' interface ';' '}'                  { $$ = $1;
796                                                   $$->fields_or_args = $3->fields_or_args;
797                                                   $$->funcs = $3->funcs;
798                                                   if (!parse_only && do_header) write_dispinterface($$);
799                                                   if (!parse_only && do_idfile) write_diid($$);
800                                                 }
801         ;
802
803 inherit:                                        { $$ = NULL; }
804         | ':' aKNOWNTYPE                        { $$ = find_type2($2, 0); }
805         ;
806
807 interface: tINTERFACE aIDENTIFIER               { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; }
808         |  tINTERFACE aKNOWNTYPE                { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; }
809         ;
810
811 interfacehdr: attributes interface              { $$.interface = $2;
812                                                   $$.old_pointer_default = pointer_default;
813                                                   if (is_attr($1, ATTR_POINTERDEFAULT))
814                                                     pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
815                                                   is_object_interface = is_object($1);
816                                                   if ($2->defined) error_loc("multiple definition error\n");
817                                                   $2->attrs = $1;
818                                                   $2->defined = TRUE;
819                                                   if (!parse_only && do_header) write_forward($2);
820                                                 }
821         ;
822
823 interfacedef: interfacehdr inherit
824           '{' int_statements '}' semicolon_opt  { $$ = $1.interface;
825                                                   $$->ref = $2;
826                                                   $$->funcs = $4;
827                                                   compute_method_indexes($$);
828                                                   if (!parse_only && do_header) write_interface($$);
829                                                   if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
830                                                   if (!parse_only && do_idfile) write_iid($$);
831                                                   pointer_default = $1.old_pointer_default;
832                                                 }
833 /* MIDL is able to import the definition of a base class from inside the
834  * definition of a derived class, I'll try to support it with this rule */
835         | interfacehdr ':' aIDENTIFIER
836           '{' import int_statements '}'
837            semicolon_opt                        { $$ = $1.interface;
838                                                   $$->ref = find_type2($3, 0);
839                                                   if (!$$->ref) error_loc("base class '%s' not found in import\n", $3);
840                                                   $$->funcs = $6;
841                                                   compute_method_indexes($$);
842                                                   if (!parse_only && do_header) write_interface($$);
843                                                   if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
844                                                   if (!parse_only && do_idfile) write_iid($$);
845                                                   pointer_default = $1.old_pointer_default;
846                                                 }
847         | dispinterfacedef semicolon_opt        { $$ = $1; }
848         ;
849
850 interfacedec:
851           interface ';'                         { $$ = $1; if (!parse_only && do_header) write_forward($$); }
852         | dispinterface ';'                     { $$ = $1; if (!parse_only && do_header) write_forward($$); }
853         ;
854
855 module:   tMODULE aIDENTIFIER                   { $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; }
856         | tMODULE aKNOWNTYPE                    { $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; }
857         ;
858
859 modulehdr: attributes module                    { $$ = $2;
860                                                   $$->attrs = $1;
861                                                 }
862         ;
863
864 moduledef: modulehdr '{' int_statements '}'
865            semicolon_opt                        { $$ = $1;
866                                                   $$->funcs = $3;
867                                                   /* FIXME: if (!parse_only && do_header) write_module($$); */
868                                                 }
869         ;
870
871 pident:   '*' pident %prec PPTR                 { $$ = $2; $$->ptr_level++; }
872         | tCONST pident                         { $$ = $2; /* FIXME */ }
873         | callconv pident                       { $$ = $2;
874                                                   if ($$->callconv) parser_warning("multiple calling conventions %s, %s for function %s\n", $$->callconv, $1, $$->var->name);
875                                                   $$->callconv = $1;
876                                                 }
877         | direct_ident
878         ;
879
880 func_ident: direct_ident '(' m_args ')'
881                                                 { $$ = $1;
882                                                   $1->args = $3;
883                                                   $1->is_func = TRUE;
884                                                 }
885         ;
886
887 direct_ident: ident                             { $$ = make_pident($1); }
888         | '(' pident ')'                        { $$ = $2; }
889         | func_ident                            { $$ = $1;
890                                                   $$->func_ptr_level = $$->ptr_level;
891                                                   $$->ptr_level = 0;
892                                                 }
893         ;
894
895 pident_list:
896         pident                                  { $$ = append_pident( NULL, $1 ); }
897         | pident_list ',' pident                { $$ = append_pident( $1, $3 ); }
898         ;
899
900 pointer_type:
901           tREF                                  { $$ = RPC_FC_RP; }
902         | tUNIQUE                               { $$ = RPC_FC_UP; }
903         | tPTR                                  { $$ = RPC_FC_FP; }
904         ;
905
906 structdef: tSTRUCT t_ident '{' fields '}'       { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
907                                                   /* overwrite RPC_FC_STRUCT with a more exact type */
908                                                   $$->type = get_struct_type( $4 );
909                                                   $$->kind = TKIND_RECORD;
910                                                   $$->fields_or_args = $4;
911                                                   $$->defined = TRUE;
912                                                   if(in_typelib)
913                                                       add_typelib_entry($$);
914                                                 }
915         ;
916
917 type:     tVOID                                 { $$ = duptype(find_type("void", 0), 1); }
918         | aKNOWNTYPE                            { $$ = find_type($1, 0); }
919         | base_type                             { $$ = $1; }
920         | tCONST type                           { $$ = duptype($2, 1); $$->is_const = TRUE; }
921         | enumdef                               { $$ = $1; }
922         | tENUM aIDENTIFIER                     { $$ = find_type2($2, tsENUM); }
923         | structdef                             { $$ = $1; }
924         | tSTRUCT aIDENTIFIER                   { $$ = get_type(RPC_FC_STRUCT, $2, tsSTRUCT); }
925         | uniondef                              { $$ = $1; }
926         | tUNION aIDENTIFIER                    { $$ = find_type2($2, tsUNION); }
927         | tSAFEARRAY '(' type ')'               { $$ = make_safearray($3); }
928         ;
929
930 typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, $2);
931                                                   process_typedefs($4);
932                                                 }
933         ;
934
935 uniondef: tUNION t_ident '{' fields '}'         { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
936                                                   $$->kind = TKIND_UNION;
937                                                   $$->fields_or_args = $4;
938                                                   $$->defined = TRUE;
939                                                 }
940         | tUNION t_ident
941           tSWITCH '(' s_field ')'
942           m_ident '{' cases '}'                 { var_t *u = $7;
943                                                   $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
944                                                   $$->kind = TKIND_UNION;
945                                                   if (!u) u = make_var( xstrdup("tagged_union") );
946                                                   u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
947                                                   u->type->kind = TKIND_UNION;
948                                                   u->type->fields_or_args = $9;
949                                                   u->type->defined = TRUE;
950                                                   $$->fields_or_args = append_var( $$->fields_or_args, $5 );
951                                                   $$->fields_or_args = append_var( $$->fields_or_args, u );
952                                                   $$->defined = TRUE;
953                                                 }
954         ;
955
956 version:
957           aNUM                                  { $$ = MAKEVERSION($1, 0); }
958         | aNUM '.' aNUM                         { $$ = MAKEVERSION($1, $3); }
959         ;
960
961 %%
962
963 static void decl_builtin(const char *name, unsigned char type)
964 {
965   type_t *t = make_type(type, NULL);
966   t->name = xstrdup(name);
967   reg_type(t, name, 0);
968 }
969
970 static type_t *make_builtin(char *name)
971 {
972   /* NAME is strdup'd in the lexer */
973   type_t *t = duptype(find_type(name, 0), 0);
974   t->name = name;
975   return t;
976 }
977
978 static type_t *make_int(int sign)
979 {
980   type_t *t = duptype(find_type("int", 0), 1);
981
982   t->sign = sign;
983   if (sign < 0)
984     t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT;
985
986   return t;
987 }
988
989 void init_types(void)
990 {
991   decl_builtin("void", 0);
992   decl_builtin("byte", RPC_FC_BYTE);
993   decl_builtin("wchar_t", RPC_FC_WCHAR);
994   decl_builtin("int", RPC_FC_LONG);     /* win32 */
995   decl_builtin("short", RPC_FC_SHORT);
996   decl_builtin("small", RPC_FC_SMALL);
997   decl_builtin("long", RPC_FC_LONG);
998   decl_builtin("hyper", RPC_FC_HYPER);
999   decl_builtin("__int64", RPC_FC_HYPER);
1000   decl_builtin("char", RPC_FC_CHAR);
1001   decl_builtin("float", RPC_FC_FLOAT);
1002   decl_builtin("double", RPC_FC_DOUBLE);
1003   decl_builtin("boolean", RPC_FC_BYTE);
1004   decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T);
1005   decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE);
1006 }
1007
1008 static str_list_t *append_str(str_list_t *list, char *str)
1009 {
1010     struct str_list_entry_t *entry;
1011
1012     if (!str) return list;
1013     if (!list)
1014     {
1015         list = xmalloc( sizeof(*list) );
1016         list_init( list );
1017     }
1018     entry = xmalloc( sizeof(*entry) );
1019     entry->str = str;
1020     list_add_tail( list, &entry->entry );
1021     return list;
1022 }
1023
1024 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
1025 {
1026     if (!attr) return list;
1027     if (!list)
1028     {
1029         list = xmalloc( sizeof(*list) );
1030         list_init( list );
1031     }
1032     list_add_tail( list, &attr->entry );
1033     return list;
1034 }
1035
1036 static attr_t *make_attr(enum attr_type type)
1037 {
1038   attr_t *a = xmalloc(sizeof(attr_t));
1039   a->type = type;
1040   a->u.ival = 0;
1041   return a;
1042 }
1043
1044 static attr_t *make_attrv(enum attr_type type, unsigned long val)
1045 {
1046   attr_t *a = xmalloc(sizeof(attr_t));
1047   a->type = type;
1048   a->u.ival = val;
1049   return a;
1050 }
1051
1052 static attr_t *make_attrp(enum attr_type type, void *val)
1053 {
1054   attr_t *a = xmalloc(sizeof(attr_t));
1055   a->type = type;
1056   a->u.pval = val;
1057   return a;
1058 }
1059
1060 static expr_t *make_expr(enum expr_type type)
1061 {
1062   expr_t *e = xmalloc(sizeof(expr_t));
1063   e->type = type;
1064   e->ref = NULL;
1065   e->u.lval = 0;
1066   e->is_const = FALSE;
1067   e->cval = 0;
1068   return e;
1069 }
1070
1071 static expr_t *make_exprl(enum expr_type type, long val)
1072 {
1073   expr_t *e = xmalloc(sizeof(expr_t));
1074   e->type = type;
1075   e->ref = NULL;
1076   e->u.lval = val;
1077   e->is_const = FALSE;
1078   /* check for numeric constant */
1079   if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) {
1080     /* make sure true/false value is valid */
1081     assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
1082     e->is_const = TRUE;
1083     e->cval = val;
1084   }
1085   return e;
1086 }
1087
1088 static expr_t *make_exprd(enum expr_type type, double val)
1089 {
1090   expr_t *e = xmalloc(sizeof(expr_t));
1091   e->type = type;
1092   e->ref = NULL;
1093   e->u.dval = val;
1094   e->is_const = TRUE;
1095   e->cval = val;
1096   return e;
1097 }
1098
1099 static expr_t *make_exprs(enum expr_type type, char *val)
1100 {
1101   expr_t *e;
1102   e = xmalloc(sizeof(expr_t));
1103   e->type = type;
1104   e->ref = NULL;
1105   e->u.sval = val;
1106   e->is_const = FALSE;
1107   /* check for predefined constants */
1108   if (type == EXPR_IDENTIFIER) {
1109     var_t *c = find_const(val, 0);
1110     if (c) {
1111       e->u.sval = c->name;
1112       free(val);
1113       e->is_const = TRUE;
1114       e->cval = c->eval->cval;
1115     }
1116   }
1117   return e;
1118 }
1119
1120 static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
1121 {
1122   expr_t *e;
1123   e = xmalloc(sizeof(expr_t));
1124   e->type = type;
1125   e->ref = expr;
1126   e->u.tref = tref;
1127   e->is_const = FALSE;
1128   /* check for cast of constant expression */
1129   if (type == EXPR_SIZEOF) {
1130     switch (tref->type) {
1131       case RPC_FC_BYTE:
1132       case RPC_FC_CHAR:
1133       case RPC_FC_SMALL:
1134       case RPC_FC_USMALL:
1135         e->is_const = TRUE;
1136         e->cval = 1;
1137         break;
1138       case RPC_FC_WCHAR:
1139       case RPC_FC_USHORT:
1140       case RPC_FC_SHORT:
1141         e->is_const = TRUE;
1142         e->cval = 2;
1143         break;
1144       case RPC_FC_LONG:
1145       case RPC_FC_ULONG:
1146       case RPC_FC_FLOAT:
1147       case RPC_FC_ERROR_STATUS_T:
1148         e->is_const = TRUE;
1149         e->cval = 4;
1150         break;
1151       case RPC_FC_HYPER:
1152       case RPC_FC_DOUBLE:
1153         e->is_const = TRUE;
1154         e->cval = 8;
1155         break;
1156     }
1157   }
1158   if (type == EXPR_CAST && expr->is_const) {
1159     e->is_const = TRUE;
1160     e->cval = expr->cval;
1161   }
1162   return e;
1163 }
1164
1165 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
1166 {
1167   expr_t *e;
1168   if (type == EXPR_ADDRESSOF && expr->type != EXPR_IDENTIFIER)
1169     error("address-of operator applied to invalid expression\n");
1170   e = xmalloc(sizeof(expr_t));
1171   e->type = type;
1172   e->ref = expr;
1173   e->u.lval = 0;
1174   e->is_const = FALSE;
1175   /* check for compile-time optimization */
1176   if (expr->is_const) {
1177     e->is_const = TRUE;
1178     switch (type) {
1179     case EXPR_NEG:
1180       e->cval = -expr->cval;
1181       break;
1182     case EXPR_NOT:
1183       e->cval = ~expr->cval;
1184       break;
1185     default:
1186       e->is_const = FALSE;
1187       break;
1188     }
1189   }
1190   return e;
1191 }
1192
1193 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
1194 {
1195   expr_t *e;
1196   e = xmalloc(sizeof(expr_t));
1197   e->type = type;
1198   e->ref = expr1;
1199   e->u.ext = expr2;
1200   e->is_const = FALSE;
1201   /* check for compile-time optimization */
1202   if (expr1->is_const && expr2->is_const) {
1203     e->is_const = TRUE;
1204     switch (type) {
1205     case EXPR_ADD:
1206       e->cval = expr1->cval + expr2->cval;
1207       break;
1208     case EXPR_SUB:
1209       e->cval = expr1->cval - expr2->cval;
1210       break;
1211     case EXPR_MUL:
1212       e->cval = expr1->cval * expr2->cval;
1213       break;
1214     case EXPR_DIV:
1215       e->cval = expr1->cval / expr2->cval;
1216       break;
1217     case EXPR_OR:
1218       e->cval = expr1->cval | expr2->cval;
1219       break;
1220     case EXPR_AND:
1221       e->cval = expr1->cval & expr2->cval;
1222       break;
1223     case EXPR_SHL:
1224       e->cval = expr1->cval << expr2->cval;
1225       break;
1226     case EXPR_SHR:
1227       e->cval = expr1->cval >> expr2->cval;
1228       break;
1229     default:
1230       e->is_const = FALSE;
1231       break;
1232     }
1233   }
1234   return e;
1235 }
1236
1237 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
1238 {
1239   expr_t *e;
1240   e = xmalloc(sizeof(expr_t));
1241   e->type = type;
1242   e->ref = expr1;
1243   e->u.ext = expr2;
1244   e->ext2 = expr3;
1245   e->is_const = FALSE;
1246   /* check for compile-time optimization */
1247   if (expr1->is_const && expr2->is_const && expr3->is_const) {
1248     e->is_const = TRUE;
1249     switch (type) {
1250     case EXPR_COND:
1251       e->cval = expr1->cval ? expr2->cval : expr3->cval;
1252       break;
1253     default:
1254       e->is_const = FALSE;
1255       break;
1256     }
1257   }
1258   return e;
1259 }
1260
1261 static expr_list_t *append_expr(expr_list_t *list, expr_t *expr)
1262 {
1263     if (!expr) return list;
1264     if (!list)
1265     {
1266         list = xmalloc( sizeof(*list) );
1267         list_init( list );
1268     }
1269     list_add_tail( list, &expr->entry );
1270     return list;
1271 }
1272
1273 static array_dims_t *append_array(array_dims_t *list, expr_t *expr)
1274 {
1275     if (!expr) return list;
1276     if (!list)
1277     {
1278         list = xmalloc( sizeof(*list) );
1279         list_init( list );
1280     }
1281     list_add_tail( list, &expr->entry );
1282     return list;
1283 }
1284
1285 static struct list type_pool = LIST_INIT(type_pool);
1286 typedef struct
1287 {
1288   type_t data;
1289   struct list link;
1290 } type_pool_node_t;
1291
1292 type_t *alloc_type(void)
1293 {
1294   type_pool_node_t *node = xmalloc(sizeof *node);
1295   list_add_tail(&type_pool, &node->link);
1296   return &node->data;
1297 }
1298
1299 void set_all_tfswrite(int val)
1300 {
1301   type_pool_node_t *node;
1302   LIST_FOR_EACH_ENTRY(node, &type_pool, type_pool_node_t, link)
1303     node->data.tfswrite = val;
1304 }
1305
1306 static type_t *make_type(unsigned char type, type_t *ref)
1307 {
1308   type_t *t = alloc_type();
1309   t->name = NULL;
1310   t->kind = TKIND_PRIMITIVE;
1311   t->type = type;
1312   t->ref = ref;
1313   t->attrs = NULL;
1314   t->orig = NULL;
1315   t->funcs = NULL;
1316   t->fields_or_args = NULL;
1317   t->ifaces = NULL;
1318   t->dim = 0;
1319   t->size_is = NULL;
1320   t->length_is = NULL;
1321   t->typestring_offset = 0;
1322   t->ptrdesc = 0;
1323   t->declarray = FALSE;
1324   t->ignore = (parse_only != 0);
1325   t->is_const = FALSE;
1326   t->sign = 0;
1327   t->defined = FALSE;
1328   t->written = FALSE;
1329   t->user_types_registered = FALSE;
1330   t->tfswrite = FALSE;
1331   t->typelib_idx = -1;
1332   return t;
1333 }
1334
1335 static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_t *arr,
1336                      int top)
1337 {
1338   expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS);
1339   expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS);
1340   int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE);
1341   int ptr_type = ptr_attr;
1342   int sizeless, has_varconf;
1343   expr_t *dim;
1344   type_t *atype, **ptype;
1345   int ptr_level = (pident ? pident->ptr_level : 0);
1346
1347   v->type = type;
1348
1349   if (!ptr_type && top)
1350     ptr_type = RPC_FC_RP;
1351
1352   for ( ; 0 < ptr_level; --ptr_level)
1353   {
1354     v->type = make_type(pointer_default, v->type);
1355     if (ptr_level == 1 && ptr_type && !arr)
1356     {
1357       v->type->type = ptr_type;
1358       ptr_type = 0;
1359     }
1360   }
1361
1362   if (ptr_type && !arr)
1363   {
1364     if (is_ptr(v->type))
1365     {
1366       if (v->type->type != ptr_type)
1367       {
1368         v->type = duptype(v->type, 1);
1369         v->type->type = ptr_type;
1370       }
1371     }
1372     else if (!arr && ptr_attr)
1373       error("%s: pointer attribute applied to non-pointer type\n", v->name);
1374   }
1375
1376   if (pident && pident->is_func) {
1377     int func_ptr_level = pident->func_ptr_level;
1378     v->type = make_type(RPC_FC_FUNCTION, v->type);
1379     v->type->fields_or_args = pident->args;
1380     if (pident->callconv)
1381       v->type->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, pident->callconv));
1382     else if (is_object_interface) {
1383       static char *stdmethodcalltype;
1384       if (!stdmethodcalltype) stdmethodcalltype = strdup("STDMETHODCALLTYPE");
1385       v->type->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
1386     }
1387     for (; func_ptr_level > 0; func_ptr_level--)
1388       v->type = make_type(ptr_type, v->type);
1389   }
1390
1391   sizeless = FALSE;
1392   if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry)
1393   {
1394     if (sizeless)
1395       error("%s: only the first array dimension can be unspecified\n", v->name);
1396
1397     if (dim->is_const)
1398     {
1399       unsigned int align = 0;
1400       size_t size = type_memsize(v->type, &align);
1401
1402       if (dim->cval <= 0)
1403         error("%s: array dimension must be positive\n", v->name);
1404
1405       if (0xffffffffuL / size < (unsigned long) dim->cval)
1406         error("%s: total array size is too large\n", v->name);
1407       else if (0xffffuL < size * dim->cval)
1408         v->type = make_type(RPC_FC_LGFARRAY, v->type);
1409       else
1410         v->type = make_type(RPC_FC_SMFARRAY, v->type);
1411     }
1412     else
1413     {
1414       sizeless = TRUE;
1415       v->type = make_type(RPC_FC_CARRAY, v->type);
1416     }
1417
1418     v->type->declarray = TRUE;
1419     v->type->dim = dim->cval;
1420   }
1421
1422   ptype = &v->type;
1423   has_varconf = FALSE;
1424   if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
1425   {
1426     if (dim->type != EXPR_VOID)
1427     {
1428       has_varconf = TRUE;
1429       atype = *ptype = duptype(*ptype, 0);
1430
1431       if (atype->type == RPC_FC_SMFARRAY || atype->type == RPC_FC_LGFARRAY)
1432         error("%s: cannot specify size_is for a fixed sized array\n", v->name);
1433
1434       if (atype->type != RPC_FC_CARRAY && !is_ptr(atype))
1435         error("%s: size_is attribute applied to illegal type\n", v->name);
1436
1437       atype->type = RPC_FC_CARRAY;
1438       atype->size_is = dim;
1439     }
1440
1441     ptype = &(*ptype)->ref;
1442     if (*ptype == NULL)
1443       error("%s: too many expressions in size_is attribute\n", v->name);
1444   }
1445
1446   ptype = &v->type;
1447   if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
1448   {
1449     if (dim->type != EXPR_VOID)
1450     {
1451       has_varconf = TRUE;
1452       atype = *ptype = duptype(*ptype, 0);
1453
1454       if (atype->type == RPC_FC_SMFARRAY)
1455         atype->type = RPC_FC_SMVARRAY;
1456       else if (atype->type == RPC_FC_LGFARRAY)
1457         atype->type = RPC_FC_LGVARRAY;
1458       else if (atype->type == RPC_FC_CARRAY)
1459         atype->type = RPC_FC_CVARRAY;
1460       else
1461         error("%s: length_is attribute applied to illegal type\n", v->name);
1462
1463       atype->length_is = dim;
1464     }
1465
1466     ptype = &(*ptype)->ref;
1467     if (*ptype == NULL)
1468       error("%s: too many expressions in length_is attribute\n", v->name);
1469   }
1470
1471   if (has_varconf && !last_array(v->type))
1472   {
1473     ptype = &v->type;
1474     for (ptype = &v->type; is_array(*ptype); ptype = &(*ptype)->ref)
1475     {
1476       *ptype = duptype(*ptype, 0);
1477       (*ptype)->type = RPC_FC_BOGUS_ARRAY;
1478     }
1479   }
1480
1481   if (is_array(v->type))
1482   {
1483     const type_t *rt = v->type->ref;
1484     if (is_user_type(rt))
1485       v->type->type = RPC_FC_BOGUS_ARRAY;
1486     else
1487       switch (rt->type)
1488         {
1489         case RPC_FC_BOGUS_STRUCT:
1490         case RPC_FC_NON_ENCAPSULATED_UNION:
1491         case RPC_FC_ENCAPSULATED_UNION:
1492         case RPC_FC_ENUM16:
1493           v->type->type = RPC_FC_BOGUS_ARRAY;
1494           break;
1495           /* FC_RP should be above, but widl overuses these, and will break things.  */
1496         case RPC_FC_UP:
1497         case RPC_FC_RP:
1498           if (rt->ref->type == RPC_FC_IP)
1499             v->type->type = RPC_FC_BOGUS_ARRAY;
1500           break;
1501         }
1502   }
1503 }
1504
1505 static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface)
1506 {
1507     if (!iface) return list;
1508     if (!list)
1509     {
1510         list = xmalloc( sizeof(*list) );
1511         list_init( list );
1512     }
1513     list_add_tail( list, &iface->entry );
1514     return list;
1515 }
1516
1517 static ifref_t *make_ifref(type_t *iface)
1518 {
1519   ifref_t *l = xmalloc(sizeof(ifref_t));
1520   l->iface = iface;
1521   l->attrs = NULL;
1522   return l;
1523 }
1524
1525 static var_list_t *append_var(var_list_t *list, var_t *var)
1526 {
1527     if (!var) return list;
1528     if (!list)
1529     {
1530         list = xmalloc( sizeof(*list) );
1531         list_init( list );
1532     }
1533     list_add_tail( list, &var->entry );
1534     return list;
1535 }
1536
1537 static var_t *make_var(char *name)
1538 {
1539   var_t *v = xmalloc(sizeof(var_t));
1540   v->name = name;
1541   v->type = NULL;
1542   v->attrs = NULL;
1543   v->eval = NULL;
1544   return v;
1545 }
1546
1547 static pident_list_t *append_pident(pident_list_t *list, pident_t *p)
1548 {
1549   if (!p) return list;
1550   if (!list) {
1551     list = xmalloc(sizeof(*list));
1552     list_init(list);
1553   }
1554   list_add_tail(list, &p->entry);
1555   return list;
1556 }
1557
1558 static pident_t *make_pident(var_t *var)
1559 {
1560   pident_t *p = xmalloc(sizeof(*p));
1561   p->var = var;
1562   p->is_func = FALSE;
1563   p->ptr_level = 0;
1564   p->func_ptr_level = 0;
1565   p->args = NULL;
1566   p->callconv = NULL;
1567   return p;
1568 }
1569
1570 static func_list_t *append_func(func_list_t *list, func_t *func)
1571 {
1572     if (!func) return list;
1573     if (!list)
1574     {
1575         list = xmalloc( sizeof(*list) );
1576         list_init( list );
1577     }
1578     list_add_tail( list, &func->entry );
1579     return list;
1580 }
1581
1582 static func_t *make_func(var_t *def, var_list_t *args)
1583 {
1584   func_t *f = xmalloc(sizeof(func_t));
1585   f->def = def;
1586   f->args = args;
1587   f->ignore = parse_only;
1588   f->idx = -1;
1589   return f;
1590 }
1591
1592 static type_t *make_class(char *name)
1593 {
1594   type_t *c = make_type(0, NULL);
1595   c->name = name;
1596   c->kind = TKIND_COCLASS;
1597   return c;
1598 }
1599
1600 static type_t *make_safearray(type_t *type)
1601 {
1602   type_t *sa = duptype(find_type("SAFEARRAY", 0), 1);
1603   sa->ref = type;
1604   return make_type(pointer_default, sa);
1605 }
1606
1607 #define HASHMAX 64
1608
1609 static int hash_ident(const char *name)
1610 {
1611   const char *p = name;
1612   int sum = 0;
1613   /* a simple sum hash is probably good enough */
1614   while (*p) {
1615     sum += *p;
1616     p++;
1617   }
1618   return sum & (HASHMAX-1);
1619 }
1620
1621 /***** type repository *****/
1622
1623 struct rtype {
1624   const char *name;
1625   type_t *type;
1626   int t;
1627   struct rtype *next;
1628 };
1629
1630 struct rtype *type_hash[HASHMAX];
1631
1632 static type_t *reg_type(type_t *type, const char *name, int t)
1633 {
1634   struct rtype *nt;
1635   int hash;
1636   if (!name) {
1637     error_loc("registering named type without name\n");
1638     return type;
1639   }
1640   hash = hash_ident(name);
1641   nt = xmalloc(sizeof(struct rtype));
1642   nt->name = name;
1643   nt->type = type;
1644   nt->t = t;
1645   nt->next = type_hash[hash];
1646   type_hash[hash] = nt;
1647   return type;
1648 }
1649
1650 static int is_incomplete(const type_t *t)
1651 {
1652   return !t->defined && (is_struct(t->type) || is_union(t->type));
1653 }
1654
1655 static void add_incomplete(type_t *t)
1656 {
1657   struct typenode *tn = xmalloc(sizeof *tn);
1658   tn->type = t;
1659   list_add_tail(&incomplete_types, &tn->entry);
1660 }
1661
1662 static void fix_type(type_t *t)
1663 {
1664   if (t->kind == TKIND_ALIAS && is_incomplete(t)) {
1665     type_t *ot = t->orig;
1666     fix_type(ot);
1667     t->fields_or_args = ot->fields_or_args;
1668     t->defined = ot->defined;
1669   }
1670 }
1671
1672 static void fix_incomplete(void)
1673 {
1674   struct typenode *tn, *next;
1675
1676   LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) {
1677     fix_type(tn->type);
1678     free(tn);
1679   }
1680 }
1681
1682 static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs)
1683 {
1684   type_t *ptr = type;
1685   const pident_t *pident;
1686   int ptrc = 0;
1687   int is_str = is_attr(attrs, ATTR_STRING);
1688   unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE);
1689
1690   if (is_str)
1691   {
1692     type_t *t = type;
1693     unsigned char c;
1694
1695     while (is_ptr(t))
1696       t = t->ref;
1697
1698     c = t->type;
1699     if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR)
1700     {
1701       pident = LIST_ENTRY( list_head( pidents ), const pident_t, entry );
1702       error_loc("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays\n",
1703               pident->var->name);
1704     }
1705   }
1706
1707   /* We must generate names for tagless enum, struct or union.
1708      Typedef-ing a tagless enum, struct or union means we want the typedef
1709      to be included in a library whether it has other attributes or not,
1710      hence the public attribute.  */
1711   if ((type->kind == TKIND_ENUM || type->kind == TKIND_RECORD
1712        || type->kind == TKIND_UNION) && ! type->name && ! parse_only)
1713   {
1714     if (! is_attr(attrs, ATTR_PUBLIC))
1715       attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) );
1716     type->name = gen_name();
1717   }
1718
1719   LIST_FOR_EACH_ENTRY( pident, pidents, const pident_t, entry )
1720   {
1721     var_t *name = pident->var;
1722
1723     if (name->name) {
1724       type_t *cur = ptr;
1725       int cptr = pident->ptr_level;
1726       if (cptr > ptrc) {
1727         while (cptr > ptrc) {
1728           cur = ptr = make_type(pointer_default, cur);
1729           ptrc++;
1730         }
1731       } else {
1732         while (cptr < ptrc) {
1733           cur = cur->ref;
1734           cptr++;
1735         }
1736       }
1737       if (pident->is_func) {
1738         int func_ptr_level = pident->func_ptr_level;
1739         cur = make_type(RPC_FC_FUNCTION, cur);
1740         cur->fields_or_args = pident->args;
1741         if (pident->callconv)
1742           cur->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, pident->callconv));
1743         else if (is_object_interface) {
1744           static char *stdmethodcalltype;
1745           if (!stdmethodcalltype) stdmethodcalltype = strdup("STDMETHODCALLTYPE");
1746           cur->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
1747         }
1748         for (; func_ptr_level > 0; func_ptr_level--)
1749           cur = make_type(pointer_default, cur);
1750       }
1751       cur = alias(cur, name->name);
1752       cur->attrs = attrs;
1753       if (ptr_type)
1754       {
1755         if (is_ptr(cur))
1756           cur->type = ptr_type;
1757         else
1758           error_loc("'%s': pointer attribute applied to non-pointer type\n",
1759                   cur->name);
1760       }
1761       else if (is_str && ! is_ptr(cur))
1762         error_loc("'%s': [string] attribute applied to non-pointer type\n",
1763                 cur->name);
1764
1765       if (is_incomplete(cur))
1766         add_incomplete(cur);
1767       reg_type(cur, cur->name, 0);
1768     }
1769   }
1770   return type;
1771 }
1772
1773 static type_t *find_type(const char *name, int t)
1774 {
1775   struct rtype *cur = type_hash[hash_ident(name)];
1776   while (cur && (cur->t != t || strcmp(cur->name, name)))
1777     cur = cur->next;
1778   if (!cur) {
1779     error_loc("type '%s' not found\n", name);
1780     return NULL;
1781   }
1782   return cur->type;
1783 }
1784
1785 static type_t *find_type2(char *name, int t)
1786 {
1787   type_t *tp = find_type(name, t);
1788   free(name);
1789   return tp;
1790 }
1791
1792 int is_type(const char *name)
1793 {
1794   struct rtype *cur = type_hash[hash_ident(name)];
1795   while (cur && (cur->t || strcmp(cur->name, name)))
1796     cur = cur->next;
1797   if (cur) return TRUE;
1798   return FALSE;
1799 }
1800
1801 static type_t *get_type(unsigned char type, char *name, int t)
1802 {
1803   struct rtype *cur = NULL;
1804   type_t *tp;
1805   if (name) {
1806     cur = type_hash[hash_ident(name)];
1807     while (cur && (cur->t != t || strcmp(cur->name, name)))
1808       cur = cur->next;
1809   }
1810   if (cur) {
1811     free(name);
1812     return cur->type;
1813   }
1814   tp = make_type(type, NULL);
1815   tp->name = name;
1816   if (!name) return tp;
1817   return reg_type(tp, name, t);
1818 }
1819
1820 static type_t *get_typev(unsigned char type, var_t *name, int t)
1821 {
1822   char *sname = NULL;
1823   if (name) {
1824     sname = name->name;
1825     free(name);
1826   }
1827   return get_type(type, sname, t);
1828 }
1829
1830 static int get_struct_type(var_list_t *fields)
1831 {
1832   int has_pointer = 0;
1833   int has_conformance = 0;
1834   int has_variance = 0;
1835   var_t *field;
1836
1837   if (get_padding(fields))
1838     return RPC_FC_BOGUS_STRUCT;
1839
1840   if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
1841   {
1842     type_t *t = field->type;
1843
1844     if (is_user_type(t))
1845       return RPC_FC_BOGUS_STRUCT;
1846
1847     if (is_ptr(t))
1848     {
1849         do
1850             t = t->ref;
1851         while (is_ptr(t));
1852
1853         switch (t->type)
1854         {
1855         case RPC_FC_IP:
1856         case RPC_FC_ENCAPSULATED_UNION:
1857         case RPC_FC_NON_ENCAPSULATED_UNION:
1858         case RPC_FC_BOGUS_STRUCT:
1859             return RPC_FC_BOGUS_STRUCT;
1860         }
1861
1862         has_pointer = 1;
1863         continue;
1864     }
1865
1866     if (field->type->declarray)
1867     {
1868         if (is_string_type(field->attrs, field->type))
1869         {
1870             if (is_conformant_array(field->type))
1871                 has_conformance = 1;
1872             has_variance = 1;
1873             continue;
1874         }
1875
1876         if (is_array(field->type->ref))
1877             return RPC_FC_BOGUS_STRUCT;
1878
1879         if (is_conformant_array(field->type))
1880         {
1881             has_conformance = 1;
1882             if (field->type->declarray && list_next(fields, &field->entry))
1883                 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
1884                         field->name);
1885         }
1886         if (field->type->length_is)
1887             has_variance = 1;
1888
1889         t = field->type->ref;
1890     }
1891
1892     switch (t->type)
1893     {
1894     /*
1895      * RPC_FC_BYTE, RPC_FC_STRUCT, etc
1896      *  Simple types don't effect the type of struct.
1897      *  A struct containing a simple struct is still a simple struct.
1898      *  So long as we can block copy the data, we return RPC_FC_STRUCT.
1899      */
1900     case 0: /* void pointer */
1901     case RPC_FC_BYTE:
1902     case RPC_FC_CHAR:
1903     case RPC_FC_SMALL:
1904     case RPC_FC_USMALL:
1905     case RPC_FC_WCHAR:
1906     case RPC_FC_SHORT:
1907     case RPC_FC_USHORT:
1908     case RPC_FC_LONG:
1909     case RPC_FC_ULONG:
1910     case RPC_FC_INT3264:
1911     case RPC_FC_UINT3264:
1912     case RPC_FC_HYPER:
1913     case RPC_FC_FLOAT:
1914     case RPC_FC_DOUBLE:
1915     case RPC_FC_STRUCT:
1916     case RPC_FC_ENUM32:
1917       break;
1918
1919     case RPC_FC_RP:
1920     case RPC_FC_UP:
1921     case RPC_FC_FP:
1922     case RPC_FC_OP:
1923     case RPC_FC_CARRAY:
1924     case RPC_FC_CVARRAY:
1925     case RPC_FC_BOGUS_ARRAY:
1926       has_pointer = 1;
1927       break;
1928
1929     /*
1930      * Propagate member attributes
1931      *  a struct should be at least as complex as its member
1932      */
1933     case RPC_FC_CVSTRUCT:
1934       has_conformance = 1;
1935       has_variance = 1;
1936       has_pointer = 1;
1937       break;
1938
1939     case RPC_FC_CPSTRUCT:
1940       has_conformance = 1;
1941       if (list_next( fields, &field->entry ))
1942           error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
1943                   field->name);
1944       has_pointer = 1;
1945       break;
1946
1947     case RPC_FC_CSTRUCT:
1948       has_conformance = 1;
1949       if (list_next( fields, &field->entry ))
1950           error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
1951                   field->name);
1952       break;
1953
1954     case RPC_FC_PSTRUCT:
1955       has_pointer = 1;
1956       break;
1957
1958     default:
1959       error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, t->type);
1960       /* fallthru - treat it as complex */
1961
1962     /* as soon as we see one of these these members, it's bogus... */
1963     case RPC_FC_ENCAPSULATED_UNION:
1964     case RPC_FC_NON_ENCAPSULATED_UNION:
1965     case RPC_FC_BOGUS_STRUCT:
1966     case RPC_FC_ENUM16:
1967       return RPC_FC_BOGUS_STRUCT;
1968     }
1969   }
1970
1971   if( has_variance )
1972   {
1973     if ( has_conformance )
1974       return RPC_FC_CVSTRUCT;
1975     else
1976       return RPC_FC_BOGUS_STRUCT;
1977   }
1978   if( has_conformance && has_pointer )
1979     return RPC_FC_CPSTRUCT;
1980   if( has_conformance )
1981     return RPC_FC_CSTRUCT;
1982   if( has_pointer )
1983     return RPC_FC_PSTRUCT;
1984   return RPC_FC_STRUCT;
1985 }
1986
1987 /***** constant repository *****/
1988
1989 struct rconst {
1990   char *name;
1991   var_t *var;
1992   struct rconst *next;
1993 };
1994
1995 struct rconst *const_hash[HASHMAX];
1996
1997 static var_t *reg_const(var_t *var)
1998 {
1999   struct rconst *nc;
2000   int hash;
2001   if (!var->name) {
2002     error_loc("registering constant without name\n");
2003     return var;
2004   }
2005   hash = hash_ident(var->name);
2006   nc = xmalloc(sizeof(struct rconst));
2007   nc->name = var->name;
2008   nc->var = var;
2009   nc->next = const_hash[hash];
2010   const_hash[hash] = nc;
2011   return var;
2012 }
2013
2014 static var_t *find_const(char *name, int f)
2015 {
2016   struct rconst *cur = const_hash[hash_ident(name)];
2017   while (cur && strcmp(cur->name, name))
2018     cur = cur->next;
2019   if (!cur) {
2020     if (f) error_loc("constant '%s' not found\n", name);
2021     return NULL;
2022   }
2023   return cur->var;
2024 }
2025
2026 static void write_libid(const char *name, const attr_list_t *attr)
2027 {
2028   const UUID *uuid = get_attrp(attr, ATTR_UUID);
2029   write_guid(idfile, "LIBID", name, uuid);
2030 }
2031
2032 static void write_clsid(type_t *cls)
2033 {
2034   const UUID *uuid = get_attrp(cls->attrs, ATTR_UUID);
2035   write_guid(idfile, "CLSID", cls->name, uuid);
2036 }
2037
2038 static void write_diid(type_t *iface)
2039 {
2040   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
2041   write_guid(idfile, "DIID", iface->name, uuid);
2042 }
2043
2044 static void write_iid(type_t *iface)
2045 {
2046   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
2047   write_guid(idfile, "IID", iface->name, uuid);
2048 }
2049
2050 static int compute_method_indexes(type_t *iface)
2051 {
2052   int idx;
2053   func_t *f;
2054
2055   if (iface->ref)
2056     idx = compute_method_indexes(iface->ref);
2057   else
2058     idx = 0;
2059
2060   if (!iface->funcs)
2061     return idx;
2062
2063   LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry )
2064     if (! is_callas(f->def->attrs))
2065       f->idx = idx++;
2066
2067   return idx;
2068 }
2069
2070 static char *gen_name(void)
2071 {
2072   static const char format[] = "__WIDL_%s_generated_name_%08lX";
2073   static unsigned long n = 0;
2074   static const char *file_id;
2075   static size_t size;
2076   char *name;
2077
2078   if (! file_id)
2079   {
2080     char *dst = dup_basename(input_name, ".idl");
2081     file_id = dst;
2082
2083     for (; *dst; ++dst)
2084       if (! isalnum((unsigned char) *dst))
2085         *dst = '_';
2086
2087     size = sizeof format - 7 + strlen(file_id) + 8;
2088   }
2089
2090   name = xmalloc(size);
2091   sprintf(name, format, file_id, n++);
2092   return name;
2093 }
2094
2095 static void process_typedefs(pident_list_t *pidents)
2096 {
2097   pident_t *pident, *next;
2098
2099   if (!pidents) return;
2100   LIST_FOR_EACH_ENTRY_SAFE( pident, next, pidents, pident_t, entry )
2101   {
2102     var_t *var = pident->var;
2103     type_t *type = find_type(var->name, 0);
2104
2105     if (! parse_only && do_header)
2106       write_typedef(type);
2107     if (in_typelib && type->attrs)
2108       add_typelib_entry(type);
2109
2110     free(pident);
2111     free(var);
2112   }
2113 }
2114
2115 static void check_arg(var_t *arg)
2116 {
2117   type_t *t = arg->type;
2118
2119   if (t->type == 0 && ! is_var_ptr(arg))
2120     error_loc("argument '%s' has void type\n", arg->name);
2121 }
2122
2123 static void check_all_user_types(ifref_list_t *ifrefs)
2124 {
2125   const ifref_t *ifref;
2126   const func_t *f;
2127
2128   if (ifrefs) LIST_FOR_EACH_ENTRY(ifref, ifrefs, const ifref_t, entry)
2129   {
2130     const func_list_t *fs = ifref->iface->funcs;
2131     if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry)
2132       check_for_additional_prototype_types(f->args);
2133   }
2134 }
2135
2136 int is_valid_uuid(const char *s)
2137 {
2138   int i;
2139
2140   for (i = 0; i < 36; ++i)
2141     if (i == 8 || i == 13 || i == 18 || i == 23)
2142     {
2143       if (s[i] != '-')
2144         return FALSE;
2145     }
2146     else
2147       if (!isxdigit(s[i]))
2148         return FALSE;
2149
2150   return s[i] == '\0';
2151 }