parser.y 93.6 KB
Newer Older
1 2 3 4 5
%{
/*
 * IDL Compiler
 *
 * Copyright 2002 Ove Kaaven
6
 * Copyright 2006-2008 Robert Shearman
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>

#include "widl.h"
#include "utils.h"
#include "parser.h"
#include "header.h"
36
#include "typelib.h"
37
#include "typegen.h"
38
#include "expr.h"
39
#include "typetree.h"
40 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

#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

66 67
#define YYERROR_VERBOSE

68
static unsigned char pointer_default = RPC_FC_UP;
69

70 71 72 73 74 75
typedef struct list typelist_t;
struct typenode {
  type_t *type;
  struct list entry;
};

76 77 78 79 80 81
struct _import_t
{
  char *name;
  int import_performed;
};

82 83 84 85 86 87 88
typedef struct _decl_spec_t
{
  type_t *type;
  attr_list_t *attrs;
  enum storage_class stgclass;
} decl_spec_t;

89 90 91
typelist_t incomplete_types = LIST_INIT(incomplete_types);

static void fix_incomplete(void);
92
static void fix_incomplete_types(type_t *complete_type);
93

94
static str_list_t *append_str(str_list_t *list, char *str);
95
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
96
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
97
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
98
static attr_t *make_attr(enum attr_type type);
99
static attr_t *make_attrv(enum attr_type type, unsigned int val);
100
static attr_t *make_attrp(enum attr_type type, void *val);
101 102
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);
103
static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, int top);
104
static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls);
105
static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
106
static ifref_t *make_ifref(type_t *iface);
107
static var_list_t *append_var_list(var_list_t *list, var_list_t *vars);
108 109
static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p);
static declarator_t *make_declarator(var_t *var);
110
static type_t *make_safearray(type_t *type);
111
static typelib_t *make_library(const char *name, const attr_list_t *attrs);
112
static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type);
113

114
static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs);
115 116
static type_t *find_type_or_error(const char *name, int t);
static type_t *find_type_or_error2(char *name, int t);
117

118 119
static var_t *reg_const(var_t *var);

120
static char *gen_name(void);
121
static void check_arg_attrs(const var_t *arg);
122
static void check_statements(const statement_list_t *stmts, int is_inside_library);
123
static void check_all_user_types(const statement_list_t *stmts);
124
static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs);
125
static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs);
126
static attr_list_t *check_typedef_attrs(attr_list_t *attrs);
127 128 129
static attr_list_t *check_enum_attrs(attr_list_t *attrs);
static attr_list_t *check_struct_attrs(attr_list_t *attrs);
static attr_list_t *check_union_attrs(attr_list_t *attrs);
130
static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs);
131
static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs);
132
static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs);
133 134
static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs);
static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs);
135
const char *get_attr_display_name(enum attr_type type);
136
static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func);
137
static void check_def(const type_t *t);
138

139 140 141
static statement_t *make_statement(enum statement_type type);
static statement_t *make_statement_type_decl(type_t *type);
static statement_t *make_statement_reference(type_t *type);
142
static statement_t *make_statement_declaration(var_t *var);
143 144 145 146
static statement_t *make_statement_library(typelib_t *typelib);
static statement_t *make_statement_cppquote(const char *str);
static statement_t *make_statement_importlib(const char *str);
static statement_t *make_statement_module(type_t *type);
147
static statement_t *make_statement_typedef(var_list_t *names);
148
static statement_t *make_statement_import(const char *str);
149
static statement_t *make_statement_typedef(var_list_t *names);
150 151
static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt);

152 153 154
%}
%union {
	attr_t *attr;
155
	attr_list_t *attr_list;
156
	str_list_t *str_list;
157
	expr_t *expr;
158 159
	expr_list_t *expr_list;
	array_dims_t *array_dims;
160 161
	type_t *type;
	var_t *var;
162
	var_list_t *var_list;
163 164
	declarator_t *declarator;
	declarator_list_t *declarator_list;
165 166
	statement_t *statement;
	statement_list_t *stmt_list;
167
	ifref_t *ifref;
168
	ifref_list_t *ifref_list;
169
	char *str;
170
	UUID *uuid;
171
	unsigned int num;
172
	double dbl;
173
	interface_info_t ifinfo;
174 175
	typelib_t *typelib;
	struct _import_t *import;
176 177
	struct _decl_spec_t *declspec;
	enum storage_class stgclass;
178 179 180 181
}

%token <str> aIDENTIFIER
%token <str> aKNOWNTYPE
182
%token <num> aNUM aHEXNUM
183
%token <dbl> aDOUBLE
184
%token <str> aSTRING aWSTRING aSQSTRING
185
%token <uuid> aUUID
186
%token aEOF
187
%token SHL SHR
188
%token MEMBERPTR
189 190 191
%token EQUALITY INEQUALITY
%token GREATEREQUAL LESSEQUAL
%token LOGICALOR LOGICALAND
192
%token ELLIPSIS
193
%token tAGGREGATABLE tALLOCATE tANNOTATION tAPPOBJECT tASYNC tASYNCUUID
194 195 196 197
%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
198
%token tDECODE tDEFAULT tDEFAULTBIND
199
%token tDEFAULTCOLLELEM
200
%token tDEFAULTVALUE
201
%token tDEFAULTVTABLE
202
%token tDISABLECONSISTENCYCHECK tDISPLAYBIND
203 204
%token tDISPINTERFACE
%token tDLLNAME tDOUBLE tDUAL
205
%token tENABLEALLOCATE tENCODE tENDPOINT
206
%token tENTRY tENUM tERRORSTATUST
207
%token tEXPLICITHANDLE tEXTERN
208
%token tFALSE
209 210
%token tFASTCALL tFAULTSTATUS
%token tFLOAT tFORCEALLOCATE
211
%token tHANDLE
212
%token tHANDLET
213 214
%token tHELPCONTEXT tHELPFILE
%token tHELPSTRING tHELPSTRINGCONTEXT tHELPSTRINGDLL
215
%token tHIDDEN
216
%token tHYPER tID tIDEMPOTENT
217
%token tIGNORE tIIDIS
218
%token tIMMEDIATEBIND
219
%token tIMPLICITHANDLE
220
%token tIMPORT tIMPORTLIB
221
%token tIN tIN_LINE tINLINE
222
%token tINPUTSYNC
223
%token tINT tINT3264 tINT64
224
%token tINTERFACE
225
%token tLCID
226
%token tLENGTHIS tLIBRARY
227
%token tLICENSED tLOCAL
228
%token tLONG
229
%token tMAYBE tMESSAGE
230 231
%token tMETHODS
%token tMODULE
232
%token tNOCODE tNONBROWSABLE
Huw Davies's avatar
Huw Davies committed
233
%token tNONCREATABLE
234
%token tNONEXTENSIBLE
235
%token tNOTIFY tNOTIFYFLAG
236
%token tNULL
237
%token tOBJECT tODL tOLEAUTOMATION
238
%token tOPTIMIZE tOPTIONAL
239
%token tOUT
240
%token tPARTIALIGNORE tPASCAL
241
%token tPOINTERDEFAULT
242
%token tPROGID tPROPERTIES
243
%token tPROPGET tPROPPUT tPROPPUTREF
244
%token tPROXY tPTR
245
%token tPUBLIC
246
%token tRANGE
247
%token tREADONLY tREF
248
%token tREGISTER tREPRESENTAS
249
%token tREQUESTEDIT
250
%token tRESTRICTED
251
%token tRETVAL
252
%token tSAFEARRAY
253 254 255
%token tSHORT
%token tSIGNED
%token tSIZEIS tSIZEOF
256
%token tSMALL
257
%token tSOURCE
258
%token tSTATIC
259
%token tSTDCALL
260
%token tSTRICTCONTEXTHANDLE
261 262
%token tSTRING tSTRUCT
%token tSWITCH tSWITCHIS tSWITCHTYPE
263
%token tTHREADING tTRANSMITAS
264
%token tTRUE
265
%token tTYPEDEF
266
%token tUIDEFAULT tUNION
267 268
%token tUNIQUE
%token tUNSIGNED
269
%token tUSESGETLASTERROR tUSERMARSHAL tUUID
270
%token tV1ENUM
271
%token tVARARG
272
%token tVERSION tVIPROGID
273 274
%token tVOID
%token tWCHAR tWIREMARSHAL
275
%token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH
276

277
%type <attr> attribute type_qualifier function_specifier
278
%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
279
%type <str_list> str_list
280
%type <expr> m_expr expr expr_const expr_int_const array m_bitfield
281
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
282
%type <ifinfo> interfacehdr
283
%type <stgclass> storage_cls_spec
284
%type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
285
%type <type> inherit interface interfacedef interfacedec
286 287
%type <type> dispinterface dispinterfacehdr dispinterfacedef
%type <type> module modulehdr moduledef
288
%type <type> base_type int_std
289
%type <type> enumdef structdef uniondef typedecl
290
%type <type> type
291
%type <ifref> coclass_int
292
%type <ifref_list> coclass_ints
293
%type <var> arg ne_union_field union_field s_field case enum declaration
Rob Shearman's avatar
Rob Shearman committed
294 295
%type <var> funcdef
%type <var_list> m_args arg_list args dispint_meths
296
%type <var_list> fields ne_union_fields cases enums enum_list dispint_props field
297
%type <var> m_ident ident
298
%type <declarator> declarator direct_declarator init_declarator struct_declarator
299 300
%type <declarator> m_any_declarator any_declarator any_declarator_no_direct any_direct_declarator
%type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator
301
%type <declarator_list> declarator_list struct_declarator_list
302
%type <type> coclass coclasshdr coclassdef
303
%type <num> pointer_type threading_type version
304
%type <str> libraryhdr callconv cppquote importlib import t_ident
305
%type <uuid> uuid_string
306
%type <import> import_start
307
%type <typelib> library_start librarydef
308
%type <statement> statement typedef
Rob Shearman's avatar
Rob Shearman committed
309
%type <stmt_list> gbl_statements imp_statements int_statements
310 311

%left ','
312
%right '?' ':'
313 314
%left LOGICALOR
%left LOGICALAND
315
%left '|'
316
%left '^'
317
%left '&'
318 319
%left EQUALITY INEQUALITY
%left '<' '>' LESSEQUAL GREATEREQUAL
320
%left SHL SHR
321
%left '-' '+'
322
%left '*' '/' '%'
323
%right '!' '~' CAST PPTR POS NEG ADDRESSOF tSIZEOF
324
%left '.' MEMBERPTR '[' ']'
325 326 327

%%

328
input:   gbl_statements				{ fix_incomplete();
329
						  check_statements($1, FALSE);
330
						  check_all_user_types($1);
331
						  write_header($1);
332
						  write_id_data($1);
333 334 335
						  write_proxies($1);
						  write_client($1);
						  write_server($1);
336
						  write_regscript($1);
337
						  write_dlldata($1);
338
						  write_local_stubs($1);
339
						}
340 341
	;

342
gbl_statements:					{ $$ = NULL; }
343
	| gbl_statements interfacedec		{ $$ = append_statement($1, make_statement_reference($2)); }
344
	| gbl_statements interfacedef		{ $$ = append_statement($1, make_statement_type_decl($2)); }
345 346 347
	| gbl_statements coclass ';'		{ $$ = $1;
						  reg_type($2, $2->name, 0);
						}
348
	| gbl_statements coclassdef		{ $$ = append_statement($1, make_statement_type_decl($2));
349 350
						  reg_type($2, $2->name, 0);
						}
351
	| gbl_statements moduledef		{ $$ = append_statement($1, make_statement_module($2)); }
352 353
	| gbl_statements librarydef		{ $$ = append_statement($1, make_statement_library($2)); }
	| gbl_statements statement		{ $$ = append_statement($1, $2); }
354 355
	;

356
imp_statements:					{ $$ = NULL; }
357 358
	| imp_statements interfacedec		{ $$ = append_statement($1, make_statement_reference($2)); }
	| imp_statements interfacedef		{ $$ = append_statement($1, make_statement_type_decl($2)); }
359
	| imp_statements coclass ';'		{ $$ = $1; reg_type($2, $2->name, 0); }
360
	| imp_statements coclassdef		{ $$ = append_statement($1, make_statement_type_decl($2));
361 362
						  reg_type($2, $2->name, 0);
						}
363
	| imp_statements moduledef		{ $$ = append_statement($1, make_statement_module($2)); }
364 365 366
	| imp_statements statement		{ $$ = append_statement($1, $2); }
	| imp_statements importlib		{ $$ = append_statement($1, make_statement_importlib($2)); }
	| imp_statements librarydef		{ $$ = append_statement($1, make_statement_library($2)); }
367 368 369
	;

int_statements:					{ $$ = NULL; }
370
	| int_statements statement		{ $$ = append_statement($1, $2); }
371 372
	;

373 374 375 376
semicolon_opt:
	| ';'
	;

377 378
statement:
	  cppquote				{ $$ = make_statement_cppquote($1); }
379 380
	| typedecl ';'				{ $$ = make_statement_type_decl($1); }
	| declaration ';'			{ $$ = make_statement_declaration($1); }
381
	| import				{ $$ = make_statement_import($1); }
382
	| typedef ';'				{ $$ = $1; }
383 384 385 386
	;

typedecl:
	  enumdef
387
	| tENUM aIDENTIFIER                     { $$ = type_new_enum($2, FALSE, NULL); }
388
	| structdef
389
	| tSTRUCT aIDENTIFIER                   { $$ = type_new_struct($2, FALSE, NULL); }
390
	| uniondef
391
	| tUNION aIDENTIFIER                    { $$ = type_new_nonencapsulated_union($2, FALSE, NULL); }
392 393 394
	| attributes enumdef                    { $$ = $2; $$->attrs = check_enum_attrs($1); }
	| attributes structdef                  { $$ = $2; $$->attrs = check_struct_attrs($1); }
	| attributes uniondef                   { $$ = $2; $$->attrs = check_union_attrs($1); }
395 396
	;

397
cppquote: tCPPQUOTE '(' aSTRING ')'		{ $$ = $3; }
398
	;
399
import_start: tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
400 401 402 403
						  $$ = xmalloc(sizeof(struct _import_t));
						  $$->name = $2;
						  $$->import_performed = do_import($2);
						  if (!$$->import_performed) yychar = aEOF;
404
						}
405
	;
406

407 408 409 410
import: import_start imp_statements aEOF	{ $$ = $1->name;
						  if ($1->import_performed) pop_import();
						  free($1);
						}
411 412
	;

413
importlib: tIMPORTLIB '(' aSTRING ')'
414
	   semicolon_opt			{ $$ = $3; if(!parse_only) add_importlib($3); }
Jacek Caban's avatar
Jacek Caban committed
415
	;
416

417 418
libraryhdr: tLIBRARY aIDENTIFIER		{ $$ = $2; }
	;
419 420
library_start: attributes libraryhdr '{'	{ $$ = make_library($2, check_library_attrs($2, $1));
						  if (!parse_only) start_typelib($$);
421
						}
422
	;
423
librarydef: library_start imp_statements '}'
424 425 426 427
	    semicolon_opt			{ $$ = $1;
						  $$->stmts = $2;
						  if (!parse_only) end_typelib();
						}
428
	;
429 430 431 432 433

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

434 435 436 437 438 439
arg_list: arg					{ check_arg_attrs($1); $$ = append_var( NULL, $1 ); }
	| arg_list ',' arg			{ check_arg_attrs($3); $$ = append_var( $1, $3 ); }
	;

args:	  arg_list
	| arg_list ',' ELLIPSIS			{ $$ = append_var( $1, make_var(strdup("...")) ); }
440 441 442
	;

/* split into two rules to get bison to resolve a tVOID conflict */
443
arg:	  attributes decl_spec m_any_declarator	{ if ($2->stgclass != STG_NONE && $2->stgclass != STG_REGISTER)
444
						    error_loc("invalid storage class for function parameter\n");
445
						  $$ = declare_var($1, $2, $3, TRUE);
446
						  free($2); free($3);
447
						}
448
	| decl_spec m_any_declarator		{ if ($1->stgclass != STG_NONE && $1->stgclass != STG_REGISTER)
449
						    error_loc("invalid storage class for function parameter\n");
450
						  $$ = declare_var(NULL, $1, $2, TRUE);
451
						  free($1); free($2);
452 453 454
						}
	;

455 456 457 458
array:	  '[' expr ']'				{ $$ = $2;
						  if (!$$->is_const)
						      error_loc("array dimension is not an integer constant\n");
						}
459
	| '[' '*' ']'				{ $$ = make_expr(EXPR_VOID); }
460
	| '[' ']'				{ $$ = make_expr(EXPR_VOID); }
461 462
	;

463 464 465 466 467
m_attributes:					{ $$ = NULL; }
	| attributes
	;

attributes:
468
	  '[' attrib_list ']'			{ $$ = $2; }
469 470
	;

471 472 473
attrib_list: attribute                          { $$ = append_attr( NULL, $1 ); }
	| attrib_list ',' attribute             { $$ = append_attr( $1, $3 ); }
	| attrib_list ']' '[' attribute         { $$ = append_attr( $1, $4 ); }
474 475
	;

476 477 478 479
str_list: aSTRING                               { $$ = append_str( NULL, $1 ); }
	| str_list ',' aSTRING                  { $$ = append_str( $1, $3 ); }
	;

480 481
attribute:					{ $$ = NULL; }
	| tAGGREGATABLE				{ $$ = make_attr(ATTR_AGGREGATABLE); }
482
	| tANNOTATION '(' aSTRING ')'		{ $$ = make_attrp(ATTR_ANNOTATION, $3); }
483 484
	| tAPPOBJECT				{ $$ = make_attr(ATTR_APPOBJECT); }
	| tASYNC				{ $$ = make_attr(ATTR_ASYNC); }
485
	| tAUTOHANDLE				{ $$ = make_attr(ATTR_AUTO_HANDLE); }
486
	| tBINDABLE				{ $$ = make_attr(ATTR_BINDABLE); }
487
	| tBROADCAST				{ $$ = make_attr(ATTR_BROADCAST); }
488
	| tCALLAS '(' ident ')'			{ $$ = make_attrp(ATTR_CALLAS, $3); }
489
	| tCASE '(' expr_list_int_const ')'	{ $$ = make_attrp(ATTR_CASE, $3); }
490 491
	| tCODE					{ $$ = make_attr(ATTR_CODE); }
	| tCOMMSTATUS				{ $$ = make_attr(ATTR_COMMSTATUS); }
492 493 494
	| 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 */ }
