parser.y 48.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
%{
/*
 * IDL Compiler
 *
 * Copyright 2002 Ove Kaaven
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23 24 25 26 27 28 29 30 31 32 33
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif

34 35
#include "windef.h"

36 37 38 39
#include "widl.h"
#include "utils.h"
#include "parser.h"
#include "header.h"
40
#include "typelib.h"
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

#if defined(YYBYACC)
	/* Berkeley yacc (byacc) doesn't seem to know about these */
	/* Some *BSD supplied versions do define these though */
# ifndef YYEMPTY
#  define YYEMPTY	(-1)	/* Empty lookahead value of yychar */
# endif
# ifndef YYLEX
#  define YYLEX		yylex()
# endif

#elif defined(YYBISON)
	/* Bison was used for original development */
	/* #define YYEMPTY -2 */
	/* #define YYLEX   yylex() */

#else
	/* No yacc we know yet */
# if !defined(YYEMPTY) || !defined(YYLEX)
#  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
# elif defined(__GNUC__)	/* gcc defines the #warning directive */
#  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
  /* #else we just take a chance that it works... */
# endif
#endif

67
static str_list_t *append_str(str_list_t *list, char *str);
68
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
69
static attr_t *make_attr(enum attr_type type);
70
static attr_t *make_attrv(enum attr_type type, unsigned long val);
71
static attr_t *make_attrp(enum attr_type type, void *val);
72 73 74
static expr_t *make_expr(enum expr_type type);
static expr_t *make_exprl(enum expr_type type, long val);
static expr_t *make_exprs(enum expr_type type, char *val);
75
static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr);
76 77
static expr_t *make_expr1(enum expr_type type, expr_t *expr);
static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
78 79
static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3);
static type_t *make_type(unsigned char type, type_t *ref);
80 81
static expr_list_t *append_expr(expr_list_t *list, expr_t *expr);
static array_dims_t *append_array(array_dims_t *list, expr_t *expr);
82
static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr);
83
static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
84
static ifref_t *make_ifref(type_t *iface);
85
static var_list_t *append_var(var_list_t *list, var_t *var);
86
static var_t *make_var(char *name);
87 88
static pident_list_t *append_pident(pident_list_t *list, pident_t *p);
static pident_t *make_pident(var_t *var);
89
static func_list_t *append_func(func_list_t *list, func_t *func);
90
static func_t *make_func(var_t *def, var_list_t *args);
91
static type_t *make_class(char *name);
92
static type_t *make_safearray(type_t *type);
93 94
static type_t *make_builtin(char *name);
static type_t *make_int(int sign);
95

96
static type_t *reg_type(type_t *type, const char *name, int t);
97
static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs);
98
static type_t *find_type(const char *name, int t);
99
static type_t *find_type2(char *name, int t);
100 101
static type_t *get_type(unsigned char type, char *name, int t);
static type_t *get_typev(unsigned char type, var_t *name, int t);
102
static int get_struct_type(var_list_t *fields);
103

104 105 106
static var_t *reg_const(var_t *var);
static var_t *find_const(char *name, int f);

107
static void write_libid(const char *name, const attr_list_t *attr);
108 109 110 111
static void write_clsid(type_t *cls);
static void write_diid(type_t *iface);
static void write_iid(type_t *iface);

112
static int compute_method_indexes(type_t *iface);
113
static char *gen_name(void);
114
static void process_typedefs(var_list_t *names);
115
static void check_arg(var_t *arg);
116

117 118 119 120 121 122 123
#define tsENUM   1
#define tsSTRUCT 2
#define tsUNION  3

%}
%union {
	attr_t *attr;
124
	attr_list_t *attr_list;
125
	str_list_t *str_list;
126
	expr_t *expr;
127 128
	expr_list_t *expr_list;
	array_dims_t *array_dims;
129 130
	type_t *type;
	var_t *var;
131
	var_list_t *var_list;
132 133
	pident_t *pident;
	pident_list_t *pident_list;
134
	func_t *func;
135
	func_list_t *func_list;
136
	ifref_t *ifref;
137
	ifref_list_t *ifref_list;
138
	char *str;
139
	UUID *uuid;
140
	unsigned int num;
141 142 143 144
}

%token <str> aIDENTIFIER
%token <str> aKNOWNTYPE
145
%token <num> aNUM aHEXNUM
146 147
%token <str> aSTRING
%token <uuid> aUUID
148
%token aEOF
149
%token SHL SHR
150
%token tAGGREGATABLE tALLOCATE tAPPOBJECT tASYNC tASYNCUUID
151 152 153 154 155
%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
%token tDEFAULT
156
%token tDEFAULTCOLLELEM
157
%token tDEFAULTVALUE
158
%token tDEFAULTVTABLE
159
%token tDISPLAYBIND
160 161
%token tDISPINTERFACE
%token tDLLNAME tDOUBLE tDUAL
162
%token tENDPOINT
163
%token tENTRY tENUM tERRORSTATUST
164
%token tEXPLICITHANDLE tEXTERN
165
%token tFALSE
166
%token tFLOAT
167
%token tHANDLE
168
%token tHANDLET
169 170
%token tHELPCONTEXT tHELPFILE
%token tHELPSTRING tHELPSTRINGCONTEXT tHELPSTRINGDLL
171
%token tHIDDEN
172
%token tHYPER tID tIDEMPOTENT
173
%token tIIDIS
174
%token tIMMEDIATEBIND
175
%token tIMPLICITHANDLE
176
%token tIMPORT tIMPORTLIB
177
%token tIN tINLINE
178
%token tINPUTSYNC
179 180
%token tINT tINT64
%token tINTERFACE
181
%token tLCID
182
%token tLENGTHIS tLIBRARY
183 184
%token tLOCAL
%token tLONG
185 186
%token tMETHODS
%token tMODULE
187
%token tNONBROWSABLE
Huw Davies's avatar
Huw Davies committed
188
%token tNONCREATABLE
189
%token tNONEXTENSIBLE
190
%token tOBJECT tODL tOLEAUTOMATION
191
%token tOPTIONAL
192 193
%token tOUT
%token tPOINTERDEFAULT
194
%token tPROPERTIES
195
%token tPROPGET tPROPPUT tPROPPUTREF
196
%token tPTR
197
%token tPUBLIC
198
%token tRANGE
199
%token tREADONLY tREF
200
%token tREQUESTEDIT
201
%token tRESTRICTED
202
%token tRETVAL
203
%token tSAFEARRAY
204 205
%token tSHORT
%token tSIGNED
206
%token tSINGLE
207
%token tSIZEIS tSIZEOF
208
%token tSMALL
209
%token tSOURCE
210 211 212
%token tSTDCALL
%token tSTRING tSTRUCT
%token tSWITCH tSWITCHIS tSWITCHTYPE
213
%token tTRANSMITAS
214
%token tTRUE
215 216 217 218 219 220
%token tTYPEDEF
%token tUNION
%token tUNIQUE
%token tUNSIGNED
%token tUUID
%token tV1ENUM
221
%token tVARARG
222 223 224 225
%token tVERSION
%token tVOID
%token tWCHAR tWIREMARSHAL

226 227
%type <attr> attribute
%type <attr_list> m_attributes attributes attrib_list
228
%type <str_list> str_list
229 230 231
%type <expr> m_expr expr expr_const
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_const
%type <array_dims> array array_list
232 233 234
%type <type> inherit interface interfacehdr interfacedef interfacedec
%type <type> dispinterface dispinterfacehdr dispinterfacedef
%type <type> module modulehdr moduledef
235
%type <type> base_type int_std
236
%type <type> enumdef structdef uniondef
237
%type <type> type
238 239
%type <ifref> coclass_int
%type <ifref_list> gbl_statements coclass_ints
240
%type <var> arg field s_field case enum constdef externdef
241 242 243 244
%type <var_list> m_args no_args args fields cases enums enum_list dispint_props
%type <var> m_ident t_ident ident
%type <pident> p_ident pident
%type <pident_list> pident_list
245 246
%type <func> funcdef
%type <func_list> int_statements dispint_meths
247
%type <type> coclass coclasshdr coclassdef
248
%type <num> pointer_type version
249
%type <str> libraryhdr
250 251

