source: trunk/third/libIDL/parser.y @ 21474

Revision 21474, 49.6 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21473, which included commits to RCS files with non-trunk default branches.
Line 
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.1.1.2 2005-03-10 21:56:55 ghudson 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
88extern int              yylex                           (void);
89static IDL_declspec_t   IDL_parse_declspec              (const char *strspec);
90static int              IDL_binop_chktypes              (enum IDL_binop op,
91                                                         IDL_tree a,
92                                                         IDL_tree b);
93static int              IDL_unaryop_chktypes            (enum IDL_unaryop op,
94                                                         IDL_tree a);
95static IDL_tree         IDL_binop_eval                  (enum IDL_binop op,
96                                                         IDL_tree a,
97                                                         IDL_tree b);
98static IDL_tree         IDL_unaryop_eval                (enum IDL_unaryop op,
99                                                         IDL_tree a);
100static IDL_tree         list_start                      (IDL_tree a,
101                                                         gboolean filter_null);
102static IDL_tree         list_chain                      (IDL_tree a,
103                                                         IDL_tree b,
104                                                         gboolean filter_null);
105static IDL_tree         zlist_chain                     (IDL_tree a,
106                                                         IDL_tree b,
107                                                         gboolean filter_null);
108static int              do_token_error                  (IDL_tree p,
109                                                         const char *message,
110                                                         gboolean prev);
111static void             illegal_context_type_error      (IDL_tree p,
112                                                         const char *what);
113static 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
309specification:          /* empty */                     { yyerror ("Empty file"); YYABORT; }
310|                       definition_list                 { __IDL_root = $1; }
311        ;
312
313z_definition_list:      /* empty */                     { $$ = NULL; }
314|                       definition_list
315        ;
316
317definition_list:        definition                      { $$ = list_start ($1, TRUE); }
318|                       definition_list definition      { $$ = list_chain ($1, $2, TRUE); }
319        ;
320
321check_semicolon:        ';'
322|                       /* empty */                     {
323        if (do_token_error ($<tree>0, "Missing semicolon after", TRUE))
324                YYABORT;
325}
326        ;
327
328useless_semicolon:      ';'                             {
329        yyerror ("Dangling semicolon has no effect");
330        $$ = NULL;
331}
332        ;
333
334check_comma:            ','
335|                       /* empty */                     {
336        if (do_token_error ($<tree>0, "Missing comma after", TRUE))
337                YYABORT;
338}
339        ;
340
341illegal_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
350definition:             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
361module_declspec:        z_declspec TOK_MODULE
362        ;
363
364module:                 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 */
402interface_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
413interface:              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
464z_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
511scoped_name_list:       scoped_name                     { $$ = list_start ($1, TRUE); }
512|                       scoped_name_list
513                        check_comma scoped_name         { $$ = list_chain ($1, $3, TRUE); }
514        ;
515
516interface_body:         export_list
517        ;
518
519export_list:            /* empty */                     { $$ = NULL; }
520|                       export_list export              { $$ = zlist_chain ($1, $2, TRUE); }
521        ;
522
523export:                 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
532type_dcl:               z_declspec type_dcl_def         {
533        $$ = $2;
534        assign_declspec ($$, $1);
535}
536        ;
537
538type_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
575type_declarator:        type_spec declarator_list       { $$ = IDL_type_dcl_new ($1, $2); }
576        ;
577
578type_spec:              simple_type_spec
579|                       constr_type_spec
580        ;
581
582simple_type_spec:       base_type_spec
583|                       template_type_spec
584|                       scoped_name
585        ;
586
587constr_type_spec:       struct_type
588|                       union_type
589|                       enum_type
590        ;
591
592z_new_ident_catch:      /* empty */                     {
593        yyerrorv ("Missing identifier in %s definition", $<str>0);
594        YYABORT;
595}
596|                       new_ident
597        ;
598
599z_new_scope_catch:      /* empty */                     {
600        yyerrorv ("Missing identifier in %s definition", $<str>0);
601        YYABORT;
602}
603|                       new_scope
604        ;
605
606struct_type:            z_props TOK_STRUCT
607                        { $<str>$ = "struct"; }
608                        z_new_scope_catch '{'           {
609        g_hash_table_insert (__IDL_structunion_ht, $4, $4);
610        $$ = 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
621union_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        $$ = 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
638switch_type_spec:       integer_type
639|                       char_type
640|                       boolean_type
641|                       enum_type
642|                       scoped_name
643        ;
644
645switch_body:            case_stmt_list
646        ;
647
648case_stmt_list:         case_stmt                       { $$ = list_start ($1, TRUE); }
649|                       case_stmt_list case_stmt        { $$ = list_chain ($1, $2, TRUE); }
650        ;
651
652case_stmt:              case_label_list
653                        element_spec check_semicolon    { $$ = IDL_case_stmt_new ($1, $2); }
654        ;
655
656element_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
670case_label_list:        case_label                      { $$ = list_start ($1, FALSE); }
671|                       case_label_list case_label      { $$ = list_chain ($1, $2, FALSE); }
672        ;
673
674case_label:             TOK_CASE const_exp ':'          { $$ = $2; }
675|                       TOK_DEFAULT ':'                 { $$ = NULL; }
676        ;
677
678const_dcl:              z_declspec const_dcl_def        {
679        $$ = $2;
680        assign_declspec ($$, $1);
681}
682        ;
683
684const_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
691except_dcl:             z_declspec except_dcl_def       {
692        $$ = $2;
693        assign_declspec ($$, $1);
694}
695        ;
696
697except_dcl_def:         TOK_EXCEPTION new_scope '{'
698                                member_zlist
699                        '}' pop_scope                   { $$ = IDL_except_dcl_new ($2, $4); }
700        ;
701
702member_zlist:           /* empty */                     { $$ = NULL; }
703|                       member_zlist member             { $$ = zlist_chain ($1, $2, TRUE); }
704        ;
705
706is_readonly:            /* empty */                     { $$ = FALSE; }
707|                       TOK_READONLY                    { $$ = TRUE; }
708        ;
709
710attr_dcl:               z_declspec attr_dcl_def         {
711        $$ = $2;
712        assign_declspec ($$, $1);
713}
714        ;
715
716attr_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
735param_type_spec:        op_param_type_spec
736|                       TOK_VOID                        {
737        yyerrorv ("Illegal type `void' for %s", $<str>0);
738        $$ = NULL;
739}
740        ;
741
742op_param_type_spec_illegal:
743                        sequence_type
744|                       constr_type_spec
745        ;
746
747op_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
758is_oneway:              /* empty */                     { $$ = FALSE; }
759|                       TOK_ONEWAY                      { $$ = TRUE; }
760        ;
761
762op_dcl:         z_declspec op_dcl_def                   {
763        $$ = $2;
764        assign_declspec ($$, $1);
765}
766        ;
767
768op_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
780op_type_spec:           { $<str>$ = "operation return value"; }
781                        op_param_type_spec              { $$ = $2; }
782|                       TOK_VOID                        { $$ = NULL; }
783        ;
784
785is_varargs:             /* empty */                     { $$ = FALSE; }
786|                       TOK_VARARGS                     { $$ = TRUE; }
787        ;
788
789is_cvarargs:            /* empty */                     { $$ = FALSE; }
790|                       ',' TOK_VARARGS                 { $$ = TRUE; }
791        ;
792
793parameter_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
806param_dcl_list:         param_dcl                       { $$ = list_start ($1, TRUE); }
807|                       param_dcl_list
808                        check_comma param_dcl           { $$ = list_chain ($1, $3, TRUE); }
809        ;
810
811param_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
821param_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
830is_raises_expr:         /* empty */                     { $$ = NULL; }
831|                       raises_expr
832        ;
833
834is_context_expr:        /* empty */                     { $$ = NULL; }
835|                       context_expr
836        ;
837
838raises_expr:            TOK_RAISES '('
839                                scoped_name_list
840                        ')'                             { $$ = $3; }
841        ;
842
843context_expr:           TOK_CONTEXT '('
844                                string_lit_list
845                        ')'                             { $$ = $3; }
846        ;
847
848const_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
860const_exp:              or_expr
861        ;
862
863or_expr:                xor_expr
864|                       or_expr '|' xor_expr            { do_binop ($$, IDL_BINOP_OR, $1, $3); }
865        ;
866
867xor_expr:               and_expr
868|                       xor_expr '^' and_expr           { do_binop ($$, IDL_BINOP_XOR, $1, $3); }
869        ;
870
871and_expr:               shift_expr
872|                       and_expr '&' shift_expr         { do_binop ($$, IDL_BINOP_AND, $1, $3); }
873        ;
874
875shift_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
880add_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
885mult_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
891unary_expr:             unary_op primary_expr           { do_unaryop ($$, $1, $2); }
892|                       primary_expr
893        ;
894
895unary_op:               '-'                             { $$ = IDL_UNARYOP_MINUS; }
896|                       '+'                             { $$ = IDL_UNARYOP_PLUS; }
897|                       '~'                             { $$ = IDL_UNARYOP_COMPLEMENT; }
898        ;
899
900primary_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
918literal:                integer_lit
919|                       string_lit
920|                       char_lit
921|                       fixed_pt_lit
922|                       floating_pt_lit
923|                       boolean_lit
924        ;
925
926enum_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
936scoped_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
944ns_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
972enumerator_list:        new_ident                       { $$ = list_start ($1, TRUE); }
973|                       enumerator_list
974                        check_comma new_ident           { $$ = list_chain ($1, $3, TRUE); }
975        ;
976
977member_list:            member                          { $$ = list_start ($1, TRUE); }
978|                       member_list member              { $$ = list_chain ($1, $2, TRUE); }
979        ;
980
981member:                 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
996base_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
1007template_type_spec:     sequence_type
1008|                       string_type
1009|                       wide_string_type
1010|                       fixed_pt_type
1011        ;
1012
1013sequence_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
1021floating_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
1026fixed_pt_type:          TOK_FIXED '<'
1027                                positive_int_const ',' integer_lit
1028                        '>'                             { $$ = IDL_type_fixed_new ($3, $5); }
1029        ;
1030
1031fixed_pt_const_type:    TOK_FIXED                       { $$ = IDL_type_fixed_new (NULL, NULL); }
1032        ;
1033
1034integer_type:           signed_int                      { $$ = IDL_type_integer_new (TRUE, $1); }
1035|                       unsigned_int                    { $$ = IDL_type_integer_new (FALSE, $1); }
1036        ;
1037
1038signed_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
1043signed_short_int:       TOK_SHORT
1044        ;
1045
1046signed_long_int:        TOK_LONG
1047        ;
1048
1049signed_longlong_int:    TOK_LONG TOK_LONG
1050        ;
1051
1052unsigned_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
1057unsigned_short_int:     TOK_UNSIGNED TOK_SHORT
1058        ;
1059
1060unsigned_long_int:      TOK_UNSIGNED TOK_LONG
1061        ;
1062
1063unsigned_longlong_int:  TOK_UNSIGNED TOK_LONG TOK_LONG
1064        ;
1065
1066char_type:              TOK_CHAR                        { $$ = IDL_type_char_new (); }
1067        ;
1068
1069wide_char_type:         TOK_WCHAR                       { $$ = IDL_type_wide_char_new (); }
1070        ;
1071
1072boolean_type:           TOK_BOOLEAN                     { $$ = IDL_type_boolean_new (); }
1073        ;
1074
1075octet_type:             TOK_OCTET                       { $$ = IDL_type_octet_new (); }
1076        ;
1077
1078any_type:               TOK_ANY                         { $$ = IDL_type_any_new (); }
1079        ;
1080
1081object_type:            TOK_OBJECT                      { $$ = IDL_type_object_new (); }
1082        ;
1083
1084typecode_type:          TOK_TYPECODE                    { $$ = IDL_type_typecode_new (); }
1085        ;
1086
1087string_type:            TOK_STRING '<'
1088                                positive_int_const
1089                                '>'                     { $$ = IDL_type_string_new ($3); }
1090|                       TOK_STRING                      { $$ = IDL_type_string_new (NULL); }
1091        ;
1092
1093wide_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
1099declarator_list:        declarator                      { $$ = list_start ($1, TRUE); }
1100|                       declarator_list
1101                        check_comma declarator          { $$ = list_chain ($1, $3, TRUE); }
1102        ;
1103
1104declarator:             simple_declarator
1105|                       complex_declarator
1106        ;
1107
1108simple_declarator:      new_ident
1109        ;
1110
1111complex_declarator:     array_declarator
1112        ;
1113
1114simple_declarator_list: simple_declarator               { $$ = list_start ($1, TRUE); }
1115|                       simple_declarator_list
1116                        check_comma simple_declarator   { $$ = list_chain ($1, $3, TRUE); }
1117        ;
1118
1119array_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
1134fixed_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
1139fixed_array_size:       '[' positive_int_const ']'      { $$ = $2; }
1140|                       '[' ']'                         { $$ = NULL; }
1141        ;
1142
1143prop_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
1165ident:                  TOK_IDENT                       { $$ = IDL_ident_new ($1); }
1166        ;
1167
1168new_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
1176new_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
1189new_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
1206pop_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
1218ns_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
1256ns_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
1274cur_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
1305ns_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
1324string_lit_list:        string_lit                      { $$ = list_start ($1, TRUE); }
1325|                       string_lit_list
1326                        check_comma string_lit          { $$ = list_chain ($1, $3, TRUE); }
1327        ;
1328
1329positive_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
1368z_declspec:             /* empty */                     { $$ = 0; }
1369|                       TOK_DECLSPEC                    {
1370        $$ = IDL_parse_declspec ($1);
1371        g_free ($1);
1372}
1373        ;
1374
1375z_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
1388integer_lit:            TOK_INTEGER                     { $$ = IDL_integer_new ($1); }
1389        ;
1390
1391string_lit:             dqstring_cat                    { $$ = IDL_string_new ($1); }
1392        ;
1393
1394char_lit:               sqstring                        { $$ = IDL_char_new ($1); }
1395        ;
1396
1397fixed_pt_lit:           TOK_FIXEDP                      { $$ = IDL_fixed_new ($1); }
1398        ;
1399
1400floating_pt_lit:        TOK_FLOATP                      { $$ = IDL_float_new ($1); }
1401        ;
1402
1403boolean_lit:            TOK_TRUE                        { $$ = IDL_boolean_new (TRUE); }
1404|                       TOK_FALSE                       { $$ = IDL_boolean_new (FALSE); }
1405        ;
1406
1407codefrag:               z_declspec TOK_CODEFRAG         {
1408        $$ = $2;
1409        assign_declspec ($$, $1);
1410}
1411        ;
1412
1413srcfile:                TOK_SRCFILE             {
1414        $$ = $1;
1415}
1416        ;
1417
1418dqstring_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
1427dqstring:               TOK_DQSTRING                    {
1428        char *s = IDL_do_escapes ($1);
1429        g_free ($1);
1430        $$ = s;
1431}
1432        ;
1433
1434sqstring:               TOK_SQSTRING                    {
1435        char *s = IDL_do_escapes ($1);
1436        g_free ($1);
1437        $$ = s;
1438}
1439        ;
1440
1441%%
1442
1443void __IDL_parser_reset (void)
1444{
1445        yyclearin;
1446}
1447
1448static 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
1462gchar *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
1493static 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
1536static 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
1571void 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
1603void 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
1648int IDL_inhibit_get (void)
1649{
1650        g_return_val_if_fail (__IDL_is_parsing, -1);
1651
1652        return __IDL_inhibits;
1653}
1654
1655void IDL_inhibit_push (void)
1656{
1657        g_return_if_fail (__IDL_is_parsing);
1658
1659        ++__IDL_inhibits;
1660}
1661
1662void 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
1670static 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
1678static 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
1686static 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
1694void __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
1721static 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
1738IDL_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
1784void 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
1795static 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
1814static 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
1823static 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
1832static 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
1844static 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
1861static 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
1869static 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
1908static 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
1928static 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
1987static 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
2021static 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
2032static 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
2055static 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
2073static 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
2095static 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
2105IDL_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
2152void 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 */
Note: See TracBrowser for help on using the repository browser.