Get rid of the ThunkData stubs, these are not functions.
[wine/multimedia.git] / tools / widl / parser.y
blob6448d8f520d25a9563adddb54ec5dccb8e660896
1 %{
2 /*
3 * IDL Compiler
5 * Copyright 2002 Ove Kaaven
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <string.h>
30 #ifdef HAVE_ALLOCA_H
31 #include <alloca.h>
32 #endif
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38 #include "proxy.h"
39 #include "typelib.h"
41 #if defined(YYBYACC)
42 /* Berkeley yacc (byacc) doesn't seem to know about these */
43 /* Some *BSD supplied versions do define these though */
44 # ifndef YYEMPTY
45 # define YYEMPTY (-1) /* Empty lookahead value of yychar */
46 # endif
47 # ifndef YYLEX
48 # define YYLEX yylex()
49 # endif
51 #elif defined(YYBISON)
52 /* Bison was used for original development */
53 /* #define YYEMPTY -2 */
54 /* #define YYLEX yylex() */
56 #else
57 /* No yacc we know yet */
58 # if !defined(YYEMPTY) || !defined(YYLEX)
59 # error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
60 # elif defined(__GNUC__) /* gcc defines the #warning directive */
61 # warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
62 /* #else we just take a chance that it works... */
63 # endif
64 #endif
66 static attr_t *make_attr(enum attr_type type);
67 static attr_t *make_attrv(enum attr_type type, unsigned long val);
68 static attr_t *make_attrp(enum attr_type type, void *val);
69 static expr_t *make_expr(enum expr_type type);
70 static expr_t *make_exprl(enum expr_type type, long val);
71 static expr_t *make_exprs(enum expr_type type, char *val);
72 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr);
73 static expr_t *make_expr1(enum expr_type type, expr_t *expr);
74 static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2);
75 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3);
76 static type_t *make_type(unsigned char type, type_t *ref);
77 static typeref_t *make_tref(char *name, type_t *ref);
78 static typeref_t *uniq_tref(typeref_t *ref);
79 static type_t *type_ref(typeref_t *ref);
80 static void set_type(var_t *v, typeref_t *ref, expr_t *arr);
81 static ifref_t *make_ifref(type_t *iface);
82 static var_t *make_var(char *name);
83 static func_t *make_func(var_t *def, var_t *args);
84 static class_t *make_class(char *name);
86 static type_t *reg_type(type_t *type, char *name, int t);
87 static type_t *reg_types(type_t *type, var_t *names, int t);
88 static type_t *find_type(char *name, int t);
89 static type_t *find_type2(char *name, int t);
90 static type_t *get_type(unsigned char type, char *name, int t);
91 static type_t *get_typev(unsigned char type, var_t *name, int t);
92 static int get_struct_type(var_t *fields);
94 static var_t *reg_const(var_t *var);
95 static var_t *find_const(char *name, int f);
97 #define tsENUM 1
98 #define tsSTRUCT 2
99 #define tsUNION 3
101 static type_t std_bool = { "boolean" };
102 static type_t std_int = { "int" };
103 static type_t std_int64 = { "__int64" };
104 static type_t std_uhyper = { "MIDL_uhyper" };
107 %union {
108 attr_t *attr;
109 expr_t *expr;
110 type_t *type;
111 typeref_t *tref;
112 var_t *var;
113 func_t *func;
114 ifref_t *ifref;
115 class_t *clas;
116 char *str;
117 UUID *uuid;
118 unsigned int num;
121 %token <str> aIDENTIFIER
122 %token <str> aKNOWNTYPE
123 %token <num> aNUM aHEXNUM
124 %token <str> aSTRING
125 %token <uuid> aUUID
126 %token aEOF
127 %token SHL SHR
128 %token tAGGREGATABLE tALLOCATE tAPPOBJECT tARRAYS tASYNC tASYNCUUID
129 %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
130 %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
131 %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
132 %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
133 %token tDEFAULT
134 %token tDEFAULTVALUE
135 %token tDISPINTERFACE
136 %token tDLLNAME tDOUBLE tDUAL
137 %token tENDPOINT
138 %token tENTRY tENUM tERRORSTATUST
139 %token tEXTERN
140 %token tFLOAT
141 %token tHANDLE
142 %token tHANDLET
143 %token tHELPSTRING
144 %token tHYPER tID tIDEMPOTENT
145 %token tIIDIS
146 %token tIMPORT tIMPORTLIB
147 %token tIN tINCLUDE tINLINE
148 %token tINPUTSYNC
149 %token tINT tINT64
150 %token tINTERFACE
151 %token tLENGTHIS tLIBRARY
152 %token tLOCAL
153 %token tLONG
154 %token tMETHODS
155 %token tMODULE
156 %token tOBJECT tODL tOLEAUTOMATION
157 %token tOPTIONAL
158 %token tOUT
159 %token tPOINTERDEFAULT
160 %token tPROPERTIES
161 %token tPROPGET tPROPPUT
162 %token tPUBLIC
163 %token tREADONLY tREF
164 %token tRETVAL
165 %token tSHORT
166 %token tSIGNED
167 %token tSIZEIS tSIZEOF
168 %token tSOURCE
169 %token tSTDCALL
170 %token tSTRING tSTRUCT
171 %token tSWITCH tSWITCHIS tSWITCHTYPE
172 %token tTRANSMITAS
173 %token tTYPEDEF
174 %token tUNION
175 %token tUNIQUE
176 %token tUNSIGNED
177 %token tUUID
178 %token tV1ENUM
179 %token tVARARG
180 %token tVERSION
181 %token tVOID
182 %token tWCHAR tWIREMARSHAL
184 /* used in attr_t */
185 %token tPOINTERTYPE
187 %type <attr> m_attributes attributes attrib_list attribute
188 %type <expr> m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const
189 %type <expr> array array_list
190 %type <type> inherit interface interfacehdr interfacedef interfacedec
191 %type <type> dispinterface dispinterfacehdr dispinterfacedef
192 %type <type> module modulehdr moduledef
193 %type <type> base_type int_std
194 %type <type> enumdef structdef typedef uniondef
195 %type <ifref> gbl_statements coclass_ints coclass_int
196 %type <tref> type
197 %type <var> m_args no_args args arg
198 %type <var> fields field s_field cases case enums enum_list enum constdef externdef
199 %type <var> m_ident t_ident ident p_ident pident pident_list
200 %type <var> dispint_props
201 %type <func> funcdef int_statements
202 %type <func> dispint_meths
203 %type <clas> coclass coclasshdr coclassdef
204 %type <num> pointer_type version
205 %type <str> libraryhdr
207 %left ','
208 %left '|'
209 %left '&'
210 %left '-' '+'
211 %left '*' '/'
212 %left SHL SHR
213 %right '~'
214 %right CAST
215 %right PPTR
216 %right NEG
220 input: gbl_statements { write_proxies($1); }
223 gbl_statements: { $$ = NULL; }
224 | gbl_statements interfacedec { $$ = $1; }
225 | gbl_statements interfacedef { $$ = make_ifref($2); LINK($$, $1); }
226 | gbl_statements coclassdef { $$ = $1; add_coclass($2); }
227 | gbl_statements moduledef { $$ = $1; add_module($2); }
228 | gbl_statements librarydef { $$ = $1; }
229 | gbl_statements statement { $$ = $1; }
232 imp_statements: {}
233 | imp_statements interfacedec { if (!parse_only) add_interface($2); }
234 | imp_statements interfacedef { if (!parse_only) add_interface($2); }
235 | imp_statements coclassdef { if (!parse_only) add_coclass($2); }
236 | imp_statements moduledef { if (!parse_only) add_module($2); }
237 | imp_statements statement {}
240 int_statements: { $$ = NULL; }
241 | int_statements funcdef ';' { $$ = $2; LINK($$, $1); }
242 | int_statements statement { $$ = $1; }
245 statement: ';' {}
246 | constdef ';' { if (!parse_only) { write_constdef($1); } }
247 | cppquote {}
248 | enumdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
249 | externdef ';' { if (!parse_only) { write_externdef($1); } }
250 | import {}
251 | structdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
252 | typedef ';' {}
253 | uniondef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
256 cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only) fprintf(header, "%s\n", $3); }
258 import_start: tIMPORT aSTRING ';' { assert(yychar == YYEMPTY);
259 if (!do_import($2)) yychar = aEOF; }
261 import: import_start imp_statements aEOF {}
264 libraryhdr: tLIBRARY aIDENTIFIER { $$ = $2; }
266 library_start: attributes libraryhdr '{' { start_typelib($2, $1); }
268 librarydef: library_start imp_statements '}' { end_typelib(); }
271 m_args: { $$ = NULL; }
272 | args
275 no_args: tVOID { $$ = NULL; }
278 args: arg
279 | args ',' arg { LINK($3, $1); $$ = $3; }
280 | no_args
283 /* split into two rules to get bison to resolve a tVOID conflict */
284 arg: attributes type pident array { $$ = $3;
285 set_type($$, $2, $4);
286 $$->attrs = $1;
287 if (!is_attr($$->attrs, ATTR_OUT) &&
288 !is_attr($$->attrs, ATTR_IN)) {
289 attr_t *a = make_attr(ATTR_IN);
290 LINK(a, $$->attrs); $$->attrs = a;
293 | type pident array { $$ = $2;
294 set_type($$, $1, $3);
295 $$->attrs = make_attr(ATTR_IN);
297 | attributes type pident '(' m_args ')' { $$ = $3;
298 $$->ptr_level--;
299 set_type($$, $2, NULL);
300 $$->attrs = $1;
301 $$->args = $5;
302 if (!is_attr($$->attrs, ATTR_OUT) &&
303 !is_attr($$->attrs, ATTR_IN)) {
304 attr_t *a = make_attr(ATTR_IN);
305 LINK(a, $$->attrs); $$->attrs = a;
308 | type pident '(' m_args ')' { $$ = $2;
309 $$->ptr_level--;
310 set_type($$, $1, NULL);
311 $$->attrs = make_attr(ATTR_IN);
312 $$->args = $4;
316 array: { $$ = NULL; }
317 | '[' array_list ']' { $$ = $2; }
318 | '[' '*' ']' { $$ = make_expr(EXPR_VOID); }
321 array_list: m_expr /* size of first dimension is optional */
322 | array_list ',' expr { LINK($3, $1); $$ = $3; }
323 | array_list ']' '[' expr { LINK($4, $1); $$ = $4; }
326 m_attributes: { $$ = NULL; }
327 | attributes
330 attributes:
331 '[' attrib_list ']' { $$ = $2; }
334 attrib_list: attribute
335 | attrib_list ',' attribute { LINK($3, $1); $$ = $3; }
336 | attrib_list ']' '[' attribute { LINK($4, $1); $$ = $4; }
339 attribute:
340 tASYNC { $$ = make_attr(ATTR_ASYNC); }
341 | tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); }
342 | tCASE '(' expr_list_const ')' { $$ = make_attrp(ATTR_CASE, $3); }
343 | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
344 | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
345 | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
346 | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); }
347 | tDEFAULTVALUE '(' expr_const ')' { $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
348 | tDEFAULTVALUE '(' aSTRING ')' { $$ = make_attrp(ATTR_DEFAULTVALUE, $3); }
349 | tDLLNAME '(' aSTRING ')' { $$ = make_attrp(ATTR_DLLNAME, $3); }
350 | tDUAL { $$ = make_attr(ATTR_DUAL); }
351 | tENDPOINT '(' aSTRING ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); }
352 | tENTRY '(' aSTRING ')' { $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
353 | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
354 | tHANDLE { $$ = make_attr(ATTR_HANDLE); }
355 | tHELPSTRING '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPSTRING, $3); }
356 | tID '(' expr_const ')' { $$ = make_attrp(ATTR_ID, $3); }
357 | tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); }
358 | tIIDIS '(' ident ')' { $$ = make_attrp(ATTR_IIDIS, $3); }
359 | tIN { $$ = make_attr(ATTR_IN); }
360 | tINPUTSYNC { $$ = make_attr(ATTR_INPUTSYNC); }
361 | tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); }
362 | tLOCAL { $$ = make_attr(ATTR_LOCAL); }
363 | tOBJECT { $$ = make_attr(ATTR_OBJECT); }
364 | tODL { $$ = make_attr(ATTR_ODL); }
365 | tOLEAUTOMATION { $$ = make_attr(ATTR_OLEAUTOMATION); }
366 | tOPTIONAL { $$ = make_attr(ATTR_OPTIONAL); }
367 | tOUT { $$ = make_attr(ATTR_OUT); }
368 | tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
369 | tPROPGET { $$ = make_attr(ATTR_PROPGET); }
370 | tPROPPUT { $$ = make_attr(ATTR_PROPPUT); }
371 | tPUBLIC { $$ = make_attr(ATTR_PUBLIC); }
372 | tREADONLY { $$ = make_attr(ATTR_READONLY); }
373 | tRETVAL { $$ = make_attr(ATTR_RETVAL); }
374 | tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); }
375 | tSOURCE { $$ = make_attr(ATTR_SOURCE); }
376 | tSTRING { $$ = make_attr(ATTR_STRING); }
377 | tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); }
378 | tSWITCHTYPE '(' type ')' { $$ = make_attrp(ATTR_SWITCHTYPE, type_ref($3)); }
379 | tTRANSMITAS '(' type ')' { $$ = make_attrp(ATTR_TRANSMITAS, type_ref($3)); }
380 | tUUID '(' aUUID ')' { $$ = make_attrp(ATTR_UUID, $3); }
381 | tV1ENUM { $$ = make_attr(ATTR_V1ENUM); }
382 | tVARARG { $$ = make_attr(ATTR_VARARG); }
383 | tVERSION '(' version ')' { $$ = make_attrv(ATTR_VERSION, $3); }
384 | tWIREMARSHAL '(' type ')' { $$ = make_attrp(ATTR_WIREMARSHAL, type_ref($3)); }
385 | pointer_type { $$ = make_attrv(ATTR_POINTERTYPE, $1); }
388 callconv:
389 | tSTDCALL
392 cases: { $$ = NULL; }
393 | cases case { if ($2) { LINK($2, $1); $$ = $2; }
394 else { $$ = $1; }
398 case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, $2);
399 $$ = $4; if (!$$) $$ = make_var(NULL);
400 LINK(a, $$->attrs); $$->attrs = a;
402 | tDEFAULT ':' field { attr_t *a = make_attr(ATTR_DEFAULT);
403 $$ = $3; if (!$$) $$ = make_var(NULL);
404 LINK(a, $$->attrs); $$->attrs = a;
408 constdef: tCONST type ident '=' expr_const { $$ = reg_const($3);
409 set_type($$, $2, NULL);
410 $$->eval = $5;
411 $$->lval = $5->cval;
415 enums: { $$ = NULL; }
416 | enum_list ',' { $$ = $1; }
417 | enum_list
420 enum_list: enum
421 | enum_list ',' enum { LINK($3, $1); $$ = $3;
422 if ($1 && !$3->eval)
423 $3->lval = $1->lval + 1;
427 enum: ident '=' expr_const { $$ = reg_const($1);
428 $$->eval = $3;
429 $$->lval = $3->cval;
431 | ident { $$ = reg_const($1);
432 $$->lval = 0; /* default for first enum entry */
436 enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
437 $$->fields = $4;
438 $$->defined = TRUE;
442 m_exprs: m_expr
443 | m_exprs ',' m_expr { LINK($3, $1); $$ = $3; }
447 exprs: { $$ = make_expr(EXPR_VOID); }
448 | expr_list
451 expr_list: expr
452 | expr_list ',' expr { LINK($3, $1); $$ = $3; }
456 m_expr: { $$ = make_expr(EXPR_VOID); }
457 | expr
460 expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); }
461 | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); }
462 | aIDENTIFIER { $$ = make_exprs(EXPR_IDENTIFIER, $1); }
463 | expr '?' expr ':' expr { $$ = make_expr3(EXPR_COND, $1, $3, $5); }
464 | expr '|' expr { $$ = make_expr2(EXPR_OR , $1, $3); }
465 | expr '&' expr { $$ = make_expr2(EXPR_AND, $1, $3); }
466 | expr '+' expr { $$ = make_expr2(EXPR_ADD, $1, $3); }
467 | expr '-' expr { $$ = make_expr2(EXPR_SUB, $1, $3); }
468 | expr '*' expr { $$ = make_expr2(EXPR_MUL, $1, $3); }
469 | expr '/' expr { $$ = make_expr2(EXPR_DIV, $1, $3); }
470 | expr SHL expr { $$ = make_expr2(EXPR_SHL, $1, $3); }
471 | expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); }
472 | '~' expr { $$ = make_expr1(EXPR_NOT, $2); }
473 | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); }
474 | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); }
475 | '(' type ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, $2, $4); }
476 | tSIZEOF '(' type ')' { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); }
477 | '(' expr ')' { $$ = $2; }
480 expr_list_const: expr_const
481 | expr_list_const ',' expr_const { LINK($3, $1); $$ = $3; }
484 expr_const: expr { $$ = $1;
485 if (!$$->is_const) yyerror("expression is not constant\n");
489 externdef: tEXTERN tCONST type ident { $$ = $4;
490 set_type($$, $3, NULL);
494 fields: { $$ = NULL; }
495 | fields field { if ($2) { LINK($2, $1); $$ = $2; }
496 else { $$ = $1; }
500 field: s_field ';' { $$ = $1; }
501 | m_attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
502 | attributes ';' { $$ = make_var(NULL); $$->attrs = $1; }
503 | ';' { $$ = NULL; }
506 s_field: m_attributes type pident array { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; }
509 funcdef:
510 m_attributes type callconv pident
511 '(' m_args ')' { set_type($4, $2, NULL);
512 $4->attrs = $1;
513 $$ = make_func($4, $6);
514 if (is_attr($4->attrs, ATTR_IN)) {
515 yyerror("Inapplicable attribute");
517 if (!is_attr($4->attrs, ATTR_OUT)) {
518 attr_t *a = make_attr(ATTR_OUT);
519 LINK(a, $4->attrs); $4->attrs = a;
524 m_ident: { $$ = NULL; }
525 | ident
528 t_ident: { $$ = NULL; }
529 | aIDENTIFIER { $$ = make_var($1); }
530 | aKNOWNTYPE { $$ = make_var($1); }
533 ident: aIDENTIFIER { $$ = make_var($1); }
534 /* some "reserved words" used in attributes are also used as field names in some MS IDL files */
535 | aKNOWNTYPE { $$ = make_var($<str>1); }
536 | tID { $$ = make_var($<str>1); }
537 | tRETVAL { $$ = make_var($<str>1); }
538 | tVERSION { $$ = make_var($<str>1); }
541 base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); }
542 | tWCHAR { $$ = make_type(RPC_FC_WCHAR, NULL); }
543 | int_std
544 | tSIGNED int_std { $$ = $2; $$->sign = 1; }
545 | tUNSIGNED int_std { $$ = $2; $$->sign = -1;
546 switch ($$->type) {
547 case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
548 case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
549 case RPC_FC_LONG: $$->type = RPC_FC_ULONG; break;
550 case RPC_FC_HYPER:
551 if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
552 break;
553 default: break;
556 | tFLOAT { $$ = make_type(RPC_FC_FLOAT, NULL); }
557 | tDOUBLE { $$ = make_type(RPC_FC_DOUBLE, NULL); }
558 | tBOOLEAN { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
559 | tERRORSTATUST { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
560 | tHANDLET { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
563 m_int:
564 | tINT
567 int_std: tINT { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
568 | tSHORT m_int { $$ = make_type(RPC_FC_SHORT, NULL); }
569 | tLONG m_int { $$ = make_type(RPC_FC_LONG, NULL); }
570 | tHYPER m_int { $$ = make_type(RPC_FC_HYPER, NULL); }
571 | tINT64 { $$ = make_type(RPC_FC_HYPER, &std_int64); }
572 | tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); }
575 coclass: tCOCLASS aIDENTIFIER { $$ = make_class($2); }
576 | tCOCLASS aKNOWNTYPE { $$ = make_class($2); }
579 coclasshdr: attributes coclass { $$ = $2;
580 $$->attrs = $1;
581 if (!parse_only) write_coclass($$);
585 coclassdef: coclasshdr '{' coclass_ints '}' { $$ = $1;
586 $$->ifaces = $3;
590 coclass_ints: { $$ = NULL; }
591 | coclass_ints coclass_int { LINK($2, $1); $$ = $2; }
594 coclass_int:
595 m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; }
598 dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(0, $2, 0); }
599 | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(0, $2, 0); }
602 dispinterfacehdr: attributes dispinterface { $$ = $2;
603 if ($$->defined) yyerror("multiple definition error\n");
604 $$->attrs = $1;
605 $$->attrs = make_attr(ATTR_DISPINTERFACE);
606 LINK($$->attrs, $1);
607 $$->ref = find_type("IDispatch", 0);
608 if (!$$->ref) yyerror("IDispatch is undefined\n");
609 $$->defined = TRUE;
610 if (!parse_only) write_forward($$);
614 dispint_props: tPROPERTIES ':' { $$ = NULL; }
615 | dispint_props s_field ';' { LINK($2, $1); $$ = $2; }
618 dispint_meths: tMETHODS ':' { $$ = NULL; }
619 | dispint_meths funcdef ';' { LINK($2, $1); $$ = $2; }
622 dispinterfacedef: dispinterfacehdr '{'
623 dispint_props
624 dispint_meths
625 '}' { $$ = $1;
626 $$->fields = $3;
627 $$->funcs = $4;
628 if (!parse_only) write_dispinterface($$);
630 /* FIXME: not sure how to handle this yet
631 | dispinterfacehdr '{' interface '}' { $$ = $1;
632 if (!parse_only) write_interface($$);
637 inherit: { $$ = NULL; }
638 | ':' aKNOWNTYPE { $$ = find_type2($2, 0); }
641 interface: tINTERFACE aIDENTIFIER { $$ = get_type(RPC_FC_IP, $2, 0); }
642 | tINTERFACE aKNOWNTYPE { $$ = get_type(RPC_FC_IP, $2, 0); }
645 interfacehdr: attributes interface { $$ = $2;
646 if ($$->defined) yyerror("multiple definition error\n");
647 $$->attrs = $1;
648 $$->defined = TRUE;
649 if (!parse_only) write_forward($$);
653 interfacedef: interfacehdr inherit
654 '{' int_statements '}' { $$ = $1;
655 $$->ref = $2;
656 $$->funcs = $4;
657 if (!parse_only) write_interface($$);
659 /* MIDL is able to import the definition of a base class from inside the
660 * definition of a derived class, I'll try to support it with this rule */
661 | interfacehdr ':' aIDENTIFIER
662 '{' import int_statements '}' { $$ = $1;
663 $$->ref = find_type2($3, 0);
664 if (!$$->ref) yyerror("base class %s not found in import\n", $3);
665 $$->funcs = $6;
666 if (!parse_only) write_interface($$);
668 | dispinterfacedef { $$ = $1; }
671 interfacedec:
672 interface ';' { $$ = $1; if (!parse_only) write_forward($$); }
673 | dispinterface ';' { $$ = $1; if (!parse_only) write_forward($$); }
676 module: tMODULE aIDENTIFIER { $$ = make_type(0, NULL); $$->name = $2; }
677 | tMODULE aKNOWNTYPE { $$ = make_type(0, NULL); $$->name = $2; }
680 modulehdr: attributes module { $$ = $2;
681 $$->attrs = $1;
685 moduledef: modulehdr '{' int_statements '}' { $$ = $1;
686 $$->funcs = $3;
687 /* FIXME: if (!parse_only) write_module($$); */
691 p_ident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; }
692 | tCONST p_ident { $$ = $2; /* FIXME */ }
695 pident: ident
696 | p_ident
697 | '(' pident ')' { $$ = $2; }
700 pident_list:
701 pident
702 | pident_list ',' pident { LINK($3, $1); $$ = $3; }
705 pointer_type:
706 tREF { $$ = RPC_FC_RP; }
707 | tUNIQUE { $$ = RPC_FC_UP; }
710 structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
711 /* overwrite RPC_FC_STRUCT with a more exact type */
712 $$->type = get_struct_type( $4 );
713 $$->fields = $4;
714 $$->defined = TRUE;
718 type: tVOID { $$ = make_tref(NULL, make_type(0, NULL)); }
719 | aKNOWNTYPE { $$ = make_tref($1, find_type($1, 0)); }
720 | base_type { $$ = make_tref(NULL, $1); }
721 | tCONST type { $$ = uniq_tref($2); $$->ref->is_const = TRUE; }
722 | enumdef { $$ = make_tref(NULL, $1); }
723 | tENUM aIDENTIFIER { $$ = make_tref(NULL, find_type2($2, tsENUM)); }
724 | structdef { $$ = make_tref(NULL, $1); }
725 | tSTRUCT aIDENTIFIER { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); }
726 | uniondef { $$ = make_tref(NULL, $1); }
727 | tUNION aIDENTIFIER { $$ = make_tref(NULL, find_type2($2, tsUNION)); }
730 typedef: tTYPEDEF m_attributes type pident_list { typeref_t *tref = uniq_tref($3);
731 $4->tname = tref->name;
732 tref->name = NULL;
733 $$ = type_ref(tref);
734 $$->attrs = $2;
735 if (!parse_only) write_typedef($$, $4);
736 reg_types($$, $4, 0);
740 uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
741 $$->fields = $4;
742 $$->defined = TRUE;
744 | tUNION t_ident
745 tSWITCH '(' s_field ')'
746 m_ident '{' cases '}' { var_t *u = $7;
747 $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
748 if (!u) u = make_var("tagged_union");
749 u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
750 u->type->fields = $9;
751 u->type->defined = TRUE;
752 LINK(u, $5); $$->fields = u;
753 $$->defined = TRUE;
757 version:
758 aNUM { $$ = MAKELONG($1, 0); }
759 | aNUM '.' aNUM { $$ = MAKELONG($1, $3); }
764 static attr_t *make_attr(enum attr_type type)
766 attr_t *a = xmalloc(sizeof(attr_t));
767 a->type = type;
768 a->u.ival = 0;
769 INIT_LINK(a);
770 return a;
773 static attr_t *make_attrv(enum attr_type type, unsigned long val)
775 attr_t *a = xmalloc(sizeof(attr_t));
776 a->type = type;
777 a->u.ival = val;
778 INIT_LINK(a);
779 return a;
782 static attr_t *make_attrp(enum attr_type type, void *val)
784 attr_t *a = xmalloc(sizeof(attr_t));
785 a->type = type;
786 a->u.pval = val;
787 INIT_LINK(a);
788 return a;
791 static expr_t *make_expr(enum expr_type type)
793 expr_t *e = xmalloc(sizeof(expr_t));
794 e->type = type;
795 e->ref = NULL;
796 e->u.lval = 0;
797 e->is_const = FALSE;
798 INIT_LINK(e);
799 return e;
802 static expr_t *make_exprl(enum expr_type type, long val)
804 expr_t *e = xmalloc(sizeof(expr_t));
805 e->type = type;
806 e->ref = NULL;
807 e->u.lval = val;
808 e->is_const = FALSE;
809 INIT_LINK(e);
810 /* check for numeric constant */
811 if (type == EXPR_NUM || type == EXPR_HEXNUM) {
812 e->is_const = TRUE;
813 e->cval = val;
815 return e;
818 static expr_t *make_exprs(enum expr_type type, char *val)
820 expr_t *e;
821 e = xmalloc(sizeof(expr_t));
822 e->type = type;
823 e->ref = NULL;
824 e->u.sval = val;
825 e->is_const = FALSE;
826 INIT_LINK(e);
827 /* check for predefined constants */
828 if (type == EXPR_IDENTIFIER) {
829 var_t *c = find_const(val, 0);
830 if (c) {
831 e->u.sval = c->name;
832 free(val);
833 e->is_const = TRUE;
834 e->cval = c->lval;
837 return e;
840 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr)
842 expr_t *e;
843 e = xmalloc(sizeof(expr_t));
844 e->type = type;
845 e->ref = expr;
846 e->u.tref = tref;
847 e->is_const = FALSE;
848 INIT_LINK(e);
849 /* check for cast of constant expression */
850 if (type == EXPR_CAST && expr->is_const) {
851 e->is_const = TRUE;
852 e->cval = expr->cval;
854 return e;
857 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
859 expr_t *e;
860 e = xmalloc(sizeof(expr_t));
861 e->type = type;
862 e->ref = expr;
863 e->u.lval = 0;
864 e->is_const = FALSE;
865 INIT_LINK(e);
866 /* check for compile-time optimization */
867 if (expr->is_const) {
868 e->is_const = TRUE;
869 switch (type) {
870 case EXPR_NEG:
871 e->cval = -expr->cval;
872 break;
873 case EXPR_NOT:
874 e->cval = ~expr->cval;
875 break;
876 default:
877 e->is_const = FALSE;
878 break;
881 return e;
884 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
886 expr_t *e;
887 e = xmalloc(sizeof(expr_t));
888 e->type = type;
889 e->ref = expr1;
890 e->u.ext = expr2;
891 e->is_const = FALSE;
892 INIT_LINK(e);
893 /* check for compile-time optimization */
894 if (expr1->is_const && expr2->is_const) {
895 e->is_const = TRUE;
896 switch (type) {
897 case EXPR_ADD:
898 e->cval = expr1->cval + expr2->cval;
899 break;
900 case EXPR_SUB:
901 e->cval = expr1->cval - expr2->cval;
902 break;
903 case EXPR_MUL:
904 e->cval = expr1->cval * expr2->cval;
905 break;
906 case EXPR_DIV:
907 e->cval = expr1->cval / expr2->cval;
908 break;
909 case EXPR_OR:
910 e->cval = expr1->cval | expr2->cval;
911 break;
912 case EXPR_AND:
913 e->cval = expr1->cval & expr2->cval;
914 break;
915 case EXPR_SHL:
916 e->cval = expr1->cval << expr2->cval;
917 break;
918 case EXPR_SHR:
919 e->cval = expr1->cval >> expr2->cval;
920 break;
921 default:
922 e->is_const = FALSE;
923 break;
926 return e;
929 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
931 expr_t *e;
932 e = xmalloc(sizeof(expr_t));
933 e->type = type;
934 e->ref = expr1;
935 e->u.ext = expr2;
936 e->ext2 = expr3;
937 e->is_const = FALSE;
938 INIT_LINK(e);
939 /* check for compile-time optimization */
940 if (expr1->is_const && expr2->is_const && expr3->is_const) {
941 e->is_const = TRUE;
942 switch (type) {
943 case EXPR_COND:
944 e->cval = expr1->cval ? expr2->cval : expr3->cval;
945 break;
946 default:
947 e->is_const = FALSE;
948 break;
951 return e;
954 static type_t *make_type(unsigned char type, type_t *ref)
956 type_t *t = xmalloc(sizeof(type_t));
957 t->name = NULL;
958 t->type = type;
959 t->ref = ref;
960 t->rname = NULL;
961 t->attrs = NULL;
962 t->funcs = NULL;
963 t->fields = NULL;
964 t->ignore = parse_only;
965 t->is_const = FALSE;
966 t->sign = 0;
967 t->defined = FALSE;
968 t->written = FALSE;
969 INIT_LINK(t);
970 return t;
973 static typeref_t *make_tref(char *name, type_t *ref)
975 typeref_t *t = xmalloc(sizeof(typeref_t));
976 t->name = name;
977 t->ref = ref;
978 t->uniq = ref ? 0 : 1;
979 return t;
982 static typeref_t *uniq_tref(typeref_t *ref)
984 typeref_t *t = ref;
985 type_t *tp;
986 if (t->uniq) return t;
987 tp = make_type(0, t->ref);
988 tp->name = t->name;
989 t->name = NULL;
990 t->ref = tp;
991 t->uniq = 1;
992 return t;
995 static type_t *type_ref(typeref_t *ref)
997 type_t *t = ref->ref;
998 if (ref->name) free(ref->name);
999 free(ref);
1000 return t;
1003 static void set_type(var_t *v, typeref_t *ref, expr_t *arr)
1005 v->type = ref->ref;
1006 v->tname = ref->name;
1007 ref->name = NULL;
1008 free(ref);
1009 v->array = arr;
1012 static ifref_t *make_ifref(type_t *iface)
1014 ifref_t *l = xmalloc(sizeof(ifref_t));
1015 l->iface = iface;
1016 l->attrs = NULL;
1017 INIT_LINK(l);
1018 return l;
1021 static var_t *make_var(char *name)
1023 var_t *v = xmalloc(sizeof(var_t));
1024 v->name = name;
1025 v->ptr_level = 0;
1026 v->type = NULL;
1027 v->tname = NULL;
1028 v->attrs = NULL;
1029 v->array = NULL;
1030 v->eval = NULL;
1031 v->lval = 0;
1032 INIT_LINK(v);
1033 return v;
1036 static func_t *make_func(var_t *def, var_t *args)
1038 func_t *f = xmalloc(sizeof(func_t));
1039 f->def = def;
1040 f->args = args;
1041 f->ignore = parse_only;
1042 f->idx = -1;
1043 INIT_LINK(f);
1044 return f;
1047 static class_t *make_class(char *name)
1049 class_t *c = xmalloc(sizeof(class_t));
1050 c->name = name;
1051 c->attrs = NULL;
1052 c->ifaces = NULL;
1053 INIT_LINK(c);
1054 return c;
1057 #define HASHMAX 64
1059 static int hash_ident(const char *name)
1061 const char *p = name;
1062 int sum = 0;
1063 /* a simple sum hash is probably good enough */
1064 while (*p) {
1065 sum += *p;
1066 p++;
1068 return sum & (HASHMAX-1);
1071 /***** type repository *****/
1073 struct rtype {
1074 char *name;
1075 type_t *type;
1076 int t;
1077 struct rtype *next;
1080 struct rtype *type_hash[HASHMAX];
1082 static type_t *reg_type(type_t *type, char *name, int t)
1084 struct rtype *nt;
1085 int hash;
1086 if (!name) {
1087 yyerror("registering named type without name\n");
1088 return type;
1090 hash = hash_ident(name);
1091 nt = xmalloc(sizeof(struct rtype));
1092 nt->name = name;
1093 nt->type = type;
1094 nt->t = t;
1095 nt->next = type_hash[hash];
1096 type_hash[hash] = nt;
1097 return type;
1100 /* determine pointer type from attrs */
1101 static unsigned char get_pointer_type( type_t *type )
1103 int t;
1104 if (is_attr( type->attrs, ATTR_STRING ))
1106 type_t *t = type;
1107 while( t->type == 0 && t->ref )
1108 t = t->ref;
1109 switch( t->type )
1111 case RPC_FC_CHAR:
1112 return RPC_FC_C_CSTRING;
1113 case RPC_FC_WCHAR:
1114 return RPC_FC_C_WSTRING;
1117 t = get_attrv( type->attrs, ATTR_POINTERTYPE );
1118 if (t) return t;
1119 return RPC_FC_FP;
1122 static type_t *reg_types(type_t *type, var_t *names, int t)
1124 type_t *ptr = type;
1125 int ptrc = 0;
1127 while (names) {
1128 var_t *next = NEXT_LINK(names);
1129 if (names->name) {
1130 type_t *cur = ptr;
1131 int cptr = names->ptr_level;
1132 if (cptr > ptrc) {
1133 while (cptr > ptrc) {
1134 int t = get_pointer_type( cur );
1135 cur = ptr = make_type(t, cur);
1136 ptrc++;
1138 } else {
1139 while (cptr < ptrc) {
1140 cur = cur->ref;
1141 cptr++;
1144 reg_type(cur, names->name, t);
1146 free(names);
1147 names = next;
1149 return type;
1152 static type_t *find_type(char *name, int t)
1154 struct rtype *cur = type_hash[hash_ident(name)];
1155 while (cur && (cur->t != t || strcmp(cur->name, name)))
1156 cur = cur->next;
1157 if (!cur) {
1158 yyerror("type %s not found\n", name);
1159 return NULL;
1161 return cur->type;
1164 static type_t *find_type2(char *name, int t)
1166 type_t *tp = find_type(name, t);
1167 free(name);
1168 return tp;
1171 int is_type(const char *name)
1173 struct rtype *cur = type_hash[hash_ident(name)];
1174 while (cur && (cur->t || strcmp(cur->name, name)))
1175 cur = cur->next;
1176 if (cur) return TRUE;
1177 return FALSE;
1180 static type_t *get_type(unsigned char type, char *name, int t)
1182 struct rtype *cur = NULL;
1183 type_t *tp;
1184 if (name) {
1185 cur = type_hash[hash_ident(name)];
1186 while (cur && (cur->t != t || strcmp(cur->name, name)))
1187 cur = cur->next;
1189 if (cur) {
1190 free(name);
1191 return cur->type;
1193 tp = make_type(type, NULL);
1194 tp->name = name;
1195 if (!name) return tp;
1196 return reg_type(tp, name, t);
1199 static type_t *get_typev(unsigned char type, var_t *name, int t)
1201 char *sname = NULL;
1202 if (name) {
1203 sname = name->name;
1204 free(name);
1206 return get_type(type, sname, t);
1209 static int get_struct_type(var_t *field)
1211 int has_pointer = 0;
1212 int has_conformant_array = 0;
1213 int has_conformant_string = 0;
1215 while (field)
1217 type_t *t = field->type;
1219 /* get the base type */
1220 while( (t->type == 0) && t->ref )
1221 t = t->ref;
1223 switch (t->type)
1226 * RPC_FC_BYTE, RPC_FC_STRUCT, etc
1227 * Simple types don't effect the type of struct.
1228 * A struct containing a simple struct is still a simple struct.
1229 * So long as we can block copy the data, we return RPC_FC_STRUCT.
1231 case 0: /* void pointer */
1232 case RPC_FC_BYTE:
1233 case RPC_FC_CHAR:
1234 case RPC_FC_SMALL:
1235 case RPC_FC_USMALL:
1236 case RPC_FC_WCHAR:
1237 case RPC_FC_SHORT:
1238 case RPC_FC_USHORT:
1239 case RPC_FC_LONG:
1240 case RPC_FC_ULONG:
1241 case RPC_FC_INT3264:
1242 case RPC_FC_UINT3264:
1243 case RPC_FC_HYPER:
1244 case RPC_FC_FLOAT:
1245 case RPC_FC_DOUBLE:
1246 case RPC_FC_STRUCT:
1247 case RPC_FC_ENUM16:
1248 case RPC_FC_ENUM32:
1249 break;
1251 case RPC_FC_UP:
1252 case RPC_FC_FP:
1253 has_pointer = 1;
1254 break;
1255 case RPC_FC_CARRAY:
1256 has_conformant_array = 1;
1257 break;
1258 case RPC_FC_C_CSTRING:
1259 case RPC_FC_C_WSTRING:
1260 has_conformant_string = 1;
1261 break;
1264 * Propagate member attributes
1265 * a struct should be at least as complex as its member
1267 case RPC_FC_CVSTRUCT:
1268 has_conformant_string = 1;
1269 has_pointer = 1;
1270 break;
1272 case RPC_FC_CPSTRUCT:
1273 has_conformant_array = 1;
1274 has_pointer = 1;
1275 break;
1277 case RPC_FC_CSTRUCT:
1278 has_conformant_array = 1;
1279 break;
1281 case RPC_FC_PSTRUCT:
1282 has_pointer = 1;
1283 break;
1285 default:
1286 fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n",
1287 field->name, t->type);
1288 /* fallthru - treat it as complex */
1290 /* as soon as we see one of these these members, it's bogus... */
1291 case RPC_FC_IP:
1292 case RPC_FC_ENCAPSULATED_UNION:
1293 case RPC_FC_NON_ENCAPSULATED_UNION:
1294 case RPC_FC_TRANSMIT_AS:
1295 case RPC_FC_REPRESENT_AS:
1296 case RPC_FC_PAD:
1297 case RPC_FC_EMBEDDED_COMPLEX:
1298 case RPC_FC_BOGUS_STRUCT:
1299 return RPC_FC_BOGUS_STRUCT;
1301 field = NEXT_LINK(field);
1304 if( has_conformant_string && has_pointer )
1305 return RPC_FC_CVSTRUCT;
1306 if( has_conformant_array && has_pointer )
1307 return RPC_FC_CPSTRUCT;
1308 if( has_conformant_array )
1309 return RPC_FC_CSTRUCT;
1310 if( has_pointer )
1311 return RPC_FC_PSTRUCT;
1312 return RPC_FC_STRUCT;
1315 /***** constant repository *****/
1317 struct rconst {
1318 char *name;
1319 var_t *var;
1320 struct rconst *next;
1323 struct rconst *const_hash[HASHMAX];
1325 static var_t *reg_const(var_t *var)
1327 struct rconst *nc;
1328 int hash;
1329 if (!var->name) {
1330 yyerror("registering constant without name\n");
1331 return var;
1333 hash = hash_ident(var->name);
1334 nc = xmalloc(sizeof(struct rconst));
1335 nc->name = var->name;
1336 nc->var = var;
1337 nc->next = const_hash[hash];
1338 const_hash[hash] = nc;
1339 return var;
1342 static var_t *find_const(char *name, int f)
1344 struct rconst *cur = const_hash[hash_ident(name)];
1345 while (cur && strcmp(cur->name, name))
1346 cur = cur->next;
1347 if (!cur) {
1348 if (f) yyerror("constant %s not found\n", name);
1349 return NULL;
1351 return cur->var;