495
	| tCONTROL				{ $$ = make_attr(ATTR_CONTROL); }
496
	| tDECODE				{ $$ = make_attr(ATTR_DECODE); }
497
	| tDEFAULT				{ $$ = make_attr(ATTR_DEFAULT); }
498
	| tDEFAULTBIND				{ $$ = make_attr(ATTR_DEFAULTBIND); }
499
	| tDEFAULTCOLLELEM			{ $$ = make_attr(ATTR_DEFAULTCOLLELEM); }
500
	| tDEFAULTVALUE '(' expr_const ')'	{ $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
501
	| tDEFAULTVTABLE			{ $$ = make_attr(ATTR_DEFAULTVTABLE); }
502
	| tDISABLECONSISTENCYCHECK		{ $$ = make_attr(ATTR_DISABLECONSISTENCYCHECK); }
503
	| tDISPLAYBIND				{ $$ = make_attr(ATTR_DISPLAYBIND); }
504 505
	| tDLLNAME '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DLLNAME, $3); }
	| tDUAL					{ $$ = make_attr(ATTR_DUAL); }
506 507
	| tENABLEALLOCATE			{ $$ = make_attr(ATTR_ENABLEALLOCATE); }
	| tENCODE				{ $$ = make_attr(ATTR_ENCODE); }
508
	| tENDPOINT '(' str_list ')'		{ $$ = make_attrp(ATTR_ENDPOINT, $3); }
509
	| tENTRY '(' expr_const ')'		{ $$ = make_attrp(ATTR_ENTRY, $3); }
510
	| tEXPLICITHANDLE			{ $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
511 512
	| tFAULTSTATUS				{ $$ = make_attr(ATTR_FAULTSTATUS); }
	| tFORCEALLOCATE			{ $$ = make_attr(ATTR_FORCEALLOCATE); }
513
	| tHANDLE				{ $$ = make_attr(ATTR_HANDLE); }
514
	| tHELPCONTEXT '(' expr_int_const ')'	{ $$ = make_attrp(ATTR_HELPCONTEXT, $3); }
515
	| tHELPFILE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_HELPFILE, $3); }
516
	| tHELPSTRING '(' aSTRING ')'		{ $$ = make_attrp(ATTR_HELPSTRING, $3); }
517
	| tHELPSTRINGCONTEXT '(' expr_int_const ')'	{ $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); }
518
	| tHELPSTRINGDLL '(' aSTRING ')'	{ $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); }
519
	| tHIDDEN				{ $$ = make_attr(ATTR_HIDDEN); }
520
	| tID '(' expr_int_const ')'		{ $$ = make_attrp(ATTR_ID, $3); }
521
	| tIDEMPOTENT				{ $$ = make_attr(ATTR_IDEMPOTENT); }
522
	| tIGNORE				{ $$ = make_attr(ATTR_IGNORE); }
523
	| tIIDIS '(' expr ')'			{ $$ = make_attrp(ATTR_IIDIS, $3); }
524
	| tIMMEDIATEBIND			{ $$ = make_attr(ATTR_IMMEDIATEBIND); }
525
	| tIMPLICITHANDLE '(' arg ')'		{ $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $3); }
526
	| tIN					{ $$ = make_attr(ATTR_IN); }
527
	| tINPUTSYNC				{ $$ = make_attr(ATTR_INPUTSYNC); }
528
	| tLENGTHIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_LENGTHIS, $3); }
529
	| tLCID	'(' expr_int_const ')'		{ $$ = make_attrp(ATTR_LIBLCID, $3); }
530
	| tLCID					{ $$ = make_attr(ATTR_PARAMLCID); }
531
	| tLICENSED				{ $$ = make_attr(ATTR_LICENSED); }
532
	| tLOCAL				{ $$ = make_attr(ATTR_LOCAL); }
533 534 535
	| tMAYBE				{ $$ = make_attr(ATTR_MAYBE); }
	| tMESSAGE				{ $$ = make_attr(ATTR_MESSAGE); }
	| tNOCODE				{ $$ = make_attr(ATTR_NOCODE); }
536
	| tNONBROWSABLE				{ $$ = make_attr(ATTR_NONBROWSABLE); }
Huw Davies's avatar
Huw Davies committed
537
	| tNONCREATABLE				{ $$ = make_attr(ATTR_NONCREATABLE); }
538
	| tNONEXTENSIBLE			{ $$ = make_attr(ATTR_NONEXTENSIBLE); }
539 540
	| tNOTIFY				{ $$ = make_attr(ATTR_NOTIFY); }
	| tNOTIFYFLAG				{ $$ = make_attr(ATTR_NOTIFYFLAG); }
541
	| tOBJECT				{ $$ = make_attr(ATTR_OBJECT); }
542
	| tODL					{ $$ = make_attr(ATTR_ODL); }
543
	| tOLEAUTOMATION			{ $$ = make_attr(ATTR_OLEAUTOMATION); }
544
	| tOPTIMIZE '(' aSTRING ')'		{ $$ = make_attrp(ATTR_OPTIMIZE, $3); }
545
	| tOPTIONAL                             { $$ = make_attr(ATTR_OPTIONAL); }
546
	| tOUT					{ $$ = make_attr(ATTR_OUT); }
547
	| tPARTIALIGNORE			{ $$ = make_attr(ATTR_PARTIALIGNORE); }
548
	| tPOINTERDEFAULT '(' pointer_type ')'	{ $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
549
	| tPROGID '(' aSTRING ')'		{ $$ = make_attrp(ATTR_PROGID, $3); }
550 551
	| tPROPGET				{ $$ = make_attr(ATTR_PROPGET); }
	| tPROPPUT				{ $$ = make_attr(ATTR_PROPPUT); }
552
	| tPROPPUTREF				{ $$ = make_attr(ATTR_PROPPUTREF); }
553
	| tPROXY				{ $$ = make_attr(ATTR_PROXY); }
554
	| tPUBLIC				{ $$ = make_attr(ATTR_PUBLIC); }
555 556 557 558
	| tRANGE '(' expr_int_const ',' expr_int_const ')'
						{ expr_list_t *list = append_expr( NULL, $3 );
						  list = append_expr( list, $5 );
						  $$ = make_attrp(ATTR_RANGE, list); }
559
	| tREADONLY				{ $$ = make_attr(ATTR_READONLY); }
560
	| tREPRESENTAS '(' type ')'		{ $$ = make_attrp(ATTR_REPRESENTAS, $3); }
561
	| tREQUESTEDIT				{ $$ = make_attr(ATTR_REQUESTEDIT); }
562
	| tRESTRICTED				{ $$ = make_attr(ATTR_RESTRICTED); }
563
	| tRETVAL				{ $$ = make_attr(ATTR_RETVAL); }
564
	| tSIZEIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_SIZEIS, $3); }
565
	| tSOURCE				{ $$ = make_attr(ATTR_SOURCE); }
566
	| tSTRICTCONTEXTHANDLE                  { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); }
567
	| tSTRING				{ $$ = make_attr(ATTR_STRING); }