%left ','
252
%right '?' ':'
253 254 255 256 257
%left '|'
%left '&'
%left '-' '+'
%left '*' '/'
%left SHL SHR
258
%right '~'
259 260 261 262 263 264
%right CAST
%right PPTR
%right NEG

%%

265
input:   gbl_statements                        { write_proxies($1); write_client($1); write_server($1); }
266 267
	;

268 269
gbl_statements:					{ $$ = NULL; }
	| gbl_statements interfacedec		{ $$ = $1; }
270
	| gbl_statements interfacedef		{ $$ = append_ifref( $1, make_ifref($2) ); }
271 272 273 274 275
	| gbl_statements coclass ';'		{ $$ = $1;
						  reg_type($2, $2->name, 0);
						  if (!parse_only && do_header) write_coclass_forward($2);
						}
	| gbl_statements coclassdef		{ $$ = $1;
276
						  add_typelib_entry($2);
277
						  reg_type($2, $2->name, 0);
278
						  if (!parse_only && do_header) write_coclass_forward($2);
279
						}
280
	| gbl_statements moduledef		{ $$ = $1; add_typelib_entry($2); }
281 282 283 284 285
	| gbl_statements librarydef		{ $$ = $1; }
	| gbl_statements statement		{ $$ = $1; }
	;

imp_statements:					{}
286 287
	| imp_statements interfacedec		{ if (!parse_only) add_typelib_entry($2); }
	| imp_statements interfacedef		{ if (!parse_only) add_typelib_entry($2); }
288
	| imp_statements coclass ';'		{ reg_type($2, $2->name, 0); if (!parse_only && do_header) write_coclass_forward($2); }
289
	| imp_statements coclassdef		{ if (!parse_only) add_typelib_entry($2);
290
						  reg_type($2, $2->name, 0);
291
						  if (!parse_only && do_header) write_coclass_forward($2);
292
						}
293
	| imp_statements moduledef		{ if (!parse_only) add_typelib_entry($2); }
294
	| imp_statements statement		{}
295
	| imp_statements importlib		{}
296 297 298
	;

int_statements:					{ $$ = NULL; }
299
	| int_statements funcdef ';'		{ $$ = append_func( $1, $2 ); }
300
	| int_statements statement		{ $$ = $1; }
301 302 303
	;

statement: ';'					{}
Huw Davies's avatar
Huw Davies committed
304
	| constdef ';'				{ if (!parse_only && do_header) { write_constdef($1); } }
305
	| cppquote				{}
306
	| enumdef ';'				{ if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } }
Huw Davies's avatar
Huw Davies committed
307
	| externdef ';'				{ if (!parse_only && do_header) { write_externdef($1); } }
308
	| import				{}
309
	| structdef ';'				{ if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } }
310
	| typedef ';'				{}
311
	| uniondef ';'				{ if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } }
312 313
	;

Huw Davies's avatar
Huw Davies committed
314
cppquote: tCPPQUOTE '(' aSTRING ')'		{ if (!parse_only && do_header) fprintf(header, "%s\n", $3); }
315
	;
316
import_start: tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
317
						  if (!do_import($2)) yychar = aEOF; }
318
	;
319 320 321
import:   import_start imp_statements aEOF	{}
	;

322
importlib: tIMPORTLIB '(' aSTRING ')'		{ if(!parse_only) add_importlib($3); }
Jacek Caban's avatar
Jacek Caban committed
323
	;
324

325 326
libraryhdr: tLIBRARY aIDENTIFIER		{ $$ = $2; }
	;
327
library_start: attributes libraryhdr '{'	{ start_typelib($2, $1);
328 329 330
						  if (!parse_only && do_header) write_library($2, $1);
						  if (!parse_only && do_idfile) write_libid($2, $1);
						}
331 332
	;
librarydef: library_start imp_statements '}'	{ end_typelib(); }
333
	;
334 335 336 337 338 339 340 341

m_args:						{ $$ = NULL; }
	| args
	;

no_args:  tVOID					{ $$ = NULL; }
	;

342 343
args:	  arg					{ check_arg($1); $$ = append_var( NULL, $1 ); }
	| args ',' arg				{ check_arg($3); $$ = append_var( $1, $3); }
344 345 346 347
	| no_args
	;

/* split into two rules to get bison to resolve a tVOID conflict */
348 349 350
arg:	  attributes type pident array		{ $$ = $3->var;
						  set_type($$, $2, $3->ptr_level, $4);
						  free($3);
351
						  $$->attrs = $1;
352
						}
353 354 355
	| type pident array			{ $$ = $2->var;
						  set_type($$, $1, $2->ptr_level, $3);
						  free($2);
356
						}
357 358 359
	| attributes type pident '(' m_args ')'	{ $$ = $3->var;
						  set_type($$, $2, $3->ptr_level - 1, NULL);
						  free($3);
360 361 362
						  $$->attrs = $1;
						  $$->args = $5;
						}
363 364 365
	| type pident '(' m_args ')'		{ $$ = $2->var;
						  set_type($$, $1, $2->ptr_level - 1, NULL);
						  free($2);
366 367
						  $$->args = $4;
						}
368 369
	;

370
array:						{ $$ = NULL; }
371
	| '[' array_list ']'			{ $$ = $2; }
372
	| '[' '*' ']'				{ $$ = append_array( NULL, make_expr(EXPR_VOID) ); }
373 374
	;

375 376 377
array_list: m_expr /* size of first dimension is optional */ { $$ = append_array( NULL, $1 ); }
	| array_list ',' expr                   { $$ = append_array( $1, $3 ); }
	| array_list ']' '[' expr               { $$ = append_array( $1, $4 ); }
378 379
	;

380 381 382 383 384
m_attributes:					{ $$ = NULL; }
	| attributes
	;

attributes:
385 386 387 388
	  '[' attrib_list ']'			{ $$ = $2;
						  if (!$$)
						    yyerror("empty attribute lists unsupported");
						}
389 390
	;

391 392 393
attrib_list: attribute                          { $$ = append_attr( NULL, $1 ); }
	| attrib_list ',' attribute             { $$ = append_attr( $1, $3 ); }
	| attrib_list ']' '[' attribute         { $$ = append_attr( $1, $4 ); }
394 395
	;

396 397 398 399
str_list: aSTRING                               { $$ = append_str( NULL, $1 ); }
	| str_list ',' aSTRING                  { $$ = append_str( $1, $3 ); }
	;

400 401
attribute:					{ $$ = NULL; }
	| tAGGREGATABLE				{ $$ = make_attr(ATTR_AGGREGATABLE); }
402 403
	| tAPPOBJECT				{ $$ = make_attr(ATTR_APPOBJECT); }
	| tASYNC				{ $$ = make_attr(ATTR_ASYNC); }
404
	| tAUTOHANDLE				{ $$ = make_attr(ATTR_AUTO_HANDLE); }
405
	| tBINDABLE				{ $$ = make_attr(ATTR_BINDABLE); }
406
	| tCALLAS '(' ident ')'			{ $$ = make_attrp(ATTR_CALLAS, $3); }
407 408 409 410
	| tCASE '(' expr_list_const ')'		{ $$ = make_attrp(ATTR_CASE, $3); }
	| tCONTEXTHANDLE			{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
	| tCONTEXTHANDLENOSERIALIZE		{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
	| tCONTEXTHANDLESERIALIZE		{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
411
	| tCONTROL				{ $$ = make_attr(ATTR_CONTROL); }
412
	| tDEFAULT				{ $$ = make_attr(ATTR_DEFAULT); }
413
	| tDEFAULTCOLLELEM			{ $$ = make_attr(ATTR_DEFAULTCOLLELEM); }
414 415
	| tDEFAULTVALUE '(' expr_const ')'	{ $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); }
	| tDEFAULTVALUE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); }
