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