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

Revision 18251, 49.6 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18250, 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.1 2002-12-26 17:10:40 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|                       wide_char_type
851|                       boolean_type
852|                       floating_pt_type
853|                       string_type
854|                       wide_string_type
855|                       fixed_pt_const_type
856|                       scoped_name
857        ;
858
859const_exp:              or_expr
860        ;
861
862or_expr:                xor_expr
863|                       or_expr '|' xor_expr            { do_binop ($$, IDL_BINOP_OR, $1, $3); }
864        ;
865
866xor_expr:               and_expr
867|                       xor_expr '^' and_expr           { do_binop ($$, IDL_BINOP_XOR, $1, $3); }
868        ;
869
870and_expr:               shift_expr
871|                       and_expr '&' shift_expr         { do_binop ($$, IDL_BINOP_AND, $1, $3); }
872        ;
873
874shift_expr:             add_expr
875|                       shift_expr TOK_OP_SHR add_expr  { do_binop ($$, IDL_BINOP_SHR, $1, $3); }
876|                       shift_expr TOK_OP_SHL add_expr  { do_binop ($$, IDL_BINOP_SHL, $1, $3); }
877        ;
878
879add_expr:               mult_expr
880|                       add_expr '+' mult_expr          { do_binop ($$, IDL_BINOP_ADD, $1, $3); }
881|                       add_expr '-' mult_expr          { do_binop ($$, IDL_BINOP_SUB, $1, $3); }
882        ;
883
884mult_expr:              unary_expr
885|                       mult_expr '*' unary_expr        { do_binop ($$, IDL_BINOP_MULT, $1, $3); }
886|                       mult_expr '/' unary_expr        { do_binop ($$, IDL_BINOP_DIV, $1, $3); }
887|                       mult_expr '%' unary_expr        { do_binop ($$, IDL_BINOP_MOD, $1, $3); }
888        ;
889
890unary_expr:             unary_op primary_expr           { do_unaryop ($$, $1, $2); }
891|                       primary_expr
892        ;
893
894unary_op:               '-'                             { $$ = IDL_UNARYOP_MINUS; }
895|                       '+'                             { $$ = IDL_UNARYOP_PLUS; }
896|                       '~'                             { $$ = IDL_UNARYOP_COMPLEMENT; }
897        ;
898
899primary_expr:           scoped_name                     {
900        IDL_tree p, literal;
901       
902        assert (IDL_NODE_TYPE ($1) == IDLN_IDENT);
903
904        p = IDL_NODE_UP ($1);
905       
906        if ((literal = IDL_resolve_const_exp ($1, IDLN_ANY))) {
907                ++IDL_NODE_REFS (literal);
908                $$ = literal;
909                IDL_tree_free ($1);
910        } else
911                $$ = $1;
912}
913|                       literal
914|                       '(' const_exp ')'               { $$ = $2; }
915        ;
916
917literal:                integer_lit
918|                       string_lit
919|                       char_lit
920|                       fixed_pt_lit
921|                       floating_pt_lit
922|                       boolean_lit
923        ;
924
925enum_type:              z_props TOK_ENUM
926                        { $<str>$ = "enum"; }
927                        z_new_ident_catch '{'
928                                enumerator_list
929                        '}'                             {
930        $$ = IDL_type_enum_new ($4, $6);
931        assign_props (IDL_TYPE_ENUM ($$).ident, $1);
932}
933        ;
934
935scoped_name:            ns_scoped_name                  {
936        assert ($1 != NULL);
937        assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
938        assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
939        $$ = IDL_GENTREE ($1).data;
940}
941        ;
942
943ns_scoped_name:         ns_prev_ident
944|                       TOK_OP_SCOPE ns_global_ident    { $$ = $2; }
945|                       ns_scoped_name TOK_OP_SCOPE
946                        ident                           {
947        IDL_tree p;
948
949        assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
950        assert (IDL_NODE_TYPE ($3) == IDLN_IDENT);
951
952#ifdef YYDEBUG
953        if (yydebug)
954                fprintf (stderr, "ns: looking in `%s' for `%s'\n",
955                  IDL_IDENT (IDL_GENTREE ($1).data).str, IDL_IDENT($3).str);
956#endif
957
958        if ((p = IDL_ns_lookup_this_scope (__IDL_root_ns, $1, $3, NULL)) == NULL) {
959                yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($3).str);
960                IDL_tree_free ($3);
961                YYABORT;
962        }
963        IDL_tree_free ($3);
964#ifdef REF_IDENTS
965        ++IDL_NODE_REFS (IDL_GENTREE (p).data);
966#endif
967        $$ = p;
968}
969        ;
970
971enumerator_list:        new_ident                       { $$ = list_start ($1, TRUE); }
972|                       enumerator_list
973                        check_comma new_ident           { $$ = list_chain ($1, $3, TRUE); }
974        ;
975
976member_list:            member                          { $$ = list_start ($1, TRUE); }
977|                       member_list member              { $$ = list_chain ($1, $2, TRUE); }
978        ;
979
980member:                 type_spec declarator_list
981                        check_semicolon                 {
982        char *s;
983
984        $$ = IDL_member_new ($1, $2);
985        if (IDL_NODE_TYPE ($1) == IDLN_IDENT &&
986            g_hash_table_lookup (__IDL_structunion_ht, $1)) {
987                s = IDL_ns_ident_to_qstring (IDL_LIST ($2).data, "::", 0);
988                yyerrorv ("Member `%s'", s);
989                do_token_error (IDL_NODE_UP ($1), "recurses", TRUE);
990                g_free (s);
991        }
992}
993        ;
994
995base_type_spec:         floating_pt_type
996|                       integer_type
997|                       char_type
998|                       wide_char_type
999|                       boolean_type
1000|                       octet_type
1001|                       any_type
1002|                       object_type
1003|                       typecode_type
1004        ;
1005
1006template_type_spec:     sequence_type
1007|                       string_type
1008|                       wide_string_type
1009|                       fixed_pt_type
1010        ;
1011
1012sequence_type:          TOK_SEQUENCE '<'
1013                                simple_type_spec ',' positive_int_const
1014                        '>'                             { $$ = IDL_type_sequence_new ($3, $5); }
1015|                       TOK_SEQUENCE '<'
1016                                simple_type_spec
1017                        '>'                             { $$ = IDL_type_sequence_new ($3, NULL); }
1018        ;
1019
1020floating_pt_type:       TOK_FLOAT                       { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_FLOAT); }
1021|                       TOK_DOUBLE                      { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_DOUBLE); }
1022|                       TOK_LONG TOK_DOUBLE             { $$ = IDL_type_float_new (IDL_FLOAT_TYPE_LONGDOUBLE); }
1023        ;
1024
1025fixed_pt_type:          TOK_FIXED '<'
1026                                positive_int_const ',' integer_lit
1027                        '>'                             { $$ = IDL_type_fixed_new ($3, $5); }
1028        ;
1029
1030fixed_pt_const_type:    TOK_FIXED                       { $$ = IDL_type_fixed_new (NULL, NULL); }
1031        ;
1032
1033integer_type:           signed_int                      { $$ = IDL_type_integer_new (TRUE, $1); }
1034|                       unsigned_int                    { $$ = IDL_type_integer_new (FALSE, $1); }
1035        ;
1036
1037signed_int:             signed_short_int                { $$ = IDL_INTEGER_TYPE_SHORT; }
1038|                       signed_long_int                 { $$ = IDL_INTEGER_TYPE_LONG; }
1039|                       signed_longlong_int             { $$ = IDL_INTEGER_TYPE_LONGLONG; }
1040        ;
1041
1042signed_short_int:       TOK_SHORT
1043        ;
1044
1045signed_long_int:        TOK_LONG
1046        ;
1047
1048signed_longlong_int:    TOK_LONG TOK_LONG
1049        ;
1050
1051unsigned_int:           unsigned_short_int              { $$ = IDL_INTEGER_TYPE_SHORT; }
1052|                       unsigned_long_int               { $$ = IDL_INTEGER_TYPE_LONG; }
1053|                       unsigned_longlong_int           { $$ = IDL_INTEGER_TYPE_LONGLONG; }
1054        ;
1055
1056unsigned_short_int:     TOK_UNSIGNED TOK_SHORT
1057        ;
1058
1059unsigned_long_int:      TOK_UNSIGNED TOK_LONG
1060        ;
1061
1062unsigned_longlong_int:  TOK_UNSIGNED TOK_LONG TOK_LONG
1063        ;
1064
1065char_type:              TOK_CHAR                        { $$ = IDL_type_char_new (); }
1066        ;
1067
1068wide_char_type:         TOK_WCHAR                       { $$ = IDL_type_wide_char_new (); }
1069        ;
1070
1071boolean_type:           TOK_BOOLEAN                     { $$ = IDL_type_boolean_new (); }
1072        ;
1073
1074octet_type:             TOK_OCTET                       { $$ = IDL_type_octet_new (); }
1075        ;
1076
1077any_type:               TOK_ANY                         { $$ = IDL_type_any_new (); }
1078        ;
1079
1080object_type:            TOK_OBJECT                      { $$ = IDL_type_object_new (); }
1081        ;
1082
1083typecode_type:          TOK_TYPECODE                    { $$ = IDL_type_typecode_new (); }
1084        ;
1085
1086string_type:            TOK_STRING '<'
1087                                positive_int_const
1088                                '>'                     { $$ = IDL_type_string_new ($3); }
1089|                       TOK_STRING                      { $$ = IDL_type_string_new (NULL); }
1090        ;
1091
1092wide_string_type:       TOK_WSTRING '<'
1093                                positive_int_const
1094                        '>'                             { $$ = IDL_type_wide_string_new ($3); }
1095|                       TOK_WSTRING                     { $$ = IDL_type_wide_string_new (NULL); }
1096        ;
1097
1098declarator_list:        declarator                      { $$ = list_start ($1, TRUE); }
1099|                       declarator_list
1100                        check_comma declarator          { $$ = list_chain ($1, $3, TRUE); }
1101        ;
1102
1103declarator:             simple_declarator
1104|                       complex_declarator
1105        ;
1106
1107simple_declarator:      new_ident
1108        ;
1109
1110complex_declarator:     array_declarator
1111        ;
1112
1113simple_declarator_list: simple_declarator               { $$ = list_start ($1, TRUE); }
1114|                       simple_declarator_list
1115                        check_comma simple_declarator   { $$ = list_chain ($1, $3, TRUE); }
1116        ;
1117
1118array_declarator:       new_ident
1119                        fixed_array_size_list           {
1120        IDL_tree p;
1121        int i;
1122
1123        $$ = IDL_type_array_new ($1, $2);
1124        for (i = 1, p = $2; p; ++i, p = IDL_LIST (p).next)
1125                if (!IDL_LIST (p).data) {
1126                        char *s = IDL_ns_ident_to_qstring ($1, "::", 0);
1127                        yyerrorv ("Missing value in dimension %d of array `%s'", i, s);
1128                        g_free (s);
1129                }
1130}
1131        ;
1132
1133fixed_array_size_list:  fixed_array_size                { $$ = list_start ($1, FALSE); }
1134|                       fixed_array_size_list
1135                        fixed_array_size                { $$ = list_chain ($1, $2, FALSE); }
1136        ;
1137
1138fixed_array_size:       '[' positive_int_const ']'      { $$ = $2; }
1139|                       '[' ']'                         { $$ = NULL; }
1140        ;
1141
1142prop_hash:              TOK_PROP_KEY
1143                        TOK_PROP_VALUE                  {
1144        $$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal);
1145        g_hash_table_insert ($$, $1, $2);
1146}
1147|                       prop_hash ','
1148                        TOK_PROP_KEY
1149                        TOK_PROP_VALUE                  {
1150        $$ = $1;
1151        g_hash_table_insert ($$, $3, $4);
1152}
1153|                       TOK_PROP_KEY                    {
1154        $$ = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal);
1155        g_hash_table_insert ($$, $1, g_strdup (""));
1156}
1157|                       prop_hash ','
1158                        TOK_PROP_KEY                    {
1159        $$ = $1;
1160        g_hash_table_insert ($$, $3, g_strdup (""));
1161}
1162        ;
1163
1164ident:                  TOK_IDENT                       { $$ = IDL_ident_new ($1); }
1165        ;
1166
1167new_ident:              ns_new_ident                    {
1168        assert ($1 != NULL);
1169        assert (IDL_NODE_TYPE ($1) == IDLN_GENTREE);
1170        assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1171        $$ = IDL_GENTREE ($1).data;
1172}
1173        ;
1174
1175new_scope:              ns_new_ident                    {
1176        IDL_tree        old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1177        IDL_ns_push_scope (__IDL_root_ns, $1);
1178#ifdef YYDEBUG
1179        if (yydebug)
1180                fprintf (stderr, "ns: entering new scope `%s' of `%s'\n",
1181                       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str);
1182#endif
1183        assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1184        $$ = IDL_GENTREE ($1).data;
1185}
1186        ;
1187
1188new_or_prev_scope:      cur_ns_new_or_prev_ident        {
1189        IDL_tree        old_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1190        IDL_ns_push_scope (__IDL_root_ns, $1);
1191        assert (IDL_NS (__IDL_root_ns).current != NULL);
1192        assert (IDL_NODE_TYPE (IDL_NS (__IDL_root_ns).current) == IDLN_GENTREE);
1193        assert (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data != NULL);
1194        assert (IDL_NODE_TYPE (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data) == IDLN_IDENT);
1195#ifdef YYDEBUG
1196        if (yydebug)
1197                fprintf (stderr,"ns: entering new/prev scope `%s' of `%s'\n",
1198                       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str, IDL_IDENT(old_top).str);
1199#endif
1200        assert (IDL_NODE_TYPE (IDL_GENTREE ($1).data) == IDLN_IDENT);
1201        $$ = IDL_GENTREE ($1).data;
1202}
1203        ;
1204
1205pop_scope:              /* empty */                     {
1206        IDL_tree cur_top = IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data;
1207        IDL_ns_pop_scope (__IDL_root_ns);
1208#ifdef YYDEBUG
1209        if (yydebug)
1210                fprintf (stderr, "ns: pop scope from `%s' to `%s'\n",
1211                       IDL_IDENT(cur_top).str,
1212                       IDL_IDENT (IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str);
1213#endif
1214}
1215        ;
1216
1217ns_new_ident:           ident                           {
1218        IDL_tree p;
1219
1220        if ((p = IDL_ns_place_new (__IDL_root_ns, $1)) == NULL) {
1221                IDL_tree q;
1222                int i;
1223
1224                p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL);
1225
1226                for (i = 0, q = IDL_GENTREE (p).data;
1227                     q && (IDL_NODE_TYPE (q) == IDLN_IDENT ||
1228                           IDL_NODE_TYPE (q) == IDLN_LIST) && i < 4;
1229                     ++i)
1230                        if (IDL_NODE_UP (q))
1231                                q = IDL_NODE_UP (q);
1232
1233                if (q) {
1234                        IDL_tree_error ($1, "`%s' conflicts", IDL_IDENT ($1).str);
1235                        do_token_error (q, "with", FALSE);
1236                } else
1237                        yyerrorv ("`%s' duplicate identifier", IDL_IDENT ($1).str);
1238
1239                IDL_tree_free ($1);
1240                YYABORT;
1241        }
1242        assert (IDL_IDENT ($1)._ns_ref == p);
1243#ifdef REF_IDENTS
1244        ++IDL_NODE_REFS (IDL_GENTREE (p).data);
1245#endif
1246        if (__IDL_new_ident_comments != NULL) {
1247                assert (IDL_IDENT ($1).comments == NULL);
1248                IDL_IDENT ($1).comments = __IDL_new_ident_comments;
1249                __IDL_new_ident_comments = NULL;
1250        }
1251        $$ = p;
1252}
1253        ;
1254
1255ns_prev_ident:          ident                           {
1256        IDL_tree p;
1257
1258        if ((p = IDL_ns_resolve_ident (__IDL_root_ns, $1)) == NULL) {
1259                yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str);
1260                IDL_tree_free ($1);
1261                YYABORT;
1262        }
1263        IDL_tree_free ($1);
1264        assert (IDL_GENTREE (p).data != NULL);
1265        assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1266#ifdef REF_IDENTS
1267        ++IDL_NODE_REFS (IDL_GENTREE (p).data);
1268#endif
1269        $$ = p;
1270}
1271        ;
1272
1273cur_ns_new_or_prev_ident:
1274                        ident                           {
1275        IDL_tree p;
1276
1277        if ((p = IDL_ns_lookup_cur_scope (__IDL_root_ns, $1, NULL)) == NULL) {
1278#ifdef YYDEBUG
1279                if (yydebug)
1280                        fprintf (stderr, "ns: place_new `%s' in `%s'\n",
1281                          IDL_IDENT($1).str,
1282                          IDL_IDENT(IDL_GENTREE (IDL_NS (__IDL_root_ns).current).data).str );
1283#endif
1284                p = IDL_ns_place_new (__IDL_root_ns, $1);
1285                assert (p != NULL);
1286                assert (IDL_IDENT ($1)._ns_ref == p);
1287                if (__IDL_new_ident_comments != NULL) {
1288                        assert (IDL_IDENT ($1).comments == NULL);
1289                        IDL_IDENT ($1).comments = __IDL_new_ident_comments;
1290                        __IDL_new_ident_comments = NULL;
1291                }
1292        } else {
1293                IDL_tree_free ($1);
1294                assert (IDL_GENTREE (p).data != NULL);
1295                assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1296        }
1297#ifdef REF_IDENTS
1298        ++IDL_NODE_REFS (IDL_GENTREE (p).data);
1299#endif
1300        $$ = p;
1301}
1302        ;
1303
1304ns_global_ident:        ident                           {
1305        IDL_tree p;
1306
1307        if ((p = IDL_ns_lookup_this_scope (
1308                __IDL_root_ns,IDL_NS (__IDL_root_ns).file, $1, NULL)) == NULL) {
1309                yyerrorv ("`%s' undeclared identifier", IDL_IDENT ($1).str);
1310                IDL_tree_free ($1);
1311                YYABORT;
1312        }
1313        IDL_tree_free ($1);
1314        assert (IDL_GENTREE (p).data != NULL);
1315        assert (IDL_IDENT (IDL_GENTREE (p).data)._ns_ref == p);
1316#ifdef REF_IDENTS
1317        ++IDL_NODE_REFS (IDL_GENTREE (p).data);
1318#endif
1319        $$ = p;
1320}
1321        ;
1322
1323string_lit_list:        string_lit                      { $$ = list_start ($1, TRUE); }
1324|                       string_lit_list
1325                        check_comma string_lit          { $$ = list_chain ($1, $3, TRUE); }
1326        ;
1327
1328positive_int_const:     const_exp                       {
1329        IDL_tree literal, ident = NULL;
1330        IDL_longlong_t value = 0;
1331
1332        if ((literal = IDL_resolve_const_exp ($1, IDLN_INTEGER))) {
1333                assert (IDL_NODE_TYPE (literal) == IDLN_INTEGER);
1334                ++IDL_NODE_REFS (literal);
1335                value = IDL_INTEGER (literal).value;
1336                if ( literal != $1 )
1337                        IDL_tree_free ($1);
1338        }
1339
1340        if (literal && IDL_NODE_UP (literal) &&
1341            IDL_NODE_TYPE (IDL_NODE_UP (literal)) == IDLN_CONST_DCL)
1342                ident = IDL_CONST_DCL (IDL_NODE_UP (literal)).ident;
1343       
1344        if (literal == NULL) {
1345                if (!(__IDL_flags & IDLF_NO_EVAL_CONST))
1346                        yyerror ("Could not resolve constant expression");
1347                $$ = $1;
1348        } else if (value == 0) {
1349                yyerror ("Zero array size is illegal");
1350                if (ident)
1351                        IDL_tree_error (ident, "From constant declared here");
1352                $$ = NULL;
1353        } else if (value < 0) {
1354                yywarningv (IDL_WARNING1, "Cannot use negative value %"
1355                            IDL_LL "d, using %" IDL_LL "d",
1356                           value, -value);
1357                if (ident)
1358                        IDL_tree_warning (ident,
1359                                          IDL_WARNING1, "From constant declared here");
1360                $$ = IDL_integer_new (-value);
1361        }
1362        else
1363                $$ = IDL_integer_new (value);
1364}
1365        ;
1366
1367z_declspec:             /* empty */                     { $$ = 0; }
1368|                       TOK_DECLSPEC                    {
1369        $$ = IDL_parse_declspec ($1);
1370        g_free ($1);
1371}
1372        ;
1373
1374z_props:                /* empty */                     { $$ = NULL; }
1375|                       '['                             {
1376        /* Enable property scanning */
1377        if (__IDL_flags & IDLF_PROPERTIES)
1378                __IDL_flagsi |= IDLFP_PROPERTIES;
1379        else {
1380                yyerror ("Property syntax not enabled");
1381                YYABORT;
1382        }
1383}                       prop_hash
1384                        ']'                             { $$ = $3; }
1385        ;
1386
1387integer_lit:            TOK_INTEGER                     { $$ = IDL_integer_new ($1); }
1388        ;
1389
1390string_lit:             dqstring_cat                    { $$ = IDL_string_new ($1); }
1391        ;
1392
1393char_lit:               sqstring                        { $$ = IDL_char_new ($1); }
1394        ;
1395
1396fixed_pt_lit:           TOK_FIXEDP                      { $$ = IDL_fixed_new ($1); }
1397        ;
1398
1399floating_pt_lit:        TOK_FLOATP                      { $$ = IDL_float_new ($1); }
1400        ;
1401
1402boolean_lit:            TOK_TRUE                        { $$ = IDL_boolean_new (TRUE); }
1403|                       TOK_FALSE                       { $$ = IDL_boolean_new (FALSE); }
1404        ;
1405
1406codefrag:               z_declspec TOK_CODEFRAG         {
1407        $$ = $2;
1408        assign_declspec ($$, $1);
1409}
1410        ;
1411
1412srcfile:                TOK_SRCFILE             {
1413        $$ = $1;
1414}
1415        ;
1416
1417dqstring_cat:           dqstring
1418|                       dqstring_cat dqstring           {
1419        char *catstr = g_malloc (strlen ($1) + strlen ($2) + 1);
1420        strcpy (catstr, $1); g_free ($1);
1421        strcat (catstr, $2); g_free ($2);
1422        $$ = catstr;
1423}
1424        ;
1425
1426dqstring:               TOK_DQSTRING                    {
1427        char *s = IDL_do_escapes ($1);
1428        g_free ($1);
1429        $$ = s;
1430}
1431        ;
1432
1433sqstring:               TOK_SQSTRING                    {
1434        char *s = IDL_do_escapes ($1);
1435        g_free ($1);
1436        $$ = s;
1437}
1438        ;
1439
1440%%
1441
1442void __IDL_parser_reset (void)
1443{
1444        yyclearin;
1445}
1446
1447static const char *IDL_ns_get_cur_prefix (IDL_ns ns)
1448{
1449        IDL_tree p;
1450
1451        p = IDL_NS (ns).current;
1452
1453        assert (p != NULL);
1454
1455        while (p && !IDL_GENTREE (p)._cur_prefix)
1456                p = IDL_NODE_UP (p);
1457
1458        return p ? IDL_GENTREE (p)._cur_prefix : NULL;
1459}
1460
1461gchar *IDL_ns_ident_make_repo_id (IDL_ns ns, IDL_tree p,
1462                                  const char *p_prefix, int *major, int *minor)
1463{
1464        GString *s = g_string_new (NULL);
1465        const char *prefix;
1466        char *q;
1467
1468        assert (p != NULL);
1469       
1470        if (IDL_NODE_TYPE (p) == IDLN_IDENT)
1471                p = IDL_IDENT_TO_NS (p);
1472
1473        assert (p != NULL);
1474
1475        prefix = p_prefix ? p_prefix : IDL_ns_get_cur_prefix (ns);
1476
1477        q = IDL_ns_ident_to_qstring (p, "/", 0);
1478        g_string_printf (s, "IDL:%s%s%s:%d.%d",
1479                          prefix ? prefix : "",
1480                          prefix && *prefix ? "/" : "",
1481                          q,
1482                          major ? *major : 1,
1483                          minor ? *minor : 0);
1484        g_free (q);
1485
1486        q = s->str;
1487        g_string_free (s, FALSE);
1488
1489        return q;
1490}
1491
1492static const char *get_name_token (const char *s, char **tok)
1493{
1494        const char *begin = s;
1495        int state = 0;
1496
1497        if (!s)
1498                return NULL;
1499
1500        while (g_ascii_isspace (*s)) ++s;
1501       
1502        while (1) switch (state) {
1503        case 0:         /* Unknown */
1504                if (*s == ':')
1505                        state = 1;
1506                else if (isalnum ((int)*s) || *s == '_') {
1507                        begin = s;
1508                        state = 2;
1509                } else
1510                        return NULL;
1511                break;
1512        case 1:         /* Scope */
1513                if (strncmp (s, "::", 2) == 0) {
1514                        char *r = g_malloc (3);
1515                        strcpy (r, "::");
1516                        *tok = r;
1517                        return s + 2;
1518                } else  /* Invalid */
1519                        return NULL;
1520                break;
1521        case 2:
1522                if (isalnum ((int)*s) || *s == '_')
1523                        ++s;
1524                else {
1525                        char *r = g_malloc (s - begin + 1);
1526                        strncpy (r, begin, s - begin + 1);
1527                        r[s - begin] = 0;
1528                        *tok = r;
1529                        return s;
1530                }
1531                break;
1532        }
1533}
1534
1535static IDL_tree IDL_ns_pragma_parse_name (IDL_ns ns, const char *s)
1536{
1537        IDL_tree p = IDL_NS (ns).current, q;
1538        int start = 1;
1539        char *tok;
1540
1541        /* This is a hack to allow directives for an ident (such
1542         * as and interface) to be located within the scope of
1543         * that identifier. */
1544        if ( p && (q=IDL_GENTREE(p).data)!=0
1545          && IDL_NODE_TYPE(q)==IDLN_IDENT
1546          && strcmp(s,IDL_IDENT(q).str)==0 ) {
1547                return p;
1548        }
1549
1550        while (p && *s && (s = get_name_token (s, &tok))) {
1551                if (tok == NULL)
1552                        return NULL;
1553                if (strcmp (tok, "::") == 0) {
1554                        if (start) {
1555                                /* Globally scoped */
1556                                p = IDL_NS (ns).file;
1557                        }
1558                        g_free (tok);
1559                } else {
1560                        IDL_tree ident = IDL_ident_new (tok);
1561                        p = IDL_ns_lookup_this_scope (__IDL_root_ns, p, ident, NULL);
1562                        IDL_tree_free (ident);
1563                }
1564                start = 0;
1565        }
1566       
1567        return p;
1568}
1569
1570void IDL_ns_ID (IDL_ns ns, const char *s)
1571{
1572        char name[1024], id[1024];
1573        IDL_tree p, ident;
1574        int n;
1575
1576        n = sscanf (s, "%1023s \"%1023s\"", name, id);
1577        if (n < 2 && __IDL_is_parsing) {
1578                yywarning (IDL_WARNING1, "Malformed pragma ID");
1579                return;
1580        }
1581        if (id[strlen (id) - 1] == '"')
1582                id[strlen (id) - 1] = 0;
1583
1584        p = IDL_ns_pragma_parse_name (__IDL_root_ns, name);
1585        if (!p && __IDL_is_parsing) {
1586                yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma ID", name);
1587                return;
1588        }
1589
1590        /* We have resolved the identifier, so assign the repo id */
1591        assert (IDL_NODE_TYPE (p) == IDLN_GENTREE);
1592        assert (IDL_GENTREE (p).data != NULL);
1593        assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
1594        ident = IDL_GENTREE (p).data;
1595
1596        if (IDL_IDENT_REPO_ID (ident) != NULL)
1597                g_free (IDL_IDENT_REPO_ID (ident));
1598
1599        IDL_IDENT_REPO_ID (ident) = g_strdup (id);
1600}
1601
1602void IDL_ns_version (IDL_ns ns, const char *s)
1603{
1604        char name[1024];
1605        int n, major, minor;
1606        IDL_tree p, ident;
1607
1608        n = sscanf (s, "%1023s %u.%u", name, &major, &minor);
1609        if (n < 3 && __IDL_is_parsing) {
1610                yywarning (IDL_WARNING1, "Malformed pragma version");
1611                return;
1612        }
1613
1614        p = IDL_ns_pragma_parse_name (__IDL_root_ns, name);
1615        if (!p && __IDL_is_parsing) {
1616                yywarningv (IDL_WARNING1, "Unknown identifier `%s' in pragma version", name);
1617                return;
1618        }
1619
1620        /* We have resolved the identifier, so assign the repo id */
1621        assert (IDL_NODE_TYPE (p) == IDLN_GENTREE);
1622        assert (IDL_GENTREE (p).data != NULL);
1623        assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
1624        ident = IDL_GENTREE (p).data;
1625
1626        if (IDL_IDENT_REPO_ID (ident) != NULL) {
1627                char *v = strrchr (IDL_IDENT_REPO_ID (ident), ':');
1628                if (v) {
1629                        GString *s;
1630
1631                        *v = 0;
1632                        s = g_string_new (NULL);
1633                        g_string_printf (s, "%s:%d.%d",
1634                                          IDL_IDENT_REPO_ID (ident), major, minor);
1635                        g_free (IDL_IDENT_REPO_ID (ident));
1636                        IDL_IDENT_REPO_ID (ident) = s->str;
1637                        g_string_free (s, FALSE);
1638                } else if (__IDL_is_parsing)
1639                        yywarningv (IDL_WARNING1, "Cannot find RepositoryID OMG IDL version in ID `%s'",
1640                                    IDL_IDENT_REPO_ID (ident));
1641        } else
1642                IDL_IDENT_REPO_ID (ident) =
1643                        IDL_ns_ident_make_repo_id (
1644                                __IDL_root_ns, p, NULL, &major, &minor);
1645}
1646
1647int IDL_inhibit_get (void)
1648{
1649        g_return_val_if_fail (__IDL_is_parsing, -1);
1650
1651        return __IDL_inhibits;
1652}
1653
1654void IDL_inhibit_push (void)
1655{
1656        g_return_if_fail (__IDL_is_parsing);
1657
1658        ++__IDL_inhibits;
1659}
1660
1661void IDL_inhibit_pop (void)
1662{
1663        g_return_if_fail (__IDL_is_parsing);
1664
1665        if (--__IDL_inhibits < 0)
1666                __IDL_inhibits = 0;
1667}
1668
1669static void IDL_inhibit (IDL_ns ns, const char *s)
1670{
1671        if (g_ascii_strcasecmp ("push", s) == 0)
1672                IDL_inhibit_push ();
1673        else if (g_ascii_strcasecmp ("pop", s) == 0)
1674                IDL_inhibit_pop ();
1675}
1676
1677static void IDL_typecodes_as_tok (IDL_ns ns, const char *s)
1678{
1679        if (g_ascii_strcasecmp ("push", s) == 0)
1680                ++(__IDL_typecodes_as_tok);
1681        else if (g_ascii_strcasecmp ("pop", s) == 0)
1682                --(__IDL_typecodes_as_tok);
1683}
1684
1685static void IDL_pidl (IDL_ns ns, const char *s)
1686{
1687        if (g_ascii_strcasecmp ("push", s) == 0)
1688                ++(__IDL_pidl);
1689        else if (g_ascii_strcasecmp ("pop", s) == 0)
1690                --(__IDL_pidl);
1691}
1692
1693void __IDL_do_pragma (const char *s)
1694{
1695        int n;
1696        char directive[256];
1697
1698        g_return_if_fail (__IDL_is_parsing);
1699        g_return_if_fail (s != NULL);
1700
1701        if (sscanf (s, "%255s%n", directive, &n) < 1)
1702                return;
1703        s += n;
1704        while (g_ascii_isspace (*s)) ++s;
1705
1706        if (strcmp (directive, "prefix") == 0)
1707                IDL_ns_prefix (__IDL_root_ns, s);
1708        else if (strcmp (directive, "ID") == 0)
1709                IDL_ns_ID (__IDL_root_ns, s);
1710        else if (strcmp (directive, "version") == 0)
1711                IDL_ns_version (__IDL_root_ns, s);
1712        else if (strcmp (directive, "inhibit") == 0)
1713                IDL_inhibit (__IDL_root_ns, s);
1714        else if (strcmp (directive, "typecodes_as_tok") == 0)
1715                IDL_typecodes_as_tok (__IDL_root_ns, s);
1716        else if (strcmp (directive, "pidl") == 0)
1717                IDL_pidl (__IDL_root_ns, s);
1718}
1719
1720static IDL_declspec_t IDL_parse_declspec (const char *strspec)
1721{
1722        IDL_declspec_t flags = IDLF_DECLSPEC_EXIST;
1723
1724        if (strspec == NULL)
1725                return flags;
1726
1727        if (strcmp (strspec, "inhibit") == 0)
1728                flags |= IDLF_DECLSPEC_INHIBIT;
1729        if (strcmp (strspec, "pidl") == 0)
1730                flags |= IDLF_DECLSPEC_PIDL;
1731        else if (__IDL_is_parsing)
1732                yywarningv (IDL_WARNING1, "Ignoring unknown declspec `%s'", strspec);
1733
1734        return flags;
1735}
1736
1737IDL_tree IDL_file_set (const char *filename, int line)
1738{
1739        IDL_fileinfo *fi;
1740        IDL_tree tree = NULL;
1741
1742        g_return_val_if_fail (__IDL_is_parsing, 0);
1743
1744        if (filename) {
1745                const char *oldfilename = __IDL_cur_filename;
1746                gboolean wasInhibit = IS_INHIBIT_STATE();
1747                gboolean isTop =
1748#ifdef HAVE_CPP_PIPE_STDIN
1749                        strlen (filename)==0;
1750#else
1751                        __IDL_tmp_filename &&
1752                        strcmp (filename, __IDL_tmp_filename)==0;
1753#endif
1754                if ( isTop ) {
1755                        filename = __IDL_real_filename;
1756                        __IDL_flagsi &= ~IDLFP_IN_INCLUDES;
1757                } else {
1758                        __IDL_flagsi |= IDLFP_IN_INCLUDES;
1759                }
1760
1761                if ((fi=g_hash_table_lookup(__IDL_filename_hash, filename)) ) {
1762                        __IDL_cur_fileinfo = fi;
1763                        ++(fi->seenCnt);
1764                } else {
1765                        fi = g_new0 (IDL_fileinfo, 1);
1766                        fi->name = g_strdup(filename);
1767                        g_hash_table_insert (__IDL_filename_hash, fi->name, fi);
1768                }
1769                __IDL_cur_fileinfo = fi;
1770                __IDL_cur_filename = fi->name;
1771                if ( (__IDL_flags & IDLF_SRCFILES)!=0
1772                  && (oldfilename==0
1773                            || strcmp(oldfilename,fi->name)!=0) ) {
1774                        tree = IDL_srcfile_new(fi->name, fi->seenCnt, isTop, wasInhibit);
1775                }
1776        }
1777
1778        if (__IDL_cur_line > 0)
1779                __IDL_cur_line = line;
1780        return tree;
1781}
1782
1783void IDL_file_get (const char **filename, int *line)
1784{
1785        g_return_if_fail (__IDL_is_parsing);
1786
1787        if (filename)
1788                *filename = __IDL_cur_filename;
1789
1790        if (line)
1791                *line = __IDL_cur_line;
1792}
1793
1794static int do_token_error (IDL_tree p, const char *message, gboolean prev)
1795{
1796        int dienow;
1797        char *what = NULL, *who = NULL;
1798
1799        assert (p != NULL);
1800
1801        dienow = IDL_tree_get_node_info (p, &what, &who);
1802
1803        assert (what != NULL);
1804       
1805        if (who && *who)
1806                IDL_tree_error (p, "%s %s `%s'", message, what, who);
1807        else
1808                IDL_tree_error (p, "%s %s", message, what);
1809       
1810        return dienow;
1811}
1812
1813static void illegal_context_type_error (IDL_tree p, const char *what)
1814{
1815        GString *s = g_string_new (NULL);
1816
1817        g_string_printf (s, "Illegal type `%%s' for %s", what);
1818        illegal_type_error (p, s->str);
1819        g_string_free (s, TRUE);
1820}
1821
1822static void illegal_type_error (IDL_tree p, const char *message)
1823{
1824        GString *s;
1825
1826        s = IDL_tree_to_IDL_string (p, NULL, IDLF_OUTPUT_NO_NEWLINES);
1827        yyerrorv (message, s->str);
1828        g_string_free (s, TRUE);
1829}
1830
1831static IDL_tree list_start (IDL_tree a, gboolean filter_null)
1832{
1833        IDL_tree p;
1834
1835        if (!a && filter_null)
1836                return NULL;
1837
1838        p = IDL_list_new (a);
1839
1840        return p;
1841}
1842
1843static IDL_tree list_chain (IDL_tree a, IDL_tree b, gboolean filter_null)
1844{
1845        IDL_tree p;
1846
1847        if (filter_null) {
1848                if (!b)
1849                        return a;
1850                if (!a)
1851                        return list_start (b, filter_null);
1852        }
1853
1854        p = IDL_list_new (b);
1855        a = IDL_list_concat (a, p);
1856
1857        return a;
1858}
1859
1860static IDL_tree zlist_chain (IDL_tree a, IDL_tree b, gboolean filter_null)
1861{
1862        if (a == NULL)
1863                return list_start (b, filter_null);
1864        else
1865                return list_chain (a, b, filter_null);
1866}
1867
1868static int IDL_binop_chktypes (enum IDL_binop op, IDL_tree a, IDL_tree b)
1869{
1870        if (IDL_NODE_TYPE (a) != IDLN_BINOP &&
1871            IDL_NODE_TYPE (b) != IDLN_BINOP &&
1872            IDL_NODE_TYPE (a) != IDLN_UNARYOP &&
1873            IDL_NODE_TYPE (b) != IDLN_UNARYOP &&
1874            IDL_NODE_TYPE (a) != IDL_NODE_TYPE (b)) {
1875                yyerror ("Invalid mix of types in constant expression");
1876                return -1;
1877        }
1878
1879        switch (op) {
1880        case IDL_BINOP_MULT:
1881        case IDL_BINOP_DIV:
1882        case IDL_BINOP_ADD:
1883        case IDL_BINOP_SUB:
1884                break;
1885
1886        case IDL_BINOP_MOD:
1887        case IDL_BINOP_SHR:
1888        case IDL_BINOP_SHL:
1889        case IDL_BINOP_AND:
1890        case IDL_BINOP_OR:
1891        case IDL_BINOP_XOR:
1892                if ((IDL_NODE_TYPE (a) != IDLN_INTEGER ||
1893                     IDL_NODE_TYPE (b) != IDLN_INTEGER) &&
1894                    !(IDL_NODE_TYPE (a) == IDLN_BINOP ||
1895                      IDL_NODE_TYPE (b) == IDLN_BINOP ||
1896                      IDL_NODE_TYPE (a) == IDLN_UNARYOP ||
1897                      IDL_NODE_TYPE (b) == IDLN_UNARYOP)) {
1898                        yyerror ("Invalid operation on non-integer value");
1899                        return -1;
1900                }
1901                break;
1902        }
1903
1904        return 0;
1905}
1906
1907static int IDL_unaryop_chktypes (enum IDL_unaryop op, IDL_tree a)
1908{
1909        switch (op) {
1910        case IDL_UNARYOP_PLUS:
1911        case IDL_UNARYOP_MINUS:
1912                break;
1913
1914        case IDL_UNARYOP_COMPLEMENT:
1915                if (IDL_NODE_TYPE (a) != IDLN_INTEGER &&
1916                    !(IDL_NODE_TYPE (a) == IDLN_BINOP ||
1917                      IDL_NODE_TYPE (a) == IDLN_UNARYOP)) {
1918                        yyerror ("Operand to complement must be integer");
1919                        return -1;
1920                }
1921                break;
1922        }
1923
1924        return 0;
1925}
1926
1927static IDL_tree IDL_binop_eval_integer (enum IDL_binop op, IDL_tree a, IDL_tree b)
1928{
1929        IDL_tree p = NULL;
1930
1931        assert (IDL_NODE_TYPE (a) == IDLN_INTEGER);
1932
1933        switch (op) {
1934        case IDL_BINOP_MULT:
1935                p = IDL_integer_new (IDL_INTEGER (a).value * IDL_INTEGER (b).value);
1936                break;
1937
1938        case IDL_BINOP_DIV:
1939                if (IDL_INTEGER (b).value == 0) {
1940                        yyerror ("Divide by zero in constant expression");
1941                        return NULL;
1942                }
1943                p = IDL_integer_new (IDL_INTEGER (a).value / IDL_INTEGER (b).value);
1944                break;
1945
1946        case IDL_BINOP_ADD:
1947                p = IDL_integer_new (IDL_INTEGER (a).value + IDL_INTEGER (b).value);
1948                break;
1949
1950        case IDL_BINOP_SUB:
1951                p = IDL_integer_new (IDL_INTEGER (a).value - IDL_INTEGER (b).value);
1952                break;
1953
1954        case IDL_BINOP_MOD:
1955                if (IDL_INTEGER (b).value == 0) {
1956                        yyerror ("Modulo by zero in constant expression");
1957                        return NULL;
1958                }
1959                p = IDL_integer_new (IDL_INTEGER (a).value % IDL_INTEGER (b).value);
1960                break;
1961
1962        case IDL_BINOP_SHR:
1963                p = IDL_integer_new (IDL_INTEGER (a).value >> IDL_INTEGER (b).value);
1964                break;
1965
1966        case IDL_BINOP_SHL:
1967                p = IDL_integer_new (IDL_INTEGER (a).value << IDL_INTEGER (b).value);
1968                break;
1969
1970        case IDL_BINOP_AND:
1971                p = IDL_integer_new (IDL_INTEGER (a).value & IDL_INTEGER (b).value);
1972                break;
1973
1974        case IDL_BINOP_OR:
1975                p = IDL_integer_new (IDL_INTEGER (a).value | IDL_INTEGER (b).value);
1976                break;
1977
1978        case IDL_BINOP_XOR:
1979                p = IDL_integer_new (IDL_INTEGER (a).value ^ IDL_INTEGER (b).value);
1980                break;
1981        }
1982
1983        return p;
1984}
1985
1986static IDL_tree IDL_binop_eval_float (enum IDL_binop op, IDL_tree a, IDL_tree b)
1987{
1988        IDL_tree p = NULL;
1989
1990        assert (IDL_NODE_TYPE (a) == IDLN_FLOAT);
1991
1992        switch (op) {
1993        case IDL_BINOP_MULT:
1994                p = IDL_float_new (IDL_FLOAT (a).value * IDL_FLOAT (b).value);
1995                break;
1996
1997        case IDL_BINOP_DIV:
1998                if (IDL_FLOAT (b).value == 0.0) {
1999                        yyerror ("Divide by zero in constant expression");
2000                        return NULL;
2001                }
2002                p = IDL_float_new (IDL_FLOAT (a).value / IDL_FLOAT (b).value);
2003                break;
2004
2005        case IDL_BINOP_ADD:
2006                p = IDL_float_new (IDL_FLOAT (a).value + IDL_FLOAT (b).value);
2007                break;
2008
2009        case IDL_BINOP_SUB:
2010                p = IDL_float_new (IDL_FLOAT (a).value - IDL_FLOAT (b).value);
2011                break;
2012
2013        default:
2014                break;
2015        }
2016
2017        return p;
2018}
2019
2020static IDL_tree IDL_binop_eval (enum IDL_binop op, IDL_tree a, IDL_tree b)
2021{
2022        assert (IDL_NODE_TYPE (a) == IDL_NODE_TYPE (b));
2023
2024        switch (IDL_NODE_TYPE (a)) {
2025        case IDLN_INTEGER: return IDL_binop_eval_integer (op, a, b);
2026        case IDLN_FLOAT: return IDL_binop_eval_float (op, a, b);
2027        default: return NULL;
2028        }
2029}
2030
2031static IDL_tree IDL_unaryop_eval_integer (enum IDL_unaryop op, IDL_tree a)
2032{
2033        IDL_tree p = NULL;
2034
2035        assert (IDL_NODE_TYPE (a) == IDLN_INTEGER);
2036
2037        switch (op) {
2038        case IDL_UNARYOP_PLUS:
2039                p = IDL_integer_new (IDL_INTEGER (a).value);
2040                break;
2041
2042        case IDL_UNARYOP_MINUS:
2043                p = IDL_integer_new (-IDL_INTEGER (a).value);
2044                break;
2045
2046        case IDL_UNARYOP_COMPLEMENT:
2047                p = IDL_integer_new (~IDL_INTEGER (a).value);
2048                break;
2049        }
2050       
2051        return p;
2052}
2053
2054static IDL_tree IDL_unaryop_eval_fixed (enum IDL_unaryop op, IDL_tree a)
2055{
2056        IDL_tree p = NULL;
2057
2058        assert (IDL_NODE_TYPE (a) == IDLN_FIXED);
2059
2060        switch (op) {
2061        case IDL_UNARYOP_PLUS:
2062                p = IDL_fixed_new (IDL_FIXED (a).value);
2063                break;
2064
2065        default:
2066                break;
2067        }
2068       
2069        return p;
2070}
2071
2072static IDL_tree IDL_unaryop_eval_float (enum IDL_unaryop op, IDL_tree a)
2073{
2074        IDL_tree p = NULL;
2075
2076        assert (IDL_NODE_TYPE (a) == IDLN_FLOAT);
2077
2078        switch (op) {
2079        case IDL_UNARYOP_PLUS:
2080                p = IDL_float_new (IDL_FLOAT (a).value);
2081                break;
2082
2083        case IDL_UNARYOP_MINUS:
2084                p = IDL_float_new (-IDL_FLOAT (a).value);
2085                break;
2086
2087        default:
2088                break;
2089        }
2090       
2091        return p;
2092}
2093
2094static IDL_tree IDL_unaryop_eval (enum IDL_unaryop op, IDL_tree a)
2095{
2096        switch (IDL_NODE_TYPE (a)) {
2097        case IDLN_INTEGER: return IDL_unaryop_eval_integer (op, a);
2098        case IDLN_FIXED: return IDL_unaryop_eval_fixed (op, a);
2099        case IDLN_FLOAT: return IDL_unaryop_eval_float (op, a);
2100        default: return NULL;
2101        }
2102}
2103
2104IDL_tree IDL_resolve_const_exp (IDL_tree p, IDL_tree_type type)
2105{
2106        gboolean resolved_value = FALSE, die = FALSE;
2107        gboolean wrong_type = FALSE;
2108
2109        while (!resolved_value && !die) {
2110                if (IDL_NODE_TYPE (p) == IDLN_IDENT) {
2111                        IDL_tree q = IDL_NODE_UP (p);
2112                       
2113                        assert (q != NULL);
2114                        if (IDL_NODE_UP (q) &&
2115                            IDL_NODE_TYPE (IDL_NODE_UP (q)) == IDLN_TYPE_ENUM) {
2116                                p = q;
2117                                die = TRUE;
2118                                break;
2119                        } else if (IDL_NODE_TYPE (q) != IDLN_CONST_DCL) {
2120                                p = q;
2121                                wrong_type = TRUE;
2122                                die = TRUE;
2123                        } else
2124                                p = IDL_CONST_DCL (q).const_exp;
2125                }
2126               
2127                if (p == NULL ||
2128                    IDL_NODE_TYPE (p) == IDLN_BINOP ||
2129                    IDL_NODE_TYPE (p) == IDLN_UNARYOP) {
2130                        die = TRUE;
2131                        continue;
2132                }
2133               
2134                resolved_value = IDL_NODE_IS_LITERAL (p);
2135        }
2136
2137        if (resolved_value &&
2138            type != IDLN_ANY &&
2139            IDL_NODE_TYPE (p) != type)
2140                wrong_type = TRUE;
2141       
2142        if (wrong_type) {
2143                yyerror ("Invalid type for constant");
2144                IDL_tree_error (p, "Previous resolved type declaration");
2145                return NULL;
2146        }
2147
2148        return resolved_value ? p : NULL;
2149}
2150
2151void IDL_queue_new_ident_comment (const char *str)
2152{
2153        g_return_if_fail (str != NULL);
2154
2155        __IDL_new_ident_comments = g_slist_append (__IDL_new_ident_comments, g_strdup (str));
2156}
2157
2158/*
2159 * Local variables:
2160 * mode: C
2161 * c-basic-offset: 8
2162 * tab-width: 8
2163 * indent-tabs-mode: t
2164 * End:
2165 */
Note: See TracBrowser for help on using the repository browser.