568
	| tSWITCHIS '(' expr ')'		{ $$ = make_attrp(ATTR_SWITCHIS, $3); }
569 570
	| tSWITCHTYPE '(' type ')'		{ $$ = make_attrp(ATTR_SWITCHTYPE, $3); }
	| tTRANSMITAS '(' type ')'		{ $$ = make_attrp(ATTR_TRANSMITAS, $3); }
571
	| tTHREADING '(' threading_type ')'	{ $$ = make_attrv(ATTR_THREADING, $3); }
572 573 574
	| tUIDEFAULT				{ $$ = make_attr(ATTR_UIDEFAULT); }
	| tUSESGETLASTERROR			{ $$ = make_attr(ATTR_USESGETLASTERROR); }
	| tUSERMARSHAL '(' type ')'		{ $$ = make_attrp(ATTR_USERMARSHAL, $3); }
575
	| tUUID '(' uuid_string ')'		{ $$ = make_attrp(ATTR_UUID, $3); }
576
	| tV1ENUM				{ $$ = make_attr(ATTR_V1ENUM); }
577
	| tVARARG				{ $$ = make_attr(ATTR_VARARG); }
578
	| tVERSION '(' version ')'		{ $$ = make_attrv(ATTR_VERSION, $3); }
579
	| tVIPROGID '(' aSTRING ')'		{ $$ = make_attrp(ATTR_VIPROGID, $3); }
580
	| tWIREMARSHAL '(' type ')'		{ $$ = make_attrp(ATTR_WIREMARSHAL, $3); }
581
	| pointer_type				{ $$ = make_attrv(ATTR_POINTERTYPE, $1); }
582 583
	;

584 585 586
uuid_string:
	  aUUID
	| aSTRING				{ if (!is_valid_uuid($1))
587
						    error_loc("invalid UUID: %s\n", $1);
588
						  $$ = parse_uuid($1); }
589
        ;
590

591 592 593 594
callconv: tCDECL				{ $$ = xstrdup("__cdecl"); }
	| tFASTCALL				{ $$ = xstrdup("__fastcall"); }
	| tPASCAL				{ $$ = xstrdup("__pascal"); }
	| tSTDCALL				{ $$ = xstrdup("__stdcall"); }
595 596
	;

597
cases:						{ $$ = NULL; }
598
	| cases case				{ $$ = append_var( $1, $2 ); }
599 600
	;

601
case:	  tCASE expr_int_const ':' union_field	{ attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, $2 ));
602
						  $$ = $4; if (!$$) $$ = make_var(NULL);
603
						  $$->attrs = append_attr( $$->attrs, a );
604
						}
605
	| tDEFAULT ':' union_field		{ attr_t *a = make_attr(ATTR_DEFAULT);
606
						  $$ = $3; if (!$$) $$ = make_var(NULL);
607
						  $$->attrs = append_attr( $$->attrs, a );
608
						}
609 610
	;

611 612
enums:						{ $$ = NULL; }
	| enum_list ','				{ $$ = $1; }
613 614 615
	| enum_list
	;

616 617 618
enum_list: enum					{ if (!$1->eval)
						    $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */);
                                                  $$ = append_var( NULL, $1 );
619
						}
620 621 622 623 624 625
	| 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 );
626
						}
627 628
	;

629
enum:	  ident '=' expr_int_const		{ $$ = reg_const($1);
630
						  $$->eval = $3;
631
                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
632 633
						}
	| ident					{ $$ = reg_const($1);
634
                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
635
						}
636 637
	;

638
enumdef: tENUM t_ident '{' enums '}'		{ $$ = type_new_enum($2, TRUE, $4); }
639 640
	;

641 642
m_exprs:  m_expr                                { $$ = append_expr( NULL, $1 ); }
	| m_exprs ',' m_expr                    { $$ = append_expr( $1, $3 ); }
643 644 645 646 647
	;

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

649 650
expr:	  aNUM					{ $$ = make_exprl(EXPR_NUM, $1); }
	| aHEXNUM				{ $$ = make_exprl(EXPR_HEXNUM, $1); }
651
	| aDOUBLE				{ $$ = make_exprd(EXPR_DOUBLE, $1); }
652
	| tFALSE				{ $$ = make_exprl(EXPR_TRUEFALSE, 0); }
653
	| tNULL					{ $$ = make_exprl(EXPR_NUM, 0); }
654
	| tTRUE					{ $$ = make_exprl(EXPR_TRUEFALSE, 1); }
655 656
	| aSTRING				{ $$ = make_exprs(EXPR_STRLIT, $1); }
	| aWSTRING				{ $$ = make_exprs(EXPR_WSTRLIT, $1); }
657
	| aSQSTRING				{ $$ = make_exprs(EXPR_CHARCONST, $1); }
658
	| aIDENTIFIER				{ $$ = make_exprs(EXPR_IDENTIFIER, $1); }
659
	| expr '?' expr ':' expr		{ $$ = make_expr3(EXPR_COND, $1, $3, $5); }
660 661
	| expr LOGICALOR expr			{ $$ = make_expr2(EXPR_LOGOR, $1, $3); }
	| expr LOGICALAND expr			{ $$ = make_expr2(EXPR_LOGAND, $1, $3); }
662
	| expr '|' expr				{ $$ = make_expr2(EXPR_OR , $1, $3); }
663
	| expr '^' expr				{ $$ = make_expr2(EXPR_XOR, $1, $3); }
664
	| expr '&' expr				{ $$ = make_expr2(EXPR_AND, $1, $3); }
665 666 667 668 669 670 671 672
	| expr EQUALITY expr			{ $$ = make_expr2(EXPR_EQUALITY, $1, $3); }
	| expr INEQUALITY expr			{ $$ = make_expr2(EXPR_INEQUALITY, $1, $3); }
	| expr '>' expr				{ $$ = make_expr2(EXPR_GTR, $1, $3); }
	| expr '<' expr				{ $$ = make_expr2(EXPR_LESS, $1, $3); }
	| expr GREATEREQUAL expr		{ $$ = make_expr2(EXPR_GTREQL, $1, $3); }
	| expr LESSEQUAL expr			{ $$ = make_expr2(EXPR_LESSEQL, $1, $3); }
	| expr SHL expr				{ $$ = make_expr2(EXPR_SHL, $1, $3); }
	| expr SHR expr				{ $$ = make_expr2(EXPR_SHR, $1, $3); }
673 674
	| expr '+' expr				{ $$ = make_expr2(EXPR_ADD, $1, $3); }
	| expr '-' expr				{ $$ = make_expr2(EXPR_SUB, $1, $3); }
675
	| expr '%' expr				{ $$ = make_expr2(EXPR_MOD, $1, $3); }
676 677
	| expr '*' expr				{ $$ = make_expr2(EXPR_MUL, $1, $3); }
	| expr '/' expr				{ $$ = make_expr2(EXPR_DIV, $1, $3); }
678
	| '!' expr				{ $$ = make_expr1(EXPR_LOGNOT, $2); }
679
	| '~' expr				{ $$ = make_expr1(EXPR_NOT, $2); }
680
	| '+' expr %prec POS			{ $$ = make_expr1(EXPR_POS, $2); }
681
	| '-' expr %prec NEG			{ $$ = make_expr1(EXPR_NEG, $2); }
682
	| '&' expr %prec ADDRESSOF		{ $$ = make_expr1(EXPR_ADDRESSOF, $2); }
683
	| '*' expr %prec PPTR			{ $$ = make_expr1(EXPR_PPTR, $2); }
684 685
	| expr MEMBERPTR aIDENTIFIER		{ $$ = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, $1), make_exprs(EXPR_IDENTIFIER, $3)); }
	| expr '.' aIDENTIFIER			{ $$ = make_expr2(EXPR_MEMBER, $1, make_exprs(EXPR_IDENTIFIER, $3)); }
686 687 688 689
	| '(' decl_spec m_abstract_declarator ')' expr %prec CAST
						{ $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); }
	| tSIZEOF '(' decl_spec m_abstract_declarator ')'
						{ $$ = make_exprt(EXPR_SIZEOF, declare_var(NULL, $3, $4, 0), NULL); free($3); free($4); }
690
	| expr '[' expr ']'			{ $$ = make_expr2(EXPR_ARRAY, $1, $3); }
691 692 693
	| '(' expr ')'				{ $$ = $2; }
	;

694 695
expr_list_int_const: expr_int_const		{ $$ = append_expr( NULL, $1 ); }
	| expr_list_int_const ',' expr_int_const	{ $$ = append_expr( $1, $3 ); }
696 697
	;

698
expr_int_const: expr				{ $$ = $1;
699
						  if (!$$->is_const)
700 701 702 703 704 705
						      error_loc("expression is not an integer constant\n");
						}
	;

expr_const: expr				{ $$ = $1;
						  if (!$$->is_const && $$->type != EXPR_STRLIT && $$->type != EXPR_WSTRLIT)
706
						      error_loc("expression is not constant\n");
707 708 709
						}
	;

710
fields:						{ $$ = NULL; }
711
	| fields field				{ $$ = append_var_list($1, $2); }
712 713
	;

714
field:	  m_attributes decl_spec struct_declarator_list ';'
715
						{ const char *first = LIST_ENTRY(list_head($3), declarator_t, entry)->var->name;
716
						  check_field_attrs(first, $1);
717 718
						  $$ = set_var_types($1, $2, $3);
						}
719 720 721 722
	| m_attributes uniondef ';'		{ var_t *v = make_var(NULL);
						  v->type = $2; v->attrs = $1;
						  $$ = append_var(NULL, v);
						}
723 724 725 726
	;

ne_union_field:
	  s_field ';'				{ $$ = $1; }
727
	| attributes ';'			{ $$ = make_var(NULL); $$->attrs = $1; }
728
        ;
729 730 731

ne_union_fields:				{ $$ = NULL; }
	| ne_union_fields ne_union_field	{ $$ = append_var( $1, $2 ); }
732 733
	;

734 735 736
union_field:
	  s_field ';'				{ $$ = $1; }
	| ';'					{ $$ = NULL; }
737
        ;
738

739 740
s_field:  m_attributes decl_spec declarator	{ $$ = declare_var(check_field_attrs($3->var->name, $1),
						                $2, $3, FALSE);
741 742
						  free($3);
						}
743 744 745 746
	| m_attributes structdef		{ var_t *v = make_var(NULL);
						  v->type = $2; v->attrs = $1;
						  $$ = v;
						}
747 748
	;

Rob Shearman's avatar
Rob Shearman committed
749 750 751 752
funcdef: declaration				{ $$ = $1;
						  if (type_get_type($$->type) != TYPE_FUNCTION)
						    error_loc("only methods may be declared inside the methods section of a dispinterface\n");
						  check_function_attrs($$->name, $$->attrs);
753 754 755
						}
	;

756 757
declaration:
	  attributes decl_spec init_declarator
758
						{ $$ = declare_var($1, $2, $3, FALSE);
759 760
						  free($3);
						}
761
	| decl_spec init_declarator		{ $$ = declare_var(NULL, $1, $2, FALSE);
762 763 764 765
						  free($2);
						}
	;

766 767 768 769 770
m_ident:					{ $$ = NULL; }
	| ident
	;

t_ident:					{ $$ = NULL; }
771 772
	| aIDENTIFIER				{ $$ = $1; }
	| aKNOWNTYPE				{ $$ = $1; }
773 774 775
	;

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

780 781
base_type: tBYTE				{ $$ = find_type_or_error($<str>1, 0); }
	| tWCHAR				{ $$ = find_type_or_error($<str>1, 0); }
782
	| int_std
783 784 785 786 787 788 789 790
	| tSIGNED int_std			{ $$ = type_new_int(type_basic_get_type($2), -1); }
	| tUNSIGNED int_std			{ $$ = type_new_int(type_basic_get_type($2), 1); }
	| tUNSIGNED				{ $$ = type_new_int(TYPE_BASIC_INT, 1); }
	| tFLOAT				{ $$ = find_type_or_error($<str>1, 0); }
	| tDOUBLE				{ $$ = find_type_or_error($<str>1, 0); }
	| tBOOLEAN				{ $$ = find_type_or_error($<str>1, 0); }
	| tERRORSTATUST				{ $$ = find_type_or_error($<str>1, 0); }
	| tHANDLET				{ $$ = find_type_or_error($<str>1, 0); }
791 792 793 794 795 796
	;

m_int:
	| tINT
	;

