1 /***************************************************************************
2 
3     parser.y (IDL yacc parser and tree generation)
4 
5     Copyright (C) 1998, 1999 Andrew T. Veliath
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 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     Library General Public License for more details.
16 
17     You should have received a copy of the GNU Library General Public
18     License along with this library; if not, write to the Free
19     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21     $Id: parser.y,v 1.163 2004/11/12 15:37:11 michael Exp $
22 
23 ***************************************************************************/
24 %{
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <errno.h>
32 #include "rename.h"
33 #include "util.h"
34 
35 #define REF_IDENTS
36 
37 #define do_binop(rv,op,a,b)		do {		\
38 	if (IDL_binop_chktypes (op, a, b))		\
39 		YYABORT;				\
40 	if (!(__IDL_flags & IDLF_NO_EVAL_CONST)) {	\
41 		rv = IDL_binop_eval (op, a, b);		\
42 		IDL_tree_free (a);			\
43 		IDL_tree_free (b);			\
44 		if (!rv) YYABORT;			\
45 	} else {					\
46 		rv = IDL_binop_new (op, a, b);		\
47 	}						\
48 } while (0)
49 
50 #define do_unaryop(rv,op,a)		do {		\
51 	if (IDL_unaryop_chktypes (op, a))		\
52 		YYABORT;				\
53 	if (!(__IDL_flags & IDLF_NO_EVAL_CONST)) {	\
54 		rv = IDL_unaryop_eval (op, a);		\
55 		IDL_tree_free (a);			\
56 		if (!rv) YYABORT;			\
57 	} else {					\
58 		rv = IDL_unaryop_new (op, a);		\
59 	}						\
60 } while (0)
61 
62 #define IS_INHIBIT_STATE()				\
63 	(__IDL_inhibits > 0 ||				\
64 	  ((__IDL_flags & IDLF_INHIBIT_INCLUDES) &&	\
65 	     (__IDL_flagsi & IDLFP_IN_INCLUDES) ) )
66 
67 
68 #define assign_declspec(tree,declspec)	do {		\
69 	IDL_NODE_DECLSPEC (tree) = declspec;		\
70 	if ( IS_INHIBIT_STATE() ) {			\
71 		IDL_NODE_DECLSPEC (tree) |=		\
72 			IDLF_DECLSPEC_EXIST |		\
73 			IDLF_DECLSPEC_INHIBIT;		\
74 	}						\
75 	if ( __IDL_pidl > 0 ) {				\
76 		IDL_NODE_DECLSPEC (tree) |=		\
77 			IDLF_DECLSPEC_PIDL;		\
78 	}						\
79 } while (0)
80 
81 #define assign_props(tree,props)	do {		\
82 	if (__IDL_flags & IDLF_PROPERTIES)		\
83 		IDL_NODE_PROPERTIES (tree) = (props);	\
84 	else						\
85 		__IDL_free_properties (props);		\
86 } while (0)
87 
88 extern int		yylex				(void);
89 static IDL_declspec_t	IDL_parse_declspec		(const char *strspec);
90 static int		IDL_binop_chktypes		(enum IDL_binop op,
91 							 IDL_tree a,
92 							 IDL_tree b);
93 static int		IDL_unaryop_chktypes		(enum IDL_unaryop op,
94 							 IDL_tree a);
95 static IDL_tree		IDL_binop_eval			(enum IDL_binop op,
96 							 IDL_tree a,
97 							 IDL_tree b);
98 static IDL_tree		IDL_unaryop_eval		(enum IDL_unaryop op,
99 							 IDL_tree a);
100 static IDL_tree		list_start			(IDL_tree a,
101 							 gboolean filter_null);
102 static IDL_tree		list_chain			(IDL_tree a,
103 							 IDL_tree b,
104 							 gboolean filter_null);
105 static IDL_tree		zlist_chain			(IDL_tree a,
106 							 IDL_tree b,
107 							 gboolean filter_null);
108 static int		do_token_error			(IDL_tree p,
109 							 const char *message,
110 							 gboolean prev);
111 static void		illegal_context_type_error	(IDL_tree p,
112 							 const char *what);
113 static void		illegal_type_error		(IDL_tree p,
114 							 const char *message);
115 %}
116 
117 %union {
118 	IDL_tree tree;
119 	struct {
120 		IDL_tree tree;
121 		gpointer data;
122 	} treedata;
123 	GHashTable *hash_table;
124 	char *str;
125 	gboolean boolean;
126 	IDL_declspec_t declspec;
127 	IDL_longlong_t integer;
128 	double floatp;
129 	enum IDL_unaryop unaryop;
130 	enum IDL_param_attr paramattr;
131 }
132 
133 /* Terminals */
134 %token			TOK_ANY
135 %token			TOK_ATTRIBUTE
136 %token			TOK_BOOLEAN
137 %token			TOK_CASE
138 %token			TOK_CHAR
139 %token			TOK_CONST
140 %token			TOK_CONTEXT
141 %token			TOK_DEFAULT
142 %token			TOK_DOUBLE
143 %token			TOK_ENUM
144 %token			TOK_EXCEPTION
145 %token			TOK_FALSE
146 %token			TOK_FIXED
147 %token			TOK_FLOAT
148 %token			TOK_IN
149 %token			TOK_INOUT
150 %token			TOK_INTERFACE
151 %token			TOK_LONG
152 %token			TOK_MODULE
153 %token			TOK_NATIVE
154 %token			TOK_OBJECT
155 %token			TOK_OCTET
156 %token			TOK_ONEWAY
157 %token			TOK_OP_SCOPE
158 %token			TOK_OP_SHL
159 %token			TOK_OP_SHR
160 %token			TOK_OUT
161 %token			TOK_RAISES
162 %token			TOK_READONLY
163 %token			TOK_SEQUENCE
164 %token			TOK_SHORT
165 %token			TOK_STRING
166 %token			TOK_STRUCT
167 %token			TOK_SWITCH
168 %token			TOK_TRUE
169 %token			TOK_TYPECODE
170 %token			TOK_TYPEDEF
171 %token			TOK_UNION
172 %token			TOK_UNSIGNED
173 %token			TOK_VARARGS
174 %token			TOK_VOID
175 %token			TOK_WCHAR
176 %token			TOK_WSTRING
177 %token <floatp>		TOK_FLOATP
178 %token <integer>	TOK_INTEGER
179 %token <str>		TOK_DECLSPEC TOK_PROP_KEY
180 %token <str>		TOK_PROP_VALUE TOK_NATIVE_TYPE
181 %token <str>		TOK_IDENT TOK_SQSTRING TOK_DQSTRING TOK_FIXEDP
182 %token <tree>		TOK_CODEFRAG
183 %token <tree>		TOK_SRCFILE
184 
185 /* Non-Terminals */
186 %type <tree>		add_expr
187 %type <tree>		and_expr
188 %type <tree>		any_type
189 %type <tree>		array_declarator
190 %type <tree>		attr_dcl
191 %type <tree>		attr_dcl_def
192 %type <tree>		base_type_spec
193 %type <tree>		boolean_lit
194 %type <tree>		boolean_type
195 %type <tree>		case_label
196 %type <tree>		case_label_list
197 %type <tree>		case_stmt
198 %type <tree>		case_stmt_list
199 %type <tree>		char_lit
200 %type <tree>		char_type
201 %type <tree>		codefrag
202 %type <tree>		complex_declarator
203 %type <tree>		const_dcl
204 %type <tree>		const_dcl_def
205 %type <tree>		const_exp
206 %type <tree>		const_type
207 %type <tree>		constr_type_spec
208 %type <tree>		context_expr
209 %type <tree>		cur_ns_new_or_prev_ident
210 %type <tree>		declarator
211 %type <tree>		declarator_list
212 %type <tree>		definition
213 %type <tree>		definition_list
214 %type <tree>		element_spec
215 %type <tree>		enum_type
216 %type <tree>		enumerator_list
217 %type <tree>		except_dcl
218 %type <tree>		except_dcl_def
219 %type <tree>		export
220 %type <tree>		export_list
221 %type <tree>		fixed_array_size
222 %type <tree>		fixed_array_size_list
223 %type <tree>		fixed_pt_const_type
224 %type <tree>		fixed_pt_lit
225 %type <tree>		fixed_pt_type
226 %type <tree>		floating_pt_lit
227 %type <tree>		floating_pt_type
228 %type <tree>		ident
229 %type <tree>		illegal_ident
230 %type <tree>		integer_lit
231 %type <tree>		integer_type
232 %type <tree>		interface
233 %type <tree>		interface_body
234 %type <tree>		interface_catch_ident
235 %type <tree>		is_context_expr
236 %type <tree>		is_raises_expr
237 %type <tree>		literal
238 %type <tree>		member
239 %type <tree>		member_list
240 %type <tree>		member_zlist
241 %type <tree>		module
242 %type <tree>		mult_expr
243 %type <tree>		new_ident
244 %type <tree>		new_or_prev_scope
245 %type <tree>		new_scope
246 %type <tree>		ns_global_ident
247 %type <tree>		ns_new_ident
248 %type <tree>		ns_prev_ident
249 %type <tree>		ns_scoped_name
250 %type <tree>		object_type
251 %type <tree>		octet_type
252 %type <tree>		op_dcl
253 %type <tree>		op_dcl_def
254 %type <tree>		op_param_type_spec
255 %type <tree>		op_param_type_spec_illegal
256 %type <tree>		op_type_spec
257 %type <tree>		or_expr
258 %type <tree>		param_dcl
259 %type <tree>		param_dcl_list
260 %type <tree>		param_type_spec
261 %type <tree>		pop_scope
262 %type <tree>		positive_int_const
263 %type <tree>		primary_expr
264 %type <tree>		raises_expr
265 %type <tree>		scoped_name
266 %type <tree>		scoped_name_list
267 %type <tree>		sequence_type
268 %type <tree>		shift_expr
269 %type <tree>		simple_declarator
270 %type <tree>		simple_declarator_list
271 %type <tree>		simple_type_spec
272 %type <tree>		specification
273 %type <tree>		srcfile
274 %type <tree>		string_lit
275 %type <tree>		string_lit_list
276 %type <tree>		string_type
277 %type <tree>		struct_type
278 %type <tree>		switch_body
279 %type <tree>		switch_type_spec
280 %type <tree>		template_type_spec
281 %type <tree>		type_dcl
282 %type <tree>		type_dcl_def
283 %type <tree>		type_declarator
284 %type <tree>		type_spec
285 %type <tree>		unary_expr
286 %type <tree>		union_type
287 %type <tree>		useless_semicolon
288 %type <tree>		wide_char_type
289 %type <tree>		wide_string_type
290 %type <tree>		xor_expr
291 %type <tree>		z_definition_list
292 %type <tree>		z_inheritance
293 %type <tree>		z_new_ident_catch
294 %type <tree>		z_new_scope_catch
295 %type <tree>		typecode_type
296 
297 %type <treedata>	parameter_dcls
298 %type <declspec>	z_declspec module_declspec
299 %type <hash_table>	z_props prop_hash
300 %type <boolean>		is_readonly is_oneway
301 %type <boolean>		is_varargs is_cvarargs
302 %type <integer>		signed_int unsigned_int
303 %type <paramattr>	param_attribute
304 %type <str>		sqstring dqstring dqstring_cat
305 %type <unaryop>		unary_op
306 
307 %%
308 
309 specification:		/* empty */			{ yyerror ("Empty file"); YYABORT; }
310 |			definition_list			{ __IDL_root = $1; }
311 	;
312 
313 z_definition_list:	/* empty */			{ $$ = NULL; }
314 |			definition_list
315 	;
316 
317 definition_list:	definition			{ $$ = list_start ($1, TRUE); }
318 |			definition_list definition	{ $$ = list_chain ($1, $2, TRUE); }
319 	;
320 
321 check_semicolon:	';'
322 |			/* empty */			{
323 	if (do_token_error ($<tree>0, "Missing semicolon after", TRUE))
324 		YYABORT;
325 }
326 	;
327 
328 useless_semicolon:	';'				{
329 	yyerror ("Dangling semicolon has no effect");
330 	$$ = NULL;
331 }
332 	;
333 
334 check_comma:		','
335 |			/* empty */			{
336 	if (do_token_error ($<tree>0, "Missing comma after", TRUE))
337 		YYABORT;
338 }
339 	;
340 
341 illegal_ident:		scoped_name			{
342 	if (IDL_NODE_UP ($1))
343 		do_token_error (IDL_NODE_UP ($1), "Illegal context for", FALSE);
344 	else
345 		yyerror ("Illegal context for identifier");
346 	YYABORT;
347 }
348 	;
349 
350 definition:		type_dcl check_semicolon
351 |			const_dcl check_semicolon
352 |			except_dcl check_semicolon
353 |			interface check_semicolon
354 |			module check_semicolon
355 |			codefrag
356 |			srcfile
357 |			illegal_ident
358 |			useless_semicolon
359 	;
360 
361 module_declspec:	z_declspec TOK_MODULE
362 	;
363 
364 module:			module_declspec
365 			new_or_prev_scope		{
366 	if (IDL_NODE_UP ($2) != NULL &&
367 	    IDL_NODE_TYPE (IDL_NODE_UP ($2)) != IDLN_MODULE) {
368 		yyerror ("Module definition conflicts");
369 		do_token_error (IDL_NODE_UP ($2), "with", FALSE);
370 		YYABORT;
371 	}
372 }			'{'
373 				z_definition_list
374 			'}' pop_scope			{
375 	IDL_tree module;
376 
377 	if ($5 == NULL) {
378 		yyerrorv ("Empty module declaration `%s' is not legal IDL",
379 			  IDL_IDENT ($2).str);
380 		module = NULL;
381 	}
382 
383 	if (__IDL_flags & IDLF_COMBINE_REOPENED_MODULES) {
384 		if (IDL_NODE_UP ($2) == NULL)
385 			module = IDL_module_new ($2, $5);
386 		else {
387 			module = IDL_NODE_UP ($2);
388 			IDL_MODULE (module).definition_list =
389 				IDL_list_concat (IDL_MODULE (module).definition_list, $5);
390 			module = NULL;
391 		}
392 	} else
393 		module = IDL_module_new ($2, $5);
394 
395 	$$ = module;
396 	if ($$) assign_declspec ($$, $1);
397 }
398 	;
399 
400 /* We only catch these errors for non-pidl because we want to be able to compile
401    the OMG CORBA .idl files which define interfaces by these names */
402 interface_catch_ident:	new_or_prev_scope
403 |			TOK_OBJECT			{
404 	yyerror ("Interfaces cannot be named `Object'");
405 	YYABORT;
406 }
407 |			TOK_TYPECODE			{
408 	yyerror ("Interfaces cannot be named `TypeCode'");
409 	YYABORT;
410 }
411 	;
412 
413 interface:		z_declspec
414 			z_props
415 			TOK_INTERFACE
416 			interface_catch_ident		{
417 	assert ($4 != NULL);
418 	assert (IDL_NODE_TYPE ($4) == IDLN_IDENT);
419 	assert (IDL_IDENT_TO_NS ($4) != NULL);
420 	assert (IDL_NODE_TYPE (IDL_IDENT_TO_NS ($4)) == IDLN_GENTREE);
421 
422 	if (IDL_NODE_UP ($4) != NULL &&
423 	    IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_INTERFACE &&
424 	    IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_FORWARD_DCL) {
425 		yyerrorl ("Interface definition conflicts",
426 			  __IDL_prev_token_line - __IDL_cur_token_line);
427 		do_token_error (IDL_NODE_UP ($4), "with", FALSE);
428 		YYABORT;
429 	} else if (IDL_NODE_UP ($4) != NULL &&
430 		   IDL_NODE_TYPE (IDL_NODE_UP ($4)) != IDLN_FORWARD_DCL) {
431 		yyerrorv ("Cannot redeclare interface `%s'", IDL_IDENT ($4).str);
432 		IDL_tree_error ($4, "Previous declaration of interface `%s'", IDL_IDENT ($4).str);
433 		YYABORT;
434 	} else if (IDL_NODE_UP ($4) != NULL &&
435 		   IDL_NODE_TYPE (IDL_NODE_UP ($4)) == IDLN_FORWARD_DCL)
436 		__IDL_assign_this_location ($4, __IDL_cur_filename, __IDL_cur_line);
437 }
438 			pop_scope
439 			z_inheritance			{
440 	IDL_GENTREE (IDL_IDENT_TO_NS ($4))._import = $7;
441 	IDL_ns_push_scope (__IDL_root_ns, IDL_IDENT_TO_NS ($4));
442 	if (IDL_ns_check_for_ambiguous_inheritance ($4, $7))
443 		__IDL_is_okay = FALSE;
444 }			'{'
445 				interface_body
446 			'}' pop_scope			{
447  	$$ = IDL_interface_new ($4, $7, $10);
448 	assign_declspec ($$, $1);
449 	assign_props (IDL_INTERFACE ($$).ident, $2);
450 }
451 |			z_declspec
452 			z_props
453 			TOK_INTERFACE
454 			interface_catch_ident
455 			pop_scope			{
456 	if ($2) yywarningv (IDL_WARNING1,
457 			    "Ignoring properties for forward declaration `%s'",
458 			    IDL_IDENT ($4).str);
459 	$$ = IDL_forward_dcl_new ($4);
460 	assign_declspec ($$, $1);
461 }
462 	;
463 
464 z_inheritance:		/* empty */			{ $$ = NULL; }
465 |			':' scoped_name_list		{
466 	GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal);
467 	gboolean die = FALSE;
468 	IDL_tree p = $2;
469 
470 	assert (IDL_NODE_TYPE (p) == IDLN_LIST);
471 	for (; p != NULL && !die; p = IDL_LIST (p).next) {
472 		assert (IDL_LIST (p).data != NULL);
473 		assert (IDL_NODE_TYPE (IDL_LIST (p).data) == IDLN_IDENT);
474 
475 		if (g_hash_table_lookup_extended (table, IDL_LIST (p).data, NULL, NULL)) {
476 			char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0);
477 			yyerrorv ("Cannot inherit from interface `%s' more than once", s);
478 			g_free (s);
479 			die = TRUE;
480 			break;
481 		} else
482 			g_hash_table_insert (table, IDL_LIST (p).data, NULL);
483 
484 		if (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (p).data)) == IDLN_FORWARD_DCL) {
485 			char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0);
486 			yyerrorv ("Incomplete definition of interface `%s'", s);
487 			IDL_tree_error (IDL_LIST (p).data,
488 					"Previous forward declaration of `%s'", s);
489 			g_free (s);
490 			die = TRUE;
491 		}
492 		else if (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (p).data)) != IDLN_INTERFACE) {
493 			char *s = IDL_ns_ident_to_qstring (IDL_LIST (p).data, "::", 0);
494 			yyerrorv ("`%s' is not an interface", s);
495 			IDL_tree_error (IDL_LIST (p).data,
496 					"Previous declaration of `%s'", s);
497 			g_free (s);
498 			die = TRUE;
499 		}
500 	}
501 
502 	g_hash_table_destroy (table);
503 
504 	if (die)
505 		YYABORT;
506 
507 	$$ = $2;
508 }
509 	;
510 
511 scoped_name_list:	scoped_name			{ $$ = list_start ($1, TRUE); }
512 |			scoped_name_list
513 			check_comma scoped_name		{ $$ = list_chain ($1, $3, TRUE); }
514 	;
515 
516 interface_body:		export_list
517 	;
518 
519 export_list:		/* empty */			{ $$ = NULL; }
520 |			export_list export		{ $$ = zlist_chain ($1, $2, TRUE); }
521 	;
522 
523 export:			type_dcl check_semicolon
524 |			except_dcl check_semicolon
525 |			op_dcl check_semicolon
526 |			attr_dcl check_semicolon
527 |			const_dcl check_semicolon
528 |			codefrag
529 |			useless_semicolon
530 	;
531 
532 type_dcl:		z_declspec type_dcl_def		{
533 	$$ = $2;
534 	assign_declspec ($$, $1);
535 }
536 	;
537 
538 type_dcl_def:		z_props TOK_TYPEDEF
539 			type_declarator			{
540 	IDL_tree_node node;
541 	IDL_tree p, dcl;
542 
543 	$$ = $3;
544 	node.properties = $1;
545 	for (p = IDL_TYPE_DCL ($3).dcls; p; p = IDL_LIST (p).next) {
546 		dcl = IDL_LIST (p).data;
547 		IDL_tree_properties_copy (&node, dcl);
548 	}
549 	__IDL_free_properties (node.properties);
550 }
551 |			struct_type
552 |			union_type
553 |			enum_type
554 |			z_props TOK_NATIVE
555 			simple_declarator		{
556 	$$ = IDL_native_new ($3);
557 	assign_props (IDL_NATIVE ($$).ident, $1);
558 }
559 |			z_props TOK_NATIVE simple_declarator
560 			'('				{
561 	/* Enable native type scanning */
562 	if (__IDL_pidl > 0)
563 		__IDL_flagsi |= IDLFP_NATIVE;
564 	else {
565 		yyerror ("Native syntax not enabled");
566 		YYABORT;
567 	}
568 }			TOK_NATIVE_TYPE			{
569 	$$ = IDL_native_new ($3);
570 	IDL_NATIVE ($$).user_type = $6;
571 	assign_props (IDL_NATIVE ($$).ident, $1);
572 }
573 	;
574 
575 type_declarator:	type_spec declarator_list	{ $$ = IDL_type_dcl_new ($1, $2); }
576 	;
577 
578 type_spec:		simple_type_spec
579 |			constr_type_spec
580 	;
581 
582 simple_type_spec:	base_type_spec
583 |			template_type_spec
584 |			scoped_name
585 	;
586 
587 constr_type_spec:	struct_type
588 |			union_type
589 |			enum_type
590 	;
591 
592 z_new_ident_catch:	/* empty */			{
593 	yyerrorv ("Missing identifier in %s definition", $<str>0);
594 	YYABORT;
595 }
596 |			new_ident
597 	;
598 
599 z_new_scope_catch:	/* empty */			{
600 	yyerrorv ("Missing identifier in %s definition", $<str>0);
601 	YYABORT;
602 }
603 |			new_scope
604 	;
605 
606 struct_type:		z_props TOK_STRUCT
607 			{ $<str>$ = "struct"; }
608 			z_new_scope_catch '{'		{
609 	g_hash_table_insert (__IDL_structunion_ht, $4, $4);
610 	$<tree>$ = IDL_type_struct_new ($4, NULL);
611 }				member_list
612 			'}' pop_scope			{
613 	g_hash_table_remove (__IDL_structunion_ht, $4);
614 	$$ = $<tree>6;
615 	__IDL_assign_up_node ($$, $7);
616 	IDL_TYPE_STRUCT ($$).member_list = $7;
617 	assign_props (IDL_TYPE_STRUCT ($$).ident, $1);
618 }
619 	;
620 
621 union_type:		z_props TOK_UNION
622 			{ $<str>$ = "union"; }
623 			z_new_scope_catch TOK_SWITCH '('
624 				switch_type_spec
625 			')' '{'				{
626 	g_hash_table_insert (__IDL_structunion_ht, $4, $4);
627 	$<tree>$ = IDL_type_union_new ($4, $7, NULL);
628 }				switch_body
629 			'}' pop_scope			{
630 	g_hash_table_remove (__IDL_structunion_ht, $4);
631 	$$ = $<tree>10;
632 	__IDL_assign_up_node ($$, $11);
633 	IDL_TYPE_UNION ($$).switch_body = $11;
634 	assign_props (IDL_TYPE_UNION ($$).ident, $1);
635 }
636 	;
637 
638 switch_type_spec:	integer_type
639 |			char_type
640 |			boolean_type
641 |			enum_type
642 |			scoped_name
643 	;
644 
645 switch_body:		case_stmt_list
646 	;
647 
648 case_stmt_list:		case_stmt			{ $$ = list_start ($1, TRUE); }
649 |			case_stmt_list case_stmt	{ $$ = list_chain ($1, $2, TRUE); }
650 	;
651 
652 case_stmt:		case_label_list
653 			element_spec check_semicolon	{ $$ = IDL_case_stmt_new ($1, $2); }
654 	;
655 
656 element_spec:		type_spec declarator		{
657 	char *s;
658 
659 	$$ = IDL_member_new ($1, list_start ($2, TRUE));
660 	if (IDL_NODE_TYPE ($1) == IDLN_IDENT &&
661 	    g_hash_table_lookup (__IDL_structunion_ht, $1)) {
662 		s = IDL_ns_ident_to_qstring ($2, "::", 0);
663 		yyerrorv ("Member `%s'", s);
664 		do_token_error (IDL_NODE_UP ($1), "recurses", TRUE);
665 		g_free (s);
666 	}
667 }
668 	;
669 
670 case_label_list:	case_label			{ $$ = list_start ($1, FALSE); }
671 |			case_label_list case_label	{ $$ = list_chain ($1, $2, FALSE); }
672 	;
673 
674 case_label:		TOK_CASE const_exp ':'		{ $$ = $2; }
675 |			TOK_DEFAULT ':'			{ $$ = NULL; }
676 	;
677 
678 const_dcl:		z_declspec const_dcl_def	{
679 	$$ = $2;
680 	assign_declspec ($$, $1);
681 }
682 	;
683 
684 const_dcl_def:		TOK_CONST const_type new_ident
685 			'=' const_exp			{
686 	$$ = IDL_const_dcl_new ($2, $3, $5);
687 	/* Should probably do some type checking here... */
688 }
689 	;
690 
691 except_dcl:		z_declspec except_dcl_def	{
692 	$$ = $2;
693 	assign_declspec ($$, $1);
694 }
695 	;
696 
697 except_dcl_def:		TOK_EXCEPTION new_scope '{'
698 				member_zlist
699 			'}' pop_scope			{ $$ = IDL_except_dcl_new ($2, $4); }
700 	;
701 
702 member_zlist:		/* empty */			{ $$ = NULL; }
703 |			member_zlist member		{ $$ = zlist_chain ($1, $2, TRUE); }
704 	;
705 
706 is_readonly:		/* empty */			{ $$ = FALSE; }
707 |			TOK_READONLY			{ $$ = TRUE; }
708 	;
709 
710 attr_dcl:		z_declspec attr_dcl_def		{
711 	$$ = $2;
712 	assign_declspec ($$, $1);
713 }
714 	;
715 
716 attr_dcl_def:		z_props
717 			is_readonly
718 			TOK_ATTRIBUTE
719 			{ $<str>$ = "attribute"; }
720 			param_type_spec
721 			simple_declarator_list		{
722 	IDL_tree_node node;
723 	IDL_tree p, dcl;
724 
725 	$$ = IDL_attr_dcl_new ($2, $5, $6);
726 	node.properties = $1;
727 	for (p = $6; p; p = IDL_LIST (p).next) {
728 		dcl = IDL_LIST (p).data;
729 		IDL_tree_properties_copy (&node, dcl);
730 	}
731 	__IDL_free_properties (node.properties);
732 }
733 	;
734 
735 param_type_spec:	op_param_type_spec
736 |			TOK_VOID			{
737 	yyerrorv ("Illegal type `void' for %s", $<str>0);
738 	$$ = NULL;
739 }
740 	;
741 
742 op_param_type_spec_illegal:
743 			sequence_type
744 |			constr_type_spec
745 	;
746 
747 op_param_type_spec:	base_type_spec
748 |			string_type
749 |			wide_string_type
750 |			fixed_pt_type
751 |			scoped_name
752 |			op_param_type_spec_illegal	{
753 	illegal_context_type_error ($1, $<str>0);
754 	$$ = $1;
755 }
756 	;
757 
758 is_oneway:		/* empty */			{ $$ = FALSE; }
759 |			TOK_ONEWAY			{ $$ = TRUE; }
760 	;
761 
762 op_dcl:		z_declspec op_dcl_def			{
763 	$$ = $2;
764 	assign_declspec ($$, $1);
765 }
766 	;
767 
768 op_dcl_def:		z_props
769 			is_oneway
770 			op_type_spec
771 			new_scope parameter_dcls pop_scope
772 			is_raises_expr
773 			is_context_expr			{
774 	$$ = IDL_op_dcl_new ($2, $3, $4, $5.tree, $7, $8);
775 	IDL_OP_DCL ($$).f_varargs = GPOINTER_TO_INT ($5.data);
776 	assign_props (IDL_OP_DCL ($$).ident, $1);
777 }
778 	;
779 
780 op_type_spec:		{ $<str>$ = "operation return value"; }
781 			op_param_type_spec		{ $$ = $2; }
782 |			TOK_VOID			{ $$ = NULL; }
783 	;
784 
785 is_varargs:		/* empty */			{ $$ = FALSE; }
786 |			TOK_VARARGS			{ $$ = TRUE; }
787 	;
788 
789 is_cvarargs:		/* empty */			{ $$ = FALSE; }
790 |			',' TOK_VARARGS			{ $$ = TRUE; }
791 	;
792 
793 parameter_dcls:		'('
794 			param_dcl_list
795 			is_cvarargs
796 			')'				{
797 	$$.tree = $2;
798 	$$.data = GINT_TO_POINTER ($3);
799 }
800 |			'(' is_varargs ')'		{
801 	$$.tree = NULL;
802 	$$.data = GINT_TO_POINTER ($2);
803 }
804 	;
805 
806 param_dcl_list:		param_dcl			{ $$ = list_start ($1, TRUE); }
807 |			param_dcl_list
808 			check_comma param_dcl		{ $$ = list_chain ($1, $3, TRUE); }
809 	;
810 
811 param_dcl:		z_props
812 			param_attribute
813 			{ $<str>$ = "parameter"; }
814 			param_type_spec
815 			simple_declarator		{
816 	$$ = IDL_param_dcl_new ($2, $4, $5);
817 	assign_props (IDL_PARAM_DCL ($$).simple_declarator, $1);
818 }
819 	;
820 
821 param_attribute:	TOK_IN				{ $$ = IDL_PARAM_IN; }
822 |			TOK_OUT				{ $$ = IDL_PARAM_OUT; }
823 |			TOK_INOUT			{ $$ = IDL_PARAM_INOUT; }
824 |			param_type_spec			{
825 	yyerrorv ("Missing direction attribute (in, out, inout) before parameter");
826 	IDL_tree_free ($1);
827 }
828 	;
829 
830 is_raises_expr:		/* empty */			{ $$ = NULL; }
831 |			raises_expr
832 	;
833 
834 is_context_expr:	/* empty */			{ $$ = NULL; }
835 |			context_expr
836 	;
837 
838 raises_expr:		TOK_RAISES '('
839 				scoped_name_list
840 			')'				{ $$ = $3; }
841 	;
842 
843 context_expr:		TOK_CONTEXT '('
844 				string_lit_list
845 			')'				{ $$ = $3; }
846 	;
847 
848 const_type:		integer_type
849 |			char_type
850 |			octet_type
851 |			wide_char_type
852 |			boolean_type
853 |			floating_pt_type
854 |			string_type
855 |			wide_string_type
856 |			fixed_pt_const_type
857 |			scoped_name
858 	;
859 
860 const_exp:		or_expr
861 	;
862 
863 or_expr:		xor_expr
864 |			or_expr '|' xor_expr		{ do_binop ($$, IDL_BINOP_OR, $1, $3); }
865 	;
866 
867 xor_expr:		and_expr
868 |			xor_expr '^' and_expr		{ do_binop ($$, IDL_BINOP_XOR, $1, $3); }
869 	;
870 
871 and_expr:		shift_expr
872 |			and_expr '&' shift_expr		{ do_binop ($$, IDL_BINOP_AND, $1, $3); }
873 	;
874 
875 shift_expr:		add_expr
876 |			shift_expr TOK_OP_SHR add_expr	{ do_binop ($$, IDL_BINOP_SHR, $1, $3); }
877 |			shift_expr TOK_OP_SHL add_expr	{ do_binop ($$, IDL_BINOP_SHL, $1, $3); }
878 	;
879 
880 add_expr:		mult_expr
881 |			add_expr '+' mult_expr		{ do_binop ($$, IDL_BINOP_ADD, $1, $3); }
882 |			add_expr '-' mult_expr		{ do_binop ($$, IDL_BINOP_SUB, $1, $3); }
883 	;
884 
885 mult_expr:		unary_expr
886 |			mult_expr '*' unary_expr	{ do_binop ($$, IDL_BINOP_MULT, $1, $3); }
887 |			mult_expr '/' unary_expr	{ do_binop ($$, IDL_BINOP_DIV, $1, $3); }
888 |			mult_expr '%' unary_expr	{ do_binop ($$, IDL_BINOP_MOD, $1, $3); }
889 	;
890 
891 unary_expr:		unary_op primary_expr		{ do_unaryop ($$, $1, $2); }
892 |			primary_expr
893 	;
894 
895 unary_op:		'-'				{ $$ = IDL_UNARYOP_MINUS; }
896 |			'+'				{ $$ = IDL_UNARYOP_PLUS; }
897 |			'~'				{ $$ = IDL_UNARYOP_COMPLEMENT; }
898 	;
899 
900 primary_expr:		scoped_name			{
901 	IDL_tree p, literal;
902 
903 	assert (IDL_NODE_TYPE ($1) == IDLN_IDENT);
904 
905 	p = IDL_NODE_UP ($1);
906 
907 	if ((literal = IDL_resolve_const_exp ($1, IDLN_ANY))) {
908 		++IDL_NODE_REFS (literal);
909 		$$ = literal;
910 		IDL_tree_free ($1);
911 	} else
912 		$$ = $1;
913 }
914 |			literal
915 |			'(' const_exp ')'		{ $$ = $2; }
916 	;
917 
918 literal:		integer_lit
919 |			string_lit
920 |			char_lit
921 |			fixed_pt_lit
922 |			floating_pt_lit
923 |			boolean_lit
924 	;
925 
926 enum_type:		z_props TOK_ENUM
927 			{ $<str>$ = "enum"; }
928 			z_new_ident_catch '{'
929 				enumerator_list
930 			'}'				{
931 	$$ = IDL_type_enum_new ($4, $6);
932 	assign_props (IDL_TYPE_ENUM ($$).ident, $1);
933 }
934 	;
935 
936 scoped_name:		ns_scoped_name			{
937 	assert ($1 != NULL);
938 	assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
939 	assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
940 	$$ = IDL_GENTREE ($1).data;
941 }
942 	;
943 
944 ns_scoped_name:		ns_prev_ident
945 |			TOK_OP_SCOPE ns_global_ident	{ $$ = $2; }
946 |			ns_scoped_name TOK_OP_SCOPE
947 			ident				{
948 	IDL_tree p;
949 
950 	assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
951 	assert (IDL_NODE_TYPE ($3) == IDLN_IDENT);
952 
953 #ifdef YYDEBUG
954 	if (yydebug)
955 		fprintf (stderr, "ns: looking in `%s' for `%s'\n",
956 		  IDL_IDENT (IDL_GENTREE ($1).data).str, IDL_IDENT($3).str);
957 #endif
958 
959 	if ((p = IDL_ns_lookup_this_scope (__IDL_root_ns, $1, $3, NULL)) == NULL) {
960 		yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($3).str);
961 		IDL_tree_free ($3);
962 		YYABORT;
963 	}
964 	IDL_tree_free ($3);
965 #ifdef REF_IDENTS
966 	++IDL_NODE_REFS (IDL_GENTREE (p).data);
967 #endif
968 	$$ = p;
969 }
970 	;
971 
972 enumerator_list:	new_ident			{ $$ = list_start ($1, TRUE); }
973 |			enumerator_list
974 			check_comma new_ident		{ $$ = list_chain ($1, $3, TRUE); }
975 	;
976 
977 member_list:		member				{ $$ = list_start ($1, TRUE); }
978 |			member_list member		{ $$ = list_chain ($1, $2, TRUE); }
979 	;
980 
981 member:			type_spec declarator_list
982 			check_semicolon			{
983 	char *s;
984 
985 	$$ = IDL_member_new ($1, $2);
986 	if (IDL_NODE_TYPE ($1) == IDLN_IDENT &&
987 	    g_hash_table_lookup (__IDL_structunion_ht, $1)) {
988 		s = IDL_ns_ident_to_qstring (IDL_LIST ($2).data, "::", 0);
989 		yyerrorv ("Member `%s'", s);
990 		do_token_error (IDL_NODE_UP ($1), "recurses", TRUE);
991 		g_free (s);
992 	}
993 }
994 	;
995 
996 base_type_spec:		floating_pt_type
997 |			integer_type
998 |			char_type
999 |			wide_char_type
1000 |			boolean_type
1001 |			octet_type
1002 |			any_type
1003 |			object_type
1004 |			typecode_type
1005 	;
1006 
1007 template_type_spec:	sequence_type
1008 |			string_type
1009 |			wide_string_type
1010 |			fixed_pt_type
1011 	;
1012 
1013 sequence_type:		TOK_SEQUENCE '<'
1014 				simple_type_spec ',' positive_int_const
1015 			'>'				{ $$ = IDL_type_sequence_new ($3, $5); }
1016 |			TOK_SEQUENCE '<'
1017 				simple_type_spec
1018 			'>'				{ $$ = IDL_type_sequence_new ($3, NULL); }
1019 	;
1020 
1021 floating_pt_type:	TOK_FLOAT			{ $$ = IDL_type_float_new (IDL_FLOAT_TYPE_FLOAT); }
1022 |			TOK_DOUBLE			{ $$ = IDL_type_float_new (IDL_FLOAT_TYPE_DOUBLE); }
1023 |			TOK_LONG TOK_DOUBLE		{ $$ = IDL_type_float_new (IDL_FLOAT_TYPE_LONGDOUBLE); }
1024 	;
1025 
1026 fixed_pt_type:		TOK_FIXED '<'
1027 				positive_int_const ',' integer_lit
1028 			'>'				{ $$ = IDL_type_fixed_new ($3, $5); }
1029 	;
1030 
1031 fixed_pt_const_type:	TOK_FIXED			{ $$ = IDL_type_fixed_new (NULL, NULL); }
1032 	;
1033 
1034 integer_type:		signed_int			{ $$ = IDL_type_integer_new (TRUE, $1); }
1035 |			unsigned_int			{ $$ = IDL_type_integer_new (FALSE, $1); }
1036 	;
1037 
1038 signed_int:		signed_short_int		{ $$ = IDL_INTEGER_TYPE_SHORT; }
1039 |			signed_long_int			{ $$ = IDL_INTEGER_TYPE_LONG; }
1040 |			signed_longlong_int		{ $$ = IDL_INTEGER_TYPE_LONGLONG; }
1041 	;
1042 
1043 signed_short_int:	TOK_SHORT
1044 	;
1045 
1046 signed_long_int:	TOK_LONG
1047 	;
1048 
1049 signed_longlong_int:	TOK_LONG TOK_LONG
1050 	;
1051 
1052 unsigned_int:		unsigned_short_int		{ $$ = IDL_INTEGER_TYPE_SHORT; }
1053 |			unsigned_long_int		{ $$ = IDL_INTEGER_TYPE_LONG; }
1054 |			unsigned_longlong_int		{ $$ = IDL_INTEGER_TYPE_LONGLONG; }
1055 	;
1056 
1057 unsigned_short_int:	TOK_UNSIGNED TOK_SHORT
1058 	;
1059 
1060 unsigned_long_int:	TOK_UNSIGNED TOK_LONG
1061 	;
1062 
1063 unsigned_longlong_int:	TOK_UNSIGNED TOK_LONG TOK_LONG
1064 	;
1065 
1066 char_type:		TOK_CHAR			{ $$ = IDL_type_char_new (); }
1067 	;
1068 
1069 wide_char_type:		TOK_WCHAR			{ $$ = IDL_type_wide_char_new (); }
1070 	;
1071 
1072 boolean_type:		TOK_BOOLEAN			{ $$ = IDL_type_boolean_new (); }
1073 	;
1074 
1075 octet_type:		TOK_OCTET			{ $$ = IDL_type_octet_new (); }
1076 	;
1077 
1078 any_type:		TOK_ANY				{ $$ = IDL_type_any_new (); }
1079 	;
1080 
1081 object_type:		TOK_OBJECT			{ $$ = IDL_type_object_new (); }
1082 	;
1083 
1084 typecode_type:		TOK_TYPECODE			{ $$ = IDL_type_typecode_new (); }
1085 	;
1086 
1087 string_type:		TOK_STRING '<'
1088 				positive_int_const
1089 				'>'			{ $$ = IDL_type_string_new ($3); }
1090 |			TOK_STRING			{ $$ = IDL_type_string_new (NULL); }
1091 	;
1092 
1093 wide_string_type:	TOK_WSTRING '<'
1094 				positive_int_const
1095 			'>'				{ $$ = IDL_type_wide_string_new ($3); }
1096 |			TOK_WSTRING			{ $$ = IDL_type_wide_string_new (NULL); }
1097 	;
1098 
1099 declarator_list:	declarator			{ $$ = list_start ($1, TRUE); }
1100 |			declarator_list
1101 			check_comma declarator		{ $$ = list_chain ($1, $3, TRUE); }
1102 	;
1103 
1104 declarator:		simple_declarator
1105 |			complex_declarator
1106 	;
1107 
1108 simple_declarator:	new_ident
1109 	;
1110 
1111 complex_declarator:	array_declarator
1112 	;
1113 
1114 simple_declarator_list:	simple_declarator		{ $$ = list_start ($1, TRUE); }
1115 |			simple_declarator_list
1116 			check_comma simple_declarator	{ $$ = list_chain ($1, $3, TRUE); }
1117 	;
1118 
1119 array_declarator:	new_ident
1120 			fixed_array_size_list		{
1121 	IDL_tree p;
1122 	int i;
1123 
1124 	$$ = IDL_type_array_new ($1, $2);
1125 	for (i = 1, p = $2; p; ++i, p = IDL_LIST (p).next)
1126 		if (!IDL_LIST (p).data) {
1127 			char *s = IDL_ns_ident_to_qstring ($1, "::", 0);
1128 			yyerrorv ("Missing value in dimension %d of array `%s'", i, s);
1129 			g_free (s);
1130 		}
1131 }
1132 	;
1133 
1134 fixed_array_size_list:	fixed_array_size		{ $$ = list_start ($1, FALSE); }
1135 |			fixed_array_size_list
1136 			fixed_array_size		{ $$ = list_chain ($1, $2, FALSE); }
1137 	;
1138 
1139 fixed_array_size:	'[' positive_int_const ']'	{ $$ = $2; }
1140 |			'[' ']'				{ $$ = NULL; }
1141 	;
1142 
1143 prop_hash:		TOK_PROP_KEY
1144 			TOK_PROP_VALUE			{
1145 	$$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal);
1146 	g_hash_table_insert ($$, $1, $2);
1147 }
1148 |			prop_hash ','
1149 			TOK_PROP_KEY
1150 			TOK_PROP_VALUE			{
1151 	$$ = $1;
1152 	g_hash_table_insert ($$, $3, $4);
1153 }
1154 |			TOK_PROP_KEY			{
1155 	$$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal);
1156 	g_hash_table_insert ($$, $1, g_strdup (""));
1157 }
1158 |			prop_hash ','
1159 			TOK_PROP_KEY			{
1160 	$$ = $1;
1161 	g_hash_table_insert ($$, $3, g_strdup (""));
1162 }
1163 	;
1164 
1165 ident:			TOK_IDENT			{ $$ = IDL_ident_new ($1); }
1166 	;
1167 
1168 new_ident:		ns_new_ident			{
1169 	assert ($1 != NULL);
1170 	assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
1171 	assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1172 	$$ = IDL_GENTREE ($1).data;
1173 }
1174 	;
1175 
1176 new_scope:		ns_new_ident			{
1177 	IDL_tree	old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1178 	IDL_ns_push_scope (__IDL_root_ns, $1);
1179 #ifdef YYDEBUG
1180 	if (yydebug)
1181 		fprintf (stderr, "ns: entering new scope `%s' of `%s'\n",
1182 		       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str);
1183 #endif
1184 	assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1185 	$$ = IDL_GENTREE ($1).data;
1186 }
1187 	;
1188 
1189 new_or_prev_scope:	cur_ns_new_or_prev_ident	{
1190 	IDL_tree	old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1191 	IDL_ns_push_scope (__IDL_root_ns, $1);
1192 	assert (IDL_NS (__IDL_root_ns).current != NULL);
1193 	assert (IDL_NODE_TYPE (IDL_NS (__IDL_root_ns).current) == IDLN_GENTREE);
1194 	assert (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data != NULL);
1195 	assert (IDL_NODE_TYPE (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data) == IDLN_IDENT);
1196 #ifdef YYDEBUG
1197 	if (yydebug)
1198 		fprintf (stderr,"ns: entering new/prev scope `%s' of `%s'\n",
1199 		       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str);
1200 #endif
1201 	assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1202 	$$ = IDL_GENTREE ($1).data;
1203 }
1204 	;
1205 
1206 pop_scope:		/* empty */			{
1207 	IDL_tree cur_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1208 	IDL_ns_pop_scope (__IDL_root_ns);
1209 #ifdef YYDEBUG
1210 	if (yydebug)
1211 		fprintf (stderr, "ns: pop scope from `%s' to `%s'\n",
1212 		       IDL_IDENT(cur_top).str,
1213 		       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str);
1214 #endif
1215 }
1216 	;
1217 
1218 ns_new_ident:		ident				{
1219 	IDL_tree p;
1220 
1221 	if ((p = IDL_ns_place_new (__IDL_root_ns, $1)) == NULL) {
1222 		IDL_tree q;
1223 		int i;
1224 
1225 		p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL);
1226 
1227 		for (i = 0, q = IDL_GENTREE (p).data;
1228 		     q && (IDL_NODE_TYPE (q) == IDLN_IDENT ||
1229 			   IDL_NODE_TYPE (q) == IDLN_LIST) && i < 4;
1230 		     ++i)
1231 			if (IDL_NODE_UP (q))
1232 				q = IDL_NODE_UP (q);
1233 
1234 		if (q) {
1235 			IDL_tree_error ($1, "`%s' conflicts", IDL_IDENT ($1).str);
1236 			do_token_error (q, "with", FALSE);
1237 		} else
1238 			yyerrorv ("`%s' duplicate identifier", IDL_IDENT ($1).str);
1239 
1240 		IDL_tree_free ($1);
1241 		YYABORT;
1242 	}
1243 	assert (IDL_IDENT ($1)._ns_ref == p);
1244 #ifdef REF_IDENTS
1245 	++IDL_NODE_REFS (IDL_GENTREE (p).data);
1246 #endif
1247 	if (__IDL_new_ident_comments != NULL) {
1248 		assert (IDL_IDENT ($1).comments == NULL);
1249 		IDL_IDENT ($1).comments = __IDL_new_ident_comments;
1250 		__IDL_new_ident_comments = NULL;
1251 	}
1252 	$$ = p;
1253 }
1254 	;
1255 
1256 ns_prev_ident:		ident				{
1257 	IDL_tree p;
1258 
1259 	if ((p = IDL_ns_resolve_ident (__IDL_root_ns, $1)) == NULL) {
1260 		yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str);
1261 		IDL_tree_free ($1);
1262 		YYABORT;
1263 	}
1264 	IDL_tree_free ($1);
1265 	assert (IDL_GENTREE (p).data != NULL);
1266 	assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1267 #ifdef REF_IDENTS
1268 	++IDL_NODE_REFS (IDL_GENTREE (p).data);
1269 #endif
1270 	$$ = p;
1271 }
1272 	;
1273 
1274 cur_ns_new_or_prev_ident:
1275 			ident				{
1276 	IDL_tree p;
1277 
1278 	if ((p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL)) == NULL) {
1279 #ifdef YYDEBUG
1280 		if (yydebug)
1281 			fprintf (stderr, "ns: place_new `%s' in `%s'\n",
1282 		  	  IDL_IDENT($1).str,
1283 			  IDL_IDENT(IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str );
1284 #endif
1285 		p = IDL_ns_place_new (__IDL_root_ns, $1);
1286 		assert (p != NULL);
1287 		assert (IDL_IDENT ($1)._ns_ref == p);
1288 		if (__IDL_new_ident_comments != NULL) {
1289 			assert (IDL_IDENT ($1).comments == NULL);
1290 			IDL_IDENT ($1).comments = __IDL_new_ident_comments;
1291 			__IDL_new_ident_comments = NULL;
1292 		}
1293 	} else {
1294 		IDL_tree_free ($1);
1295 		assert (IDL_GENTREE (p).data != NULL);
1296 		assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1297 	}
1298 #ifdef REF_IDENTS
1299 	++IDL_NODE_REFS (IDL_GENTREE (p).data);
1300 #endif
1301 	$$ = p;
1302 }
1303 	;
1304 
1305 ns_global_ident:	ident				{
1306 	IDL_tree p;
1307 
1308 	if ((p = IDL_ns_lookup_this_scope (
1309 		__IDL_root_ns,IDL_NS (__IDL_root_ns).file, $1, NULL)) == NULL) {
1310 		yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str);
1311 		IDL_tree_free ($1);
1312 		YYABORT;
1313 	}
1314 	IDL_tree_free ($1);
1315 	assert (IDL_GENTREE (p).data != NULL);
1316 	assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1317 #ifdef REF_IDENTS
1318 	++IDL_NODE_REFS (IDL_GENTREE (p).data);
1319 #endif
1320 	$$ = p;
1321 }
1322 	;
1323 
1324 string_lit_list:	string_lit			{ $$ = list_start ($1, TRUE); }
1325 |			string_lit_list
1326 			check_comma string_lit		{ $$ = list_chain ($1, $3, TRUE); }
1327 	;
1328 
1329 positive_int_const:	const_exp			{
1330 	IDL_tree literal, ident = NULL;
1331 	IDL_longlong_t value = 0;
1332 
1333 	if ((literal = IDL_resolve_const_exp ($1, IDLN_INTEGER))) {
1334 		assert (IDL_NODE_TYPE (literal) == IDLN_INTEGER);
1335 		++IDL_NODE_REFS (literal);
1336 		value = IDL_INTEGER (literal).value;
1337 		if ( literal != $1 )
1338 			IDL_tree_free ($1);
1339 	}
1340 
1341 	if (literal && IDL_NODE_UP (literal) &&
1342 	    IDL_NODE_TYPE (IDL_NODE_UP (literal)) == IDLN_CONST_DCL)
1343 		ident = IDL_CONST_DCL (IDL_NODE_UP (literal)).ident;
1344 
1345 	if (literal == NULL) {
1346 		if (!(__IDL_flags & IDLF_NO_EVAL_CONST))
1347 			yyerror ("Could not resolve constant expression");
1348 		$$ = $1;
1349 	} else if (value == 0) {
1350 		yyerror ("Zero array size is illegal");
1351 		if (ident)
1352 			IDL_tree_error (ident, "From constant declared here");
1353 		$$ = NULL;
1354 	} else if (value < 0) {
1355 		yywarningv (IDL_WARNING1, "Cannot use negative value %"
1356 			    IDL_LL "d, using %" IDL_LL "d",
1357 			   value, -value);
1358 		if (ident)
1359 			IDL_tree_warning (ident,
1360 					  IDL_WARNING1, "From constant declared here");
1361 		$$ = IDL_integer_new (-value);
1362 	}
1363 	else
1364 		$$ = IDL_integer_new (value);
1365 }
1366 	;
1367 
1368 z_declspec:		/* empty */			{ $$ = 0; }
1369 |			TOK_DECLSPEC			{
1370 	$$ = IDL_parse_declspec ($1);
1371 	g_free ($1);
1372 }
1373 	;
1374 
1375 z_props:		/* empty */			{ $$ = NULL; }
1376 |			'['				{
1377 	/* Enable property scanning */
1378 	if (__IDL_flags & IDLF_PROPERTIES)
1379 		__IDL_flagsi |= IDLFP_PROPERTIES;
1380 	else {
1381 		yyerror ("Property syntax not enabled");
1382 		YYABORT;
1383 	}
1384 }			prop_hash
1385 			']'				{ $$ = $3; }
1386 	;
1387 
1388 integer_lit:		TOK_INTEGER			{ $$ = IDL_integer_new ($1); }
1389 	;
1390 
1391 string_lit:		dqstring_cat			{ $$ = IDL_string_new ($1); }
1392 	;
1393 
1394 char_lit:		sqstring			{ $$ = IDL_char_new ($1); }
1395 	;
1396 
1397 fixed_pt_lit:		TOK_FIXEDP			{ $$ = IDL_fixed_new ($1); }
1398 	;
1399 
1400 floating_pt_lit:	TOK_FLOATP			{ $$ = IDL_float_new ($1); }
1401 	;
1402 
1403 boolean_lit:		TOK_TRUE			{ $$ = IDL_boolean_new (TRUE); }
1404 |			TOK_FALSE			{ $$ = IDL_boolean_new (FALSE); }
1405 	;
1406 
1407 codefrag:		z_declspec TOK_CODEFRAG		{
1408 	$$ = $2;
1409 	assign_declspec ($$, $1);
1410 }
1411 	;
1412 
1413 srcfile:		TOK_SRCFILE		{
1414 	$$ = $1;
1415 }
1416 	;
1417 
1418 dqstring_cat:		dqstring
1419 |			dqstring_cat dqstring		{
1420 	char *catstr = g_malloc (strlen ($1) + strlen ($2) + 1);
1421 	strcpy (catstr, $1); g_free ($1);
1422 	strcat (catstr, $2); g_free ($2);
1423 	$$ = catstr;
1424 }
1425 	;
1426 
1427 dqstring:		TOK_DQSTRING			{
1428 	char *s = IDL_do_escapes ($1);
1429 	g_free ($1);
1430 	$$ = s;
1431 }
1432 	;
1433 
1434 sqstring:		TOK_SQSTRING			{
1435 	char *s = IDL_do_escapes ($1);
1436 	g_free ($1);
1437 	$$ = s;
1438 }
1439 	;
1440 
1441 %%
1442 
1443 void __IDL_parser_reset (void)
1444 {
1445 	yyclearin;
1446 }
1447 
IDL_ns_get_cur_prefix(IDL_ns ns)1448 static const char *IDL_ns_get_cur_prefix (IDL_ns ns)
1449 {
1450 	IDL_tree p;
1451 
1452 	p = IDL_NS (ns).current;
1453 
1454 	assert (p != NULL);
1455 
1456 	while (p && !IDL_GENTREE (p)._cur_prefix)
1457 		p = IDL_NODE_UP (p);
1458 
1459 	return p ? IDL_GENTREE (p)._cur_prefix : NULL;
1460 }
1461 
IDL_ns_ident_make_repo_id(IDL_ns ns,IDL_tree p,const char * p_prefix,int * major,int * minor)1462 gchar *IDL_ns_ident_make_repo_id (IDL_ns ns, IDL_tree p,
1463 				  const char *p_prefix, int *major, int *minor)
1464 {
1465 	GString *s = g_string_new (NULL);
1466 	const char *prefix;
1467 	char *q;
1468 
1469 	assert (p != NULL);
1470 
1471 	if (IDL_NODE_TYPE (p) == IDLN_IDENT)
1472 		p = IDL_IDENT_TO_NS (p);
1473 
1474 	assert (p != NULL);
1475 
1476 	prefix = p_prefix ? p_prefix : IDL_ns_get_cur_prefix (ns);
1477 
1478 	q = IDL_ns_ident_to_qstring (p, "/", 0);
1479 	g_string_printf (s, "IDL:%s%s%s:%d.%d",
1480 			  prefix ? prefix : "",
1481 			  prefix && *prefix ? "/" : "",
1482 			  q,
1483 			  major ? *major : 1,
1484 			  minor ? *minor : 0);
1485 	g_free (q);
1486 
1487 	q = s->str;
1488 	g_string_free (s, FALSE);
1489 
1490 	return q;
1491 }
1492 
get_name_token(const char * s,char ** tok)1493 static const char *get_name_token (const char *s, char **tok)
1494 {
1495 	const char *begin = s;
1496 	int state = 0;
1497 
1498 	if (!s)
1499 		return NULL;
1500 
1501 	while (g_ascii_isspace (*s)) ++s;
1502 
1503 	while (1) switch (state) {
1504 	case 0:		/* Unknown */
1505 		if (*s == ':')
1506 			state = 1;
1507 		else if (isalnum ((int)*s) || *s == '_') {
1508 			begin = s;
1509 			state = 2;
1510 		} else
1511 			return NULL;
1512 		break;
1513 	case 1:		/* Scope */
1514 		if (strncmp (s, "::", 2) == 0) {
1515 			char *r = g_malloc (3);
1516 			strcpy (r, "::");
1517 			*tok = r;
1518 			return s + 2;
1519 		} else	/* Invalid */
1520 			return NULL;
1521 		break;
1522 	case 2:
1523 		if (isalnum ((int)*s) || *s == '_')
1524 			++s;
1525 		else {
1526 			char *r = g_malloc (s - begin + 1);
1527 			strncpy (r, begin, s - begin + 1);
1528 			r[s - begin] = 0;
1529 			*tok = r;
1530 			return s;
1531 		}
1532 		break;
1533 	}
1534 }
1535 
IDL_ns_pragma_parse_name(IDL_ns ns,const char * s)1536 static IDL_tree IDL_ns_pragma_parse_name (IDL_ns ns, const char *s)
1537 {
1538 	IDL_tree p = IDL_NS (ns).current, q;
1539 	int start = 1;
1540 	char *tok;
1541 
1542 	/* This is a hack to allow directives for an ident (such
1543 	 * as and interface) to be located within the scope of
1544 	 * that identifier. */
1545 	if ( p && (q=IDL_GENTREE(p).data)!=0
1546 	  && IDL_NODE_TYPE(q)==IDLN_IDENT
1547 	  && strcmp(s,IDL_IDENT(q).str)==0 ) {
1548 		return p;
1549 	}
1550 
1551 	while (p && *s && (s = get_name_token (s, &tok))) {
1552 		if (tok == NULL)
1553 			return NULL;
1554 		if (strcmp (tok, "::") == 0) {
1555 			if (start) {
1556 				/* Globally scoped */
1557 				p = IDL_NS (ns).file;
1558 			}
1559 			g_free (tok);
1560 		} else {
1561 			IDL_tree ident = IDL_ident_new (tok);
1562 			p = IDL_ns_lookup_this_scope (__IDL_root_ns, p, ident, NULL);
1563 			IDL_tree_free (ident);
1564 		}
1565 		start = 0;
1566 	}
1567 
1568 	return p;
1569 }
1570 
IDL_ns_ID(IDL_ns ns,const char * s)1571 void IDL_ns_ID (IDL_ns ns, const char *s)
1572 {
1573 	char name[1024], id[1024];
1574 	IDL_tree p, ident;
1575 	int n;
1576 
1577 	n = sscanf (s, "%1023s \"%1023s\"", name, id);
1578 	if (n < 2 && __IDL_is_parsing) {
1579 		yywarning (IDL_WARNING1, "Malformed pragma ID");
1580 		return;
1581 	}
1582 	if (id[strlen (id) - 1] == '"')
1583 		id[strlen (id) - 1] = 0;
1584 
1585 	p = IDL_ns_pragma_parse_name (__IDL_root_ns, name);
1586 	if (!p && __IDL_is_parsing) {
1587 		yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma ID", name);
1588 		return;
1589 	}
1590 
1591 	/* We have resolved the identifier, so assign the repo id */
1592 	assert (IDL_NODE_TYPE (p) == IDLN_GENTREE);
1593 	assert (IDL_GENTREE (p).data != NULL);
1594 	assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
1595 	ident = IDL_GENTREE (p).data;
1596 
1597 	if (IDL_IDENT_REPO_ID (ident) != NULL)
1598 		g_free (IDL_IDENT_REPO_ID (ident));
1599 
1600 	IDL_IDENT_REPO_ID (ident) = g_strdup (id);
1601 }
1602 
IDL_ns_version(IDL_ns ns,const char * s)1603 void IDL_ns_version (IDL_ns ns, const char *s)
1604 {
1605 	char name[1024];
1606 	int n, major, minor;
1607 	IDL_tree p, ident;
1608 
1609 	n = sscanf (s, "%1023s %u.%u", name, &major, &minor);
1610 	if (n < 3 && __IDL_is_parsing) {
1611 		yywarning (IDL_WARNING1, "Malformed pragma version");
1612 		return;
1613 	}
1614 
1615 	p = IDL_ns_pragma_parse_name (__IDL_root_ns, name);
1616 	if (!p && __IDL_is_parsing) {
1617 		yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma version", name);
1618 		return;
1619 	}
1620 
1621 	/* We have resolved the identifier, so assign the repo id */
1622 	assert (IDL_NODE_TYPE (p) == IDLN_GENTREE);
1623 	assert (IDL_GENTREE (p).data != NULL);
1624 	assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
1625 	ident = IDL_GENTREE (p).data;
1626 
1627 	if (IDL_IDENT_REPO_ID (ident) != NULL) {
1628 		char *v = strrchr (IDL_IDENT_REPO_ID (ident), ':');
1629 		if (v) {
1630 			GString *s;
1631 
1632 			*v = 0;
1633 			s = g_string_new (NULL);
1634 			g_string_printf (s, "%s:%d.%d",
1635 					  IDL_IDENT_REPO_ID (ident), major, minor);
1636 			g_free (IDL_IDENT_REPO_ID (ident));
1637 			IDL_IDENT_REPO_ID (ident) = s->str;
1638 			g_string_free (s, FALSE);
1639 		} else if (__IDL_is_parsing)
1640 			yywarningv (IDL_WARNING1, "Cannot find RepositoryID OMG IDL version in ID `%s'",
1641 				    IDL_IDENT_REPO_ID (ident));
1642 	} else
1643 		IDL_IDENT_REPO_ID (ident) =
1644 			IDL_ns_ident_make_repo_id (
1645 				__IDL_root_ns, p, NULL, &major, &minor);
1646 }
1647 
IDL_inhibit_get(void)1648 int IDL_inhibit_get (void)
1649 {
1650 	g_return_val_if_fail (__IDL_is_parsing, -1);
1651 
1652 	return __IDL_inhibits;
1653 }
1654 
IDL_inhibit_push(void)1655 void IDL_inhibit_push (void)
1656 {
1657 	g_return_if_fail (__IDL_is_parsing);
1658 
1659 	++__IDL_inhibits;
1660 }
1661 
IDL_inhibit_pop(void)1662 void IDL_inhibit_pop (void)
1663 {
1664 	g_return_if_fail (__IDL_is_parsing);
1665 
1666 	if (--__IDL_inhibits < 0)
1667 		__IDL_inhibits = 0;
1668 }
1669 
IDL_inhibit(IDL_ns ns,const char * s)1670 static void IDL_inhibit (IDL_ns ns, const char *s)
1671 {
1672 	if (g_ascii_strcasecmp ("push", s) == 0)
1673 		IDL_inhibit_push ();
1674 	else if (g_ascii_strcasecmp ("pop", s) == 0)
1675 		IDL_inhibit_pop ();
1676 }
1677 
IDL_typecodes_as_tok(IDL_ns ns,const char * s)1678 static void IDL_typecodes_as_tok (IDL_ns ns, const char *s)
1679 {
1680 	if (g_ascii_strcasecmp ("push", s) == 0)
1681 		++(__IDL_typecodes_as_tok);
1682 	else if (g_ascii_strcasecmp ("pop", s) == 0)
1683 		--(__IDL_typecodes_as_tok);
1684 }
1685 
IDL_pidl(IDL_ns ns,const char * s)1686 static void IDL_pidl (IDL_ns ns, const char *s)
1687 {
1688 	if (g_ascii_strcasecmp ("push", s) == 0)
1689 		++(__IDL_pidl);
1690 	else if (g_ascii_strcasecmp ("pop", s) == 0)
1691 		--(__IDL_pidl);
1692 }
1693 
__IDL_do_pragma(const char * s)1694 void __IDL_do_pragma (const char *s)
1695 {
1696 	int n;
1697 	char directive[256];
1698 
1699 	g_return_if_fail (__IDL_is_parsing);
1700 	g_return_if_fail (s != NULL);
1701 
1702 	if (sscanf (s, "%255s%n", directive, &n) < 1)
1703 		return;
1704 	s += n;
1705 	while (g_ascii_isspace (*s)) ++s;
1706 
1707 	if (strcmp (directive, "prefix") == 0)
1708 		IDL_ns_prefix (__IDL_root_ns, s);
1709 	else if (strcmp (directive, "ID") == 0)
1710 		IDL_ns_ID (__IDL_root_ns, s);
1711 	else if (strcmp (directive, "version") == 0)
1712 		IDL_ns_version (__IDL_root_ns, s);
1713 	else if (strcmp (directive, "inhibit") == 0)
1714 		IDL_inhibit (__IDL_root_ns, s);
1715 	else if (strcmp (directive, "typecodes_as_tok") == 0)
1716 		IDL_typecodes_as_tok (__IDL_root_ns, s);
1717 	else if (strcmp (directive, "pidl") == 0)
1718 		IDL_pidl (__IDL_root_ns, s);
1719 }
1720 
IDL_parse_declspec(const char * strspec)1721 static IDL_declspec_t IDL_parse_declspec (const char *strspec)
1722 {
1723 	IDL_declspec_t flags = IDLF_DECLSPEC_EXIST;
1724 
1725 	if (strspec == NULL)
1726 		return flags;
1727 
1728 	if (strcmp (strspec, "inhibit") == 0)
1729 		flags |= IDLF_DECLSPEC_INHIBIT;
1730 	if (strcmp (strspec, "pidl") == 0)
1731 		flags |= IDLF_DECLSPEC_PIDL;
1732 	else if (__IDL_is_parsing)
1733 		yywarningv (IDL_WARNING1, "Ignoring unknown declspec `%s'", strspec);
1734 
1735 	return flags;
1736 }
1737 
IDL_file_set(const char * filename,int line)1738 IDL_tree IDL_file_set (const char *filename, int line)
1739 {
1740 	IDL_fileinfo *fi;
1741 	IDL_tree tree = NULL;
1742 
1743 	g_return_val_if_fail (__IDL_is_parsing, NULL);
1744 
1745 	if (filename) {
1746 		const char *oldfilename = __IDL_cur_filename;
1747 		gboolean wasInhibit = IS_INHIBIT_STATE();
1748 		gboolean isTop =
1749 #ifdef HAVE_CPP_PIPE_STDIN
1750 			strlen (filename)==0;
1751 #else
1752 			__IDL_tmp_filename &&
1753 			strcmp (filename, __IDL_tmp_filename)==0;
1754 #endif
1755 		if ( isTop ) {
1756 			filename = __IDL_real_filename;
1757 			__IDL_flagsi &= ~IDLFP_IN_INCLUDES;
1758 		} else {
1759 			__IDL_flagsi |= IDLFP_IN_INCLUDES;
1760 		}
1761 
1762 		if ((fi=g_hash_table_lookup(__IDL_filename_hash, filename)) ) {
1763 			__IDL_cur_fileinfo = fi;
1764 			++(fi->seenCnt);
1765 		} else {
1766 			fi = g_new0 (IDL_fileinfo, 1);
1767 			fi->name = g_strdup(filename);
1768 			g_hash_table_insert (__IDL_filename_hash, fi->name, fi);
1769 		}
1770 		__IDL_cur_fileinfo = fi;
1771 		__IDL_cur_filename = fi->name;
1772 		if ( (__IDL_flags & IDLF_SRCFILES)!=0
1773 		  && (oldfilename==0
1774 		  	    || strcmp(oldfilename,fi->name)!=0) ) {
1775 			tree = IDL_srcfile_new(fi->name, fi->seenCnt, isTop, wasInhibit);
1776 		}
1777 	}
1778 
1779 	if (__IDL_cur_line > 0)
1780 		__IDL_cur_line = line;
1781 	return tree;
1782 }
1783 
IDL_file_get(const char ** filename,int * line)1784 void IDL_file_get (const char **filename, int *line)
1785 {
1786 	g_return_if_fail (__IDL_is_parsing);
1787 
1788 	if (filename)
1789 		*filename = __IDL_cur_filename;
1790 
1791 	if (line)
1792 		*line = __IDL_cur_line;
1793 }
1794 
do_token_error(IDL_tree p,const char * message,gboolean prev)1795 static int do_token_error (IDL_tree p, const char *message, gboolean prev)
1796 {
1797 	int dienow;
1798 	char *what = NULL, *who = NULL;
1799 
1800 	assert (p != NULL);
1801 
1802 	dienow = IDL_tree_get_node_info (p, &what, &who);
1803 
1804 	assert (what != NULL);
1805 
1806 	if (who && *who)
1807 		IDL_tree_error (p, "%s %s `%s'", message, what, who);
1808 	else
1809 		IDL_tree_error (p, "%s %s", message, what);
1810 
1811 	return dienow;
1812 }
1813 
illegal_context_type_error(IDL_tree p,const char * what)1814 static void illegal_context_type_error (IDL_tree p, const char *what)
1815 {
1816 	GString *s = g_string_new (NULL);
1817 
1818 	g_string_printf (s, "Illegal type `%%s' for %s", what);
1819 	illegal_type_error (p, s->str);
1820 	g_string_free (s, TRUE);
1821 }
1822 
illegal_type_error(IDL_tree p,const char * message)1823 static void illegal_type_error (IDL_tree p, const char *message)
1824 {
1825 	GString *s;
1826 
1827 	s = IDL_tree_to_IDL_string (p, NULL, IDLF_OUTPUT_NO_NEWLINES);
1828 	yyerrorv (message, s->str);
1829 	g_string_free (s, TRUE);
1830 }
1831 
list_start(IDL_tree a,gboolean filter_null)1832 static IDL_tree list_start (IDL_tree a, gboolean filter_null)
1833 {
1834 	IDL_tree p;
1835 
1836 	if (!a && filter_null)
1837 		return NULL;
1838 
1839 	p = IDL_list_new (a);
1840 
1841 	return p;
1842 }
1843 
list_chain(IDL_tree a,IDL_tree b,gboolean filter_null)1844 static IDL_tree list_chain (IDL_tree a, IDL_tree b, gboolean filter_null)
1845 {
1846 	IDL_tree p;
1847 
1848 	if (filter_null) {
1849 		if (!b)
1850 			return a;
1851 		if (!a)
1852 			return list_start (b, filter_null);
1853 	}
1854 
1855 	p = IDL_list_new (b);
1856 	a = IDL_list_concat (a, p);
1857 
1858 	return a;
1859 }
1860 
zlist_chain(IDL_tree a,IDL_tree b,gboolean filter_null)1861 static IDL_tree zlist_chain (IDL_tree a, IDL_tree b, gboolean filter_null)
1862 {
1863 	if (a == NULL)
1864 		return list_start (b, filter_null);
1865 	else
1866 		return list_chain (a, b, filter_null);
1867 }
1868 
IDL_binop_chktypes(enum IDL_binop op,IDL_tree a,IDL_tree b)1869 static int IDL_binop_chktypes (enum IDL_binop op, IDL_tree a, IDL_tree b)
1870 {
1871 	if (IDL_NODE_TYPE (a) != IDLN_BINOP &&
1872 	    IDL_NODE_TYPE (b) != IDLN_BINOP &&
1873 	    IDL_NODE_TYPE (a) != IDLN_UNARYOP &&
1874 	    IDL_NODE_TYPE (b) != IDLN_UNARYOP &&
1875 	    IDL_NODE_TYPE (a) != IDL_NODE_TYPE (b)) {
1876 		yyerror ("Invalid mix of types in constant expression");
1877 		return -1;
1878 	}
1879 
1880 	switch (op) {
1881 	case IDL_BINOP_MULT:
1882 	case IDL_BINOP_DIV:
1883 	case IDL_BINOP_ADD:
1884 	case IDL_BINOP_SUB:
1885 		break;
1886 
1887 	case IDL_BINOP_MOD:
1888 	case IDL_BINOP_SHR:
1889 	case IDL_BINOP_SHL:
1890 	case IDL_BINOP_AND:
1891 	case IDL_BINOP_OR:
1892 	case IDL_BINOP_XOR:
1893 		if ((IDL_NODE_TYPE (a) != IDLN_INTEGER ||
1894 		     IDL_NODE_TYPE (b) != IDLN_INTEGER) &&
1895 		    !(IDL_NODE_TYPE (a) == IDLN_BINOP ||
1896 		      IDL_NODE_TYPE (b) == IDLN_BINOP ||
1897 		      IDL_NODE_TYPE (a) == IDLN_UNARYOP ||
1898 		      IDL_NODE_TYPE (b) == IDLN_UNARYOP)) {
1899 			yyerror ("Invalid operation on non-integer value");
1900 			return -1;
1901 		}
1902 		break;
1903 	}
1904 
1905 	return 0;
1906 }
1907 
IDL_unaryop_chktypes(enum IDL_unaryop op,IDL_tree a)1908 static int IDL_unaryop_chktypes (enum IDL_unaryop op, IDL_tree a)
1909 {
1910 	switch (op) {
1911 	case IDL_UNARYOP_PLUS:
1912 	case IDL_UNARYOP_MINUS:
1913 		break;
1914 
1915 	case IDL_UNARYOP_COMPLEMENT:
1916 		if (IDL_NODE_TYPE (a) != IDLN_INTEGER &&
1917 		    !(IDL_NODE_TYPE (a) == IDLN_BINOP ||
1918 		      IDL_NODE_TYPE (a) == IDLN_UNARYOP)) {
1919 			yyerror ("Operand to complement must be integer");
1920 			return -1;
1921 		}
1922 		break;
1923 	}
1924 
1925 	return 0;
1926 }
1927 
IDL_binop_eval_integer(enum IDL_binop op,IDL_tree a,IDL_tree b)1928 static IDL_tree IDL_binop_eval_integer (enum IDL_binop op, IDL_tree a, IDL_tree b)
1929 {
1930 	IDL_tree p = NULL;
1931 
1932 	assert (IDL_NODE_TYPE (a) == IDLN_INTEGER);
1933 
1934 	switch (op) {
1935 	case IDL_BINOP_MULT:
1936 		p = IDL_integer_new (IDL_INTEGER (a).value * IDL_INTEGER (b).value);
1937 		break;
1938 
1939 	case IDL_BINOP_DIV:
1940 		if (IDL_INTEGER (b).value == 0) {
1941 			yyerror ("Divide by zero in constant expression");
1942 			return NULL;
1943 		}
1944 		p = IDL_integer_new (IDL_INTEGER (a).value / IDL_INTEGER (b).value);
1945 		break;
1946 
1947 	case IDL_BINOP_ADD:
1948 		p = IDL_integer_new (IDL_INTEGER (a).value + IDL_INTEGER (b).value);
1949 		break;
1950 
1951 	case IDL_BINOP_SUB:
1952 		p = IDL_integer_new (IDL_INTEGER (a).value - IDL_INTEGER (b).value);
1953 		break;
1954 
1955 	case IDL_BINOP_MOD:
1956 		if (IDL_INTEGER (b).value == 0) {
1957 			yyerror ("Modulo by zero in constant expression");
1958 			return NULL;
1959 		}
1960 		p = IDL_integer_new (IDL_INTEGER (a).value % IDL_INTEGER (b).value);
1961 		break;
1962 
1963 	case IDL_BINOP_SHR:
1964 		p = IDL_integer_new (IDL_INTEGER (a).value >> IDL_INTEGER (b).value);
1965 		break;
1966 
1967 	case IDL_BINOP_SHL:
1968 		p = IDL_integer_new (IDL_INTEGER (a).value << IDL_INTEGER (b).value);
1969 		break;
1970 
1971 	case IDL_BINOP_AND:
1972 		p = IDL_integer_new (IDL_INTEGER (a).value & IDL_INTEGER (b).value);
1973 		break;
1974 
1975 	case IDL_BINOP_OR:
1976 		p = IDL_integer_new (IDL_INTEGER (a).value | IDL_INTEGER (b).value);
1977 		break;
1978 
1979 	case IDL_BINOP_XOR:
1980 		p = IDL_integer_new (IDL_INTEGER (a).value ^ IDL_INTEGER (b).value);
1981 		break;
1982 	}
1983 
1984 	return p;
1985 }
1986 
IDL_binop_eval_float(enum IDL_binop op,IDL_tree a,IDL_tree b)1987 static IDL_tree IDL_binop_eval_float (enum IDL_binop op, IDL_tree a, IDL_tree b)
1988 {
1989 	IDL_tree p = NULL;
1990 
1991 	assert (IDL_NODE_TYPE (a) == IDLN_FLOAT);
1992 
1993 	switch (op) {
1994 	case IDL_BINOP_MULT:
1995 		p = IDL_float_new (IDL_FLOAT (a).value * IDL_FLOAT (b).value);
1996 		break;
1997 
1998 	case IDL_BINOP_DIV:
1999 		if (IDL_FLOAT (b).value == 0.0) {
2000 			yyerror ("Divide by zero in constant expression");
2001 			return NULL;
2002 		}
2003 		p = IDL_float_new (IDL_FLOAT (a).value / IDL_FLOAT (b).value);
2004 		break;
2005 
2006 	case IDL_BINOP_ADD:
2007 		p = IDL_float_new (IDL_FLOAT (a).value + IDL_FLOAT (b).value);
2008 		break;
2009 
2010 	case IDL_BINOP_SUB:
2011 		p = IDL_float_new (IDL_FLOAT (a).value - IDL_FLOAT (b).value);
2012 		break;
2013 
2014 	default:
2015 		break;
2016 	}
2017 
2018 	return p;
2019 }
2020 
IDL_binop_eval(enum IDL_binop op,IDL_tree a,IDL_tree b)2021 static IDL_tree IDL_binop_eval (enum IDL_binop op, IDL_tree a, IDL_tree b)
2022 {
2023 	assert (IDL_NODE_TYPE (a) == IDL_NODE_TYPE (b));
2024 
2025 	switch (IDL_NODE_TYPE (a)) {
2026 	case IDLN_INTEGER: return IDL_binop_eval_integer (op, a, b);
2027 	case IDLN_FLOAT: return IDL_binop_eval_float (op, a, b);
2028 	default: return NULL;
2029 	}
2030 }
2031 
IDL_unaryop_eval_integer(enum IDL_unaryop op,IDL_tree a)2032 static IDL_tree IDL_unaryop_eval_integer (enum IDL_unaryop op, IDL_tree a)
2033 {
2034 	IDL_tree p = NULL;
2035 
2036 	assert (IDL_NODE_TYPE (a) == IDLN_INTEGER);
2037 
2038 	switch (op) {
2039 	case IDL_UNARYOP_PLUS:
2040 		p = IDL_integer_new (IDL_INTEGER (a).value);
2041 		break;
2042 
2043 	case IDL_UNARYOP_MINUS:
2044 		p = IDL_integer_new (-IDL_INTEGER (a).value);
2045 		break;
2046 
2047 	case IDL_UNARYOP_COMPLEMENT:
2048 		p = IDL_integer_new (~IDL_INTEGER (a).value);
2049 		break;
2050 	}
2051 
2052 	return p;
2053 }
2054 
IDL_unaryop_eval_fixed(enum IDL_unaryop op,IDL_tree a)2055 static IDL_tree IDL_unaryop_eval_fixed (enum IDL_unaryop op, IDL_tree a)
2056 {
2057 	IDL_tree p = NULL;
2058 
2059 	assert (IDL_NODE_TYPE (a) == IDLN_FIXED);
2060 
2061 	switch (op) {
2062 	case IDL_UNARYOP_PLUS:
2063 		p = IDL_fixed_new (IDL_FIXED (a).value);
2064 		break;
2065 
2066 	default:
2067 		break;
2068 	}
2069 
2070 	return p;
2071 }
2072 
IDL_unaryop_eval_float(enum IDL_unaryop op,IDL_tree a)2073 static IDL_tree IDL_unaryop_eval_float (enum IDL_unaryop op, IDL_tree a)
2074 {
2075 	IDL_tree p = NULL;
2076 
2077 	assert (IDL_NODE_TYPE (a) == IDLN_FLOAT);
2078 
2079 	switch (op) {
2080 	case IDL_UNARYOP_PLUS:
2081 		p = IDL_float_new (IDL_FLOAT (a).value);
2082 		break;
2083 
2084 	case IDL_UNARYOP_MINUS:
2085 		p = IDL_float_new (-IDL_FLOAT (a).value);
2086 		break;
2087 
2088 	default:
2089 		break;
2090 	}
2091 
2092 	return p;
2093 }
2094 
IDL_unaryop_eval(enum IDL_unaryop op,IDL_tree a)2095 static IDL_tree IDL_unaryop_eval (enum IDL_unaryop op, IDL_tree a)
2096 {
2097 	switch (IDL_NODE_TYPE (a)) {
2098 	case IDLN_INTEGER: return IDL_unaryop_eval_integer (op, a);
2099 	case IDLN_FIXED: return IDL_unaryop_eval_fixed (op, a);
2100 	case IDLN_FLOAT: return IDL_unaryop_eval_float (op, a);
2101 	default: return NULL;
2102 	}
2103 }
2104 
IDL_resolve_const_exp(IDL_tree p,IDL_tree_type type)2105 IDL_tree IDL_resolve_const_exp (IDL_tree p, IDL_tree_type type)
2106 {
2107 	gboolean resolved_value = FALSE, die = FALSE;
2108 	gboolean wrong_type = FALSE;
2109 
2110 	while (!resolved_value && !die) {
2111 		if (IDL_NODE_TYPE (p) == IDLN_IDENT) {
2112 			IDL_tree q = IDL_NODE_UP (p);
2113 
2114 			assert (q != NULL);
2115 			if (IDL_NODE_UP (q) &&
2116 			    IDL_NODE_TYPE (IDL_NODE_UP (q)) == IDLN_TYPE_ENUM) {
2117 				p = q;
2118 				die = TRUE;
2119 				break;
2120 			} else if (IDL_NODE_TYPE (q) != IDLN_CONST_DCL) {
2121 				p = q;
2122 				wrong_type = TRUE;
2123 				die = TRUE;
2124 			} else
2125  				p = IDL_CONST_DCL (q).const_exp;
2126 		}
2127 
2128 		if (p == NULL ||
2129 		    IDL_NODE_TYPE (p) == IDLN_BINOP ||
2130 		    IDL_NODE_TYPE (p) == IDLN_UNARYOP) {
2131 			die = TRUE;
2132 			continue;
2133 		}
2134 
2135 		resolved_value = IDL_NODE_IS_LITERAL (p);
2136 	}
2137 
2138 	if (resolved_value &&
2139 	    type != IDLN_ANY &&
2140 	    IDL_NODE_TYPE (p) != type)
2141 		wrong_type = TRUE;
2142 
2143 	if (wrong_type) {
2144 		yyerror ("Invalid type for constant");
2145 		IDL_tree_error (p, "Previous resolved type declaration");
2146 		return NULL;
2147 	}
2148 
2149 	return resolved_value ? p : NULL;
2150 }
2151 
IDL_queue_new_ident_comment(const char * str)2152 void IDL_queue_new_ident_comment (const char *str)
2153 {
2154 	g_return_if_fail (str != NULL);
2155 
2156 	__IDL_new_ident_comments = g_slist_append (__IDL_new_ident_comments, g_strdup (str));
2157 }
2158 
2159 /*
2160  * Local variables:
2161  * mode: C
2162  * c-basic-offset: 8
2163  * tab-width: 8
2164  * indent-tabs-mode: t
2165  * End:
2166  */
2167