416
	| tDEFAULTVTABLE			{ $$ = make_attr(ATTR_DEFAULTVTABLE); }
417
	| tDISPLAYBIND				{ $$ = make_attr(ATTR_DISPLAYBIND); }
418 419
	| tDLLNAME '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DLLNAME, $3); }
	| tDUAL					{ $$ = make_attr(ATTR_DUAL); }
420
	| tENDPOINT '(' str_list ')'		{ $$ = make_attrp(ATTR_ENDPOINT, $3); }
421 422
	| tENTRY '(' aSTRING ')'		{ $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
	| tENTRY '(' expr_const ')'		{ $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
423
	| tEXPLICITHANDLE			{ $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
424
	| tHANDLE				{ $$ = make_attr(ATTR_HANDLE); }
425 426
	| tHELPCONTEXT '(' expr_const ')'	{ $$ = make_attrp(ATTR_HELPCONTEXT, $3); }
	| tHELPFILE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_HELPFILE, $3); }
427
	| tHELPSTRING '(' aSTRING ')'		{ $$ = make_attrp(ATTR_HELPSTRING, $3); }
428 429
	| tHELPSTRINGCONTEXT '(' expr_const ')'	{ $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); }
	| tHELPSTRINGDLL '(' aSTRING ')'	{ $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); }
430
	| tHIDDEN				{ $$ = make_attr(ATTR_HIDDEN); }
431
	| tID '(' expr_const ')'		{ $$ = make_attrp(ATTR_ID, $3); }
432
	| tIDEMPOTENT				{ $$ = make_attr(ATTR_IDEMPOTENT); }
433
	| tIIDIS '(' ident ')'			{ $$ = make_attrp(ATTR_IIDIS, $3); }
434
	| tIMMEDIATEBIND			{ $$ = make_attr(ATTR_IMMEDIATEBIND); }
435
	| tIMPLICITHANDLE '(' tHANDLET aIDENTIFIER ')'	{ $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $4); }
436
	| tIN					{ $$ = make_attr(ATTR_IN); }
437
	| tINPUTSYNC				{ $$ = make_attr(ATTR_INPUTSYNC); }
438
	| tLENGTHIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_LENGTHIS, $3); }
439
	| tLOCAL				{ $$ = make_attr(ATTR_LOCAL); }
440
	| tNONBROWSABLE				{ $$ = make_attr(ATTR_NONBROWSABLE); }
Huw Davies's avatar
Huw Davies committed
441
	| tNONCREATABLE				{ $$ = make_attr(ATTR_NONCREATABLE); }
442
	| tNONEXTENSIBLE			{ $$ = make_attr(ATTR_NONEXTENSIBLE); }
443
	| tOBJECT				{ $$ = make_attr(ATTR_OBJECT); }
444
	| tODL					{ $$ = make_attr(ATTR_ODL); }
445
	| tOLEAUTOMATION			{ $$ = make_attr(ATTR_OLEAUTOMATION); }
446
	| tOPTIONAL                             { $$ = make_attr(ATTR_OPTIONAL); }
447 448
	| tOUT					{ $$ = make_attr(ATTR_OUT); }
	| tPOINTERDEFAULT '(' pointer_type ')'	{ $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
449 450
	| tPROPGET				{ $$ = make_attr(ATTR_PROPGET); }
	| tPROPPUT				{ $$ = make_attr(ATTR_PROPPUT); }
451
	| tPROPPUTREF				{ $$ = make_attr(ATTR_PROPPUTREF); }
452
	| tPUBLIC				{ $$ = make_attr(ATTR_PUBLIC); }
453 454 455
	| tRANGE '(' expr_const ',' expr_const ')' { expr_list_t *list = append_expr( NULL, $3 );
                                                     list = append_expr( list, $5 );
                                                     $$ = make_attrp(ATTR_RANGE, list); }
456
	| tREADONLY				{ $$ = make_attr(ATTR_READONLY); }
457
	| tREQUESTEDIT				{ $$ = make_attr(ATTR_REQUESTEDIT); }
458
	| tRESTRICTED				{ $$ = make_attr(ATTR_RESTRICTED); }
459
	| tRETVAL				{ $$ = make_attr(ATTR_RETVAL); }
460
	| tSIZEIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_SIZEIS, $3); }
461
	| tSOURCE				{ $$ = make_attr(ATTR_SOURCE); }
462
	| tSTRING				{ $$ = make_attr(ATTR_STRING); }
463
	| tSWITCHIS '(' expr ')'		{ $$ = make_attrp(ATTR_SWITCHIS, $3); }
464 465
	| tSWITCHTYPE '(' type ')'		{ $$ = make_attrp(ATTR_SWITCHTYPE, $3); }
	| tTRANSMITAS '(' type ')'		{ $$ = make_attrp(ATTR_TRANSMITAS, $3); }
466
	| tUUID '(' aUUID ')'			{ $$ = make_attrp(ATTR_UUID, $3); }
467
	| tV1ENUM				{ $$ = make_attr(ATTR_V1ENUM); }
468
	| tVARARG				{ $$ = make_attr(ATTR_VARARG); }
469
	| tVERSION '(' version ')'		{ $$ = make_attrv(ATTR_VERSION, $3); }
470
	| tWIREMARSHAL '(' type ')'		{ $$ = make_attrp(ATTR_WIREMARSHAL, $3); }
471
	| pointer_type				{ $$ = make_attrv(ATTR_POINTERTYPE, $1); }
472 473 474 475 476 477
	;

callconv:
	| tSTDCALL
	;

478
cases:						{ $$ = NULL; }
479
	| cases case				{ $$ = append_var( $1, $2 ); }
480 481
	;

482
case:	  tCASE expr ':' field			{ attr_t *a = make_attrp(ATTR_CASE, $2);
483
						  $$ = $4; if (!$$) $$ = make_var(NULL);
484
						  $$->attrs = append_attr( $$->attrs, a );
485 486 487
						}
	| tDEFAULT ':' field			{ attr_t *a = make_attr(ATTR_DEFAULT);
						  $$ = $3; if (!$$) $$ = make_var(NULL);
488
						  $$->attrs = append_attr( $$->attrs, a );
489
						}
490 491
	;

492
constdef: tCONST type ident '=' expr_const	{ $$ = reg_const($3);
493
						  set_type($$, $2, 0, NULL);
494
						  $$->eval = $5;
495
						}
496 497
	;

498 499
enums:						{ $$ = NULL; }
	| enum_list ','				{ $$ = $1; }
500 501 502
	| enum_list
	;

503 504 505
enum_list: enum					{ if (!$1->eval)
						    $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */);
                                                  $$ = append_var( NULL, $1 );
506
						}
507 508 509 510 511 512
	| enum_list ',' enum			{ if (!$3->eval)
                                                  {
                                                    var_t *last = LIST_ENTRY( list_tail($$), var_t, entry );
                                                    $3->eval = make_exprl(EXPR_NUM, last->eval->cval + 1);
                                                  }
                                                  $$ = append_var( $1, $3 );
513
						}
514 515
	;

516 517
enum:	  ident '=' expr_const			{ $$ = reg_const($1);
						  $$->eval = $3;
518
                                                  $$->type = make_int(0);
519 520
						}
	| ident					{ $$ = reg_const($1);
521
                                                  $$->type = make_int(0);
522
						}
523 524
	;

525
enumdef: tENUM t_ident '{' enums '}'		{ $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
526
						  $$->kind = TKIND_ENUM;
527
						  $$->fields = $4;
528
						  $$->defined = TRUE;
Huw Davies's avatar
Huw Davies committed
529
                                                  if(in_typelib)
530
                                                      add_typelib_entry($$);
531 532 533
						}
	;

534 535
m_exprs:  m_expr                                { $$ = append_expr( NULL, $1 ); }
	| m_exprs ',' m_expr                    { $$ = append_expr( $1, $3 ); }
536 537 538
	;