797 798 799 800 801 802 803
int_std:  tINT					{ $$ = type_new_int(TYPE_BASIC_INT, 0); }
	| tSHORT m_int				{ $$ = type_new_int(TYPE_BASIC_INT16, 0); }
	| tSMALL				{ $$ = type_new_int(TYPE_BASIC_INT8, 0); }
	| tLONG m_int				{ $$ = type_new_int(TYPE_BASIC_INT32, 0); }
	| tHYPER m_int				{ $$ = type_new_int(TYPE_BASIC_HYPER, 0); }
	| tINT64				{ $$ = type_new_int(TYPE_BASIC_INT64, 0); }
	| tCHAR					{ $$ = type_new_int(TYPE_BASIC_CHAR, 0); }
804
	| tINT3264				{ $$ = type_new_int(TYPE_BASIC_INT3264, 0); }
805 806
	;

807
coclass:  tCOCLASS aIDENTIFIER			{ $$ = type_new_coclass($2); }
808
	| tCOCLASS aKNOWNTYPE			{ $$ = find_type($2, 0);
809
						  if (type_get_type_detect_alias($$) != TYPE_COCLASS)
810 811 812
						    error_loc("%s was not declared a coclass at %s:%d\n",
							      $2, $$->loc_info.input_name,
							      $$->loc_info.line_number);
813
						}
814 815 816
	;

coclasshdr: attributes coclass			{ $$ = $2;
817
						  check_def($$);
818
						  $$->attrs = check_coclass_attrs($2->name, $1);
819 820 821
						}
	;

822
coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
823
						{ $$ = type_coclass_define($1, $3); }
824 825 826
	;

coclass_ints:					{ $$ = NULL; }
827
	| coclass_ints coclass_int		{ $$ = append_ifref( $1, $2 ); }
828 829 830 831 832 833
	;

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

834 835
dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
	|      tDISPINTERFACE aKNOWNTYPE	{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
836 837
	;

838 839
dispinterfacehdr: attributes dispinterface	{ attr_t *attrs;
						  $$ = $2;
840
						  check_def($$);
841
						  attrs = make_attr(ATTR_DISPINTERFACE);
842
						  $$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs );
843 844 845 846 847
						  $$->defined = TRUE;
						}
	;

dispint_props: tPROPERTIES ':'			{ $$ = NULL; }
848
	| dispint_props s_field ';'		{ $$ = append_var( $1, $2 ); }
849 850 851
	;

dispint_meths: tMETHODS ':'			{ $$ = NULL; }
Rob Shearman's avatar
Rob Shearman committed
852
	| dispint_meths funcdef ';'		{ $$ = append_var( $1, $2 ); }
853 854 855 856 857 858
	;

dispinterfacedef: dispinterfacehdr '{'
	  dispint_props
	  dispint_meths
	  '}'					{ $$ = $1;
859
						  type_dispinterface_define($$, $3, $4);
860
						}
861
	| dispinterfacehdr
862
	 '{' interface ';' '}' 			{ $$ = $1;
863
						  type_dispinterface_define_from_iface($$, $3);
864 865 866
						}
	;

867
inherit:					{ $$ = NULL; }
868
	| ':' aKNOWNTYPE			{ $$ = find_type_or_error2($2, 0); }
869 870
	;

871 872
interface: tINTERFACE aIDENTIFIER		{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
	|  tINTERFACE aKNOWNTYPE		{ $$ = get_type(TYPE_INTERFACE, $2, 0); }
873 874
	;

875 876 877 878
interfacehdr: attributes interface		{ $$.interface = $2;
						  $$.old_pointer_default = pointer_default;
						  if (is_attr($1, ATTR_POINTERDEFAULT))
						    pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
879
						  check_def($2);
880
						  $2->attrs = check_iface_attrs($2->name, $1);
881
						  $2->defined = TRUE;
882 883 884 885
						}
	;

interfacedef: interfacehdr inherit
886
	  '{' int_statements '}' semicolon_opt	{ $$ = $1.interface;
887
						  type_interface_define($$, $2, $4);
888
						  pointer_default = $1.old_pointer_default;
889 890 891 892
						}
/* 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
893 894
	  '{' import int_statements '}'
	   semicolon_opt			{ $$ = $1.interface;
895
						  type_interface_define($$, find_type_or_error2($3, 0), $6);
896
						  pointer_default = $1.old_pointer_default;
897
						}
898
	| dispinterfacedef semicolon_opt	{ $$ = $1; }
899 900 901
	;

interfacedec:
902 903
	  interface ';'				{ $$ = $1; }
	| dispinterface ';'			{ $$ = $1; }
904 905
	;

906 907
module:   tMODULE aIDENTIFIER			{ $$ = type_new_module($2); }
	| tMODULE aKNOWNTYPE			{ $$ = type_new_module($2); }
908 909 910
	;

modulehdr: attributes module			{ $$ = $2;
911
						  $$->attrs = check_module_attrs($2->name, $1);
912 913 914
						}
	;

915 916
moduledef: modulehdr '{' int_statements '}'
	   semicolon_opt			{ $$ = $1;
917
                                                  type_module_define($$, $3);
918
						}
919 920
	;

921 922 923 924 925 926
storage_cls_spec:
	  tEXTERN				{ $$ = STG_EXTERN; }
	| tSTATIC				{ $$ = STG_STATIC; }
	| tREGISTER				{ $$ = STG_REGISTER; }
	;

927 928 929 930
function_specifier:
	  tINLINE				{ $$ = make_attr(ATTR_INLINE); }
	;

931 932 933 934 935 936 937 938
type_qualifier:
	  tCONST				{ $$ = make_attr(ATTR_CONST); }
	;

m_type_qual_list:				{ $$ = NULL; }
	| m_type_qual_list type_qualifier	{ $$ = append_attr($1, $2); }
	;

939
decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); }
940
	| decl_spec_no_type type m_decl_spec_no_type
941
						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); }
942 943 944 945 946 947 948
	;

m_decl_spec_no_type:				{ $$ = NULL; }
	| decl_spec_no_type
	;

decl_spec_no_type:
949 950
	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
951
	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); }
952 953
	;

954
declarator:
955
	  '*' m_type_qual_list declarator %prec PPTR
956
						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
957 958
	| callconv declarator			{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
959
	| direct_declarator
960 961
	;

962 963 964 965
direct_declarator:
	  ident					{ $$ = make_declarator($1); }
	| '(' declarator ')'			{ $$ = $2; }
	| direct_declarator array		{ $$ = $1; $$->array = append_array($$->array, $2); }
966
	| direct_declarator '(' m_args ')'	{ $$ = $1;
967
						  $$->func_type = append_ptrchain_type($$->type, type_new_function($3));
968
						  $$->type = NULL;
969
						}
970 971
	;

972 973 974 975
/* abstract declarator */
abstract_declarator:
	  '*' m_type_qual_list m_abstract_declarator %prec PPTR
						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
976 977
	| callconv m_abstract_declarator	{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
978 979 980 981 982 983 984
	| abstract_direct_declarator
	;

/* abstract declarator without accepting direct declarator */
abstract_declarator_no_direct:
	  '*' m_type_qual_list m_any_declarator %prec PPTR
						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
985 986
	| callconv m_any_declarator		{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
	;

/* abstract declarator or empty */
m_abstract_declarator: 				{ $$ = make_declarator(NULL); }
	| abstract_declarator
	;

/* abstract direct declarator */
abstract_direct_declarator:
	  '(' abstract_declarator_no_direct ')'	{ $$ = $2; }
	| abstract_direct_declarator array	{ $$ = $1; $$->array = append_array($$->array, $2); }
	| array					{ $$ = make_declarator(NULL); $$->array = append_array($$->array, $1); }
	| '(' m_args ')'
						{ $$ = make_declarator(NULL);
						  $$->func_type = append_ptrchain_type($$->type, type_new_function($2));
						  $$->type = NULL;
						}
	| abstract_direct_declarator '(' m_args ')'
						{ $$ = $1;
						  $$->func_type = append_ptrchain_type($$->type, type_new_function($3));
						  $$->type = NULL;
						}
	;

1011 1012 1013 1014 1015 1016 1017 1018
/* abstract or non-abstract declarator */
any_declarator:
	  '*' m_type_qual_list m_any_declarator %prec PPTR
						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
	| any_direct_declarator
	;

1019 1020
/* abstract or non-abstract declarator without accepting direct declarator */
any_declarator_no_direct:
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	  '*' m_type_qual_list m_any_declarator %prec PPTR
						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
	;

/* abstract or non-abstract declarator or empty */
m_any_declarator: 				{ $$ = make_declarator(NULL); }
	| any_declarator
	;

1031 1032 1033
/* abstract or non-abstract direct declarator. note: direct declarators
 * aren't accepted inside brackets to avoid ambiguity with the rule for
 * function arguments */
1034 1035
any_direct_declarator:
	  ident					{ $$ = make_declarator($1); }
1036
	| '(' any_declarator_no_direct ')'	{ $$ = $2; }
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
	| any_direct_declarator array		{ $$ = $1; $$->array = append_array($$->array, $2); }
	| array					{ $$ = make_declarator(NULL); $$->array = append_array($$->array, $1); }
	| '(' m_args ')'
						{ $$ = make_declarator(NULL);
						  $$->func_type = append_ptrchain_type($$->type, type_new_function($2));
						  $$->type = NULL;
						}
	| any_direct_declarator '(' m_args ')'
						{ $$ = $1;
						  $$->func_type = append_ptrchain_type($$->type, type_new_function($3));
						  $$->type = NULL;
						}
	;

1051 1052 1053
declarator_list:
	  declarator				{ $$ = append_declarator( NULL, $1 ); }
	| declarator_list ',' declarator	{ $$ = append_declarator( $1, $3 ); }
1054 1055
	;

1056 1057 1058 1059 1060 1061
m_bitfield:					{ $$ = NULL; }
	| ':' expr_const			{ $$ = $2; }
	;

struct_declarator: any_declarator m_bitfield	{ $$ = $1; $$->bits = $2;
						  if (!$$->bits && !$$->var->name)
1062
						    error_loc("unnamed fields are not allowed\n");
1063 1064 1065 1066 1067 1068 1069 1070 1071
						}
	;

struct_declarator_list:
	  struct_declarator			{ $$ = append_declarator( NULL, $1 ); }
	| struct_declarator_list ',' struct_declarator
						{ $$ = append_declarator( $1, $3 ); }
	;

1072 1073 1074 1075 1076
init_declarator:
	  declarator				{ $$ = $1; }
	| declarator '=' expr_const		{ $$ = $1; $1->var->eval = $3; }
	;

1077 1078 1079 1080 1081 1082 1083 1084
threading_type:
	  tAPARTMENT				{ $$ = THREADING_APARTMENT; }
	| tNEUTRAL				{ $$ = THREADING_NEUTRAL; }
	| tSINGLE				{ $$ = THREADING_SINGLE; }
	| tFREE					{ $$ = THREADING_FREE; }
	| tBOTH					{ $$ = THREADING_BOTH; }
	;

1085 1086 1087
pointer_type:
	  tREF					{ $$ = RPC_FC_RP; }
	| tUNIQUE				{ $$ = RPC_FC_UP; }
1088
	| tPTR					{ $$ = RPC_FC_FP; }
1089 1090
	;

1091
structdef: tSTRUCT t_ident '{' fields '}'	{ $$ = type_new_struct($2, TRUE, $4); }
1092 1093
	;

1094
type:	  tVOID					{ $$ = type_new_void(); }
1095
	| aKNOWNTYPE				{ $$ = find_type_or_error($1, 0); }
1096 1097
	| base_type				{ $$ = $1; }
	| enumdef				{ $$ = $1; }
1098
	| tENUM aIDENTIFIER			{ $$ = type_new_enum($2, FALSE, NULL); }
1099
	| structdef				{ $$ = $1; }
1100
	| tSTRUCT aIDENTIFIER			{ $$ = type_new_struct($2, FALSE, NULL); }
1101
	| uniondef				{ $$ = $1; }
1102
	| tUNION aIDENTIFIER			{ $$ = type_new_nonencapsulated_union($2, FALSE, NULL); }
1103
	| tSAFEARRAY '(' type ')'		{ $$ = make_safearray($3); }
1104 1105
	;

1106
typedef: tTYPEDEF m_attributes decl_spec declarator_list
1107
						{ reg_typedefs($3, $4, check_typedef_attrs($2));
1108
						  $$ = make_statement_typedef($4);
1109 1110 1111
						}
	;

1112
uniondef: tUNION t_ident '{' ne_union_fields '}'
1113
						{ $$ = type_new_nonencapsulated_union($2, TRUE, $4); }
1114
	| tUNION t_ident
1115
	  tSWITCH '(' s_field ')'
1116
	  m_ident '{' cases '}'			{ $$ = type_new_encapsulated_union($2, $5, $7, $9); }
1117 1118 1119
	;

version:
1120 1121
	  aNUM					{ $$ = MAKEVERSION($1, 0); }
	| aNUM '.' aNUM				{ $$ = MAKEVERSION($1, $3); }
1122 1123 1124 1125
	;

%%

1126
static void decl_builtin_basic(const char *name, enum type_basic_type type)
1127
{
1128
  type_t *t = type_new_basic(type);
1129 1130 1131
  reg_type(t, name, 0);
}

1132
static void decl_builtin_alias(const char *name, type_t *t)
1133
{
1134
  reg_type(type_new_alias(t, name), name, 0);
1135 1136 1137 1138
}

void init_types(void)
{
1139 1140 1141 1142 1143 1144 1145
  decl_builtin_basic("byte", TYPE_BASIC_BYTE);
  decl_builtin_basic("wchar_t", TYPE_BASIC_WCHAR);
  decl_builtin_basic("float", TYPE_BASIC_FLOAT);
  decl_builtin_basic("double", TYPE_BASIC_DOUBLE);
  decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T);
  decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE);
  decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE));
