Added support for the propget/propput function attributes.
[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         | tID                                   { $$ = make_var($<str>1); }
529         | tRETVAL                               { $$ = make_var($<str>1); }
530         | tVERSION                              { $$ = make_var($<str>1); }
531         ;
532
533 base_type: tBYTE                                { $$ = make_type(RPC_FC_BYTE, NULL); }
534         | tWCHAR                                { $$ = make_type(RPC_FC_WCHAR, NULL); }
535         | int_std
536         | tSIGNED int_std                       { $$ = $2; $$->sign = 1; }
537         | tUNSIGNED int_std                     { $$ = $2; $$->sign = -1;
538                                                   switch ($$->type) {
539                                                   case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break;
540                                                   case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break;
541                                                   case RPC_FC_LONG:  $$->type = RPC_FC_ULONG;  break;
542                                                   case RPC_FC_HYPER:
543                                                     if (!$$->ref) { $$->ref = &std_uhyper; $$->sign = 0; }
544                                                     break;
545                                                   default: break;
546                                                   }
547                                                 }
548         | tFLOAT                                { $$ = make_type(RPC_FC_FLOAT, NULL); }
549         | tDOUBLE                               { $$ = make_type(RPC_FC_DOUBLE, NULL); }
550         | tBOOLEAN                              { $$ = make_type(RPC_FC_BYTE, &std_bool); /* ? */ }
551         | tERRORSTATUST                         { $$ = make_type(RPC_FC_ERROR_STATUS_T, NULL); }
552         | tHANDLET                              { $$ = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ }
553         ;
554
555 m_int:
556         | tINT
557         ;
558
559 int_std:  tINT                                  { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */
560         | tSHORT m_int                          { $$ = make_type(RPC_FC_SHORT, NULL); }
561         | tLONG m_int                           { $$ = make_type(RPC_FC_LONG, NULL); }
562         | tHYPER m_int                          { $$ = make_type(RPC_FC_HYPER, NULL); }
563         | tINT64                                { $$ = make_type(RPC_FC_HYPER, &std_int64); }
564         | tCHAR                                 { $$ = make_type(RPC_FC_CHAR, NULL); }
565         ;
566
567 coclass:  tCOCLASS aIDENTIFIER                  { $$ = make_class($2); }
568         | tCOCLASS aKNOWNTYPE                   { $$ = make_class($2); }
569         ;
570
571 coclasshdr: attributes coclass                  { $$ = $2;
572                                                   $$->attrs = $1;
573                                                 }
574         ;
575
576 coclassdef: coclasshdr '{' coclass_ints '}'     { $$ = $1;
577                                                   $$->ifaces = $3;
578                                                 }
579         ;
580
581 coclass_ints:                                   { $$ = NULL; }
582         | coclass_ints coclass_int              { LINK($2, $1); $$ = $2; }
583         ;
584
585 coclass_int:
586           m_attributes interfacedec             { $$ = make_ifref($2); $$->attrs = $1; }
587         ;
588
589 dispinterface: tDISPINTERFACE aIDENTIFIER       { $$ = get_type(0, $2, 0); }
590         |      tDISPINTERFACE aKNOWNTYPE        { $$ = get_type(0, $2, 0); }
591         ;
592
593 dispinterfacehdr: attributes dispinterface      { $$ = $2;
594                                                   if ($$->defined) yyerror("multiple definition error\n");
595                                                   $$->attrs = $1;
596                                                 /*  $$->attrs = make_attr(ATTR_DISPINTERFACE); */
597                                                 /*  LINK($$->attrs, $1); */
598                                                   $$->ref = find_type("IDispatch", 0);
599                                                   if (!$$->ref) yyerror("IDispatch is undefined\n");
600                                                   $$->defined = TRUE;
601                                                   if (!parse_only) write_forward($$);
602                                                 }
603         ;
604
605 dispint_props: tPROPERTIES ':'                  { $$ = NULL; }
606         | dispint_props s_field ';'             { LINK($2, $1); $$ = $2; }
607         ;
608
609 dispint_meths: tMETHODS ':'                     { $$ = NULL; }
610         | dispint_meths funcdef ';'             { LINK($2, $1); $$ = $2; }
611         ;
612
613 dispinterfacedef: dispinterfacehdr '{'
614           dispint_props
615           dispint_meths
616           '}'                                   { $$ = $1;
617                                                   $$->fields = $3;
618                                                   $$->funcs = $4;
619                                                   if (!parse_only) write_interface($$);
620                                                 }
621 /* FIXME: not sure how to handle this yet
622         | dispinterfacehdr '{' interface '}'    { $$ = $1;
623                                                   if (!parse_only) write_interface($$);
624                                                 }
625 */
626         ;
627
628 inherit:                                        { $$ = NULL; }
629         | ':' aKNOWNTYPE                        { $$ = find_type2($2, 0); }
630         ;
631
632 interface: tINTERFACE aIDENTIFIER               { $$ = get_type(RPC_FC_IP, $2, 0); }
633         |  tINTERFACE aKNOWNTYPE                { $$ = get_type(RPC_FC_IP, $2, 0); }
634         ;
635
636 interfacehdr: attributes interface              { $$ = $2;
637                                                   if ($$->defined) yyerror("multiple definition error\n");
638                                                   $$->attrs = $1;
639                                                   $$->defined = TRUE;
640                                                   if (!parse_only) write_forward($$);
641                                                 }
642         ;
643
644 interfacedef: interfacehdr inherit
645           '{' int_statements '}'                { $$ = $1;
646                                                   $$->ref = $2;
647                                                   $$->funcs = $4;
648                                                   if (!parse_only) write_interface($$);
649                                                 }
650 /* MIDL is able to import the definition of a base class from inside the
651  * definition of a derived class, I'll try to support it with this rule */
652         | interfacehdr ':' aIDENTIFIER
653           '{' import int_statements '}'         { $$ = $1;
654                                                   $$->ref = find_type2($3, 0);
655                                                   if (!$$->ref) yyerror("base class %s not found in import\n", $3);
656                                                   $$->funcs = $6;
657                                                   if (!parse_only) write_interface($$);
658                                                 }
659         | dispinterfacedef                      { $$ = $1; }
660         ;
661
662 interfacedec:
663           interface ';'                         { $$ = $1; if (!parse_only) write_forward($$); }
664         | dispinterface ';'                     { $$ = $1; if (!parse_only) write_forward($$); }
665         ;
666
667 module:   tMODULE aIDENTIFIER                   { $$ = make_type(0, NULL); $$->name = $2; }
668         | tMODULE aKNOWNTYPE                    { $$ = make_type(0, NULL); $$->name = $2; }
669         ;
670
671 modulehdr: attributes module                    { $$ = $2;
672                                                   $$->attrs = $1;
673                                                 }
674         ;
675
676 moduledef: modulehdr '{' int_statements '}'     { $$ = $1;
677                                                   $$->funcs = $3;
678                                                   /* FIXME: if (!parse_only) write_module($$); */
679                                                 }
680         ;
681
682 p_ident:  '*' pident %prec PPTR                 { $$ = $2; $$->ptr_level++; }
683         | tCONST p_ident                        { $$ = $2; /* FIXME */ }
684         ;
685
686 pident:   ident
687         | p_ident
688         | '(' pident ')'                        { $$ = $2; }
689         ;
690
691 pident_list:
692           pident
693         | pident_list ',' pident                { LINK($3, $1); $$ = $3; }
694         ;
695
696 pointer_type:
697           tREF                                  { $$ = RPC_FC_RP; }
698         | tUNIQUE                               { $$ = RPC_FC_UP; }
699         ;
700
701 structdef: tSTRUCT t_ident '{' fields '}'       { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT);
702                                                   /* overwrite RPC_FC_STRUCT with a more exact type */
703                                                   $$->type = get_struct_type( $4 );
704                                                   $$->fields = $4;
705                                                   $$->defined = TRUE;
706                                                 }
707         ;
708
709 type:     tVOID                                 { $$ = make_tref(NULL, make_type(0, NULL)); }
710         | aKNOWNTYPE                            { $$ = make_tref($1, find_type($1, 0)); }
711         | base_type                             { $$ = make_tref(NULL, $1); }
712         | tCONST type                           { $$ = uniq_tref($2); $$->ref->is_const = TRUE; }
713         | enumdef                               { $$ = make_tref(NULL, $1); }
714         | tENUM aIDENTIFIER                     { $$ = make_tref(NULL, find_type2($2, tsENUM)); }
715         | structdef                             { $$ = make_tref(NULL, $1); }
716         | tSTRUCT aIDENTIFIER                   { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); }
717         | uniondef                              { $$ = make_tref(NULL, $1); }
718         | tUNION aIDENTIFIER                    { $$ = make_tref(NULL, find_type2($2, tsUNION)); }
719         ;
720
721 typedef: tTYPEDEF m_attributes type pident_list { typeref_t *tref = uniq_tref($3);
722                                                   $4->tname = tref->name;
723                                                   tref->name = NULL;
724                                                   $$ = type_ref(tref);
725                                                   $$->attrs = $2;
726                                                   if (!parse_only) write_typedef($$, $4);
727                                                   reg_types($$, $4, 0);
728                                                 }
729         ;
730
731 uniondef: tUNION t_ident '{' fields '}'         { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
732                                                   $$->fields = $4;
733                                                   $$->defined = TRUE;
734                                                 }
735         | tUNION t_ident
736           tSWITCH '(' s_field ')'
737           m_ident '{' cases '}'                 { var_t *u = $7;
738                                                   $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
739                                                   if (!u) u = make_var("tagged_union");
740                                                   u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
741                                                   u->type->fields = $9;
742                                                   u->type->defined = TRUE;
743                                                   LINK(u, $5); $$->fields = u;
744                                                   $$->defined = TRUE;
745                                                 }
746         ;
747
748 version:
749           aNUM                                  { $$ = MAKELONG($1, 0); }
750         | aNUM '.' aNUM                         { $$ = MAKELONG($1, $3); }
751         ;
752
753 %%
754
755 static attr_t *make_attr(enum attr_type type)
756 {
757   attr_t *a = xmalloc(sizeof(attr_t));
758   a->type = type;
759   a->u.ival = 0;
760   INIT_LINK(a);
761   return a;
762 }
763
764 static attr_t *make_attrv(enum attr_type type, unsigned long val)
765 {
766   attr_t *a = xmalloc(sizeof(attr_t));
767   a->type = type;
768   a->u.ival = val;
769   INIT_LINK(a);
770   return a;
771 }
772
773 static attr_t *make_attrp(enum attr_type type, void *val)
774 {
775   attr_t *a = xmalloc(sizeof(attr_t));
776   a->type = type;
777   a->u.pval = val;
778   INIT_LINK(a);
779   return a;
780 }
781
782 static expr_t *make_expr(enum expr_type type)
783 {
784   expr_t *e = xmalloc(sizeof(expr_t));
785   e->type = type;
786   e->ref = NULL;
787   e->u.lval = 0;
788   e->is_const = FALSE;
789   INIT_LINK(e);
790   return e;
791 }
792
793 static expr_t *make_exprl(enum expr_type type, long val)
794 {
795   expr_t *e = xmalloc(sizeof(expr_t));
796   e->type = type;
797   e->ref = NULL;
798   e->u.lval = val;
799   e->is_const = FALSE;
800   INIT_LINK(e);
801   /* check for numeric constant */
802   if (type == EXPR_NUM || type == EXPR_HEXNUM) {
803     e->is_const = TRUE;
804     e->cval = val;
805   }
806   return e;
807 }
808
809 static expr_t *make_exprs(enum expr_type type, char *val)
810 {
811   expr_t *e;
812   e = xmalloc(sizeof(expr_t));
813   e->type = type;
814   e->ref = NULL;
815   e->u.sval = val;
816   e->is_const = FALSE;
817   INIT_LINK(e);
818   /* check for predefined constants */
819   if (type == EXPR_IDENTIFIER) {
820     var_t *c = find_const(val, 0);
821     if (c) {
822       e->u.sval = c->name;
823       free(val);
824       e->is_const = TRUE;
825       e->cval = c->lval;
826     }
827   }
828   return e;
829 }
830
831 static expr_t *make_exprt(enum expr_type type, typeref_t *tref, expr_t *expr)
832 {
833   expr_t *e;
834   e = xmalloc(sizeof(expr_t));
835   e->type = type;
836   e->ref = expr;
837   e->u.tref = tref;
838   e->is_const = FALSE;
839   INIT_LINK(e);
840   /* check for cast of constant expression */
841   if (type == EXPR_CAST && expr->is_const) {
842     e->is_const = TRUE;
843     e->cval = expr->cval;
844   }
845   return e;
846 }
847
848 static expr_t *make_expr1(enum expr_type type, expr_t *expr)
849 {
850   expr_t *e;
851   e = xmalloc(sizeof(expr_t));
852   e->type = type;
853   e->ref = expr;
854   e->u.lval = 0;
855   e->is_const = FALSE;
856   INIT_LINK(e);
857   /* check for compile-time optimization */
858   if (expr->is_const) {
859     e->is_const = TRUE;
860     switch (type) {
861     case EXPR_NEG:
862       e->cval = -expr->cval;
863       break;
864     case EXPR_NOT:
865       e->cval = ~expr->cval;
866       break;
867     default:
868       e->is_const = FALSE;
869       break;
870     }
871   }
872   return e;
873 }
874
875 static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2)
876 {
877   expr_t *e;
878   e = xmalloc(sizeof(expr_t));
879   e->type = type;
880   e->ref = expr1;
881   e->u.ext = expr2;
882   e->is_const = FALSE;
883   INIT_LINK(e);
884   /* check for compile-time optimization */
885   if (expr1->is_const && expr2->is_const) {
886     e->is_const = TRUE;
887     switch (type) {
888     case EXPR_ADD:
889       e->cval = expr1->cval + expr2->cval;
890       break;
891     case EXPR_SUB:
892       e->cval = expr1->cval - expr2->cval;
893       break;
894     case EXPR_MUL:
895       e->cval = expr1->cval * expr2->cval;
896       break;
897     case EXPR_DIV:
898       e->cval = expr1->cval / expr2->cval;
899       break;
900     case EXPR_OR:
901       e->cval = expr1->cval | expr2->cval;
902       break;
903     case EXPR_AND:
904       e->cval = expr1->cval & expr2->cval;
905       break;
906     case EXPR_SHL:
907       e->cval = expr1->cval << expr2->cval;
908       break;
909     case EXPR_SHR:
910       e->cval = expr1->cval >> expr2->cval;
911       break;
912     default:
913       e->is_const = FALSE;
914       break;
915     }
916   }
917   return e;
918 }
919
920 static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3)
921 {
922   expr_t *e;
923   e = xmalloc(sizeof(expr_t));
924   e->type = type;
925   e->ref = expr1;
926   e->u.ext = expr2;
927   e->ext2 = expr3;
928   e->is_const = FALSE;
929   INIT_LINK(e);
930   /* check for compile-time optimization */
931   if (expr1->is_const && expr2->is_const && expr3->is_const) {
932     e->is_const = TRUE;
933     switch (type) {
934     case EXPR_COND:
935       e->cval = expr1->cval ? expr2->cval : expr3->cval;
936       break;
937     default:
938       e->is_const = FALSE;
939       break;
940     }
941   }
942   return e;
943 }
944
945 static type_t *make_type(unsigned char type, type_t *ref)
946 {
947   type_t *t = xmalloc(sizeof(type_t));
948   t->name = NULL;
949   t->type = type;
950   t->ref = ref;
951   t->rname = NULL;
952   t->attrs = NULL;
953   t->funcs = NULL;
954   t->fields = NULL;
955   t->ignore = parse_only;
956   t->is_const = FALSE;
957   t->sign = 0;
958   t->defined = FALSE;
959   t->written = FALSE;
960   INIT_LINK(t);
961   return t;
962 }
963
964 static typeref_t *make_tref(char *name, type_t *ref)
965 {
966   typeref_t *t = xmalloc(sizeof(typeref_t));
967   t->name = name;
968   t->ref = ref;
969   t->uniq = ref ? 0 : 1;
970   return t;
971 }
972
973 static typeref_t *uniq_tref(typeref_t *ref)
974 {
975   typeref_t *t = ref;
976   type_t *tp;
977   if (t->uniq) return t;
978   tp = make_type(0, t->ref);
979   tp->name = t->name;
980   t->name = NULL;
981   t->ref = tp;
982   t->uniq = 1;
983   return t;
984 }
985
986 static type_t *type_ref(typeref_t *ref)
987 {
988   type_t *t = ref->ref;
989   if (ref->name) free(ref->name);
990   free(ref);
991   return t;
992 }
993
994 static void set_type(var_t *v, typeref_t *ref, expr_t *arr)
995 {
996   v->type = ref->ref;
997   v->tname = ref->name;
998   ref->name = NULL;
999   free(ref);
1000   v->array = arr;
1001 }
1002
1003 static ifref_t *make_ifref(type_t *iface)
1004 {
1005   ifref_t *l = xmalloc(sizeof(ifref_t));
1006   l->iface = iface;
1007   l->attrs = NULL;
1008   INIT_LINK(l);
1009   return l;
1010 }
1011
1012 static var_t *make_var(char *name)
1013 {
1014   var_t *v = xmalloc(sizeof(var_t));
1015   v->name = name;
1016   v->ptr_level = 0;
1017   v->type = NULL;
1018   v->tname = NULL;
1019   v->attrs = NULL;
1020   v->array = NULL;
1021   v->eval = NULL;
1022   v->lval = 0;
1023   INIT_LINK(v);
1024   return v;
1025 }
1026
1027 static func_t *make_func(var_t *def, var_t *args)
1028 {
1029   func_t *f = xmalloc(sizeof(func_t));
1030   f->def = def;
1031   f->args = args;
1032   f->ignore = parse_only;
1033   f->idx = -1;
1034   INIT_LINK(f);
1035   return f;
1036 }
1037
1038 static class_t *make_class(char *name)
1039 {
1040   class_t *c = xmalloc(sizeof(class_t));
1041   c->name = name;
1042   c->attrs = NULL;
1043   c->ifaces = NULL;
1044   INIT_LINK(c);
1045   return c;
1046 }
1047
1048 #define HASHMAX 64
1049
1050 static int hash_ident(const char *name)
1051 {
1052   const char *p = name;
1053   int sum = 0;
1054   /* a simple sum hash is probably good enough */
1055   while (*p) {
1056     sum += *p;
1057     p++;
1058   }
1059   return sum & (HASHMAX-1);
1060 }
1061
1062 /***** type repository *****/
1063
1064 struct rtype {
1065   char *name;
1066   type_t *type;
1067   int t;
1068   struct rtype *next;
1069 };
1070
1071 struct rtype *type_hash[HASHMAX];
1072
1073 static type_t *reg_type(type_t *type, char *name, int t)
1074 {
1075   struct rtype *nt;
1076   int hash;
1077   if (!name) {
1078     yyerror("registering named type without name\n");
1079     return type;
1080   }
1081   hash = hash_ident(name);
1082   nt = xmalloc(sizeof(struct rtype));
1083   nt->name = name;
1084   nt->type = type;
1085   nt->t = t;
1086   nt->next = type_hash[hash];
1087   type_hash[hash] = nt;
1088   return type;
1089 }
1090
1091 /* determine pointer type from attrs */
1092 static unsigned char get_pointer_type( type_t *type )
1093 {
1094   int t;
1095   if (is_attr( type->attrs, ATTR_STRING ))
1096   {
1097     type_t *t = type;
1098     while( t->type == 0 && t->ref )
1099       t = t->ref;
1100     switch( t->type )
1101     {
1102     case RPC_FC_CHAR:
1103       return RPC_FC_C_CSTRING;
1104     case RPC_FC_WCHAR:
1105       return RPC_FC_C_WSTRING;
1106     }
1107   }
1108   t = get_attrv( type->attrs, ATTR_POINTERTYPE );
1109   if (t) return t;
1110   return RPC_FC_FP;
1111 }
1112
1113 static type_t *reg_types(type_t *type, var_t *names, int t)
1114 {
1115   type_t *ptr = type;
1116   int ptrc = 0;
1117
1118   while (names) {
1119     var_t *next = NEXT_LINK(names);
1120     if (names->name) {
1121       type_t *cur = ptr;
1122       int cptr = names->ptr_level;
1123       if (cptr > ptrc) {
1124         while (cptr > ptrc) {
1125           int t = get_pointer_type( cur );
1126           cur = ptr = make_type(t, cur);
1127           ptrc++;
1128         }
1129       } else {
1130         while (cptr < ptrc) {
1131           cur = cur->ref;
1132           cptr++;
1133         }
1134       }
1135       reg_type(cur, names->name, t);
1136     }
1137     free(names);
1138     names = next;
1139   }
1140   return type;
1141 }
1142
1143 static type_t *find_type(char *name, int t)
1144 {
1145   struct rtype *cur = type_hash[hash_ident(name)];
1146   while (cur && (cur->t != t || strcmp(cur->name, name)))
1147     cur = cur->next;
1148   if (!cur) {
1149     yyerror("type %s not found\n", name);
1150     return NULL;
1151   }
1152   return cur->type;
1153 }
1154
1155 static type_t *find_type2(char *name, int t)
1156 {
1157   type_t *tp = find_type(name, t);
1158   free(name);
1159   return tp;
1160 }
1161
1162 int is_type(const char *name)
1163 {
1164   struct rtype *cur = type_hash[hash_ident(name)];
1165   while (cur && (cur->t || strcmp(cur->name, name)))
1166     cur = cur->next;
1167   if (cur) return TRUE;
1168   return FALSE;
1169 }
1170
1171 static type_t *get_type(unsigned char type, char *name, int t)
1172 {
1173   struct rtype *cur = NULL;
1174   type_t *tp;
1175   if (name) {
1176     cur = type_hash[hash_ident(name)];
1177     while (cur && (cur->t != t || strcmp(cur->name, name)))
1178       cur = cur->next;
1179   }
1180   if (cur) {
1181     free(name);
1182     return cur->type;
1183   }
1184   tp = make_type(type, NULL);
1185   tp->name = name;
1186   if (!name) return tp;
1187   return reg_type(tp, name, t);
1188 }
1189
1190 static type_t *get_typev(unsigned char type, var_t *name, int t)
1191 {
1192   char *sname = NULL;
1193   if (name) {
1194     sname = name->name;
1195     free(name);
1196   }
1197   return get_type(type, sname, t);
1198 }
1199
1200 static int get_struct_type(var_t *field)
1201 {
1202   int has_pointer = 0;
1203   int has_conformant_array = 0;
1204   int has_conformant_string = 0;
1205
1206   while (field)
1207   {
1208     type_t *t = field->type;
1209
1210     /* get the base type */
1211     while( (t->type == 0) && t->ref )
1212       t = t->ref;
1213
1214     switch (t->type)
1215     {
1216     /*
1217      * RPC_FC_BYTE, RPC_FC_STRUCT, etc
1218      *  Simple types don't effect the type of struct.
1219      *  A struct containing a simple struct is still a simple struct.
1220      *  So long as we can block copy the data, we return RPC_FC_STRUCT.
1221      */
1222     case 0: /* void pointer */
1223     case RPC_FC_BYTE:
1224     case RPC_FC_CHAR:
1225     case RPC_FC_SMALL:
1226     case RPC_FC_USMALL:
1227     case RPC_FC_WCHAR:
1228     case RPC_FC_SHORT:
1229     case RPC_FC_USHORT:
1230     case RPC_FC_LONG:
1231     case RPC_FC_ULONG:
1232     case RPC_FC_INT3264:
1233     case RPC_FC_UINT3264:
1234     case RPC_FC_HYPER:
1235     case RPC_FC_FLOAT:
1236     case RPC_FC_DOUBLE:
1237     case RPC_FC_STRUCT:
1238     case RPC_FC_ENUM16:
1239     case RPC_FC_ENUM32:
1240       break;
1241
1242     case RPC_FC_UP:
1243     case RPC_FC_FP:
1244       has_pointer = 1;
1245       break;
1246     case RPC_FC_CARRAY:
1247       has_conformant_array = 1;
1248       break;
1249     case RPC_FC_C_CSTRING:
1250     case RPC_FC_C_WSTRING:
1251       has_conformant_string = 1;
1252       break;
1253
1254     /*
1255      * Propagate member attributes
1256      *  a struct should be at least as complex as its member
1257      */
1258     case RPC_FC_CVSTRUCT:
1259       has_conformant_string = 1;
1260       has_pointer = 1;
1261       break;
1262
1263     case RPC_FC_CPSTRUCT:
1264       has_conformant_array = 1;
1265       has_pointer = 1;
1266       break;
1267
1268     case RPC_FC_CSTRUCT:
1269       has_conformant_array = 1;
1270       break;
1271
1272     case RPC_FC_PSTRUCT:
1273       has_pointer = 1;
1274       break;
1275
1276     default:
1277       fprintf(stderr,"Unknown struct member %s with type (0x%02x)\n",
1278               field->name, t->type);
1279       /* fallthru - treat it as complex */
1280
1281     /* as soon as we see one of these these members, it's bogus... */
1282     case RPC_FC_IP:
1283     case RPC_FC_ENCAPSULATED_UNION:
1284     case RPC_FC_NON_ENCAPSULATED_UNION:
1285     case RPC_FC_TRANSMIT_AS:
1286     case RPC_FC_REPRESENT_AS:
1287     case RPC_FC_PAD:
1288     case RPC_FC_EMBEDDED_COMPLEX:
1289     case RPC_FC_BOGUS_STRUCT:
1290       return RPC_FC_BOGUS_STRUCT;
1291     }
1292     field = NEXT_LINK(field);
1293   }
1294
1295   if( has_conformant_string && has_pointer )
1296     return RPC_FC_CVSTRUCT;
1297   if( has_conformant_array && has_pointer )
1298     return RPC_FC_CPSTRUCT;
1299   if( has_conformant_array )
1300     return RPC_FC_CSTRUCT;
1301   if( has_pointer )
1302     return RPC_FC_PSTRUCT;
1303   return RPC_FC_STRUCT;
1304 }
1305
1306 /***** constant repository *****/
1307
1308 struct rconst {
1309   char *name;
1310   var_t *var;
1311   struct rconst *next;
1312 };
1313
1314 struct rconst *const_hash[HASHMAX];
1315
1316 static var_t *reg_const(var_t *var)
1317 {
1318   struct rconst *nc;
1319   int hash;
1320   if (!var->name) {
1321     yyerror("registering constant without name\n");
1322     return var;
1323   }
1324   hash = hash_ident(var->name);
1325   nc = xmalloc(sizeof(struct rconst));
1326   nc->name = var->name;
1327   nc->var = var;
1328   nc->next = const_hash[hash];
1329   const_hash[hash] = nc;
1330   return var;
1331 }
1332
1333 static var_t *find_const(char *name, int f)
1334 {
1335   struct rconst *cur = const_hash[hash_ident(name)];
1336   while (cur && strcmp(cur->name, name))
1337     cur = cur->next;
1338   if (!cur) {
1339     if (f) yyerror("constant %s not found\n", name);
1340     return NULL;
1341   }
1342   return cur->var;
1343 }