/*
539 540
exprs:						{ $$ = make_expr(EXPR_VOID); }
	| expr_list
541 542
	;

543 544
expr_list: expr
	| expr_list ',' expr			{ LINK($3, $1); $$ = $3; }
545
	;
546 547 548 549 550
*/

m_expr:						{ $$ = make_expr(EXPR_VOID); }
	| expr
	;
551

552 553
expr:	  aNUM					{ $$ = make_exprl(EXPR_NUM, $1); }
	| aHEXNUM				{ $$ = make_exprl(EXPR_HEXNUM, $1); }
554 555
	| tFALSE				{ $$ = make_exprl(EXPR_TRUEFALSE, 0); }
	| tTRUE					{ $$ = make_exprl(EXPR_TRUEFALSE, 1); }
556
	| aIDENTIFIER				{ $$ = make_exprs(EXPR_IDENTIFIER, $1); }
557
	| expr '?' expr ':' expr		{ $$ = make_expr3(EXPR_COND, $1, $3, $5); }
558 559 560 561 562 563 564 565
	| expr '|' expr				{ $$ = make_expr2(EXPR_OR , $1, $3); }
	| expr '&' expr				{ $$ = make_expr2(EXPR_AND, $1, $3); }
	| expr '+' expr				{ $$ = make_expr2(EXPR_ADD, $1, $3); }
	| expr '-' expr				{ $$ = make_expr2(EXPR_SUB, $1, $3); }
	| expr '*' expr				{ $$ = make_expr2(EXPR_MUL, $1, $3); }
	| expr '/' expr				{ $$ = make_expr2(EXPR_DIV, $1, $3); }
	| expr SHL expr				{ $$ = make_expr2(EXPR_SHL, $1, $3); }
	| expr SHR expr				{ $$ = make_expr2(EXPR_SHR, $1, $3); }
566
	| '~' expr				{ $$ = make_expr1(EXPR_NOT, $2); }
567 568 569 570 571 572 573
	| '-' expr %prec NEG			{ $$ = make_expr1(EXPR_NEG, $2); }
	| '*' expr %prec PPTR			{ $$ = make_expr1(EXPR_PPTR, $2); }
	| '(' type ')' expr %prec CAST		{ $$ = make_exprt(EXPR_CAST, $2, $4); }
	| tSIZEOF '(' type ')'			{ $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
	| '(' expr ')'				{ $$ = $2; }
	;

574 575
expr_list_const: expr_const                     { $$ = append_expr( NULL, $1 ); }
	| expr_list_const ',' expr_const        { $$ = append_expr( $1, $3 ); }
576 577
	;

578
expr_const: expr				{ $$ = $1;
579
						  if (!$$->is_const)
580
						      yyerror("expression is not constant");
581 582 583 584
						}
	;

externdef: tEXTERN tCONST type ident		{ $$ = $4;
585
						  set_type($$, $3, 0, NULL);
586
						}
587 588 589
	;

fields:						{ $$ = NULL; }
590
	| fields field				{ $$ = append_var( $1, $2 ); }
591 592
	;

593
field:	  s_field ';'				{ $$ = $1; }
594 595 596 597 598
	| m_attributes uniondef ';'		{ $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
	| attributes ';'			{ $$ = make_var(NULL); $$->attrs = $1; }
	| ';'					{ $$ = NULL; }
	;

599 600 601 602 603
s_field:  m_attributes type pident array	{ $$ = $3->var;
						  set_type($$, $2, $3->ptr_level, $4);
						  free($3);
						  $$->attrs = $1;
						}
604 605
	;

606 607
funcdef:
	  m_attributes type callconv pident
608 609 610 611 612 613
	  '(' m_args ')'			{ var_t *v = $4->var;
						  set_type(v, $2, $4->ptr_level, NULL);
						  free($4);
						  v->attrs = $1;
						  $$ = make_func(v, $6);
						  if (is_attr(v->attrs, ATTR_IN)) {
614
						    yyerror("inapplicable attribute [in] for function '%s'",$$->def->name);
615
						  }
616 617 618 619 620 621 622 623 624 625 626 627 628
						}
	;

m_ident:					{ $$ = NULL; }
	| ident
	;

t_ident:					{ $$ = NULL; }
	| aIDENTIFIER				{ $$ = make_var($1); }
	| aKNOWNTYPE				{ $$ = make_var($1); }
	;

ident:	  aIDENTIFIER				{ $$ = make_var($1); }
629
/* some "reserved words" used in attributes are also used as field names in some MS IDL files */
630
	| aKNOWNTYPE				{ $$ = make_var($<str>1); }
631 632
	;

633 634
base_type: tBYTE				{ $$ = make_builtin($<str>1); }
	| tWCHAR				{ $$ = make_builtin($<str>1); }
635
	| int_std
636 637 638
	| tSIGNED int_std			{ $$ = $2; $$->sign = 1; }
	| tUNSIGNED int_std			{ $$ = $2; $$->sign = -1;
						  switch ($$->type) {
639
						  case RPC_FC_CHAR:  break;
640 641 642
						  case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
						  case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
						  case RPC_FC_LONG:  $$->type = RPC_FC_ULONG;  break;
643
						  case RPC_FC_HYPER:
644 645 646 647 648
						    if ($$->name[0] == 'h') /* hyper, as opposed to __int64 */
                                                    {
                                                      $$ = alias($$, "MIDL_uhyper");
                                                      $$->sign = 0;
                                                    }
649
						    break;
650 651 652
						  default: break;
						  }
						}
653 654 655 656 657 658 659
	| tUNSIGNED				{ $$ = make_int(-1); }
	| tFLOAT				{ $$ = make_builtin($<str>1); }
	| tSINGLE				{ $$ = duptype(find_type("float", 0), 1); }
	| tDOUBLE				{ $$ = make_builtin($<str>1); }
	| tBOOLEAN				{ $$ = make_builtin($<str>1); }
	| tERRORSTATUST				{ $$ = make_builtin($<str>1); }
	| tHANDLET				{ $$ = make_builtin($<str>1); }
660 661 662 663 664 665
	;

m_int:
	| tINT
	;

666 667 668 669 670 671 672
int_std:  tINT					{ $$ = make_builtin($<str>1); }
	| tSHORT m_int				{ $$ = make_builtin($<str>1); }
	| tSMALL				{ $$ = make_builtin($<str>1); }
	| tLONG m_int				{ $$ = make_builtin($<str>1); }
	| tHYPER m_int				{ $$ = make_builtin($<str>1); }
	| tINT64				{ $$ = make_builtin($<str>1); }
	| tCHAR					{ $$ = make_builtin($<str>1); }
673 674
	;

675
coclass:  tCOCLASS aIDENTIFIER			{ $$ = make_class($2); }
676 677
	| tCOCLASS aKNOWNTYPE			{ $$ = find_type($2, 0);
						  if ($$->defined) yyerror("multiple definition error");
678
						  if ($$->kind != TKIND_COCLASS) yyerror("%s was not declared a coclass", $2);
679
						}
680 681 682 683
	;

coclasshdr: attributes coclass			{ $$ = $2;
						  $$->attrs = $1;
684 685
						  if (!parse_only && do_header)
						    write_coclass($$);
686 687
						  if (!parse_only && do_idfile)
						    write_clsid($$);
688 689 690 691 692
						}
	;

coclassdef: coclasshdr '{' coclass_ints '}'	{ $$ = $1;
						  $$->ifaces = $3;
693
						  $$->defined = TRUE;
694 695 696 697
						}
	;

coclass_ints:					{ $$ = NULL; }
698
	| coclass_ints coclass_int		{ $$ = append_ifref( $1, $2 ); }
699 700 701 702 703 704
	;

coclass_int:
	  m_attributes interfacedec		{ $$ = make_ifref($2); $$->attrs = $1; }
	;

705 706
dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; }
	|      tDISPINTERFACE aKNOWNTYPE	{ $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; }
707 708
	;

709 710
dispinterfacehdr: attributes dispinterface	{ attr_t *attrs;
						  $$ = $2;
711
						  if ($$->defined) yyerror("multiple definition error");
712
						  attrs = make_attr(ATTR_DISPINTERFACE);
713
						  $$->attrs = append_attr( $1, attrs );
714
						  $$->ref = find_type("IDispatch", 0);
715
						  if (!$$->ref) yyerror("IDispatch is undefined");
716
						  $$->defined = TRUE;
Huw Davies's avatar
Huw Davies committed
717
						  if (!parse_only && do_header) write_forward($$);
718 719 720 721
						}
	;

dispint_props: tPROPERTIES ':'			{ $$ = NULL; }
722
	| dispint_props s_field ';'		{ $$ = append_var( $1, $2 ); }
723 724 725
	;

dispint_meths: tMETHODS ':'			{ $$ = NULL; }
726
	| dispint_meths funcdef ';'		{ $$ = append_func( $1, $2 ); }
727 728 729 730 731 732 733 734
	;

dispinterfacedef: dispinterfacehdr '{'
	  dispint_props
	  dispint_meths
	  '}'					{ $$ = $1;
						  $$->fields = $3;
						  $$->funcs = $4;
Huw Davies's avatar
Huw Davies committed
735
						  if (!parse_only && do_header) write_dispinterface($$);
736
						  if (!parse_only && do_idfile) write_diid($$);
737
						}
738 739 740 741 742 743
	| dispinterfacehdr
	 '{' interface ';' '}'			{ $$ = $1;
						  $$->fields = $3->fields;
						  $$->funcs = $3->funcs;
						  if (!parse_only && do_header) write_dispinterface($$);
						  if (!parse_only && do_idfile) write_diid($$);
744 745 746
						}
	;

747 748 749 750
inherit:					{ $$ = NULL; }
	| ':' aKNOWNTYPE			{ $$ = find_type2($2, 0); }
	;

751 752
interface: tINTERFACE aIDENTIFIER		{ $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; }
	|  tINTERFACE aKNOWNTYPE		{ $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; }
753 754
	;

755
interfacehdr: attributes interface		{ $$ = $2;
756
						  if ($$->defined) yyerror("multiple definition error");
757 758
						  $$->attrs = $1;
						  $$->defined = TRUE;
Huw Davies's avatar
Huw Davies committed
759
						  if (!parse_only && do_header) write_forward($$);
760 761 762 763 764 765 766
						}
	;

interfacedef: interfacehdr inherit
	  '{' int_statements '}'		{ $$ = $1;
						  $$->ref = $2;
						  $$->funcs = $4;
767
						  compute_method_indexes($$);
Huw Davies's avatar
Huw Davies committed
768
						  if (!parse_only && do_header) write_interface($$);
769
						  if (!parse_only && do_idfile) write_iid($$);
770 771 772 773 774 775
						}
/* MIDL is able to import the definition of a base class from inside the
 * definition of a derived class, I'll try to support it with this rule */
	| interfacehdr ':' aIDENTIFIER
	  '{' import int_statements '}'		{ $$ = $1;
						  $$->ref = find_type2($3, 0);
776
						  if (!$$->ref) yyerror("base class '%s' not found in import", $3);
777
						  $$->funcs = $6;
778
						  compute_method_indexes($$);
Huw Davies's avatar
Huw Davies committed
779
						  if (!parse_only && do_header) write_interface($$);
780
						  if (!parse_only && do_idfile) write_iid($$);
781
						}
782 783 784 785
	| dispinterfacedef			{ $$ = $1; }
	;

interfacedec:
Huw Davies's avatar
Huw Davies committed
786 787
	  interface ';'				{ $$ = $1; if (!parse_only && do_header) write_forward($$); }
	| dispinterface ';'			{ $$ = $1; if (!parse_only && do_header) write_forward($$); }
788 789
	;

790 791
module:   tMODULE aIDENTIFIER			{ $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; }
	| tMODULE aKNOWNTYPE			{ $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; }
792 793 794 795 796 797 798 799 800
	;

modulehdr: attributes module			{ $$ = $2;
						  $$->attrs = $1;
						}
	;

moduledef: modulehdr '{' int_statements '}'	{ $$ = $1;
						  $$->funcs = $3;
Huw Davies's avatar
Huw Davies committed
801
						  /* FIXME: if (!parse_only && do_header) write_module($$); */
802
						}
803 804 805
	;

p_ident:  '*' pident %prec PPTR			{ $$ = $2; $$->ptr_level++; }
806
	| tCONST p_ident			{ $$ = $2; /* FIXME */ }
807 808
	;

809
pident:	  ident					{ $$ = make_pident($1); }
810 811 812 813 814
	| p_ident
	| '(' pident ')'			{ $$ = $2; }
	;

pident_list:
815 816
	pident                                  { $$ = append_pident( NULL, $1 ); }
	| pident_list ',' pident                { $$ = append_pident( $1, $3 ); }
817 818 819 820 821
	;

pointer_type:
	  tREF					{ $$ = RPC_FC_RP; }
	| tUNIQUE				{ $$ = RPC_FC_UP; }
822
	| tPTR					{ $$ = RPC_FC_FP; }
823 824 825
	;

structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
826 827
                                                  /* overwrite RPC_FC_STRUCT with a more exact type */
						  $$->type = get_struct_type( $4 );
828
						  $$->kind = TKIND_RECORD;
829 830
						  $$->fields = $4;
						  $$->defined = TRUE;
831
                                                  if(in_typelib)
832
                                                      add_typelib_entry($$);
833
                                                }