1146 1147
}

1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
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;
}

1164 1165
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
{
1166
    attr_t *attr_existing;
1167 1168 1169 1170 1171 1172
    if (!attr) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
1173 1174 1175 1176 1177 1178 1179 1180
    LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry)
        if (attr_existing->type == attr->type)
        {
            parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type));
            /* use the last attribute, like MIDL does */
            list_remove(&attr_existing->entry);
            break;
        }
1181 1182 1183 1184
    list_add_tail( list, &attr->entry );
    return list;
}

1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type)
{
  attr_t *attr;
  if (!src) return dst;
  LIST_FOR_EACH_ENTRY(attr, src, attr_t, entry)
    if (attr->type == type)
    {
      list_remove(&attr->entry);
      return append_attr(dst, attr);
    }
  return dst;
}

1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list)
{
  struct list *entry;

  if (!old_list) return new_list;

  while ((entry = list_head(old_list)))
  {
    attr_t *attr = LIST_ENTRY(entry, attr_t, entry);
    list_remove(entry);
    new_list = append_attr(new_list, attr);
  }
  return new_list;
}

static attr_list_t *dupattrs(const attr_list_t *list)
{
  attr_list_t *new_list;
  const attr_t *attr;

  if (!list) return NULL;

  new_list = xmalloc( sizeof(*list) );
  list_init( new_list );
  LIST_FOR_EACH_ENTRY(attr, list, const attr_t, entry)
  {
    attr_t *new_attr = xmalloc(sizeof(*new_attr));
    *new_attr = *attr;
    list_add_tail(new_list, &new_attr->entry);
  }
  return new_list;
}

1231
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
1232
{
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
  decl_spec_t *declspec = left ? left : right;
  if (!declspec)
  {
    declspec = xmalloc(sizeof(*declspec));
    declspec->type = NULL;
    declspec->attrs = NULL;
    declspec->stgclass = STG_NONE;
  }
  declspec->type = type;
  if (left && declspec != left)
  {
    declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
    if (declspec->stgclass == STG_NONE)
      declspec->stgclass = left->stgclass;
    else if (left->stgclass != STG_NONE)
      error_loc("only one storage class can be specified\n");
    assert(!left->type);
    free(left);
  }
  if (right && declspec != right)
  {
    declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
    if (declspec->stgclass == STG_NONE)
      declspec->stgclass = right->stgclass;
    else if (right->stgclass != STG_NONE)
      error_loc("only one storage class can be specified\n");
    assert(!right->type);
    free(right);
  }

  declspec->attrs = append_attr(declspec->attrs, attr);
  if (declspec->stgclass == STG_NONE)
    declspec->stgclass = stgclass;
  else if (stgclass != STG_NONE)
    error_loc("only one storage class can be specified\n");

  /* apply attributes to type */
  if (type && declspec->attrs)
1271 1272
  {
    attr_list_t *attrs;
1273
    declspec->type = duptype(type, 1);
1274
    attrs = dupattrs(type->attrs);
1275 1276
    declspec->type->attrs = append_attr_list(attrs, declspec->attrs);
    declspec->attrs = NULL;
1277
  }
1278 1279

  return declspec;
1280 1281
}

1282
static attr_t *make_attr(enum attr_type type)
1283 1284 1285 1286 1287 1288 1289
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.ival = 0;
  return a;
}

1290
static attr_t *make_attrv(enum attr_type type, unsigned int val)
1291 1292 1293 1294 1295 1296 1297
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.ival = val;
  return a;
}

1298
static attr_t *make_attrp(enum attr_type type, void *val)
1299 1300 1301 1302 1303 1304 1305
{
  attr_t *a = xmalloc(sizeof(attr_t));
  a->type = type;
  a->u.pval = val;
  return a;
}

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
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;
}

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
static struct list type_pool = LIST_INIT(type_pool);
typedef struct
{
  type_t data;
  struct list link;
} type_pool_node_t;

type_t *alloc_type(void)
{
  type_pool_node_t *node = xmalloc(sizeof *node);
  list_add_tail(&type_pool, &node->link);
  return &node->data;
}

void set_all_tfswrite(int val)
{
  type_pool_node_t *node;
  LIST_FOR_EACH_ENTRY(node, &type_pool, type_pool_node_t, link)
    node->data.tfswrite = val;
}

1351 1352 1353 1354 1355 1356 1357
void clear_all_offsets(void)
{
  type_pool_node_t *node;
  LIST_FOR_EACH_ENTRY(node, &type_pool, type_pool_node_t, link)
    node->data.typestring_offset = node->data.ptrdesc = 0;
}

1358
static void type_function_add_head_arg(type_t *type, var_t *arg)
1359
{
1360
    if (!type->details.function->args)
1361
    {
1362 1363
        type->details.function->args = xmalloc( sizeof(*type->details.function->args) );
        list_init( type->details.function->args );
1364
    }
1365
    list_add_head( type->details.function->args, &arg->entry );
1366 1367
}

1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
static int is_allowed_range_type(const type_t *type)
{
    switch (type_get_type(type))
    {
    case TYPE_ENUM:
        return TRUE;
    case TYPE_BASIC:
        switch (type_basic_get_type(type))
        {
        case TYPE_BASIC_INT8:
        case TYPE_BASIC_INT16:
        case TYPE_BASIC_INT32:
        case TYPE_BASIC_INT64:
        case TYPE_BASIC_INT:
1382
        case TYPE_BASIC_INT3264:
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
        case TYPE_BASIC_BYTE:
        case TYPE_BASIC_CHAR:
        case TYPE_BASIC_WCHAR:
        case TYPE_BASIC_HYPER:
            return TRUE;
        case TYPE_BASIC_FLOAT:
        case TYPE_BASIC_DOUBLE:
        case TYPE_BASIC_ERROR_STATUS_T:
        case TYPE_BASIC_HANDLE:
            return FALSE;
        }
        return FALSE;
    default:
        return FALSE;
    }
}

1400 1401 1402 1403 1404
static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type)
{
  type_t *ptrchain_type;
  if (!ptrchain)
    return type;
1405
  for (ptrchain_type = ptrchain; type_pointer_get_ref(ptrchain_type); ptrchain_type = type_pointer_get_ref(ptrchain_type))
1406
    ;
1407 1408
  assert(ptrchain_type->type_type == TYPE_POINTER);
  ptrchain_type->details.pointer.ref = type;
1409 1410 1411
  return ptrchain;
}

1412 1413
static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
                       int top)
1414
{
1415 1416 1417
  var_t *v = decl->var;
  expr_list_t *sizes = get_attrp(attrs, ATTR_SIZEIS);
  expr_list_t *lengs = get_attrp(attrs, ATTR_LENGTHIS);
1418
  int sizeless;
1419
  expr_t *dim;
1420
  type_t **ptype;
1421
  array_dims_t *arr = decl ? decl->array : NULL;
1422
  type_t *func_type = decl ? decl->func_type : NULL;
1423
  type_t *type = decl_spec->type;
1424

1425 1426
  if (is_attr(type->attrs, ATTR_INLINE))
  {
1427
    if (!func_type)
1428 1429 1430 1431 1432
      error_loc("inline attribute applied to non-function type\n");
    else
    {
      type_t *t;
      /* move inline attribute from return type node to function node */
1433
      for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t))
1434 1435 1436 1437 1438
        ;
      t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
    }
  }

1439
  /* add type onto the end of the pointers in pident->type */
1440
  v->type = append_ptrchain_type(decl ? decl->type : NULL, type);
1441
  v->stgclass = decl_spec->stgclass;
1442
  v->attrs = attrs;
1443

1444 1445
  /* check for pointer attribute being applied to non-pointer, non-array
   * type */
1446
  if (!arr)
1447
  {
1448
    int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE);
1449
    const type_t *ptr = NULL;
1450 1451 1452
    /* pointer attributes on the left side of the type belong to the function
     * pointer, if one is being declared */
    type_t **pt = func_type ? &func_type : &v->type;
1453
    for (ptr = *pt; ptr && !ptr_attr; )
1454
    {
1455
      ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE);
1456
      if (!ptr_attr && type_is_alias(ptr))
1457
        ptr = type_alias_get_aliasee(ptr);
1458 1459
      else
        break;
1460
    }
1461
    if (is_ptr(ptr))
1462
    {
1463 1464 1465 1466 1467
      if (ptr_attr && ptr_attr != RPC_FC_UP &&
          type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE)
          warning_loc_info(&v->loc_info,
                           "%s: pointer attribute applied to interface "
                           "pointer type has no effect\n", v->name);
1468
      if (!ptr_attr && top && (*pt)->details.pointer.def_fc != RPC_FC_RP)
1469
      {
1470 1471 1472 1473
        /* FIXME: this is a horrible hack to cope with the issue that we
         * store an offset to the typeformat string in the type object, but
         * two typeformat strings may be written depending on whether the
         * pointer is a toplevel parameter or not */
1474 1475
        *pt = duptype(*pt, 1);
      }
1476
    }
1477 1478
    else if (ptr_attr)
       error_loc("%s: pointer attribute applied to non-pointer type\n", v->name);
1479 1480
  }

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
  if (is_attr(v->attrs, ATTR_STRING))
  {
    type_t *t = type;

    if (!is_ptr(v->type) && !arr)
      error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n",
                v->name);

    while (is_ptr(t))
      t = type_pointer_get_ref(t);

    if (type_get_type(t) != TYPE_BASIC &&
        (get_basic_fc(t) != RPC_FC_CHAR &&
         get_basic_fc(t) != RPC_FC_BYTE &&
         get_basic_fc(t) != RPC_FC_WCHAR))
    {
      error_loc("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays\n",
                v->name);
    }
  }
1501

1502 1503
  if (is_attr(v->attrs, ATTR_V1ENUM))
  {
1504
    if (type_get_type_detect_alias(v->type) != TYPE_ENUM)
1505 1506 1507
      error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name);
  }

1508 1509 1510 1511
  if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type))
    error_loc("'%s': [range] attribute applied to non-integer type\n",
              v->name);

1512
  ptype = &v->type;
1513 1514 1515 1516
  sizeless = FALSE;
  if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry)
  {
    if (sizeless)
1517
      error_loc("%s: only the first array dimension can be unspecified\n", v->name);
1518 1519 1520

    if (dim->is_const)
    {
1521 1522 1523 1524 1525 1526
      if (dim->cval <= 0)
        error_loc("%s: array dimension must be positive\n", v->name);

      /* FIXME: should use a type_memsize that allows us to pass in a pointer size */
      if (0)
      {
1527
        unsigned int size = type_memsize(v->type);
1528

1529
        if (0xffffffffu / size < dim->cval)
1530 1531
          error_loc("%s: total array size is too large\n", v->name);
      }
1532 1533 1534 1535
    }
    else
      sizeless = TRUE;

1536
    *ptype = type_new_array(NULL, *ptype, FALSE,
1537
                            dim->is_const ? dim->cval : 0,
1538 1539
                            dim->is_const ? NULL : dim, NULL,
                            pointer_default);
1540 1541 1542 1543 1544 1545 1546
  }

  ptype = &v->type;
  if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
  {
    if (dim->type != EXPR_VOID)
    {
1547 1548
      if (is_array(*ptype))
      {
1549 1550 1551
        if (!type_array_get_conformance(*ptype) ||
            type_array_get_conformance(*ptype)->type != EXPR_VOID)
          error_loc("%s: cannot specify size_is for an already sized array\n", v->name);
1552 1553
        else
          *ptype = type_new_array((*ptype)->name,
1554
                                  type_array_get_element(*ptype), FALSE,
1555
                                  0, dim, NULL, 0);
1556 1557
      }
      else if (is_ptr(*ptype))
1558
        *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE,
1559
                                0, dim, NULL, pointer_default);
1560
      else
1561
        error_loc("%s: size_is attribute applied to illegal type\n", v->name);
1562 1563
    }