834 835
	;

836 837 838 839 840 841 842 843 844 845 846
type:	  tVOID					{ $$ = duptype(find_type("void", 0), 1); }
	| aKNOWNTYPE				{ $$ = find_type($1, 0); }
	| base_type				{ $$ = $1; }
	| tCONST type				{ $$ = duptype($2, 1); $$->is_const = TRUE; }
	| enumdef				{ $$ = $1; }
	| tENUM aIDENTIFIER			{ $$ = find_type2($2, tsENUM); }
	| structdef				{ $$ = $1; }
	| tSTRUCT aIDENTIFIER			{ $$ = get_type(RPC_FC_STRUCT, $2, tsSTRUCT); }
	| uniondef				{ $$ = $1; }
	| tUNION aIDENTIFIER			{ $$ = find_type2($2, tsUNION); }
	| tSAFEARRAY '(' type ')'		{ $$ = make_safearray($3); }
847 848
	;

849
typedef: tTYPEDEF m_attributes type pident_list	{ reg_typedefs($3, $4, $2);
850
						  process_typedefs($4);
851 852 853 854
						}
	;

uniondef: tUNION t_ident '{' fields '}'		{ $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
855
						  $$->kind = TKIND_UNION;
856 857 858 859
						  $$->fields = $4;
						  $$->defined = TRUE;
						}
	| tUNION t_ident
860
	  tSWITCH '(' s_field ')'
861 862
	  m_ident '{' cases '}'			{ var_t *u = $7;
						  $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
863
						  $$->kind = TKIND_UNION;
864
						  if (!u) u = make_var( xstrdup("tagged_union") );
865
						  u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
866
						  u->type->kind = TKIND_UNION;
867 868
						  u->type->fields = $9;
						  u->type->defined = TRUE;
869 870
						  $$->fields = append_var( $$->fields, $5 );
						  $$->fields = append_var( $$->fields, u );
871 872 873 874 875
						  $$->defined = TRUE;
						}
	;

version:
876 877
	  aNUM					{ $$ = MAKELONG($1, 0); }
	| aNUM '.' aNUM				{ $$ = MAKELONG($1, $3); }
878 879 880 881
	;

%%

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
static void decl_builtin(const char *name, unsigned char type)
{
  type_t *t = make_type(type, NULL);
  t->name = xstrdup(name);
  reg_type(t, name, 0);
}

static type_t *make_builtin(char *name)
{
  /* NAME is strdup'd in the lexer */
  type_t *t = duptype(find_type(name, 0), 0);
  t->name = name;
  return t;
}

static type_t *make_int(int sign)
{
  type_t *t = duptype(find_type("int", 0), 1);

  t->sign = sign;
  if (sign < 0)
    t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT;

  return t;
}

void init_types(void)
{
910
  decl_builtin("void", 0);
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
  decl_builtin("byte", RPC_FC_BYTE);
  decl_builtin("wchar_t", RPC_FC_WCHAR);
  decl_builtin("int", RPC_FC_LONG);     /* win32 */
  decl_builtin("short", RPC_FC_SHORT);
  decl_builtin("small", RPC_FC_SMALL);
  decl_builtin("long", RPC_FC_LONG);
  decl_builtin("hyper", RPC_FC_HYPER);
  decl_builtin("__int64", RPC_FC_HYPER);
  decl_builtin("char", RPC_FC_CHAR);
  decl_builtin("float", RPC_FC_FLOAT);
  decl_builtin("double", RPC_FC_DOUBLE);
  decl_builtin("boolean", RPC_FC_BYTE);
  decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T);
  decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE);
}

927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
static str_list_t *append_str(str_list_t *list, char *str)
{
    struct str_list_entry_t *entry;

    if (!str) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    entry = xmalloc( sizeof(*entry) );
    entry->str = str;
    list_add_tail( list, &entry->entry );
    return list;
}

943 944 945 946 947 948 949 950 951 952 953 954
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
{
    if (!attr) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &attr->entry );
    return list;
}

955
static attr_t *make_attr(enum attr_type type)
956 957 958 959 960 961 962
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.ival = 0;
  return a;
}

963
static attr_t *make_attrv(enum attr_type type, unsigned long val)
964 965 966 967 968 969 970
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.ival = val;
  return a;
}

971
static attr_t *make_attrp(enum attr_type type, void *val)
972 973 974 975 976 977 978
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.pval = val;
  return a;
}

979 980 981 982 983 984
static expr_t *make_expr(enum expr_type type)
{
  expr_t *e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = NULL;
  e->u.lval = 0;
985
  e->is_const = FALSE;
986 987 988 989 990 991 992 993 994
  return e;
}

static expr_t *make_exprl(enum expr_type type, long val)
{
  expr_t *e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = NULL;
  e->u.lval = val;
995 996
  e->is_const = FALSE;
  /* check for numeric constant */
997 998 999
  if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) {
    /* make sure true/false value is valid */
    assert(type != EXPR_TRUEFALSE || val == 0 || val == 1);
1000 1001 1002
    e->is_const = TRUE;
    e->cval = val;
  }
1003 1004 1005 1006 1007
  return e;
}

static expr_t *make_exprs(enum expr_type type, char *val)
{
1008 1009
  expr_t *e;
  e = xmalloc(sizeof(expr_t));
1010 1011 1012
  e->type = type;
  e->ref = NULL;
  e->u.sval = val;
1013 1014 1015 1016 1017 1018 1019 1020
  e->is_const = FALSE;
  /* check for predefined constants */
  if (type == EXPR_IDENTIFIER) {
    var_t *c = find_const(val, 0);
    if (c) {
      e->u.sval = c->name;
      free(val);
      e->is_const = TRUE;
1021
      e->cval = c->eval->cval;
1022 1023 1024 1025 1026
    }
  }
  return e;
}

1027
static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr)
1028 1029 1030 1031 1032 1033 1034 1035
{
  expr_t *e;
  e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = expr;
  e->u.tref = tref;
  e->is_const = FALSE;
  /* check for cast of constant expression */
1036
  if (type == EXPR_SIZEOF) {
1037
    switch (tref->type) {
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
      case RPC_FC_BYTE:
      case RPC_FC_CHAR:
      case RPC_FC_SMALL:
      case RPC_FC_USMALL:
        e->is_const = TRUE;
        e->cval = 1;
        break;
      case RPC_FC_WCHAR:
      case RPC_FC_USHORT:
      case RPC_FC_SHORT:
        e->is_const = TRUE;
        e->cval = 2;
        break;
      case RPC_FC_LONG:
      case RPC_FC_ULONG:
      case RPC_FC_FLOAT:
      case RPC_FC_ERROR_STATUS_T:
        e->is_const = TRUE;
        e->cval = 4;
        break;
      case RPC_FC_HYPER:
      case RPC_FC_DOUBLE:
        e->is_const = TRUE;
        e->cval = 8;
        break;
    }
  }
1065 1066 1067 1068
  if (type == EXPR_CAST && expr->is_const) {
    e->is_const = TRUE;
    e->cval = expr->cval;
  }
1069 1070 1071 1072 1073 1074
  return e;
}

static expr_t *make_expr1(enum expr_type type, expr_t *expr)
{
  expr_t *e;
1075 1076 1077 1078 1079
  e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = expr;
  e->u.lval = 0;
  e->is_const = FALSE;
1080
  /* check for compile-time optimization */
1081 1082
  if (expr->is_const) {
    e->is_const = TRUE;
1083 1084
    switch (type) {
    case EXPR_NEG:
1085 1086
      e->cval = -expr->cval;
      break;
1087 1088 1089
    case EXPR_NOT:
      e->cval = ~expr->cval;
      break;
1090
    default:
1091
      e->is_const = FALSE;
1092
      break;
1093 1094 1095 1096 1097 1098 1099 1100
    }
  }
  return e;
}

static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
{
  expr_t *e;
1101 1102 1103 1104 1105
  e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = expr1;
  e->u.ext = expr2;
  e->is_const = FALSE;
1106
  /* check for compile-time optimization */
1107 1108
  if (expr1->is_const && expr2->is_const) {
    e->is_const = TRUE;
1109 1110
    switch (type) {
    case EXPR_ADD:
1111 1112
      e->cval = expr1->cval + expr2->cval;
      break;
1113
    case EXPR_SUB:
1114 1115
      e->cval = expr1->cval - expr2->cval;
      break;
1116
    case EXPR_MUL:
1117 1118
      e->cval = expr1->cval * expr2->cval;
      break;
1119
    case EXPR_DIV:
1120 1121
      e->cval = expr1->cval / expr2->cval;
      break;
1122
    case EXPR_OR:
1123 1124
      e->cval = expr1->cval | expr2->cval;
      break;
1125
    case EXPR_AND:
1126 1127
      e->cval = expr1->cval & expr2->cval;
      break;
1128
    case EXPR_SHL:
1129 1130
      e->cval = expr1->cval << expr2->cval;
      break;
1131
    case EXPR_SHR:
1132 1133
      e->cval = expr1->cval >> expr2->cval;
      break;
1134
    default:
1135
      e->is_const = FALSE;
1136
      break;
1137
    }
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
  }
  return e;
}

static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
{
  expr_t *e;
  e = xmalloc(sizeof(expr_t));
  e->type = type;
  e->ref = expr1;
  e->u.ext = expr2;
  e->ext2 = expr3;
  e->is_const = FALSE;
  /* check for compile-time optimization */
  if (expr1->is_const && expr2->is_const && expr3->is_const) {
    e->is_const = TRUE;
    switch (type) {
    case EXPR_COND:
      e->cval = expr1->cval ? expr2->cval : expr3->cval;
      break;
    default:
      e->is_const = FALSE;
      break;
    }
1162 1163 1164 1165
  }
  return e;
}

1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
static expr_list_t *append_expr(expr_list_t *list, expr_t *expr)
{
    if (!expr) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &expr->entry );
    return list;
}

static array_dims_t *append_array(array_dims_t *list, expr_t *expr)
{
    if (!expr) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &expr->entry );
    return list;
}