1564 1565 1566 1567 1568
    if (is_ptr(*ptype))
      ptype = &(*ptype)->details.pointer.ref;
    else if (is_array(*ptype))
      ptype = &(*ptype)->details.array.elem;
    else
1569
      error_loc("%s: too many expressions in size_is attribute\n", v->name);
1570 1571 1572 1573 1574 1575 1576
  }

  ptype = &v->type;
  if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
  {
    if (dim->type != EXPR_VOID)
    {
1577 1578 1579 1580
      if (is_array(*ptype))
      {
        *ptype = type_new_array((*ptype)->name,
                                type_array_get_element(*ptype),
1581
                                type_array_is_decl_as_ptr(*ptype),
1582 1583
                                type_array_get_dim(*ptype),
                                type_array_get_conformance(*ptype),
1584
                                dim, type_array_get_ptr_default_fc(*ptype));
1585
      }
1586
      else
1587
        error_loc("%s: length_is attribute applied to illegal type\n", v->name);
1588 1589
    }

1590 1591 1592 1593 1594
    if (is_ptr(*ptype))
      ptype = &(*ptype)->details.pointer.ref;
    else if (is_array(*ptype))
      ptype = &(*ptype)->details.array.elem;
    else
1595
      error_loc("%s: too many expressions in length_is attribute\n", v->name);
1596 1597
  }

1598
  /* v->type is currently pointing to the type on the left-side of the
1599 1600
   * declaration, so we need to fix this up so that it is the return type of the
   * function and make v->type point to the function side of the declaration */
1601
  if (func_type)
1602
  {
1603
    type_t *ft, *t;
1604
    type_t *return_type = v->type;
1605
    v->type = func_type;
1606
    for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft))
1607
      ;
1608
    assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
1609 1610
    ft->details.function->retval = make_var(xstrdup("_RetVal"));
    ft->details.function->retval->type = return_type;
1611 1612
    /* move calling convention attribute, if present, from pointer nodes to
     * function node */
1613
    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
1614
      ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV);
1615
  }
1616 1617 1618
  else
  {
    type_t *t;
1619
    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
1620 1621 1622
      if (is_attr(t->attrs, ATTR_CALLCONV))
        error_loc("calling convention applied to non-function-pointer type\n");
  }
1623

1624 1625 1626
  if (decl->bits)
    v->type = type_new_bitfield(v->type, decl->bits);

1627
  return v;
1628 1629
}

1630
static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls)
1631 1632 1633 1634 1635 1636
{
  declarator_t *decl, *next;
  var_list_t *var_list = NULL;

  LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry )
  {
1637
    var_t *var = declare_var(attrs, decl_spec, decl, 0);
1638 1639 1640
    var_list = append_var(var_list, var);
    free(decl);
  }
1641
  free(decl_spec);
1642 1643 1644
  return var_list;
}

1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
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;
}

1657 1658 1659 1660 1661 1662 1663 1664
static ifref_t *make_ifref(type_t *iface)
{
  ifref_t *l = xmalloc(sizeof(ifref_t));
  l->iface = iface;
  l->attrs = NULL;
  return l;
}

1665
var_list_t *append_var(var_list_t *list, var_t *var)
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676
{
    if (!var) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &var->entry );
    return list;
}

1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
static var_list_t *append_var_list(var_list_t *list, var_list_t *vars)
{
    if (!vars) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_move_tail( list, vars );
    return list;
}

1689
var_t *make_var(char *name)
1690 1691 1692 1693 1694
{
  var_t *v = xmalloc(sizeof(var_t));
  v->name = name;
  v->type = NULL;
  v->attrs = NULL;
1695
  v->eval = NULL;
1696
  v->stgclass = STG_NONE;
1697
  init_loc_info(&v->loc_info);
1698 1699 1700
  return v;
}

1701
static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *d)
1702
{
1703
  if (!d) return list;
1704 1705 1706 1707
  if (!list) {
    list = xmalloc(sizeof(*list));
    list_init(list);
  }
1708
  list_add_tail(list, &d->entry);
1709 1710 1711
  return list;
}

1712
static declarator_t *make_declarator(var_t *var)
1713
{
1714
  declarator_t *d = xmalloc(sizeof(*d));
1715
  d->var = var ? var : make_var(NULL);
1716 1717 1718
  d->type = NULL;
  d->func_type = NULL;
  d->array = NULL;
1719
  d->bits = NULL;
1720
  return d;
1721 1722
}

1723
static type_t *make_safearray(type_t *type)
1724
{
1725 1726
  return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0,
                        NULL, NULL, RPC_FC_RP);
1727 1728
}

1729 1730 1731 1732 1733 1734 1735 1736 1737
static typelib_t *make_library(const char *name, const attr_list_t *attrs)
{
    typelib_t *typelib = xmalloc(sizeof(*typelib));
    typelib->name = xstrdup(name);
    typelib->attrs = attrs;
    list_init( &typelib->importlibs );
    return typelib;
}

1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
#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 *****/

1754
struct rtype {
1755
  const char *name;
1756 1757 1758 1759 1760
  type_t *type;
  int t;
  struct rtype *next;
};

1761
struct rtype *type_hash[HASHMAX];
1762

1763
type_t *reg_type(type_t *type, const char *name, int t)
1764 1765
{
  struct rtype *nt;
1766
  int hash;
1767
  if (!name) {
1768
    error_loc("registering named type without name\n");
1769 1770
    return type;
  }
1771
  hash = hash_ident(name);
1772 1773 1774 1775
  nt = xmalloc(sizeof(struct rtype));
  nt->name = name;
  nt->type = type;
  nt->t = t;
1776 1777
  nt->next = type_hash[hash];
  type_hash[hash] = nt;
1778 1779
  if ((t == tsSTRUCT || t == tsUNION))
    fix_incomplete_types(type);
1780 1781 1782
  return type;
}

1783 1784
static int is_incomplete(const type_t *t)
{
1785 1786 1787 1788
  return !t->defined &&
    (type_get_type_detect_alias(t) == TYPE_STRUCT ||
     type_get_type_detect_alias(t) == TYPE_UNION ||
     type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION);
1789 1790
}

1791
void add_incomplete(type_t *t)
1792 1793 1794 1795 1796 1797 1798 1799
{
  struct typenode *tn = xmalloc(sizeof *tn);
  tn->type = t;
  list_add_tail(&incomplete_types, &tn->entry);
}

static void fix_type(type_t *t)
{
1800
  if (type_is_alias(t) && is_incomplete(t)) {
1801
    type_t *ot = type_alias_get_aliasee(t);
1802
    fix_type(ot);
1803 1804 1805
    if (type_get_type_detect_alias(ot) == TYPE_STRUCT ||
        type_get_type_detect_alias(ot) == TYPE_UNION ||
        type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION)
1806
      t->details.structure = ot->details.structure;
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816
    t->defined = ot->defined;
  }
}

static void fix_incomplete(void)
{
  struct typenode *tn, *next;

  LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) {
    fix_type(tn->type);
1817
    list_remove(&tn->entry);
1818 1819 1820 1821
    free(tn);
  }
}

1822 1823 1824 1825 1826 1827
static void fix_incomplete_types(type_t *complete_type)
{
  struct typenode *tn, *next;

  LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry)
  {
1828
    if (type_is_equal(complete_type, tn->type))
1829 1830 1831 1832 1833 1834 1835 1836
    {
      tn->type->details.structure = complete_type->details.structure;
      list_remove(&tn->entry);
      free(tn);
    }
  }
}

1837
static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs)
1838
{
1839
  const declarator_t *decl;
1840
  type_t *type = decl_spec->type;
1841

1842 1843
  /* We must generate names for tagless enum, struct or union.
     Typedef-ing a tagless enum, struct or union means we want the typedef
1844
     to be included in a library hence the public attribute.  */
1845 1846 1847 1848
  if ((type_get_type_detect_alias(type) == TYPE_ENUM ||
       type_get_type_detect_alias(type) == TYPE_STRUCT ||
       type_get_type_detect_alias(type) == TYPE_UNION ||
       type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION) &&
1849
      !type->name && !parse_only)
1850 1851
  {
    if (! is_attr(attrs, ATTR_PUBLIC))
1852
      attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) );
1853 1854
    type->name = gen_name();
  }
1855 1856
  else if (is_attr(attrs, ATTR_UUID) && !is_attr(attrs, ATTR_PUBLIC))
    attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) );
1857

1858
  LIST_FOR_EACH_ENTRY( decl, decls, const declarator_t, entry )
1859
  {
1860

1861
    if (decl->var->name) {
1862
      type_t *cur;
1863
      var_t *name;
1864

1865
      cur = find_type(decl->var->name, 0);
1866 1867 1868 1869 1870
      if (cur)
          error_loc("%s: redefinition error; original definition was at %s:%d\n",
                    cur->name, cur->loc_info.input_name,
                    cur->loc_info.line_number);

1871
      name = declare_var(attrs, decl_spec, decl, 0);
1872
      cur = type_new_alias(name->type, name->name);
1873
      cur->attrs = attrs;
1874

1875 1876
      if (is_incomplete(cur))
        add_incomplete(cur);
1877
      reg_type(cur, cur->name, 0);
1878 1879 1880 1881 1882
    }
  }
  return type;
}

1883
type_t *find_type(const char *name, int t)
1884
{
1885
  struct rtype *cur = type_hash[hash_ident(name)];
1886 1887
  while (cur && (cur->t != t || strcmp(cur->name, name)))
    cur = cur->next;
1888 1889 1890
  return cur ? cur->type : NULL;
}

1891
static type_t *find_type_or_error(const char *name, int t)
1892
{
1893
  type_t *type = find_type(name, t);
1894
  if (!type) {
1895
    error_loc("type '%s' not found\n", name);
1896 1897
    return NULL;
  }
1898
  return type;
1899 1900
}

1901
static type_t *find_type_or_error2(char *name, int t)
1902
{
1903
  type_t *tp = find_type_or_error(name, t);
1904 1905 1906 1907 1908 1909
  free(name);
  return tp;
}

int is_type(const char *name)
{
1910
  return find_type(name, 0) != NULL;
1911 1912
}

1913
type_t *get_type(enum type_type type, char *name, int t)
1914 1915 1916
{
  type_t *tp;
  if (name) {
1917
    tp = find_type(name, t);
1918 1919 1920 1921
    if (tp) {
      free(name);
      return tp;
    }
1922
  }
1923
  tp = make_type(type);
1924 1925 1926 1927 1928
  tp->name = name;
  if (!name) return tp;
  return reg_type(tp, name, t);
}

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943
/***** 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) {
1944
    error_loc("registering constant without name\n");
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
    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;
}

1956
var_t *find_const(const char *name, int f)
1957 1958 1959 1960 1961
{
  struct rconst *cur = const_hash[hash_ident(name)];
  while (cur && strcmp(cur->name, name))
    cur = cur->next;
  if (!cur) {
1962
    if (f) error_loc("constant '%s' not found\n", name);
1963 1964 1965 1966
    return NULL;
  }
  return cur->var;
}
1967

1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991
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;
}
1992

1993 1994 1995 1996 1997 1998 1999 2000
struct allowed_attr
{
    unsigned int dce_compatible : 1;
    unsigned int acf : 1;
    unsigned int on_interface : 1;
    unsigned int on_function : 1;
    unsigned int on_arg : 1;
    unsigned int on_type : 1;
2001 2002 2003
    unsigned int on_enum : 1;
    unsigned int on_struct : 1;
    unsigned int on_union : 1;
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
    unsigned int on_field : 1;
    unsigned int on_library : 1;
    unsigned int on_dispinterface : 1;
    unsigned int on_module : 1;
    unsigned int on_coclass : 1;
    const char *display_name;
};

struct allowed_attr allowed_attr[] =
{
2014 2015
    /* attr                        { D ACF I Fn ARG T En St Un Fi  L  DI M  C  <display name> } */
    /* ATTR_AGGREGATABLE */        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" },