1190
static type_t *make_type(unsigned char type, type_t *ref)
1191 1192 1193
{
  type_t *t = xmalloc(sizeof(type_t));
  t->name = NULL;
1194
  t->kind = TKIND_PRIMITIVE;
1195 1196 1197
  t->type = type;
  t->ref = ref;
  t->attrs = NULL;
1198
  t->orig = NULL;
1199 1200
  t->funcs = NULL;
  t->fields = NULL;
1201
  t->ifaces = NULL;
1202
  t->typestring_offset = 0;
1203
  t->ignore = (parse_only != 0);
1204
  t->is_const = FALSE;
1205
  t->sign = 0;
1206 1207
  t->defined = FALSE;
  t->written = FALSE;
1208
  t->user_types_registered = FALSE;
1209
  t->tfswrite = FALSE;
1210
  t->typelib_idx = -1;
1211 1212 1213
  return t;
}

1214
static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr)
1215
{
1216
  v->type = type;
1217
  v->array = arr;
1218 1219 1220

  for ( ; 0 < ptr_level; --ptr_level)
    v->type = make_type(RPC_FC_RP, v->type);
1221 1222
}

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface)
{
    if (!iface) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &iface->entry );
    return list;
}

1235 1236 1237 1238 1239 1240 1241 1242
static ifref_t *make_ifref(type_t *iface)
{
  ifref_t *l = xmalloc(sizeof(ifref_t));
  l->iface = iface;
  l->attrs = NULL;
  return l;
}

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
static var_list_t *append_var(var_list_t *list, var_t *var)
{
    if (!var) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &var->entry );
    return list;
}

1255 1256 1257 1258 1259
static var_t *make_var(char *name)
{
  var_t *v = xmalloc(sizeof(var_t));
  v->name = name;
  v->type = NULL;
1260
  v->args = NULL;
1261
  v->attrs = NULL;
1262
  v->array = NULL;
1263
  v->eval = NULL;
1264
  v->corrdesc = 0;
1265 1266 1267
  return v;
}

1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
static pident_list_t *append_pident(pident_list_t *list, pident_t *p)
{
  if (!p) return list;
  if (!list) {
    list = xmalloc(sizeof(*list));
    list_init(list);
  }
  list_add_tail(list, &p->entry);
  return list;
}

static pident_t *make_pident(var_t *var)
{
  pident_t *p = xmalloc(sizeof(*p));
  p->var = var;
  p->ptr_level = 0;
  return p;
}

1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
static func_list_t *append_func(func_list_t *list, func_t *func)
{
    if (!func) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &func->entry );
    return list;
}

1299
static func_t *make_func(var_t *def, var_list_t *args)
1300 1301 1302 1303 1304 1305 1306 1307 1308
{
  func_t *f = xmalloc(sizeof(func_t));
  f->def = def;
  f->args = args;
  f->ignore = parse_only;
  f->idx = -1;
  return f;
}

1309
static type_t *make_class(char *name)
1310
{
1311
  type_t *c = make_type(0, NULL);
1312
  c->name = name;
1313
  c->kind = TKIND_COCLASS;
1314 1315 1316
  return c;
}

1317
static type_t *make_safearray(type_t *type)
1318
{
1319 1320
  type_t *sa = duptype(find_type("SAFEARRAY", 0), 1);
  sa->ref = type;
1321
  return make_type(RPC_FC_FP, sa);
1322 1323
}

1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
#define HASHMAX 64

static int hash_ident(const char *name)
{
  const char *p = name;
  int sum = 0;
  /* a simple sum hash is probably good enough */
  while (*p) {
    sum += *p;
    p++;
  }
  return sum & (HASHMAX-1);
}

/***** type repository *****/

1340
struct rtype {
1341
  const char *name;
1342 1343 1344 1345 1346
  type_t *type;
  int t;
  struct rtype *next;
};

1347
struct rtype *type_hash[HASHMAX];
1348

1349
static type_t *reg_type(type_t *type, const char *name, int t)
1350 1351
{
  struct rtype *nt;
1352
  int hash;
1353
  if (!name) {
1354
    yyerror("registering named type without name");
1355 1356
    return type;
  }
1357
  hash = hash_ident(name);
1358 1359 1360 1361
  nt = xmalloc(sizeof(struct rtype));
  nt->name = name;
  nt->type = type;
  nt->t = t;
1362 1363
  nt->next = type_hash[hash];
  type_hash[hash] = nt;
1364 1365 1366
  return type;
}

1367
static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs)
1368 1369
{
  type_t *ptr = type;
1370
  const pident_t *pident;
1371
  int ptrc = 0;
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
  int is_str = is_attr(attrs, ATTR_STRING);
  unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE);

  if (is_str)
  {
    type_t *t = type;
    unsigned char c;

    while (is_ptr(t))
      t = t->ref;

    c = t->type;
    if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR)
1385
    {
1386
      pident = LIST_ENTRY( list_head( pidents ), const pident_t, entry );
1387
      yyerror("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays",
1388
              pident->var->name);
1389
    }
1390
  }
1391

1392 1393 1394 1395 1396 1397 1398 1399
  /* We must generate names for tagless enum, struct or union.
     Typedef-ing a tagless enum, struct or union means we want the typedef
     to be included in a library whether it has other attributes or not,
     hence the public attribute.  */
  if ((type->kind == TKIND_ENUM || type->kind == TKIND_RECORD
       || type->kind == TKIND_UNION) && ! type->name && ! parse_only)
  {
    if (! is_attr(attrs, ATTR_PUBLIC))
1400
      attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) );
1401 1402 1403
    type->name = gen_name();
  }

1404
  LIST_FOR_EACH_ENTRY( pident, pidents, const pident_t, entry )
1405
  {
1406 1407
    var_t *name = pident->var;

1408
    if (name->name) {
1409
      type_t *cur = ptr;
1410
      int cptr = pident->ptr_level;
1411 1412
      if (cptr > ptrc) {
        while (cptr > ptrc) {
1413
          cur = ptr = make_type(RPC_FC_RP, cur);
1414 1415 1416 1417 1418 1419 1420 1421
          ptrc++;
        }
      } else {
        while (cptr < ptrc) {
          cur = cur->ref;
          cptr++;
        }
      }
1422
      cur = alias(cur, name->name);
1423
      cur->attrs = attrs;
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
      if (ptr_type)
      {
        if (is_ptr(cur))
          cur->type = ptr_type;
        else
          yyerror("'%s': pointer attribute applied to non-pointer type",
                  cur->name);
      }
      else if (is_str && ! is_ptr(cur))
        yyerror("'%s': [string] attribute applied to non-pointer type",
                cur->name);

1436
      reg_type(cur, cur->name, 0);
1437 1438 1439 1440 1441
    }
  }
  return type;
}

1442
static type_t *find_type(const char *name, int t)
1443
{
1444
  struct rtype *cur = type_hash[hash_ident(name)];
1445 1446 1447
  while (cur && (cur->t != t || strcmp(cur->name, name)))
    cur = cur->next;
  if (!cur) {
1448
    yyerror("type '%s' not found", name);
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
    return NULL;
  }
  return cur->type;
}

static type_t *find_type2(char *name, int t)
{
  type_t *tp = find_type(name, t);
  free(name);
  return tp;
}

int is_type(const char *name)
{
1463
  struct rtype *cur = type_hash[hash_ident(name)];
1464 1465 1466 1467 1468 1469
  while (cur && (cur->t || strcmp(cur->name, name)))
    cur = cur->next;
  if (cur) return TRUE;
  return FALSE;
}

1470
static type_t *get_type(unsigned char type, char *name, int t)
1471 1472 1473 1474
{
  struct rtype *cur = NULL;
  type_t *tp;
  if (name) {
1475
    cur = type_hash[hash_ident(name)];
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
    while (cur && (cur->t != t || strcmp(cur->name, name)))
      cur = cur->next;
  }
  if (cur) {
    free(name);
    return cur->type;
  }
  tp = make_type(type, NULL);
  tp->name = name;
  if (!name) return tp;
  return reg_type(tp, name, t);
}

1489
static type_t *get_typev(unsigned char type, var_t *name, int t)
1490 1491 1492 1493 1494 1495 1496 1497
{
  char *sname = NULL;
  if (name) {
    sname = name->name;
    free(name);
  }
  return get_type(type, sname, t);
}
1498

1499
static int get_struct_type(var_list_t *fields)
1500 1501
{
  int has_pointer = 0;
1502 1503
  int has_conformance = 0;
  int has_variance = 0;
1504
  var_t *field;
1505

1506
  if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
1507 1508 1509
  {
    type_t *t = field->type;

1510
    if (is_ptr(field->type))
1511 1512 1513 1514 1515
    {
        has_pointer = 1;
        continue;
    }

1516
    if (is_string_type(field->attrs, field->type, field->array))
1517
    {
1518 1519
        has_conformance = 1;
        has_variance = 1;
1520 1521 1522
        continue;
    }

1523
    if (is_array_type(field->attrs, field->type, field->array))
1524
    {
1525
        if (field->array && is_conformant_array(field->array))
1526 1527
        {
            has_conformance = 1;
1528
            if (list_next( fields, &field->entry ))
1529
                yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1530 1531 1532 1533
                        field->name);
        }
        if (is_attr(field->attrs, ATTR_LENGTHIS))
            has_variance = 1;
1534 1535
    }

1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
    switch (t->type)
    {
    /*
     * RPC_FC_BYTE, RPC_FC_STRUCT, etc
     *  Simple types don't effect the type of struct.
     *  A struct containing a simple struct is still a simple struct.
     *  So long as we can block copy the data, we return RPC_FC_STRUCT.
     */
    case 0: /* void pointer */
    case RPC_FC_BYTE:
    case RPC_FC_CHAR:
    case RPC_FC_SMALL:
    case RPC_FC_USMALL:
    case RPC_FC_WCHAR:
    case RPC_FC_SHORT:
    case RPC_FC_USHORT:
    case RPC_FC_LONG:
    case RPC_FC_ULONG:
    case RPC_FC_INT3264:
    case RPC_FC_UINT3264:
    case RPC_FC_HYPER:
    case RPC_FC_FLOAT:
    case RPC_FC_DOUBLE:
    case RPC_FC_STRUCT:
    case RPC_FC_ENUM16:
    case RPC_FC_ENUM32:
      break;

1564
    case RPC_FC_RP:
1565 1566
    case RPC_FC_UP:
    case RPC_FC_FP:
1567
    case RPC_FC_OP:
1568 1569 1570
      has_pointer = 1;
      break;
    case RPC_FC_CARRAY:
1571
      has_conformance = 1;
1572
      if (list_next( fields, &field->entry ))
1573
          yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1574
                  field->name);
1575 1576 1577 1578 1579 1580 1581
      break;

    /*
     * Propagate member attributes
     *  a struct should be at least as complex as its member
     */
    case RPC_FC_CVSTRUCT:
1582 1583
      has_conformance = 1;
      has_variance = 1;
1584 1585 1586 1587
      has_pointer = 1;
      break;

    case RPC_FC_CPSTRUCT:
1588
      has_conformance = 1;
1589
      if (list_next( fields, &field->entry ))
1590
          yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1591
                  field->name);
1592 1593 1594 1595
      has_pointer = 1;
      break;

    case RPC_FC_CSTRUCT:
1596
      has_conformance = 1;
1597
      if (list_next( fields, &field->entry ))
1598
          yyerror("field '%s' deriving from a conformant array must be the last field in the structure",
1599
                  field->name);
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
      break;

    case RPC_FC_PSTRUCT:
      has_pointer = 1;
      break;

    default:
      fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n",
              field->name, t->type);
      /* fallthru - treat it as complex */

    /* as soon as we see one of these these members, it's bogus... */
    case RPC_FC_IP:
    case RPC_FC_ENCAPSULATED_UNION:
    case RPC_FC_NON_ENCAPSULATED_UNION:
    case RPC_FC_TRANSMIT_AS:
    case RPC_FC_REPRESENT_AS:
    case RPC_FC_PAD:
    case RPC_FC_EMBEDDED_COMPLEX:
    case RPC_FC_BOGUS_STRUCT:
      return RPC_FC_BOGUS_STRUCT;
    }
  }

1624
  if( has_variance )
1625
    return RPC_FC_CVSTRUCT;
1626
  if( has_conformance && has_pointer )
1627
    return RPC_FC_CPSTRUCT;
1628
  if( has_conformance )
1629 1630 1631 1632 1633 1634
    return RPC_FC_CSTRUCT;
  if( has_pointer )
    return RPC_FC_PSTRUCT;
  return RPC_FC_STRUCT;
}

1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
/***** constant repository *****/

struct rconst {
  char *name;
  var_t *var;
  struct rconst *next;
};

struct rconst *const_hash[HASHMAX];

static var_t *reg_const(var_t *var)
{
  struct rconst *nc;
  int hash;
  if (!var->name) {
1650
    yyerror("registering constant without name");
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667
    return var;
  }
  hash = hash_ident(var->name);
  nc = xmalloc(sizeof(struct rconst));
  nc->name = var->name;
  nc->var = var;
  nc->next = const_hash[hash];
  const_hash[hash] = nc;
  return var;
}

static var_t *find_const(char *name, int f)
{
  struct rconst *cur = const_hash[hash_ident(name)];
  while (cur && strcmp(cur->name, name))
    cur = cur->next;
  if (!cur) {
1668
    if (f) yyerror("constant '%s' not found", name);
1669 1670 1671 1672
    return NULL;
  }
  return cur->var;
}
1673

1674
static void write_libid(const char *name, const attr_list_t *attr)
1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
{
  const UUID *uuid = get_attrp(attr, ATTR_UUID);
  write_guid(idfile, "LIBID", name, uuid);
}

static void write_clsid(type_t *cls)
{
  const UUID *uuid = get_attrp(cls->attrs, ATTR_UUID);
  write_guid(idfile, "CLSID", cls->name, uuid);
}

static void write_diid(type_t *iface)
{
  const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
  write_guid(idfile, "DIID", iface->name, uuid);
}

static void write_iid(type_t *iface)
{
  const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
  write_guid(idfile, "IID", iface->name, uuid);
}
1697 1698 1699 1700

static int compute_method_indexes(type_t *iface)
{
  int idx;
1701
  func_t *f;
1702 1703 1704 1705 1706 1707

  if (iface->ref)
    idx = compute_method_indexes(iface->ref);
  else
    idx = 0;

1708
  if (!iface->funcs)
1709 1710
    return idx;

1711
  LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry )
1712 1713 1714 1715 1716
    if (! is_callas(f->def->attrs))
      f->idx = idx++;

  return idx;
}
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741

static char *gen_name(void)
{
  static const char format[] = "__WIDL_%s_generated_name_%08lX";
  static unsigned long n = 0;
  static const char *file_id;
  static size_t size;
  char *name;

  if (! file_id)
  {
    char *dst = dup_basename(input_name, ".idl");
    file_id = dst;

    for (; *dst; ++dst)
      if (! isalnum((unsigned char) *dst))
        *dst = '_';

    size = sizeof format - 7 + strlen(file_id) + 8;
  }

  name = xmalloc(size);
  sprintf(name, format, file_id, n++);
  return name;
}
1742

1743
static void process_typedefs(pident_list_t *pidents)
1744
{
1745
  pident_t *pident, *next;
1746

1747 1748
  if (!pidents) return;
  LIST_FOR_EACH_ENTRY_SAFE( pident, next, pidents, pident_t, entry )
1749
  {
1750 1751
    var_t *var = pident->var;
    type_t *type = find_type(var->name, 0);
1752 1753 1754 1755

    if (! parse_only && do_header)
      write_typedef(type);
    if (in_typelib && type->attrs)
1756
      add_typelib_entry(type);
1757

1758 1759
    free(pident);
    free(var);
1760 1761
  }
}
1762 1763 1764 1765 1766 1767 1768 1769

static void check_arg(var_t *arg)
{
  type_t *t = arg->type;

  if (t->type == 0 && ! is_var_ptr(arg))
    yyerror("argument '%s' has void type", arg->name);
}