2016
    /* ATTR_ANNOTATION */          { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" },
2017 2018 2019 2020 2021 2022 2023 2024
    /* ATTR_APPOBJECT */           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "appobject" },
    /* ATTR_ASYNC */               { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
    /* ATTR_AUTO_HANDLE */         { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" },
    /* ATTR_BINDABLE */            { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" },
    /* ATTR_BROADCAST */           { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" },
    /* ATTR_CALLAS */              { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" },
    /* ATTR_CALLCONV */            { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
    /* ATTR_CASE */                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
2025 2026
    /* ATTR_CODE */                { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
    /* ATTR_COMMSTATUS */          { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
2027 2028 2029
    /* ATTR_CONST */               { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" },
    /* ATTR_CONTEXTHANDLE */       { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
    /* ATTR_CONTROL */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" },
2030
    /* ATTR_DECODE */              { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
2031
    /* ATTR_DEFAULT */             { 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" },
2032
    /* ATTR_DEFAULTBIND */         { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" },
2033 2034 2035
    /* ATTR_DEFAULTCOLLELEM */     { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" },
    /* ATTR_DEFAULTVALUE */        { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" },
    /* ATTR_DEFAULTVTABLE */       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" },
2036
 /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" },
2037 2038 2039 2040
    /* ATTR_DISPINTERFACE */       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
    /* ATTR_DISPLAYBIND */         { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" },
    /* ATTR_DLLNAME */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "dllname" },
    /* ATTR_DUAL */                { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" },
2041 2042
    /* ATTR_ENABLEALLOCATE */      { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" },
    /* ATTR_ENCODE */              { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "encode" },
2043 2044 2045
    /* ATTR_ENDPOINT */            { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" },
    /* ATTR_ENTRY */               { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
    /* ATTR_EXPLICIT_HANDLE */     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" },
2046 2047
    /* ATTR_FAULTSTATUS */         { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" },
    /* ATTR_FORCEALLOCATE */       { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" },
2048 2049 2050 2051 2052 2053 2054 2055 2056
    /* ATTR_HANDLE */              { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
    /* ATTR_HELPCONTEXT */         { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpcontext" },
    /* ATTR_HELPFILE */            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpfile" },
    /* ATTR_HELPSTRING */          { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpstring" },
    /* ATTR_HELPSTRINGCONTEXT */   { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpstringcontext" },
    /* ATTR_HELPSTRINGDLL */       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" },
    /* ATTR_HIDDEN */              { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, "hidden" },
    /* ATTR_ID */                  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "id" },
    /* ATTR_IDEMPOTENT */          { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" },
2057
    /* ATTR_IGNORE */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "ignore" },
2058 2059 2060 2061 2062 2063 2064 2065
    /* ATTR_IIDIS */               { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "iid_is" },
    /* ATTR_IMMEDIATEBIND */       { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
    /* ATTR_IMPLICIT_HANDLE */     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
    /* ATTR_IN */                  { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
    /* ATTR_INLINE */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" },
    /* ATTR_INPUTSYNC */           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
    /* ATTR_LENGTHIS */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" },
    /* ATTR_LIBLCID */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" },
2066
    /* ATTR_LICENSED */            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "licensed" },
2067
    /* ATTR_LOCAL */               { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
2068 2069 2070
    /* ATTR_MAYBE */               { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" },
    /* ATTR_MESSAGE */             { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" },
    /* ATTR_NOCODE */              { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" },
2071 2072 2073
    /* ATTR_NONBROWSABLE */        { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" },
    /* ATTR_NONCREATABLE */        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "noncreatable" },
    /* ATTR_NONEXTENSIBLE */       { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" },
2074 2075
    /* ATTR_NOTIFY */              { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" },
    /* ATTR_NOTIFYFLAG */          { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" },
2076 2077 2078
    /* ATTR_OBJECT */              { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" },
    /* ATTR_ODL */                 { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "odl" },
    /* ATTR_OLEAUTOMATION */       { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" },
2079
    /* ATTR_OPTIMIZE */            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" },
2080 2081
    /* ATTR_OPTIONAL */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" },
    /* ATTR_OUT */                 { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" },
2082
    /* ATTR_PARAMLCID */           { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" },
2083
    /* ATTR_PARTIALIGNORE */       { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" },
2084 2085
    /* ATTR_POINTERDEFAULT */      { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
    /* ATTR_POINTERTYPE */         { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "ref, unique or ptr" },
2086
    /* ATTR_PROGID */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "progid" },
2087 2088 2089
    /* ATTR_PROPGET */             { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" },
    /* ATTR_PROPPUT */             { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" },
    /* ATTR_PROPPUTREF */          { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" },
2090
    /* ATTR_PROXY */               { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" },
2091 2092 2093
    /* ATTR_PUBLIC */              { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
    /* ATTR_RANGE */               { 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, "range" },
    /* ATTR_READONLY */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "readonly" },
2094
    /* ATTR_REPRESENTAS */         { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" },
2095 2096 2097 2098 2099 2100 2101 2102 2103
    /* ATTR_REQUESTEDIT */         { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" },
    /* ATTR_RESTRICTED */          { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, "restricted" },
    /* ATTR_RETVAL */              { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
    /* ATTR_SIZEIS */              { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "size_is" },
    /* ATTR_SOURCE */              { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "source" },
    /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" },
    /* ATTR_STRING */              { 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "string" },
    /* ATTR_SWITCHIS */            { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "switch_is" },
    /* ATTR_SWITCHTYPE */          { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, "switch_type" },
2104
    /* ATTR_THREADING */           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "threading" },
2105
    /* ATTR_TRANSMITAS */          { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" },
2106 2107 2108
    /* ATTR_UIDEFAULT */           { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" },
    /* ATTR_USESGETLASTERROR */    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" },
    /* ATTR_USERMARSHAL */         { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" },
2109 2110 2111
    /* ATTR_UUID */                { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "uuid" },
    /* ATTR_V1ENUM */              { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, "v1_enum" },
    /* ATTR_VARARG */              { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" },
2112
    /* ATTR_VERSION */             { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "version" },
2113
    /* ATTR_VIPROGID */            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "vi_progid" },
2114
    /* ATTR_WIREMARSHAL */         { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
2115 2116
};

2117 2118 2119 2120 2121
const char *get_attr_display_name(enum attr_type type)
{
    return allowed_attr[type].display_name;
}

2122
static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs)
2123 2124 2125 2126 2127 2128 2129 2130
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_interface)
      error_loc("inapplicable attribute %s for interface %s\n",
                allowed_attr[attr->type].display_name, name);
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141
    if (attr->type == ATTR_IMPLICIT_HANDLE)
    {
        const var_t *var = attr->u.pval;
        if (type_get_type( var->type) == TYPE_BASIC &&
            type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
            continue;
        if (is_aliaschain_attr( var->type, ATTR_HANDLE ))
            continue;
      error_loc("attribute %s requires a handle type in interface %s\n",
                allowed_attr[attr->type].display_name, name);
    }
2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
  }
  return attrs;
}

static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_function)
      error_loc("inapplicable attribute %s for function %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

2159
static void check_arg_attrs(const var_t *arg)
2160
{
2161
  const attr_t *attr;
2162

2163 2164 2165 2166 2167 2168 2169 2170 2171
  if (arg->attrs)
  {
    LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
    {
      if (!allowed_attr[attr->type].on_arg)
        error_loc("inapplicable attribute %s for argument %s\n",
                  allowed_attr[attr->type].display_name, arg->name);
    }
  }
2172
}
2173

2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
static attr_list_t *check_typedef_attrs(attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_type)
      error_loc("inapplicable attribute %s for typedef\n",
                allowed_attr[attr->type].display_name);
  }
  return attrs;
}

2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225
static attr_list_t *check_enum_attrs(attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_enum)
      error_loc("inapplicable attribute %s for enum\n",
                allowed_attr[attr->type].display_name);
  }
  return attrs;
}

static attr_list_t *check_struct_attrs(attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_struct)
      error_loc("inapplicable attribute %s for struct\n",
                allowed_attr[attr->type].display_name);
  }
  return attrs;
}

static attr_list_t *check_union_attrs(attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_union)
      error_loc("inapplicable attribute %s for union\n",
                allowed_attr[attr->type].display_name);
  }
  return attrs;
}

2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_field)
      error_loc("inapplicable attribute %s for field %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

2239
static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs)
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_library)
      error_loc("inapplicable attribute %s for library %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs)
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_dispinterface)
      error_loc("inapplicable attribute %s for dispinterface %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

2265
static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs)
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_module)
      error_loc("inapplicable attribute %s for module %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

2278
static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs)
2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290
{
  const attr_t *attr;
  if (!attrs) return attrs;
  LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry)
  {
    if (!allowed_attr[attr->type].on_coclass)
      error_loc("inapplicable attribute %s for coclass %s\n",
                allowed_attr[attr->type].display_name, name);
  }
  return attrs;
}

2291 2292
static int is_allowed_conf_type(const type_t *type)
{
2293
    switch (type_get_type(type))
2294
    {
2295
    case TYPE_ENUM:
2296
        return TRUE;
2297
    case TYPE_BASIC:
2298
        switch (type_basic_get_type(type))
2299
        {
2300 2301 2302 2303 2304 2305 2306 2307 2308
        case TYPE_BASIC_INT8:
        case TYPE_BASIC_INT16:
        case TYPE_BASIC_INT32:
        case TYPE_BASIC_INT64:
        case TYPE_BASIC_INT:
        case TYPE_BASIC_CHAR:
        case TYPE_BASIC_HYPER:
        case TYPE_BASIC_BYTE:
        case TYPE_BASIC_WCHAR:
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326
            return TRUE;
        default:
            return FALSE;
        }
    case TYPE_ALIAS:
        /* shouldn't get here because of type_get_type call above */
        assert(0);
        /* fall through */
    case TYPE_STRUCT:
    case TYPE_UNION:
    case TYPE_ENCAPSULATED_UNION:
    case TYPE_ARRAY:
    case TYPE_POINTER:
    case TYPE_VOID:
    case TYPE_MODULE:
    case TYPE_COCLASS:
    case TYPE_FUNCTION:
    case TYPE_INTERFACE:
2327
    case TYPE_BITFIELD:
2328 2329
        return FALSE;
    }
2330
    return FALSE;
2331 2332 2333 2334
}

static int is_ptr_guid_type(const type_t *type)
{
2335 2336 2337 2338 2339
    /* first, make sure it is a pointer to something */
    if (!is_ptr(type)) return FALSE;

    /* second, make sure it is a pointer to something of size sizeof(GUID),
     * i.e. 16 bytes */
2340
    return (type_memsize(type_pointer_get_ref(type)) == 16);
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
}

static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list)
{
    expr_t *dim;
    struct expr_loc expr_loc;
    expr_loc.v = arg;
    expr_loc.attr = attr_name;
    if (expr_list) LIST_FOR_EACH_ENTRY(dim, expr_list, expr_t, entry)
    {
        if (dim->type != EXPR_VOID)
        {
2353 2354
            const type_t *expr_type = expr_resolve_type(&expr_loc, container_type, dim);
            if (!is_allowed_conf_type(expr_type))
2355 2356 2357 2358 2359 2360
                error_loc_info(&arg->loc_info, "expression must resolve to integral type <= 32bits for attribute %s\n",
                               attr_name);
        }
    }
}

2361
static void check_remoting_fields(const var_t *var, type_t *type);
2362 2363

/* checks that properties common to fields and arguments are consistent */
2364
static void check_field_common(const type_t *container_type,
2365 2366 2367
                               const char *container_name, const var_t *arg)
{
    type_t *type = arg->type;
2368
    int more_to_do;
2369 2370
    const char *container_type_name;
    const char *var_type;
2371

2372
    switch (type_get_type(container_type))
2373 2374
    {
    case TYPE_STRUCT:
2375
        container_type_name = "struct";
2376
        var_type = "field";
2377 2378
        break;
    case TYPE_UNION:
2379
        container_type_name = "union";
2380
        var_type = "arm";
2381 2382 2383
        break;
    case TYPE_ENCAPSULATED_UNION:
        container_type_name = "encapsulated union";
2384
        var_type = "arm";
2385 2386
        break;
    case TYPE_FUNCTION:
2387
        container_type_name = "function";
2388
        var_type = "parameter";
2389 2390
        break;
    default:
2391 2392
        /* should be no other container types */
        assert(0);
2393
        return;
2394
    }
2395 2396 2397 2398 2399 2400 2401

    if (is_attr(arg->attrs, ATTR_LENGTHIS) &&
        (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING)))
        error_loc_info(&arg->loc_info,
                       "string and length_is specified for argument %s are mutually exclusive attributes\n",
                       arg->name);

2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417
    if (is_attr(arg->attrs, ATTR_SIZEIS))
    {
        expr_list_t *size_is_exprs = get_attrp(arg->attrs, ATTR_SIZEIS);
        check_conformance_expr_list("size_is", arg, container_type, size_is_exprs);
    }
    if (is_attr(arg->attrs, ATTR_LENGTHIS))
    {
        expr_list_t *length_is_exprs = get_attrp(arg->attrs, ATTR_LENGTHIS);
        check_conformance_expr_list("length_is", arg, container_type, length_is_exprs);
    }
    if (is_attr(arg->attrs, ATTR_IIDIS))
    {
        struct expr_loc expr_loc;
        expr_t *expr = get_attrp(arg->attrs, ATTR_IIDIS);
        if (expr->type != EXPR_VOID)
        {
2418
            const type_t *expr_type;
2419 2420
            expr_loc.v = arg;
            expr_loc.attr = "iid_is";
2421 2422
            expr_type = expr_resolve_type(&expr_loc, container_type, expr);
            if (!expr_type || !is_ptr_guid_type(expr_type))
2423 2424 2425 2426 2427 2428 2429 2430 2431
                error_loc_info(&arg->loc_info, "expression must resolve to pointer to GUID type for attribute iid_is\n");
        }
    }
    if (is_attr(arg->attrs, ATTR_SWITCHIS))
    {
        struct expr_loc expr_loc;
        expr_t *expr = get_attrp(arg->attrs, ATTR_SWITCHIS);
        if (expr->type != EXPR_VOID)
        {
2432
            const type_t *expr_type;
2433 2434
            expr_loc.v = arg;
            expr_loc.attr = "switch_is";
2435 2436
            expr_type = expr_resolve_type(&expr_loc, container_type, expr);
            if (!expr_type || !is_allowed_conf_type(expr_type))
2437 2438 2439 2440 2441
                error_loc_info(&arg->loc_info, "expression must resolve to integral type <= 32bits for attribute %s\n",
                               expr_loc.attr);
        }
    }

2442
    do
2443
    {
2444 2445 2446
        more_to_do = FALSE;

        switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
2447
        {
2448 2449 2450
        case TGT_STRUCT:
        case TGT_UNION:
            check_remoting_fields(arg, type);
2451
            break;
2452
        case TGT_INVALID:
2453 2454
        {
            const char *reason = "is invalid";
2455 2456 2457
            switch (type_get_type(type))
            {
            case TYPE_VOID:
2458
                reason = "cannot derive from void *";
2459 2460
                break;
            case TYPE_FUNCTION:
2461 2462 2463 2464
                reason = "cannot be a function pointer";
                break;
            case TYPE_BITFIELD:
                reason = "cannot be a bit-field";
2465 2466
                break;
            case TYPE_COCLASS:
2467 2468
                reason = "cannot be a class";
                break;
2469
            case TYPE_INTERFACE:
2470 2471
                reason = "cannot be a non-pointer to an interface";
                break;
2472
            case TYPE_MODULE:
2473
                reason = "cannot be a module";
2474 2475 2476 2477
                break;
            default:
                break;
            }
2478 2479 2480 2481
            error_loc_info(&arg->loc_info, "%s \'%s\' of %s \'%s\' %s\n",
                           var_type, arg->name, container_type_name, container_name, reason);
            break;
        }
2482 2483
        case TGT_CTXT_HANDLE:
        case TGT_CTXT_HANDLE_POINTER:
2484 2485 2486 2487 2488
            if (type_get_type(container_type) != TYPE_FUNCTION)
                error_loc_info(&arg->loc_info,
                               "%s \'%s\' of %s \'%s\' cannot be a context handle\n",
                               var_type, arg->name, container_type_name,
                               container_name);
2489
            break;
2490 2491 2492 2493 2494 2495 2496 2497 2498
        case TGT_STRING:
        {
            const type_t *t = type;
            while (is_ptr(t))
                t = type_pointer_get_ref(t);
            if (is_aliaschain_attr(t, ATTR_RANGE))
                warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name);
            break;
        }
2499
        case TGT_POINTER:
2500
            type = type_pointer_get_ref(type);
2501 2502 2503
            more_to_do = TRUE;
            break;
        case TGT_ARRAY:
2504
            type = type_array_get_element(type);
2505
            more_to_do = TRUE;
2506
            break;
2507 2508 2509 2510
        case TGT_USER_TYPE:
        case TGT_IFACE_POINTER:
        case TGT_BASIC:
        case TGT_ENUM:
2511
        case TGT_RANGE:
2512 2513 2514 2515
            /* nothing to do */
            break;
        }
    } while (more_to_do);
2516 2517
}

2518
static void check_remoting_fields(const var_t *var, type_t *type)
2519 2520 2521 2522
{
    const var_t *field;
    const var_list_t *fields = NULL;

2523
    type = type_get_real_type(type);
2524

2525 2526 2527 2528 2529
    if (type->checked)
        return;

    type->checked = TRUE;

2530
    if (type_get_type(type) == TYPE_STRUCT)
2531
    {
2532
        if (type_is_complete(type))
2533
            fields = type_struct_get_fields(type);
2534 2535 2536
        else
            error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name);
    }
2537
    else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION)
2538
        fields = type_union_get_cases(type);
2539

2540
    if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2541
        if (field->type) check_field_common(type, type->name, field);
2542 2543
}

2544
/* checks that arguments for a function make sense for marshalling and unmarshalling */
2545
static void check_remoting_args(const var_t *func)
2546
{
2547
    const char *funcname = func->name;
2548 2549
    const var_t *arg;

2550
    if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry )
2551 2552 2553 2554 2555 2556
    {
        const type_t *type = arg->type;

        /* check that [out] parameters have enough pointer levels */
        if (is_attr(arg->attrs, ATTR_OUT))
        {
2557
            switch (typegen_detect_type(type, arg->attrs, TDT_ALL_TYPES))
2558
            {
2559 2560
            case TGT_BASIC:
            case TGT_ENUM:
2561
            case TGT_RANGE:
2562 2563 2564 2565 2566 2567 2568 2569 2570 2571
            case TGT_STRUCT:
            case TGT_UNION:
            case TGT_CTXT_HANDLE:
            case TGT_USER_TYPE:
                error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname);
                break;
            case TGT_IFACE_POINTER:
                error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname);
                break;
            case TGT_STRING:
2572 2573 2574 2575 2576 2577 2578
                if (is_array(type))
                {
                    /* needs conformance or fixed dimension */
                    if (type_array_has_conformance(type) &&
                        type_array_get_conformance(type)->type != EXPR_VOID) break;
                    if (!type_array_has_conformance(type) && type_array_get_dim(type)) break;
                }
2579
                if (is_attr( arg->attrs, ATTR_IN )) break;
2580
                error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' cannot be an unsized string\n", arg->name, funcname);
2581 2582 2583 2584 2585 2586 2587 2588
                break;
            case TGT_INVALID:
                /* already error'd before we get here */
            case TGT_CTXT_HANDLE_POINTER:
            case TGT_POINTER:
            case TGT_ARRAY:
                /* OK */
                break;
2589 2590 2591
            }
        }

2592
        check_field_common(func->type, funcname, arg);
2593
    }
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603

    if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID)
    {
        var_t var;
        var = *func;
        var.type = type_function_get_rettype(func->type);
        var.name = xstrdup("return value");
        check_field_common(func->type, funcname, &var);
        free(var.name);
    }
2604 2605
}

2606
static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func)
2607
{
2608
    unsigned char explicit_fc, implicit_fc;
2609 2610

    /* check for a defined binding handle */
2611
    if (!get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ) || !explicit_fc)
2612
    {
2613 2614 2615 2616 2617 2618 2619
        /* no explicit handle specified so add
         * "[in] handle_t IDL_handle" as the first parameter to the
         * function */
        var_t *idl_handle = make_var(xstrdup("IDL_handle"));
        idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN));
        idl_handle->type = find_type_or_error("handle_t", 0);
        type_function_add_head_arg(func->type, idl_handle);
2620 2621 2622
    }
}

2623
static void check_functions(const type_t *iface, int is_inside_library)
2624
{
2625 2626
    const statement_t *stmt;
    if (is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE))
2627
    {
2628
        STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2629 2630
        {
            var_t *func = stmt->u.var;
2631
            add_explicit_handle_if_necessary(iface, func);
2632
        }
2633
    }
2634 2635
    if (!is_inside_library && !is_attr(iface->attrs, ATTR_LOCAL))
    {
2636
        STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
2637
        {
2638 2639
            const var_t *func = stmt->u.var;
            if (!is_attr(func->attrs, ATTR_LOCAL))
2640 2641 2642 2643 2644
                check_remoting_args(func);
        }
    }
}

2645 2646 2647 2648 2649 2650 2651 2652
static void check_statements(const statement_list_t *stmts, int is_inside_library)
{
    const statement_t *stmt;

    if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
    {
      if (stmt->type == STMT_LIBRARY)
          check_statements(stmt->u.lib->stmts, TRUE);
2653
      else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
2654 2655 2656 2657
          check_functions(stmt->u.type, is_inside_library);
    }
}

2658
static void check_all_user_types(const statement_list_t *stmts)
2659
{
2660
  const statement_t *stmt;
2661

2662
  if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
2663
  {
2664 2665
    if (stmt->type == STMT_LIBRARY)
      check_all_user_types(stmt->u.lib->stmts);
2666
    else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE &&
2667
             !is_local(stmt->u.type->attrs))
2668
    {
2669
      const statement_t *stmt_func;
2670
      STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) {
2671 2672 2673
        const var_t *func = stmt_func->u.var;
        check_for_additional_prototype_types(func->type->details.function->args);
      }
2674
    }
2675 2676
  }
}
2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693

int is_valid_uuid(const char *s)
{
  int i;

  for (i = 0; i < 36; ++i)
    if (i == 8 || i == 13 || i == 18 || i == 23)
    {
      if (s[i] != '-')
        return FALSE;
    }
    else
      if (!isxdigit(s[i]))
        return FALSE;

  return s[i] == '\0';
}
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715

static statement_t *make_statement(enum statement_type type)
{
    statement_t *stmt = xmalloc(sizeof(*stmt));
    stmt->type = type;
    return stmt;
}

static statement_t *make_statement_type_decl(type_t *type)
{
    statement_t *stmt = make_statement(STMT_TYPE);
    stmt->u.type = type;
    return stmt;
}

static statement_t *make_statement_reference(type_t *type)
{
    statement_t *stmt = make_statement(STMT_TYPEREF);
    stmt->u.type = type;
    return stmt;
}

2716
static statement_t *make_statement_declaration(var_t *var)
2717
{
2718
    statement_t *stmt = make_statement(STMT_DECLARATION);
2719
    stmt->u.var = var;
2720 2721 2722 2723 2724 2725 2726
    if (var->stgclass == STG_EXTERN && var->eval)
        warning("'%s' initialised and declared extern\n", var->name);
    if (is_const_decl(var))
    {
        if (var->eval)
            reg_const(var);
    }
2727 2728 2729
    else if (type_get_type(var->type) == TYPE_FUNCTION)
        check_function_attrs(var->name, var->attrs);
    else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER)
2730
        error_loc("instantiation of data is illegal\n");
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754
    return stmt;
}

static statement_t *make_statement_library(typelib_t *typelib)
{
    statement_t *stmt = make_statement(STMT_LIBRARY);
    stmt->u.lib = typelib;
    return stmt;
}

static statement_t *make_statement_cppquote(const char *str)
{
    statement_t *stmt = make_statement(STMT_CPPQUOTE);
    stmt->u.str = str;
    return stmt;
}

static statement_t *make_statement_importlib(const char *str)
{
    statement_t *stmt = make_statement(STMT_IMPORTLIB);
    stmt->u.str = str;
    return stmt;
}

2755 2756 2757 2758 2759 2760 2761
static statement_t *make_statement_import(const char *str)
{
    statement_t *stmt = make_statement(STMT_IMPORT);
    stmt->u.str = str;
    return stmt;
}

2762 2763 2764 2765 2766 2767 2768
static statement_t *make_statement_module(type_t *type)
{
    statement_t *stmt = make_statement(STMT_MODULE);
    stmt->u.type = type;
    return stmt;
}

2769
static statement_t *make_statement_typedef(declarator_list_t *decls)
2770
{
2771
    declarator_t *decl, *next;
2772 2773 2774
    statement_t *stmt;
    type_list_t **type_list;

2775
    if (!decls) return NULL;
2776 2777 2778 2779 2780

    stmt = make_statement(STMT_TYPEDEF);
    stmt->u.type_list = NULL;
    type_list = &stmt->u.type_list;

2781
    LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry )
2782
    {
2783
        var_t *var = decl->var;
2784
        type_t *type = find_type_or_error(var->name, 0);
2785 2786 2787 2788 2789
        *type_list = xmalloc(sizeof(type_list_t));
        (*type_list)->type = type;
        (*type_list)->next = NULL;

        type_list = &(*type_list)->next;
2790
        free(decl);
2791 2792 2793 2794 2795 2796
        free(var);
    }

    return stmt;
}

2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807
static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt)
{
    if (!stmt) return list;
    if (!list)
    {
        list = xmalloc( sizeof(*list) );
        list_init( list );
    }
    list_add_tail( list, &stmt->entry );
    return list;
}
2808

2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
void init_loc_info(loc_info_t *i)
{
    i->input_name = input_name ? input_name : "stdin";
    i->line_number = line_number;
    i->near_text = parser_text;
}

static void check_def(const type_t *t)
{
    if (t->defined)
        error_loc("%s: redefinition error; original definition was at %s:%d\n",
                  t->name, t->loc_info.input_name, t->loc_info.line_number);
}