source: trunk/third/libIDL/util.c @ 20748

Revision 20748, 87.1 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20747, which included commits to RCS files with non-trunk default branches.
Line 
1/**************************************************************************
2
3    util.c
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: util.c,v 1.1.1.2 2004-09-22 23:38:50 ghudson Exp $
22
23***************************************************************************/
24#include <assert.h>
25#include <stdarg.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <ctype.h>
29#include <string.h>
30#include <errno.h>
31#ifdef HAVE_UNISTD_H
32#  include <unistd.h>
33#endif
34#include "rename.h"
35#include "util.h"
36
37IDL_EXPORT const char *IDL_tree_type_names[] = {
38        "IDLN_NONE",
39        "IDLN_ANY",
40        "IDLN_LIST",
41        "IDLN_GENTREE",
42        "IDLN_INTEGER",
43        "IDLN_STRING",
44        "IDLN_WIDE_STRING",
45        "IDLN_CHAR",
46        "IDLN_WIDE_CHAR",
47        "IDLN_FIXED",
48        "IDLN_FLOAT",
49        "IDLN_BOOLEAN",
50        "IDLN_IDENT",
51        "IDLN_TYPE_DCL",
52        "IDLN_CONST_DCL",
53        "IDLN_EXCEPT_DCL",
54        "IDLN_ATTR_DCL",
55        "IDLN_OP_DCL",
56        "IDLN_PARAM_DCL",
57        "IDLN_FORWARD_DCL",
58        "IDLN_TYPE_INTEGER",
59        "IDLN_TYPE_FLOAT",
60        "IDLN_TYPE_FIXED",
61        "IDLN_TYPE_CHAR",
62        "IDLN_TYPE_WIDE_CHAR",
63        "IDLN_TYPE_STRING",
64        "IDLN_TYPE_WIDE_STRING",
65        "IDLN_TYPE_BOOLEAN",
66        "IDLN_TYPE_OCTET",
67        "IDLN_TYPE_ANY",
68        "IDLN_TYPE_OBJECT",
69        "IDLN_TYPE_TYPECODE",
70        "IDLN_TYPE_ENUM",
71        "IDLN_TYPE_SEQUENCE",
72        "IDLN_TYPE_ARRAY",
73        "IDLN_TYPE_STRUCT",
74        "IDLN_TYPE_UNION",
75        "IDLN_MEMBER",
76        "IDLN_NATIVE",
77        "IDLN_CASE_STMT",
78        "IDLN_INTERFACE",
79        "IDLN_MODULE",
80        "IDLN_BINOP",
81        "IDLN_UNARYOP",
82        "IDLN_CODEFRAG",
83        /* IDLN_LAST */
84};
85
86IDL_EXPORT int                          __IDL_check_type_casts = FALSE;
87#ifndef HAVE_CPP_PIPE_STDIN
88char *                                  __IDL_tmp_filename = NULL;
89#endif
90const char *                            __IDL_real_filename = NULL;
91char *                                  __IDL_cur_filename = NULL;
92int                                     __IDL_cur_line;
93GHashTable *                            __IDL_filename_hash;
94IDL_fileinfo *                          __IDL_cur_fileinfo;
95GHashTable *                            __IDL_structunion_ht;
96int                                     __IDL_inhibits;
97int                                     __IDL_typecodes_as_tok;
98int                                     __IDL_pidl;
99IDL_tree                                __IDL_root;
100IDL_ns                                  __IDL_root_ns;
101int                                     __IDL_is_okay;
102int                                     __IDL_is_parsing;
103unsigned long                           __IDL_flags;
104unsigned long                           __IDL_flagsi;
105gpointer                                __IDL_inputcb_user_data;
106IDL_input_callback                      __IDL_inputcb;
107GSList *                                __IDL_new_ident_comments;
108static int                              __IDL_max_msg_level;
109static int                              __IDL_nerrors, __IDL_nwarnings;
110static IDL_msg_callback                 __IDL_msgcb;
111
112/* Case-insensitive version of g_str_hash */
113guint IDL_strcase_hash (gconstpointer v)
114{
115        const char *p;
116        guint h = 0, g;
117
118        for (p = (char *) v; *p != '\0'; ++p) {
119                h = (h << 4) + isupper ((int)*p) ? tolower (*p) : *p;
120                if ((g = h & 0xf0000000)) {
121                        h = h ^ (g >> 24);
122                        h = h ^ g;
123                }
124        }
125
126        return h /* % M */;
127}
128
129gint IDL_strcase_equal (gconstpointer a, gconstpointer b)
130{
131        return g_ascii_strcasecmp (a, b) == 0;
132}
133
134gint IDL_strcase_cmp (gconstpointer a, gconstpointer b)
135{
136        return g_ascii_strcasecmp (a, b);
137}
138
139static int my_strcmp (IDL_tree p, IDL_tree q)
140{
141        const char *a = IDL_IDENT (p).str;
142        const char *b = IDL_IDENT (q).str;
143        int cmp = IDL_strcase_cmp (a, b);
144
145        if (__IDL_is_parsing &&
146            cmp == 0 &&
147            strcmp (a, b) != 0 &&
148            !(IDL_IDENT (p)._flags & IDLF_IDENT_CASE_MISMATCH_HIT ||
149              IDL_IDENT (q)._flags & IDLF_IDENT_CASE_MISMATCH_HIT)) {
150                IDL_tree_warning (p, IDL_WARNING1, "Case mismatch between `%s'", a);
151                IDL_tree_warning (q, IDL_WARNING1, "and `%s'", b);
152                yywarning (IDL_WARNING1,
153                           "(Identifiers should be case-consistent after initial declaration)");
154                IDL_IDENT (p)._flags |= IDLF_IDENT_CASE_MISMATCH_HIT;
155                IDL_IDENT (q)._flags |= IDLF_IDENT_CASE_MISMATCH_HIT;
156        }
157
158        return cmp;
159}
160
161guint IDL_ident_hash (gconstpointer v)
162{
163        return IDL_strcase_hash (IDL_IDENT ((IDL_tree) v).str);
164}
165
166gint IDL_ident_equal (gconstpointer a, gconstpointer b)
167{
168        return my_strcmp ((IDL_tree) a, (IDL_tree) b) == 0;
169}
170
171gint IDL_ident_cmp (gconstpointer a, gconstpointer b)
172{
173        return my_strcmp ((IDL_tree) a, (IDL_tree) b);
174}
175
176const char *IDL_get_libver_string (void)
177{
178        return LIBIDL_VERSION;
179}
180
181const char *IDL_get_IDLver_string (void)
182{
183        return "2.2";
184}
185
186static void IDL_tree_optimize (IDL_tree *p, IDL_ns ns)
187{
188        if (!(__IDL_flags & IDLF_IGNORE_FORWARDS))
189                IDL_tree_process_forward_dcls (p, ns);
190        if (!(__IDL_flags & IDLF_INHIBIT_TAG_ONLY))
191                IDL_tree_remove_inhibits (p, ns);
192        IDL_tree_remove_empty_modules (p, ns);
193}
194
195static void IDL_parse_setup(unsigned long parse_flags, int max_msg_level) {
196        if (parse_flags & IDLF_XPIDL)
197                parse_flags |= IDLF_PROPERTIES;
198
199        __IDL_max_msg_level = max_msg_level;
200        __IDL_nerrors = __IDL_nwarnings = 0;
201        __IDL_inhibits = 0;
202        __IDL_typecodes_as_tok = (parse_flags & IDLF_TYPECODES) ? 1 : 0;
203        __IDL_pidl = (parse_flags & IDLF_XPIDL) ? 1 : 0;
204        __IDL_flags = parse_flags;
205        __IDL_flagsi = 0;
206        __IDL_is_parsing = TRUE;
207        __IDL_is_okay = TRUE;
208        __IDL_new_ident_comments = NULL;
209}
210
211int IDL_parse_filename (const char *filename, const char *cpp_args,
212                        IDL_msg_callback msg_cb, IDL_tree *tree, IDL_ns *ns,
213                        unsigned long parse_flags, int max_msg_level)
214{
215        extern void __IDL_lex_init (void);
216        extern void __IDL_lex_cleanup (void);
217        extern int yyparse (void);
218        extern FILE *__IDL_in;
219        FILE *input;
220        char *cmd;
221        size_t cmd_len;
222#ifdef HAVE_CPP_PIPE_STDIN
223        char *fmt = CPP_PROGRAM " " CPP_NOSTDINC " - %s%s %s < \"%s\" %s";
224        char *wd = "", *dirend;
225#else
226        char *fmt = CPP_PROGRAM " " CPP_NOSTDINC " -I- -I%s %s \"%s\" %s";
227        char *s, *tmpfilename;
228        char cwd[2048];
229        gchar *linkto;
230#endif
231        char *cpperrs = (parse_flags & IDLF_SHOW_CPP_ERRORS)
232          ? "" : "2>/dev/null";
233        GSList *slist;
234        int rv;
235
236#if 0 && defined(YYDEBUG)
237        {
238                extern int __IDL_debug;
239                __IDL_debug = 1;
240        }
241#endif
242
243        if (!filename ||
244            !tree ||
245            (tree == NULL && ns != NULL)) {
246                errno = EINVAL;
247                return -1;
248        }
249
250#ifdef HAVE_ACCESS
251        if (access (filename, R_OK))
252                return -1;
253#endif
254
255#ifdef HAVE_CPP_PIPE_STDIN
256        if ((dirend = strrchr (filename, '/'))) {
257                int len = dirend - filename + 1;
258                wd = g_malloc (len);
259                strncpy (wd, filename, len - 1);
260                wd[len - 1] = 0;
261        }
262
263        cmd_len = (strlen (filename) + (*wd ? 2 : 0) + strlen (wd) +
264                  (cpp_args ? strlen (cpp_args) : 0) +
265                  strlen(cpperrs) +
266                  strlen (fmt) - 8 + 1);
267        cmd = g_malloc (cmd_len);
268        if (!cmd) {
269                errno = ENOMEM;
270                return -1;
271        }
272
273        g_snprintf (cmd, cmd_len, fmt, *wd ? "-I" : "", wd,
274                    cpp_args ? cpp_args : "", filename, cpperrs);
275
276        if (dirend)
277                g_free (wd);
278#else
279        s = tmpnam (NULL);
280        if (s == NULL)
281                return -1;
282
283        if (!getcwd (cwd, sizeof (cwd)))
284                return -1;
285
286        if (*filename == '/') {
287                linkto = g_strdup (filename);
288        } else {
289                linkto = g_malloc (strlen (cwd) + strlen (filename) + 2);
290                if (!linkto) {
291                        errno = ENOMEM;
292                        return -1;
293                }
294                strcpy (linkto, cwd);
295                strcat (linkto, "/");
296                strcat (linkto, filename);
297        }
298
299        tmpfilename = g_malloc (strlen (s) + 3);
300        if (!tmpfilename) {
301                g_free (linkto);
302                errno = ENOMEM;
303                return -1;
304        }
305        strcpy (tmpfilename, s);
306        strcat (tmpfilename, ".c");
307#ifdef HAVE_SYMLINK
308        if (symlink (linkto, tmpfilename) < 0) {
309                g_free (linkto);
310                g_free (tmpfilename);
311                return -1;
312        }
313#endif
314        g_free (linkto);
315
316        cmd_len = (strlen (tmpfilename) + strlen (cwd) +
317                   (cpp_args ? strlen (cpp_args) : 0) +
318                   strlen(cpperrs) +
319                   strlen (fmt) - 6 + 1);
320        cmd = g_malloc (cmd_len);
321        if (!cmd) {
322                g_free (tmpfilename);
323                errno = ENOMEM;
324                return -1;
325        }
326
327        g_snprintf (cmd, cmd_len, fmt,
328                    cwd, cpp_args ? cpp_args : "", tmpfilename, cpperrs);
329#endif
330
331       /* Many versions of cpp do evil translating internal
332        * strings, producing bogus output, so clobber LC_ALL */
333       putenv ("LC_ALL=C");
334
335#ifdef HAVE_POPEN
336        input = popen (cmd, "r");
337#else
338        input = fopen (cmd, "r");
339#endif
340        g_free (cmd);
341
342        if (input == NULL || ferror (input)) {
343#ifndef HAVE_CPP_PIPE_STDIN
344                g_free (tmpfilename);
345#endif
346                return IDL_ERROR;
347        }
348
349        IDL_parse_setup(parse_flags, max_msg_level);
350
351        __IDL_in = input;
352        __IDL_msgcb = msg_cb;
353        __IDL_root_ns = IDL_ns_new ();
354        __IDL_lex_init ();
355
356        __IDL_real_filename = filename;
357#ifndef HAVE_CPP_PIPE_STDIN
358        __IDL_tmp_filename = tmpfilename;
359#endif
360        __IDL_filename_hash = IDL_NS (__IDL_root_ns).filename_hash;
361        __IDL_structunion_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
362        rv = yyparse ();
363        g_hash_table_destroy (__IDL_structunion_ht);
364        __IDL_is_parsing = FALSE;
365        __IDL_lex_cleanup ();
366        __IDL_parser_reset ();
367        __IDL_real_filename = NULL;
368#ifndef HAVE_CPP_PIPE_STDIN
369        __IDL_tmp_filename = NULL;
370#endif
371#ifdef HAVE_POPEN
372        pclose (input);
373#else
374        fclose (input);
375#endif
376#ifndef HAVE_CPP_PIPE_STDIN
377        unlink (tmpfilename);
378        g_free (tmpfilename);
379#endif
380        for (slist = __IDL_new_ident_comments; slist; slist = slist->next)
381                g_free (slist->data);
382        g_slist_free (__IDL_new_ident_comments);
383
384        if (__IDL_root != NULL) {
385                IDL_tree_optimize (&__IDL_root, __IDL_root_ns);
386
387                if (__IDL_root == NULL)
388                        yyerror ("File empty after optimization");
389        }
390
391        __IDL_msgcb = NULL;
392
393        if (rv != 0 || !__IDL_is_okay) {
394                if (tree)
395                        *tree = NULL;
396
397                if (ns)
398                        *ns = NULL;
399
400                return IDL_ERROR;
401        }
402
403        if (__IDL_flags & IDLF_PREFIX_FILENAME)
404                IDL_ns_prefix (__IDL_root_ns, filename);
405
406        if (tree)
407                *tree = __IDL_root;
408        else
409                IDL_tree_free (__IDL_root);
410
411        if (ns)
412                *ns = __IDL_root_ns;
413        else
414                IDL_ns_free (__IDL_root_ns);
415
416        return IDL_SUCCESS;
417}
418
419int IDL_parse_filename_with_input (const char *filename,
420                                   IDL_input_callback input_cb,
421                                   gpointer input_cb_user_data,
422                                   IDL_msg_callback msg_cb,
423                                   IDL_tree *tree, IDL_ns *ns,
424                                   unsigned long parse_flags,
425                                   int max_msg_level)
426{
427        extern void __IDL_lex_init (void);
428        extern void __IDL_lex_cleanup (void);
429        extern int yyparse (void);
430        union IDL_input_data data;
431        GSList *slist;
432        int rv;
433
434        if (!filename || !input_cb || !tree ||
435            (tree == NULL && ns != NULL)) {
436                errno = EINVAL;
437                return -1;
438        }
439
440
441        IDL_parse_setup(parse_flags, max_msg_level);
442
443        __IDL_msgcb = msg_cb;
444        __IDL_root_ns = IDL_ns_new ();
445
446        __IDL_lex_init ();
447        __IDL_inputcb = input_cb;
448        __IDL_inputcb_user_data = input_cb_user_data;
449
450        __IDL_real_filename = filename;
451#ifndef HAVE_CPP_PIPE_STDIN
452        __IDL_tmp_filename = NULL;
453#endif
454        __IDL_filename_hash = IDL_NS (__IDL_root_ns).filename_hash;
455        data.init.filename = filename;
456        if ((*__IDL_inputcb) (
457                IDL_INPUT_REASON_INIT, &data, __IDL_inputcb_user_data)) {
458                IDL_ns_free (__IDL_root_ns);
459                __IDL_lex_cleanup ();
460                __IDL_real_filename = NULL;
461                return -1;
462        }
463        __IDL_structunion_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
464        rv = yyparse ();
465        g_hash_table_destroy (__IDL_structunion_ht);
466        __IDL_is_parsing = FALSE;
467        __IDL_lex_cleanup ();
468        __IDL_parser_reset ();
469        __IDL_real_filename = NULL;
470        for (slist = __IDL_new_ident_comments; slist; slist = slist->next)
471                g_free (slist->data);
472        g_slist_free (__IDL_new_ident_comments);
473
474        if (__IDL_root != NULL) {
475                IDL_tree_optimize (&__IDL_root, __IDL_root_ns);
476
477                if (__IDL_root == NULL)
478                        yyerror ("File empty after optimization");
479        }
480
481        __IDL_msgcb = NULL;
482
483        if (rv != 0 || !__IDL_is_okay) {
484                if (tree)
485                        *tree = NULL;
486
487                if (ns)
488                        *ns = NULL;
489
490                (*__IDL_inputcb) (
491                        IDL_INPUT_REASON_ABORT, NULL, __IDL_inputcb_user_data);
492
493                return IDL_ERROR;
494        }
495
496        (*__IDL_inputcb) (IDL_INPUT_REASON_FINISH, NULL, __IDL_inputcb_user_data);
497
498        if (__IDL_flags & IDLF_PREFIX_FILENAME)
499                IDL_ns_prefix (__IDL_root_ns, filename);
500
501        if (tree)
502                *tree = __IDL_root;
503        else
504                IDL_tree_free (__IDL_root);
505
506        if (ns)
507                *ns = __IDL_root_ns;
508        else
509                IDL_ns_free (__IDL_root_ns);
510
511        return IDL_SUCCESS;
512}
513
514void yyerrorl (const char *s, int ofs)
515{
516        int line = __IDL_cur_line - 1 + ofs;
517        gchar *filename = NULL;
518
519        if (__IDL_cur_filename) {
520#ifdef HAVE_CPP_PIPE_STDIN
521                filename = __IDL_cur_filename;
522#else
523                filename = g_basename (__IDL_cur_filename);
524#endif
525        } else
526                line = -1;
527
528        ++__IDL_nerrors;
529        __IDL_is_okay = FALSE;
530
531        /* Errors are counted, even if not printed */
532        if (__IDL_max_msg_level < IDL_ERROR)
533                return;
534
535        if (__IDL_msgcb)
536                (*__IDL_msgcb)(IDL_ERROR, __IDL_nerrors, line, filename, s);
537        else {
538                if (line > 0)
539                        fprintf (stderr, "%s:%d: Error: %s\n", filename, line, s);
540                else
541                        fprintf (stderr, "Error: %s\n", s);
542        }
543}
544
545void yywarningl (int level, const char *s, int ofs)
546{
547        int line = __IDL_cur_line - 1 + ofs;
548        gchar *filename = NULL;
549
550        /* Unprinted warnings are not counted */
551        if (__IDL_max_msg_level < level)
552                return;
553
554        if (__IDL_cur_filename) {
555#ifdef HAVE_CPP_PIPE_STDIN
556                filename = __IDL_cur_filename;
557#else
558                filename = g_basename (__IDL_cur_filename);
559#endif
560        } else
561                line = -1;
562
563        ++__IDL_nwarnings;
564
565        if (__IDL_msgcb)
566                (*__IDL_msgcb)(level, __IDL_nwarnings, line, filename, s);
567        else {
568                if (line > 0)
569                        fprintf (stderr, "%s:%d: Warning: %s\n", filename, line, s);
570                else
571                        fprintf (stderr, "Warning: %s\n", s);
572        }
573}
574
575void yyerror (const char *s)
576{
577        yyerrorl (s, 0);
578}
579
580void yywarning (int level, const char *s)
581{
582        yywarningl (level, s, 0);
583}
584
585void yyerrorlv (const char *fmt, int ofs, ...)
586{
587        gchar *msg;
588        va_list args;
589
590        va_start (args, ofs);
591
592        msg = g_strdup_vprintf (fmt, args);
593        yyerrorl (msg, ofs);
594
595        va_end (args);
596
597        g_free (msg);
598}
599
600void yywarninglv (int level, const char *fmt, int ofs, ...)
601{
602        gchar *msg;
603        va_list args;
604
605        va_start (args, ofs);
606
607        msg = g_strdup_vprintf (fmt, args);
608        yywarningl (level, msg, ofs);
609
610        va_end (args);
611
612        g_free (msg);
613}
614
615void yyerrorv (const char *fmt, ...)
616{
617        gchar *msg;
618        va_list args;
619
620        va_start (args, fmt);
621
622        msg = g_strdup_vprintf (fmt, args);
623        yyerror (msg);
624
625        va_end (args);
626
627        g_free (msg);
628}
629
630void yywarningv (int level, const char *fmt, ...)
631{
632        gchar *msg;
633        va_list args;
634
635        va_start (args, fmt);
636
637        msg = g_strdup_vprintf (fmt, args);
638        yywarning (level, msg);
639
640        va_end (args);
641
642        g_free (msg);
643}
644
645void IDL_tree_error (IDL_tree p, const char *fmt, ...)
646{
647        char *file_save = __IDL_cur_filename;
648        int line_save = __IDL_cur_line;
649        gchar *msg;
650        va_list args;
651
652        if (p) {
653                __IDL_cur_filename = p->_file;
654                __IDL_cur_line = p->_line;
655        } else {
656                __IDL_cur_filename = NULL;
657                __IDL_cur_line = -1;
658        }
659
660        va_start (args, fmt);
661
662        msg = g_strdup_vprintf (fmt, args);
663        yyerror (msg);
664
665        va_end (args);
666
667        g_free (msg);
668
669        __IDL_cur_filename = file_save;
670        __IDL_cur_line = line_save;
671}
672
673void IDL_tree_warning (IDL_tree p, int level, const char *fmt, ...)
674{
675        char *file_save = __IDL_cur_filename;
676        int line_save = __IDL_cur_line;
677        gchar *msg;
678        va_list args;
679
680        if (p) {
681                __IDL_cur_filename = p->_file;
682                __IDL_cur_line = p->_line;
683        } else {
684                __IDL_cur_filename = NULL;
685                __IDL_cur_line = -1;
686        }
687
688        va_start (args, fmt);
689
690        msg = g_strdup_vprintf (fmt, args);
691        yywarning (level, msg);
692
693        va_end (args);
694
695        g_free (msg);
696
697        __IDL_cur_filename = file_save;
698        __IDL_cur_line = line_save;
699}
700
701int IDL_tree_get_node_info (IDL_tree p, char **what, char **who)
702{
703        int dienow = 0;
704
705        assert (what != NULL);
706        assert (who != NULL);
707
708        switch (IDL_NODE_TYPE (p)) {
709        case IDLN_TYPE_STRUCT:
710                *what = "structure definition";
711                *who = IDL_IDENT (IDL_TYPE_STRUCT (p).ident).str;
712                break;
713
714        case IDLN_TYPE_UNION:
715                *what = "union definition";
716                *who = IDL_IDENT (IDL_TYPE_UNION (p).ident).str;
717                break;
718
719        case IDLN_TYPE_ARRAY:
720                *what = "array";
721                *who = IDL_IDENT (IDL_TYPE_ARRAY (p).ident).str;
722                break;
723
724        case IDLN_TYPE_ENUM:
725                *what = "enumeration definition";
726                *who = IDL_IDENT (IDL_TYPE_ENUM (p).ident).str;
727                break;
728
729        case IDLN_IDENT:
730                *what = "identifier";
731                *who = IDL_IDENT (p).str;
732                break;
733
734        case IDLN_TYPE_DCL:
735                *what = "type definition";
736                assert (IDL_TYPE_DCL (p).dcls != NULL);
737                assert (IDL_NODE_TYPE (IDL_TYPE_DCL (p).dcls) == IDLN_LIST);
738                assert (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail != NULL);
739                assert (IDL_NODE_TYPE (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail) == IDLN_LIST);
740                *who = IDL_IDENT (IDL_LIST (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail).data).str;
741                break;
742
743        case IDLN_MEMBER:
744                *what = "member declaration";
745                assert (IDL_MEMBER (p).dcls != NULL);
746                assert (IDL_NODE_TYPE (IDL_MEMBER (p).dcls) == IDLN_LIST);
747                assert (IDL_LIST (IDL_MEMBER (p).dcls)._tail != NULL);
748                assert (IDL_NODE_TYPE (IDL_LIST (IDL_MEMBER (p).dcls)._tail) == IDLN_LIST);
749                *who = IDL_IDENT (IDL_LIST (IDL_LIST (IDL_MEMBER (p).dcls)._tail).data).str;
750                break;
751
752        case IDLN_NATIVE:
753                *what = "native declaration";
754                assert (IDL_NATIVE (p).ident != NULL);
755                assert (IDL_NODE_TYPE (IDL_NATIVE (p).ident) == IDLN_IDENT);
756                *who = IDL_IDENT (IDL_NATIVE (p).ident).str;
757                break;
758
759        case IDLN_LIST:
760                if (!IDL_LIST (p).data)
761                        break;
762                dienow = IDL_tree_get_node_info (IDL_LIST (p).data, what, who);
763                break;
764
765        case IDLN_ATTR_DCL:
766                *what = "interface attribute";
767                assert (IDL_ATTR_DCL (p).simple_declarations != NULL);
768                assert (IDL_NODE_TYPE (IDL_ATTR_DCL (p).simple_declarations) == IDLN_LIST);
769                assert (IDL_LIST (IDL_ATTR_DCL (p).simple_declarations)._tail != NULL);
770                assert (IDL_NODE_TYPE (IDL_LIST (
771                        IDL_ATTR_DCL (p).simple_declarations)._tail) == IDLN_LIST);
772                *who = IDL_IDENT (IDL_LIST (IDL_LIST (
773                        IDL_ATTR_DCL (p).simple_declarations)._tail).data).str;
774                break;
775
776        case IDLN_PARAM_DCL:
777                *what = "operation parameter";
778                assert (IDL_PARAM_DCL (p).simple_declarator != NULL);
779                assert (IDL_NODE_TYPE (IDL_PARAM_DCL (p).simple_declarator) == IDLN_IDENT);
780                *who = IDL_IDENT (IDL_PARAM_DCL (p).simple_declarator).str;
781                break;
782
783        case IDLN_CONST_DCL:
784                *what = "constant declaration for";
785                *who = IDL_IDENT (IDL_CONST_DCL (p).ident).str;
786                break;
787
788        case IDLN_EXCEPT_DCL:
789                *what = "exception";
790                *who = IDL_IDENT (IDL_EXCEPT_DCL (p).ident).str;
791                break;
792
793        case IDLN_OP_DCL:
794                *what = "interface operation";
795                *who = IDL_IDENT (IDL_OP_DCL (p).ident).str;
796                break;
797
798        case IDLN_MODULE:
799                *what = "module";
800                *who = IDL_IDENT (IDL_MODULE (p).ident).str;
801                break;
802
803        case IDLN_FORWARD_DCL:
804                *what = "forward declaration";
805                *who = IDL_IDENT (IDL_FORWARD_DCL (p).ident).str;
806                break;
807
808        case IDLN_INTERFACE:
809                *what = "interface";
810                *who = IDL_IDENT (IDL_INTERFACE (p).ident).str;
811                break;
812
813        default:
814                g_warning ("Node type: %s\n", IDL_NODE_TYPE_NAME (p));
815                *what = "unknown (internal error)";
816                break;
817        }
818
819        return dienow;
820}
821
822static IDL_tree IDL_node_new (IDL_tree_type type)
823{
824        IDL_tree p;
825
826        p = g_new0 (IDL_tree_node, 1);
827        if (p == NULL) {
828                yyerror ("IDL_node_new: memory exhausted");
829                return NULL;
830        }
831
832        IDL_NODE_TYPE (p) = type;
833        IDL_NODE_REFS (p) = 1;
834
835        p->_file = __IDL_cur_filename;
836        p->_line = __IDL_cur_line;
837
838        return p;
839}
840
841void __IDL_assign_up_node (IDL_tree up, IDL_tree node)
842{
843        if (node == NULL)
844                return;
845
846        assert (node != up);
847
848        switch (IDL_NODE_TYPE (node)) {
849        case IDLN_LIST:
850                if (IDL_NODE_UP (node) == NULL)
851                        for (; node != NULL; node = IDL_LIST (node).next)
852                                IDL_NODE_UP (node) = up;
853                break;
854
855        default:
856                if (IDL_NODE_UP (node) == NULL)
857                        IDL_NODE_UP (node) = up;
858                break;
859        }
860}
861
862void __IDL_assign_location (IDL_tree node, IDL_tree from_node)
863{
864        assert (node != NULL);
865
866        if (from_node) {
867                node->_file = from_node->_file;
868                node->_line = from_node->_line;
869        }
870}
871
872void __IDL_assign_this_location (IDL_tree node, char *filename, int line)
873{
874        assert (node != NULL);
875
876        node->_file = filename;
877        node->_line = line;
878}
879
880IDL_tree IDL_list_new (IDL_tree data)
881{
882        IDL_tree p = IDL_node_new (IDLN_LIST);
883
884        __IDL_assign_up_node (p, data);
885        IDL_LIST (p).data = data;
886        IDL_LIST (p)._tail = p;
887
888        return p;
889}
890
891IDL_tree IDL_list_concat (IDL_tree orig, IDL_tree append)
892{
893        IDL_tree p;
894
895        if (orig == NULL)
896                return append;
897
898        if (append == NULL)
899                return orig;
900
901        IDL_LIST (IDL_LIST (orig)._tail).next = append;
902        IDL_LIST (append).prev = IDL_LIST (orig)._tail;
903        IDL_LIST (orig)._tail = IDL_LIST (append)._tail;
904
905        /* Set tails on original */
906        for (p = IDL_LIST (orig).next; p && p != append; p = IDL_LIST (p).next)
907                IDL_LIST (p)._tail = IDL_LIST (orig)._tail;
908
909        /* Set up nodes on appended list */
910        for (p = append; p; p = IDL_LIST (p).next)
911                IDL_NODE_UP (p) = IDL_NODE_UP (orig);
912
913        return orig;
914}
915
916IDL_tree IDL_list_remove (IDL_tree list, IDL_tree p)
917{
918        IDL_tree new_list = list;
919
920        if (IDL_LIST (p).prev == NULL) {
921                assert (list == p);
922                new_list = IDL_LIST (p).next;
923                if (new_list)
924                        IDL_LIST (new_list).prev = NULL;
925        } else {
926                IDL_tree prev = IDL_LIST (p).prev;
927                IDL_tree next = IDL_LIST (p).next;
928
929                IDL_LIST (prev).next = next;
930                if (next)
931                        IDL_LIST (next).prev = prev;
932        }
933
934        IDL_LIST (p).prev = NULL;
935        IDL_LIST (p).next = NULL;
936        IDL_LIST (p)._tail = p;
937
938        /* Not all tails updated... */
939
940        return new_list;
941}
942
943IDL_tree IDL_gentree_new (GHashFunc hash_func, GCompareFunc key_compare_func, IDL_tree data)
944{
945        IDL_tree p = IDL_node_new (IDLN_GENTREE);
946
947        __IDL_assign_up_node (p, data);
948        IDL_GENTREE (p).data = data;
949        IDL_GENTREE (p).hash_func = hash_func;
950        IDL_GENTREE (p).key_compare_func = key_compare_func;
951        IDL_GENTREE (p).siblings = g_hash_table_new (hash_func, key_compare_func);
952        IDL_GENTREE (p).children = g_hash_table_new (hash_func, key_compare_func);
953
954        g_hash_table_insert (IDL_GENTREE (p).siblings, data, p);
955
956        return p;
957}
958
959IDL_tree IDL_gentree_new_sibling (IDL_tree from, IDL_tree data)
960{
961        IDL_tree p = IDL_node_new (IDLN_GENTREE);
962
963        __IDL_assign_up_node (p, data);
964        IDL_GENTREE (p).data = data;
965        IDL_GENTREE (p).hash_func = IDL_GENTREE (from).hash_func;
966        IDL_GENTREE (p).key_compare_func = IDL_GENTREE (from).key_compare_func;
967        IDL_GENTREE (p).siblings = IDL_GENTREE (from).siblings;
968        IDL_GENTREE (p).children = g_hash_table_new (IDL_GENTREE (from).hash_func,
969                                                     IDL_GENTREE (from).key_compare_func);
970
971        return p;
972}
973
974IDL_tree IDL_integer_new (IDL_longlong_t value)
975{
976        IDL_tree p = IDL_node_new (IDLN_INTEGER);
977
978        IDL_INTEGER (p).value = value;
979
980        return p;
981}
982
983IDL_tree IDL_string_new (char *value)
984{
985        IDL_tree p = IDL_node_new (IDLN_STRING);
986
987        IDL_STRING (p).value = value;
988
989        return p;
990}
991
992IDL_tree IDL_wide_string_new (wchar_t *value)
993{
994        IDL_tree p = IDL_node_new (IDLN_WIDE_STRING);
995
996        IDL_WIDE_STRING (p).value = value;
997
998        return p;
999}
1000
1001IDL_tree IDL_char_new (char *value)
1002{
1003        IDL_tree p = IDL_node_new (IDLN_CHAR);
1004
1005        IDL_CHAR (p).value = value;
1006
1007        return p;
1008}
1009
1010IDL_tree IDL_wide_char_new (wchar_t *value)
1011{
1012        IDL_tree p = IDL_node_new (IDLN_WIDE_CHAR);
1013
1014        IDL_WIDE_CHAR (p).value = value;
1015
1016        return p;
1017}
1018
1019IDL_tree IDL_fixed_new (char *value)
1020{
1021        IDL_tree p = IDL_node_new (IDLN_FIXED);
1022
1023        IDL_FIXED (p).value = value;
1024
1025        return p;
1026}
1027
1028IDL_tree IDL_float_new (double value)
1029{
1030        IDL_tree p = IDL_node_new (IDLN_FLOAT);
1031
1032        IDL_FLOAT (p).value = value;
1033
1034        return p;
1035}
1036
1037IDL_tree IDL_boolean_new (unsigned value)
1038{
1039        IDL_tree p = IDL_node_new (IDLN_BOOLEAN);
1040
1041        IDL_BOOLEAN (p).value = value;
1042
1043        return p;
1044}
1045
1046IDL_tree IDL_ident_new (char *str)
1047{
1048        IDL_tree p = IDL_node_new (IDLN_IDENT);
1049
1050        IDL_IDENT (p).str = str;
1051
1052        return p;
1053}
1054
1055IDL_tree IDL_member_new (IDL_tree type_spec, IDL_tree dcls)
1056{
1057        IDL_tree p = IDL_node_new (IDLN_MEMBER);
1058
1059        __IDL_assign_up_node (p, type_spec);
1060        __IDL_assign_up_node (p, dcls);
1061        IDL_MEMBER (p).type_spec = type_spec;
1062        IDL_MEMBER (p).dcls = dcls;
1063
1064        return p;
1065}
1066
1067IDL_tree IDL_native_new (IDL_tree ident)
1068{
1069        IDL_tree p = IDL_node_new (IDLN_NATIVE);
1070
1071        __IDL_assign_up_node (p, ident);
1072        __IDL_assign_location (p, ident);
1073        IDL_NATIVE (p).ident = ident;
1074
1075        return p;
1076}
1077
1078IDL_tree IDL_type_dcl_new (IDL_tree type_spec, IDL_tree dcls)
1079{
1080        IDL_tree p = IDL_node_new (IDLN_TYPE_DCL);
1081
1082        __IDL_assign_up_node (p, type_spec);
1083        __IDL_assign_up_node (p, dcls);
1084        __IDL_assign_location (p, IDL_LIST (dcls).data);
1085        IDL_TYPE_DCL (p).type_spec = type_spec;
1086        IDL_TYPE_DCL (p).dcls = dcls;
1087
1088        return p;
1089}
1090
1091IDL_tree IDL_type_float_new (enum IDL_float_type f_type)
1092{
1093        IDL_tree p = IDL_node_new (IDLN_TYPE_FLOAT);
1094
1095        IDL_TYPE_FLOAT (p).f_type = f_type;
1096
1097        return p;
1098}
1099
1100IDL_tree IDL_type_fixed_new (IDL_tree positive_int_const,
1101                             IDL_tree integer_lit)
1102{
1103        IDL_tree p = IDL_node_new (IDLN_TYPE_FIXED);
1104
1105        __IDL_assign_up_node (p, positive_int_const);
1106        __IDL_assign_up_node (p, integer_lit);
1107        IDL_TYPE_FIXED (p).positive_int_const = positive_int_const;
1108        IDL_TYPE_FIXED (p).integer_lit = integer_lit;
1109
1110        return p;
1111}
1112
1113IDL_tree IDL_type_integer_new (unsigned f_signed, enum IDL_integer_type f_type)
1114{
1115        IDL_tree p = IDL_node_new (IDLN_TYPE_INTEGER);
1116
1117        IDL_TYPE_INTEGER (p).f_signed = f_signed;
1118        IDL_TYPE_INTEGER (p).f_type = f_type;
1119
1120        return p;
1121}
1122
1123IDL_tree IDL_type_char_new (void)
1124{
1125        return IDL_node_new (IDLN_TYPE_CHAR);
1126}
1127
1128IDL_tree IDL_type_wide_char_new (void)
1129{
1130        return IDL_node_new (IDLN_TYPE_WIDE_CHAR);
1131}
1132
1133IDL_tree IDL_type_boolean_new (void)
1134{
1135        return IDL_node_new (IDLN_TYPE_BOOLEAN);
1136}
1137
1138IDL_tree IDL_type_octet_new (void)
1139{
1140        return IDL_node_new (IDLN_TYPE_OCTET);
1141}
1142
1143IDL_tree IDL_type_any_new (void)
1144{
1145        return IDL_node_new (IDLN_TYPE_ANY);
1146}
1147
1148IDL_tree IDL_type_object_new (void)
1149{
1150        return IDL_node_new (IDLN_TYPE_OBJECT);
1151}
1152
1153IDL_tree IDL_type_typecode_new (void)
1154{
1155        return IDL_node_new (IDLN_TYPE_TYPECODE);
1156}
1157
1158IDL_tree IDL_type_string_new (IDL_tree positive_int_const)
1159{
1160        IDL_tree p = IDL_node_new (IDLN_TYPE_STRING);
1161
1162        __IDL_assign_up_node (p, positive_int_const);
1163        IDL_TYPE_STRING (p).positive_int_const = positive_int_const;
1164
1165        return p;
1166}
1167
1168IDL_tree IDL_type_wide_string_new (IDL_tree positive_int_const)
1169{
1170        IDL_tree p = IDL_node_new (IDLN_TYPE_WIDE_STRING);
1171
1172        __IDL_assign_up_node (p, positive_int_const);
1173        IDL_TYPE_WIDE_STRING (p).positive_int_const = positive_int_const;
1174
1175        return p;
1176}
1177
1178IDL_tree IDL_type_array_new (IDL_tree ident,
1179                             IDL_tree size_list)
1180{
1181        IDL_tree p = IDL_node_new (IDLN_TYPE_ARRAY);
1182
1183        __IDL_assign_up_node (p, ident);
1184        __IDL_assign_up_node (p, size_list);
1185        __IDL_assign_location (p, ident);
1186        IDL_TYPE_ARRAY (p).ident = ident;
1187        IDL_TYPE_ARRAY (p).size_list = size_list;
1188
1189        return p;
1190}
1191
1192IDL_tree IDL_type_sequence_new (IDL_tree simple_type_spec,
1193                                IDL_tree positive_int_const)
1194{
1195        IDL_tree p = IDL_node_new (IDLN_TYPE_SEQUENCE);
1196
1197        __IDL_assign_up_node (p, simple_type_spec);
1198        __IDL_assign_up_node (p, positive_int_const);
1199        IDL_TYPE_SEQUENCE (p).simple_type_spec = simple_type_spec;
1200        IDL_TYPE_SEQUENCE (p).positive_int_const = positive_int_const;
1201
1202        return p;
1203}
1204
1205IDL_tree IDL_type_struct_new (IDL_tree ident, IDL_tree member_list)
1206{
1207        IDL_tree p = IDL_node_new (IDLN_TYPE_STRUCT);
1208
1209        __IDL_assign_up_node (p, ident);
1210        __IDL_assign_up_node (p, member_list);
1211        __IDL_assign_location (p, ident);
1212        IDL_TYPE_STRUCT (p).ident = ident;
1213        IDL_TYPE_STRUCT (p).member_list = member_list;
1214
1215        return p;
1216}
1217
1218IDL_tree IDL_type_union_new (IDL_tree ident, IDL_tree switch_type_spec, IDL_tree switch_body)
1219{
1220        IDL_tree p = IDL_node_new (IDLN_TYPE_UNION);
1221
1222        __IDL_assign_up_node (p, ident);
1223        __IDL_assign_up_node (p, switch_type_spec);
1224        __IDL_assign_up_node (p, switch_body);
1225        __IDL_assign_location (p, ident);
1226        IDL_TYPE_UNION (p).ident = ident;
1227        IDL_TYPE_UNION (p).switch_type_spec = switch_type_spec;
1228        IDL_TYPE_UNION (p).switch_body = switch_body;
1229
1230        return p;
1231}
1232
1233IDL_tree IDL_type_enum_new (IDL_tree ident, IDL_tree enumerator_list)
1234{
1235        IDL_tree p = IDL_node_new (IDLN_TYPE_ENUM);
1236
1237        __IDL_assign_up_node (p, ident);
1238        __IDL_assign_up_node (p, enumerator_list);
1239        __IDL_assign_location (p, ident);
1240        IDL_TYPE_ENUM (p).ident = ident;
1241        IDL_TYPE_ENUM (p).enumerator_list = enumerator_list;
1242
1243        return p;
1244}
1245
1246IDL_tree IDL_case_stmt_new (IDL_tree labels, IDL_tree element_spec)
1247{
1248        IDL_tree p = IDL_node_new (IDLN_CASE_STMT);
1249
1250        __IDL_assign_up_node (p, labels);
1251        __IDL_assign_up_node (p, element_spec);
1252        IDL_CASE_STMT (p).labels = labels;
1253        IDL_CASE_STMT (p).element_spec = element_spec;
1254
1255        return p;
1256}
1257
1258IDL_tree IDL_interface_new (IDL_tree ident, IDL_tree inheritance_spec, IDL_tree body)
1259{
1260        IDL_tree p = IDL_node_new (IDLN_INTERFACE);
1261
1262        /* Make sure the up node points to the interface */
1263        if (ident && IDL_NODE_UP (ident) &&
1264            IDL_NODE_TYPE (IDL_NODE_UP (ident)) != IDLN_INTERFACE)
1265                IDL_NODE_UP (ident) = NULL;
1266        __IDL_assign_up_node (p, ident);
1267        __IDL_assign_up_node (p, inheritance_spec);
1268        __IDL_assign_up_node (p, body);
1269        IDL_INTERFACE (p).ident = ident;
1270        IDL_INTERFACE (p).inheritance_spec = inheritance_spec;
1271        IDL_INTERFACE (p).body = body;
1272
1273        return p;
1274}
1275
1276IDL_tree IDL_module_new (IDL_tree ident, IDL_tree definition_list)
1277{
1278        IDL_tree p = IDL_node_new (IDLN_MODULE);
1279
1280        __IDL_assign_up_node (p, ident);
1281        __IDL_assign_up_node (p, definition_list);
1282        __IDL_assign_location (p, ident);
1283        IDL_MODULE (p).ident = ident;
1284        IDL_MODULE (p).definition_list = definition_list;
1285
1286        return p;
1287}
1288
1289IDL_tree IDL_binop_new (enum IDL_binop op, IDL_tree left, IDL_tree right)
1290{
1291        IDL_tree p = IDL_node_new (IDLN_BINOP);
1292
1293        __IDL_assign_up_node (p, left);
1294        __IDL_assign_up_node (p, right);
1295        IDL_BINOP (p).op = op;
1296        IDL_BINOP (p).left = left;
1297        IDL_BINOP (p).right = right;
1298
1299        return p;
1300}
1301
1302IDL_tree IDL_unaryop_new (enum IDL_unaryop op, IDL_tree operand)
1303{
1304        IDL_tree p = IDL_node_new (IDLN_UNARYOP);
1305
1306        __IDL_assign_up_node (p, operand);
1307        IDL_UNARYOP (p).op = op;
1308        IDL_UNARYOP (p).operand = operand;
1309
1310        return p;
1311}
1312
1313IDL_tree IDL_codefrag_new (char *desc, GSList *lines)
1314{
1315        IDL_tree p = IDL_node_new (IDLN_CODEFRAG);
1316
1317        IDL_CODEFRAG (p).desc = desc;
1318        IDL_CODEFRAG (p).lines = lines;
1319
1320        return p;
1321}
1322
1323IDL_tree IDL_srcfile_new (char *filename, int seenCnt, gboolean isTop, gboolean wasInhibit)
1324{
1325        IDL_tree p = IDL_node_new (IDLN_SRCFILE);
1326        IDL_SRCFILE (p).filename = filename;
1327        IDL_SRCFILE (p).seenCnt = seenCnt;
1328        IDL_SRCFILE (p).isTop = isTop;
1329        IDL_SRCFILE (p).wasInhibit = wasInhibit;
1330
1331        return p;
1332}
1333
1334IDL_tree IDL_const_dcl_new (IDL_tree const_type, IDL_tree ident, IDL_tree const_exp)
1335{
1336        IDL_tree p = IDL_node_new (IDLN_CONST_DCL);
1337
1338        __IDL_assign_up_node (p, const_type);
1339        __IDL_assign_up_node (p, ident);
1340        __IDL_assign_up_node (p, const_exp);
1341        __IDL_assign_location (p, ident);
1342        IDL_CONST_DCL (p).const_type = const_type;
1343        IDL_CONST_DCL (p).ident = ident;
1344        IDL_CONST_DCL (p).const_exp = const_exp;
1345
1346        return p;
1347}
1348
1349IDL_tree IDL_except_dcl_new (IDL_tree ident, IDL_tree members)
1350{
1351        IDL_tree p = IDL_node_new (IDLN_EXCEPT_DCL);
1352
1353        __IDL_assign_up_node (p, ident);
1354        __IDL_assign_up_node (p, members);
1355        __IDL_assign_location (p, ident);
1356        IDL_EXCEPT_DCL (p).ident = ident;
1357        IDL_EXCEPT_DCL (p).members = members;
1358
1359        return p;
1360}
1361
1362IDL_tree IDL_attr_dcl_new (unsigned f_readonly,
1363                           IDL_tree param_type_spec,
1364                           IDL_tree simple_declarations)
1365{
1366        IDL_tree p = IDL_node_new (IDLN_ATTR_DCL);
1367
1368        __IDL_assign_up_node (p, param_type_spec);
1369        __IDL_assign_up_node (p, simple_declarations);
1370        __IDL_assign_location (p, IDL_LIST (simple_declarations).data);
1371        IDL_ATTR_DCL (p).f_readonly = f_readonly;
1372        IDL_ATTR_DCL (p).param_type_spec = param_type_spec;
1373        IDL_ATTR_DCL (p).simple_declarations = simple_declarations;
1374
1375        return p;
1376}
1377
1378IDL_tree IDL_op_dcl_new (unsigned f_oneway,
1379                         IDL_tree op_type_spec,
1380                         IDL_tree ident,
1381                         IDL_tree parameter_dcls,
1382                         IDL_tree raises_expr,
1383                         IDL_tree context_expr)
1384{
1385        IDL_tree p = IDL_node_new (IDLN_OP_DCL);
1386
1387        __IDL_assign_up_node (p, op_type_spec);
1388        __IDL_assign_up_node (p, ident);
1389        __IDL_assign_up_node (p, parameter_dcls);
1390        __IDL_assign_up_node (p, raises_expr);
1391        __IDL_assign_up_node (p, context_expr);
1392        __IDL_assign_location (p, ident);
1393        IDL_OP_DCL (p).f_oneway = f_oneway;
1394        IDL_OP_DCL (p).op_type_spec = op_type_spec;
1395        IDL_OP_DCL (p).ident = ident;
1396        IDL_OP_DCL (p).parameter_dcls = parameter_dcls;
1397        IDL_OP_DCL (p).raises_expr = raises_expr;
1398        IDL_OP_DCL (p).context_expr = context_expr;
1399
1400        return p;
1401}
1402
1403IDL_tree IDL_param_dcl_new (enum IDL_param_attr attr,
1404                            IDL_tree param_type_spec,
1405                            IDL_tree simple_declarator)
1406{
1407        IDL_tree p = IDL_node_new (IDLN_PARAM_DCL);
1408
1409        __IDL_assign_up_node (p, param_type_spec);
1410        __IDL_assign_up_node (p, simple_declarator);
1411        __IDL_assign_location (p, simple_declarator);
1412        IDL_PARAM_DCL (p).attr = attr;
1413        IDL_PARAM_DCL (p).param_type_spec = param_type_spec;
1414        IDL_PARAM_DCL (p).simple_declarator = simple_declarator;
1415
1416        return p;
1417}
1418
1419IDL_tree IDL_forward_dcl_new (IDL_tree ident)
1420{
1421        IDL_tree p = IDL_node_new (IDLN_FORWARD_DCL);
1422
1423        __IDL_assign_up_node (p, ident);
1424        __IDL_assign_location (p, ident);
1425        IDL_FORWARD_DCL (p).ident = ident;
1426
1427        return p;
1428}
1429
1430IDL_tree IDL_check_type_cast (const IDL_tree tree, IDL_tree_type type,
1431                              const char *file, int line, const char *function)
1432{
1433        if (__IDL_check_type_casts) {
1434                if (tree == NULL) {
1435                        g_warning ("file %s: line %d: (%s) invalid type cast attempt,"
1436                                   " NULL tree to %s\n",
1437                                   file, line, function,
1438                                   IDL_tree_type_names[type]);
1439                }
1440                else if (IDL_NODE_TYPE (tree) != type) {
1441                        g_warning ("file %s: line %d: (%s) expected IDL tree type %s,"
1442                                   " but got %s\n",
1443                                   file, line, function,
1444                                   IDL_tree_type_names[type], IDL_NODE_TYPE_NAME (tree));
1445
1446                }
1447        }
1448        return tree;
1449}
1450
1451IDL_tree IDL_gentree_chain_sibling (IDL_tree from, IDL_tree data)
1452{
1453        IDL_tree p;
1454
1455        if (from == NULL)
1456                return NULL;
1457
1458        p = IDL_gentree_new_sibling (from, data);
1459        IDL_NODE_UP (p) = IDL_NODE_UP (from);
1460
1461        return p;
1462}
1463
1464IDL_tree IDL_gentree_chain_child (IDL_tree from, IDL_tree data)
1465{
1466        IDL_tree p;
1467
1468        if (from == NULL)
1469                return NULL;
1470
1471        p = IDL_gentree_new (IDL_GENTREE (from).hash_func,
1472                             IDL_GENTREE (from).key_compare_func,
1473                             data);
1474        IDL_NODE_UP (p) = from;
1475
1476        g_hash_table_insert (IDL_GENTREE (from).children, data, p);
1477
1478        return p;
1479}
1480
1481IDL_tree IDL_get_parent_node (IDL_tree p, IDL_tree_type type, int *levels)
1482{
1483        int count = 0;
1484
1485        if (p == NULL)
1486                return NULL;
1487
1488        if (type == IDLN_ANY)
1489                return IDL_NODE_UP (p);
1490
1491        while (p != NULL && IDL_NODE_TYPE (p) != type) {
1492
1493                if (IDL_NODE_IS_SCOPED (p))
1494                        ++count;
1495
1496                p = IDL_NODE_UP (p);
1497        }
1498
1499        if (p != NULL)
1500                if (levels != NULL)
1501                        *levels = count;
1502
1503        return p;
1504}
1505
1506IDL_tree IDL_tree_get_scope (IDL_tree p)
1507{
1508        g_return_val_if_fail (p != NULL, NULL);
1509
1510        if (IDL_NODE_TYPE (p) == IDLN_GENTREE)
1511                return p;
1512
1513        if (!IDL_NODE_IS_SCOPED (p)) {
1514                g_warning ("Node type %s isn't scoped", IDL_NODE_TYPE_NAME (p));
1515                return NULL;
1516        }
1517
1518        switch (IDL_NODE_TYPE (p)) {
1519        case IDLN_IDENT:
1520                return IDL_IDENT_TO_NS (p);
1521
1522        case IDLN_INTERFACE:
1523                return IDL_IDENT_TO_NS (IDL_INTERFACE (p).ident);
1524
1525        case IDLN_MODULE:
1526                return IDL_IDENT_TO_NS (IDL_MODULE (p).ident);
1527
1528        case IDLN_EXCEPT_DCL:
1529                return IDL_IDENT_TO_NS (IDL_EXCEPT_DCL (p).ident);
1530
1531        case IDLN_OP_DCL:
1532                return IDL_IDENT_TO_NS (IDL_OP_DCL (p).ident);
1533
1534        case IDLN_TYPE_ENUM:
1535                return IDL_IDENT_TO_NS (IDL_TYPE_ENUM (p).ident);
1536
1537        case IDLN_TYPE_STRUCT:
1538                return IDL_IDENT_TO_NS (IDL_TYPE_STRUCT (p).ident);
1539
1540        case IDLN_TYPE_UNION:
1541                return IDL_IDENT_TO_NS (IDL_TYPE_UNION (p).ident);
1542
1543        default:
1544                return NULL;
1545        }
1546}
1547
1548typedef struct {
1549        IDL_tree_func pre_tree_func;
1550        IDL_tree_func post_tree_func;
1551        gpointer user_data;
1552} IDLTreeWalkRealData;
1553
1554static void IDL_tree_walk_real (IDL_tree_func_data *tfd, IDLTreeWalkRealData *data)
1555{
1556        IDL_tree_func_data down_tfd;
1557        gboolean recurse = TRUE;
1558        IDL_tree p, q;
1559
1560        if (tfd->tree == NULL)
1561                return;
1562
1563        tfd->state->bottom = tfd;
1564        tfd->step = 0;
1565        tfd->data = NULL;
1566
1567        if (data->pre_tree_func)
1568                recurse = (*data->pre_tree_func) (tfd, data->user_data);
1569        ++tfd->step;
1570
1571        down_tfd.state = tfd->state;
1572        down_tfd.up = tfd;
1573        down_tfd.level = tfd->level + 1;
1574
1575        p = tfd->tree;
1576
1577        if (recurse) switch (IDL_NODE_TYPE (p)) {
1578        case IDLN_INTEGER:
1579        case IDLN_STRING:
1580        case IDLN_CHAR:
1581        case IDLN_FIXED:
1582        case IDLN_FLOAT:
1583        case IDLN_BOOLEAN:
1584        case IDLN_IDENT:
1585        case IDLN_TYPE_WIDE_CHAR:
1586        case IDLN_TYPE_BOOLEAN:
1587        case IDLN_TYPE_OCTET:
1588        case IDLN_TYPE_ANY:
1589        case IDLN_TYPE_OBJECT:
1590        case IDLN_TYPE_TYPECODE:
1591        case IDLN_TYPE_FLOAT:
1592        case IDLN_TYPE_INTEGER:
1593        case IDLN_TYPE_CHAR:
1594        case IDLN_CODEFRAG:
1595        case IDLN_SRCFILE:
1596                break;
1597
1598        case IDLN_LIST:
1599                for (q = p; q; q = IDL_LIST (q).next) {
1600                        down_tfd.tree = IDL_LIST (q).data;
1601                        IDL_tree_walk_real (&down_tfd, data);
1602                }
1603                break;
1604
1605        case IDLN_GENTREE:
1606                g_error ("IDLN_GENTREE walk not implemented!");
1607                break;
1608
1609        case IDLN_MEMBER:
1610                down_tfd.tree = IDL_MEMBER (p).type_spec;
1611                IDL_tree_walk_real (&down_tfd, data);
1612                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1613                        down_tfd.tree = IDL_MEMBER (p).dcls;
1614                        IDL_tree_walk_real (&down_tfd, data);
1615                }
1616                break;
1617
1618        case IDLN_NATIVE:
1619                down_tfd.tree = IDL_NATIVE (p).ident;
1620                IDL_tree_walk_real (&down_tfd, data);
1621                break;
1622
1623        case IDLN_TYPE_DCL:
1624                down_tfd.tree = IDL_TYPE_DCL (p).type_spec;
1625                IDL_tree_walk_real (&down_tfd, data);
1626                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1627                        down_tfd.tree = IDL_TYPE_DCL (p).dcls;
1628                        IDL_tree_walk_real (&down_tfd, data);
1629                }
1630                break;
1631
1632        case IDLN_CONST_DCL:
1633                down_tfd.tree = IDL_CONST_DCL (p).const_type;
1634                IDL_tree_walk_real (&down_tfd, data);
1635                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1636                        down_tfd.tree = IDL_CONST_DCL (p).ident;
1637                        IDL_tree_walk_real (&down_tfd, data);
1638                        down_tfd.tree = IDL_CONST_DCL (p).const_exp;
1639                        IDL_tree_walk_real (&down_tfd, data);
1640                }
1641                break;
1642
1643        case IDLN_EXCEPT_DCL:
1644                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1645                        down_tfd.tree = IDL_EXCEPT_DCL (p).ident;
1646                        IDL_tree_walk_real (&down_tfd, data);
1647                }
1648                down_tfd.tree = IDL_EXCEPT_DCL (p).members;
1649                IDL_tree_walk_real (&down_tfd, data);
1650                break;
1651
1652        case IDLN_ATTR_DCL:
1653                down_tfd.tree = IDL_ATTR_DCL (p).param_type_spec;
1654                IDL_tree_walk_real (&down_tfd, data);
1655                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1656                        down_tfd.tree = IDL_ATTR_DCL (p).simple_declarations;
1657                        IDL_tree_walk_real (&down_tfd, data);
1658                }
1659                break;
1660
1661        case IDLN_OP_DCL:
1662                down_tfd.tree = IDL_OP_DCL (p).op_type_spec;
1663                IDL_tree_walk_real (&down_tfd, data);
1664                down_tfd.tree = IDL_OP_DCL (p).ident;
1665                IDL_tree_walk_real (&down_tfd, data);
1666                down_tfd.tree = IDL_OP_DCL (p).parameter_dcls;
1667                IDL_tree_walk_real (&down_tfd, data);
1668                down_tfd.tree = IDL_OP_DCL (p).raises_expr;
1669                IDL_tree_walk_real (&down_tfd, data);
1670                down_tfd.tree = IDL_OP_DCL (p).context_expr;
1671                IDL_tree_walk_real (&down_tfd, data);
1672                break;
1673
1674        case IDLN_PARAM_DCL:
1675                down_tfd.tree = IDL_PARAM_DCL (p).param_type_spec;
1676                IDL_tree_walk_real (&down_tfd, data);
1677                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1678                        down_tfd.tree = IDL_PARAM_DCL (p).simple_declarator;
1679                        IDL_tree_walk_real (&down_tfd, data);
1680                }
1681                break;
1682
1683        case IDLN_FORWARD_DCL:
1684                down_tfd.tree = IDL_FORWARD_DCL (p).ident;
1685                IDL_tree_walk_real (&down_tfd, data);
1686                break;
1687
1688        case IDLN_TYPE_FIXED:
1689                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1690                        down_tfd.tree = IDL_TYPE_FIXED (p).positive_int_const;
1691                        IDL_tree_walk_real (&down_tfd, data);
1692                        down_tfd.tree = IDL_TYPE_FIXED (p).integer_lit;
1693                        IDL_tree_walk_real (&down_tfd, data);
1694                }
1695                break;
1696
1697        case IDLN_TYPE_STRING:
1698                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1699                        down_tfd.tree = IDL_TYPE_STRING (p).positive_int_const;
1700                        IDL_tree_walk_real (&down_tfd, data);
1701                }
1702                break;
1703
1704        case IDLN_TYPE_WIDE_STRING:
1705                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1706                        down_tfd.tree = IDL_TYPE_WIDE_STRING (p).positive_int_const;
1707                        IDL_tree_walk_real (&down_tfd, data);
1708                }
1709                break;
1710
1711        case IDLN_TYPE_ENUM:
1712                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1713                        down_tfd.tree = IDL_TYPE_ENUM (p).ident;
1714                        IDL_tree_walk_real (&down_tfd, data);
1715                        down_tfd.tree = IDL_TYPE_ENUM (p).enumerator_list;
1716                        IDL_tree_walk_real (&down_tfd, data);
1717                }
1718                break;
1719
1720        case IDLN_TYPE_SEQUENCE:
1721                down_tfd.tree = IDL_TYPE_SEQUENCE (p).simple_type_spec;
1722                IDL_tree_walk_real (&down_tfd, data);
1723                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1724                        down_tfd.tree = IDL_TYPE_SEQUENCE (p).positive_int_const;
1725                        IDL_tree_walk_real (&down_tfd, data);
1726                }
1727                break;
1728
1729        case IDLN_TYPE_ARRAY:
1730                down_tfd.tree = IDL_TYPE_ARRAY (p).ident;
1731                IDL_tree_walk_real (&down_tfd, data);
1732                if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) {
1733                        down_tfd.tree = IDL_TYPE_ARRAY (p).size_list;
1734                        IDL_tree_walk_real (&down_tfd, data);
1735                }
1736                break;
1737
1738        case IDLN_TYPE_STRUCT:
1739                down_tfd.tree = IDL_TYPE_STRUCT (p).ident;
1740                IDL_tree_walk_real (&down_tfd, data);
1741                down_tfd.tree = IDL_TYPE_STRUCT (p).member_list;
1742                IDL_tree_walk_real (&down_tfd, data);
1743                break;
1744
1745        case IDLN_TYPE_UNION:
1746                down_tfd.tree = IDL_TYPE_UNION (p).ident;
1747                IDL_tree_walk_real (&down_tfd, data);
1748                down_tfd.tree = IDL_TYPE_UNION (p).switch_type_spec;
1749                IDL_tree_walk_real (&down_tfd, data);
1750                down_tfd.tree = IDL_TYPE_UNION (p).switch_body;
1751                IDL_tree_walk_real (&down_tfd, data);
1752                break;
1753
1754        case IDLN_CASE_STMT:
1755                down_tfd.tree = IDL_CASE_STMT (p).labels;
1756                IDL_tree_walk_real (&down_tfd, data);
1757                /* FIXME */
1758                down_tfd.tree = IDL_CASE_STMT (p).element_spec;
1759                IDL_tree_walk_real (&down_tfd, data);
1760                break;
1761
1762        case IDLN_INTERFACE:
1763                down_tfd.tree = IDL_INTERFACE (p).ident;
1764                IDL_tree_walk_real (&down_tfd, data);
1765                down_tfd.tree = IDL_INTERFACE (p).inheritance_spec;
1766                IDL_tree_walk_real (&down_tfd, data);
1767                down_tfd.tree = IDL_INTERFACE (p).body;
1768                IDL_tree_walk_real (&down_tfd, data);
1769                break;
1770
1771        case IDLN_MODULE:
1772                down_tfd.tree = IDL_MODULE (p).ident;
1773                IDL_tree_walk_real (&down_tfd, data);
1774                down_tfd.tree = IDL_MODULE (p).definition_list;
1775                IDL_tree_walk_real (&down_tfd, data);
1776                break;
1777
1778        case IDLN_BINOP:
1779                down_tfd.tree = IDL_BINOP (p).left;
1780                IDL_tree_walk_real (&down_tfd, data);
1781                down_tfd.tree = IDL_BINOP (p).right;
1782                IDL_tree_walk_real (&down_tfd, data);
1783                break;
1784
1785        case IDLN_UNARYOP:
1786                down_tfd.tree = IDL_UNARYOP (p).operand;
1787                IDL_tree_walk_real (&down_tfd, data);
1788                break;
1789
1790        default:
1791                g_warning ("IDL_tree_walk_real: unknown node type %s\n",
1792                           IDL_NODE_TYPE_NAME (p));
1793                break;
1794        }
1795
1796        if (data->post_tree_func)
1797                        (void) (*data->post_tree_func) (tfd, data->user_data);
1798
1799        tfd->state->bottom = tfd->up;
1800}
1801
1802void IDL_tree_walk2 (IDL_tree p, IDL_tree_func_data *current,
1803                    glong flags,
1804                    IDL_tree_func pre_tree_func, IDL_tree_func post_tree_func,
1805                    gpointer user_data)
1806{
1807        IDLTreeWalkRealData data;
1808        IDL_tree_func_state tfs;
1809        IDL_tree_func_data tfd;
1810
1811        g_return_if_fail (!(pre_tree_func == NULL && post_tree_func == NULL));
1812
1813        data.pre_tree_func = pre_tree_func;
1814        data.post_tree_func = post_tree_func;
1815        data.user_data = user_data;
1816
1817        tfs.up = current ? current->state : NULL;
1818        tfs.start = p;
1819        tfs.flags = flags;
1820
1821        tfd.level = 0;
1822        if (current) {
1823            tfd = *current;
1824            tfd.level = ((tfd.level / 1000)+1) * 1000;
1825        }
1826        tfd.state = &tfs;
1827        tfd.up = current;
1828        tfd.tree = p;
1829
1830        IDL_tree_walk_real (&tfd, &data);
1831}
1832
1833void IDL_tree_walk (IDL_tree p, IDL_tree_func_data *current,
1834                    IDL_tree_func pre_tree_func, IDL_tree_func post_tree_func,
1835                    gpointer user_data)
1836{
1837    IDL_tree_walk2 (p, current, /*flags*/0,
1838      pre_tree_func, post_tree_func, user_data);
1839}
1840
1841void IDL_tree_walk_in_order (IDL_tree p, IDL_tree_func tree_func, gpointer user_data)
1842{
1843        IDL_tree_walk2 (p, NULL, /*flags*/0, tree_func, NULL, user_data);
1844}
1845
1846static void __IDL_tree_free (IDL_tree p);
1847
1848static int tree_free_but_this (IDL_tree data, IDL_tree p, IDL_tree this_one)
1849{
1850        if (p == this_one)
1851                return TRUE;
1852
1853        __IDL_tree_free (p);
1854
1855        return TRUE;
1856}
1857
1858static void property_free (char *key, char *value)
1859{
1860        g_free (key);
1861        g_free (value);
1862}
1863
1864void __IDL_free_properties (GHashTable *table)
1865{
1866        if (table) {
1867                g_hash_table_foreach (table, (GHFunc) property_free, NULL);
1868                g_hash_table_destroy (table);
1869        }
1870}
1871
1872/* Free associated node data, regardless of refcounts */
1873static void IDL_tree_free_real (IDL_tree p)
1874{
1875        GSList *slist;
1876
1877        assert (p != NULL);
1878
1879        switch (IDL_NODE_TYPE (p)) {
1880        case IDLN_GENTREE:
1881                g_hash_table_foreach (IDL_GENTREE (p).children,
1882                                      (GHFunc) tree_free_but_this, NULL);
1883                g_hash_table_destroy (IDL_GENTREE (p).children);
1884                break;
1885
1886        case IDLN_FIXED:
1887                g_free (IDL_FIXED (p).value);
1888                break;
1889
1890        case IDLN_STRING:
1891                g_free (IDL_STRING (p).value);
1892                break;
1893
1894        case IDLN_CHAR:
1895                g_free (IDL_CHAR (p).value);
1896                break;
1897
1898        case IDLN_IDENT:
1899                g_free (IDL_IDENT (p).str);
1900                g_free (IDL_IDENT_REPO_ID (p));
1901                for (slist = IDL_IDENT (p).comments; slist; slist = slist->next)
1902                        g_free (slist->data);
1903                g_slist_free (IDL_IDENT (p).comments);
1904                break;
1905
1906        case IDLN_NATIVE:
1907                g_free (IDL_NATIVE (p).user_type);
1908                break;
1909
1910        case IDLN_INTERFACE:
1911                break;
1912
1913        case IDLN_CODEFRAG:
1914                g_free (IDL_CODEFRAG (p).desc);
1915                for (slist = IDL_CODEFRAG (p).lines; slist; slist = slist->next)
1916                        g_free (slist->data);
1917                g_slist_free (IDL_CODEFRAG (p).lines);
1918                break;
1919
1920        default:
1921                break;
1922        }
1923
1924        __IDL_free_properties (IDL_NODE_PROPERTIES (p));
1925
1926        g_free (p);
1927}
1928
1929/* Free node taking into account refcounts */
1930static void __IDL_tree_free (IDL_tree p)
1931{
1932        if (p == NULL)
1933                return;
1934
1935        if (--IDL_NODE_REFS (p) <= 0)
1936                IDL_tree_free_real (p);
1937}
1938
1939/* Free a set of references of an entire tree */
1940void IDL_tree_free (IDL_tree p)
1941{
1942        IDL_tree q;
1943
1944        if (p == NULL)
1945                return;
1946
1947        switch (IDL_NODE_TYPE (p)) {
1948        case IDLN_INTEGER:
1949        case IDLN_FLOAT:
1950        case IDLN_BOOLEAN:
1951        case IDLN_TYPE_FLOAT:
1952        case IDLN_TYPE_INTEGER:
1953        case IDLN_TYPE_CHAR:
1954        case IDLN_TYPE_WIDE_CHAR:
1955        case IDLN_TYPE_BOOLEAN:
1956        case IDLN_TYPE_OCTET:
1957        case IDLN_TYPE_ANY:
1958        case IDLN_TYPE_OBJECT:
1959        case IDLN_TYPE_TYPECODE:
1960        case IDLN_FIXED:
1961        case IDLN_STRING:
1962        case IDLN_CHAR:
1963        case IDLN_IDENT:
1964        case IDLN_CODEFRAG:
1965                __IDL_tree_free (p);
1966                break;
1967
1968        case IDLN_LIST:
1969                while (p) {
1970                        IDL_tree_free (IDL_LIST (p).data);
1971                        q = IDL_LIST (p).next;
1972                        __IDL_tree_free (p);
1973                        p = q;
1974                }
1975                break;
1976
1977        case IDLN_GENTREE:
1978                g_hash_table_foreach (IDL_GENTREE (p).siblings,
1979                                      (GHFunc) tree_free_but_this, p);
1980                g_hash_table_destroy (IDL_GENTREE (p).siblings);
1981                __IDL_tree_free (p);
1982                break;
1983
1984        case IDLN_MEMBER:
1985                IDL_tree_free (IDL_MEMBER (p).type_spec);
1986                IDL_tree_free (IDL_MEMBER (p).dcls);
1987                __IDL_tree_free (p);
1988                break;
1989
1990        case IDLN_NATIVE:
1991                IDL_tree_free (IDL_NATIVE (p).ident);
1992                __IDL_tree_free (p);
1993                break;
1994
1995        case IDLN_TYPE_ENUM:
1996                IDL_tree_free (IDL_TYPE_ENUM (p).ident);
1997                IDL_tree_free (IDL_TYPE_ENUM (p).enumerator_list);
1998                __IDL_tree_free (p);
1999                break;
2000
2001        case IDLN_TYPE_SEQUENCE:
2002                IDL_tree_free (IDL_TYPE_SEQUENCE (p).simple_type_spec);
2003                IDL_tree_free (IDL_TYPE_SEQUENCE (p).positive_int_const);
2004                __IDL_tree_free (p);
2005                break;
2006
2007        case IDLN_TYPE_ARRAY:
2008                IDL_tree_free (IDL_TYPE_ARRAY (p).ident);
2009                IDL_tree_free (IDL_TYPE_ARRAY (p).size_list);
2010                __IDL_tree_free (p);
2011                break;
2012
2013        case IDLN_TYPE_STRUCT:
2014                IDL_tree_free (IDL_TYPE_STRUCT (p).ident);
2015                IDL_tree_free (IDL_TYPE_STRUCT (p).member_list);
2016                __IDL_tree_free (p);
2017                break;
2018
2019        case IDLN_TYPE_UNION:
2020                IDL_tree_free (IDL_TYPE_UNION (p).ident);
2021                IDL_tree_free (IDL_TYPE_UNION (p).switch_type_spec);
2022                IDL_tree_free (IDL_TYPE_UNION (p).switch_body);
2023                __IDL_tree_free (p);
2024                break;
2025
2026        case IDLN_TYPE_DCL:
2027                IDL_tree_free (IDL_TYPE_DCL (p).type_spec);
2028                IDL_tree_free (IDL_TYPE_DCL (p).dcls);
2029                __IDL_tree_free (p);
2030                break;
2031
2032        case IDLN_CONST_DCL:
2033                IDL_tree_free (IDL_CONST_DCL (p).const_type);
2034                IDL_tree_free (IDL_CONST_DCL (p).ident);
2035                IDL_tree_free (IDL_CONST_DCL (p).const_exp);
2036                __IDL_tree_free (p);
2037                break;
2038
2039        case IDLN_EXCEPT_DCL:
2040                IDL_tree_free (IDL_EXCEPT_DCL (p).ident);
2041                IDL_tree_free (IDL_EXCEPT_DCL (p).members);
2042                __IDL_tree_free (p);
2043                break;
2044
2045        case IDLN_ATTR_DCL:
2046                IDL_tree_free (IDL_ATTR_DCL (p).param_type_spec);
2047                IDL_tree_free (IDL_ATTR_DCL (p).simple_declarations);
2048                __IDL_tree_free (p);
2049                break;
2050
2051        case IDLN_OP_DCL:
2052                IDL_tree_free (IDL_OP_DCL (p).op_type_spec);
2053                IDL_tree_free (IDL_OP_DCL (p).ident);
2054                IDL_tree_free (IDL_OP_DCL (p).parameter_dcls);
2055                IDL_tree_free (IDL_OP_DCL (p).raises_expr);
2056                IDL_tree_free (IDL_OP_DCL (p).context_expr);
2057                __IDL_tree_free (p);
2058                break;
2059
2060        case IDLN_PARAM_DCL:
2061                IDL_tree_free (IDL_PARAM_DCL (p).param_type_spec);
2062                IDL_tree_free (IDL_PARAM_DCL (p).simple_declarator);
2063                __IDL_tree_free (p);
2064                break;
2065
2066        case IDLN_FORWARD_DCL:
2067                IDL_tree_free (IDL_FORWARD_DCL (p).ident);
2068                __IDL_tree_free (p);
2069                break;
2070
2071        case IDLN_TYPE_STRING:
2072                IDL_tree_free (IDL_TYPE_STRING (p).positive_int_const);
2073                __IDL_tree_free (p);
2074                break;
2075
2076        case IDLN_TYPE_WIDE_STRING:
2077                IDL_tree_free (IDL_TYPE_WIDE_STRING (p).positive_int_const);
2078                __IDL_tree_free (p);
2079                break;
2080
2081        case IDLN_TYPE_FIXED:
2082                IDL_tree_free (IDL_TYPE_FIXED (p).positive_int_const);
2083                IDL_tree_free (IDL_TYPE_FIXED (p).integer_lit);
2084                __IDL_tree_free (p);
2085                break;
2086
2087        case IDLN_CASE_STMT:
2088                IDL_tree_free (IDL_CASE_STMT (p).labels);
2089                IDL_tree_free (IDL_CASE_STMT (p).element_spec);
2090                __IDL_tree_free (p);
2091                break;
2092
2093        case IDLN_INTERFACE:
2094                IDL_tree_free (IDL_INTERFACE (p).ident);
2095                IDL_tree_free (IDL_INTERFACE (p).inheritance_spec);
2096                IDL_tree_free (IDL_INTERFACE (p).body);
2097                __IDL_tree_free (p);
2098                break;
2099
2100        case IDLN_MODULE:
2101                IDL_tree_free (IDL_MODULE (p).ident);
2102                IDL_tree_free (IDL_MODULE (p).definition_list);
2103                __IDL_tree_free (p);
2104                break;
2105
2106        case IDLN_BINOP:
2107                IDL_tree_free (IDL_BINOP (p).left);
2108                IDL_tree_free (IDL_BINOP (p).right);
2109                __IDL_tree_free (p);
2110                break;
2111
2112        case IDLN_UNARYOP:
2113                IDL_tree_free (IDL_UNARYOP (p).operand);
2114                __IDL_tree_free (p);
2115                break;
2116
2117        default:
2118                g_warning ("Free unknown node: %d\n", IDL_NODE_TYPE (p));
2119                break;
2120        }
2121}
2122
2123#define C_ESC(a,b)                              case a: *p++ = b; ++s; break
2124gchar *IDL_do_escapes (const char *s)
2125{
2126        char *p, *q;
2127
2128        if (!s)
2129                return NULL;
2130
2131        p = q = g_malloc (strlen (s) + 1);
2132
2133        while (*s) {
2134                if (*s != '\\') {
2135                        *p++ = *s++;
2136                        continue;
2137                }
2138                ++s;
2139                if (*s == 'x') {
2140                        char hex[3];
2141                        int n;
2142                        hex[0] = 0;
2143                        ++s;
2144                        sscanf (s, "%2[0-9a-fA-F]", hex);
2145                        s += strlen (hex);
2146                        sscanf (hex, "%x", &n);
2147                        *p++ = n;
2148                        continue;
2149                }
2150                if (*s >= '0' && *s <= '7') {
2151                        char oct[4];
2152                        int n;
2153                        oct[0] = 0;
2154                        sscanf (s, "%3[0-7]", oct);
2155                        s += strlen (oct);
2156                        sscanf (oct, "%o", &n);
2157                        *p++ = n;
2158                        continue;
2159                }
2160                switch (*s) {
2161                        C_ESC ('n','\n');
2162                        C_ESC ('t','\t');
2163                        C_ESC ('v','\v');
2164                        C_ESC ('b','\b');
2165                        C_ESC ('r','\r');
2166                        C_ESC ('f','\f');
2167                        C_ESC ('a','\a');
2168                        C_ESC ('\\','\\');
2169                        C_ESC ('?','?');
2170                        C_ESC ('\'','\'');
2171                        C_ESC ('"','"');
2172                }
2173        }
2174        *p = 0;
2175
2176        return q;
2177}
2178
2179int IDL_list_length (IDL_tree list)
2180{
2181        IDL_tree curitem;
2182        int length;
2183
2184        for (curitem = list, length = 0; curitem;
2185             curitem = IDL_LIST (curitem).next)
2186                length++;
2187
2188        return length;
2189}
2190
2191IDL_tree IDL_list_nth (IDL_tree list, int n)
2192{
2193        IDL_tree curitem;
2194        int i;
2195
2196        for (curitem = list, i = 0; i < n && curitem;
2197             curitem = IDL_LIST (curitem).next, i++) ;
2198
2199        return curitem;
2200}
2201
2202const char *IDL_tree_property_get (IDL_tree tree, const char *key)
2203{
2204        g_return_val_if_fail (tree != NULL, NULL);
2205        g_return_val_if_fail (key != NULL, NULL);
2206
2207        if (!IDL_NODE_PROPERTIES (tree))
2208                return NULL;
2209
2210        return g_hash_table_lookup (IDL_NODE_PROPERTIES (tree), key);
2211}
2212
2213void IDL_tree_property_set (IDL_tree tree, const char *key, const char *value)
2214{
2215        g_return_if_fail (tree != NULL);
2216        g_return_if_fail (key != NULL);
2217
2218        if (!IDL_NODE_PROPERTIES (tree))
2219                IDL_NODE_PROPERTIES (tree) = g_hash_table_new (
2220                        IDL_strcase_hash, IDL_strcase_equal);
2221        else if (IDL_tree_property_get (tree, key))
2222                IDL_tree_property_remove (tree, key);
2223
2224        g_hash_table_insert (IDL_NODE_PROPERTIES (tree), g_strdup (key), g_strdup (value));
2225}
2226
2227gboolean IDL_tree_property_remove (IDL_tree tree, const char *key)
2228{
2229        gboolean removed = FALSE;
2230        char *val;
2231
2232        g_return_val_if_fail (tree != NULL, FALSE);
2233        g_return_val_if_fail (key != NULL, FALSE);
2234
2235        if (!IDL_NODE_PROPERTIES (tree))
2236                return FALSE;
2237
2238        if ((val = g_hash_table_lookup (IDL_NODE_PROPERTIES (tree), key))) {
2239                g_hash_table_remove (IDL_NODE_PROPERTIES (tree), key);
2240                g_free (val);
2241                removed = TRUE;
2242        }
2243
2244        return removed;
2245}
2246
2247static void property_set (char *key, char *value, IDL_tree tree)
2248{
2249        IDL_tree_property_set (tree, key, value);
2250}
2251
2252void IDL_tree_properties_copy (IDL_tree from_tree, IDL_tree to_tree)
2253{
2254        g_return_if_fail (from_tree != NULL);
2255        g_return_if_fail (to_tree != NULL);
2256
2257        if (IDL_NODE_PROPERTIES (from_tree))
2258                g_hash_table_foreach (IDL_NODE_PROPERTIES (from_tree),
2259                                      (GHFunc) property_set, to_tree);
2260}
2261
2262typedef struct {
2263        IDL_tree *root;
2264        GHashTable *removed_nodes;
2265} RemoveListNodeData;
2266
2267static int remove_list_node (IDL_tree p, IDL_tree *list_head, RemoveListNodeData *data)
2268{
2269        assert (p != NULL);
2270        assert (IDL_NODE_TYPE (p) == IDLN_LIST);
2271
2272        if (list_head)
2273                *list_head = IDL_list_remove (*list_head, p);
2274        else
2275                *data->root = IDL_list_remove (*data->root, p);
2276
2277        if (data->removed_nodes) {
2278                if (!g_hash_table_lookup_extended (data->removed_nodes, p, NULL, NULL))
2279                        g_hash_table_insert (data->removed_nodes, p, p);
2280                /*
2281                  We shouldn't need this since we have removed it from the tree,
2282                  but we might need it for multiple declspec (inhibits) in the same
2283                  subtree.
2284                  IDL_tree_walk_in_order (p, (IDL_tree_func) inc_node_ref, NULL);
2285                */
2286        } else
2287                IDL_tree_free (p);
2288
2289        return TRUE;
2290}
2291
2292/* Forward Declaration Resolution */
2293static int load_forward_dcls (IDL_tree_func_data *tfd, GHashTable *table)
2294{
2295        if (IDL_NODE_TYPE (tfd->tree) == IDLN_FORWARD_DCL) {
2296                char *s = IDL_ns_ident_to_qstring (IDL_FORWARD_DCL (tfd->tree).ident, "::", 0);
2297
2298                if (!g_hash_table_lookup_extended (table, s, NULL, NULL))
2299                        g_hash_table_insert (table, s, tfd->tree);
2300                else
2301                        g_free (s);
2302        }
2303
2304        return TRUE;
2305}
2306
2307static int resolve_forward_dcls (IDL_tree_func_data *tfd, GHashTable *table)
2308{
2309        if (IDL_NODE_TYPE (tfd->tree) == IDLN_INTERFACE) {
2310                char *orig, *s = IDL_ns_ident_to_qstring (IDL_INTERFACE (tfd->tree).ident, "::", 0);
2311
2312                if (g_hash_table_lookup_extended (table, s, (gpointer)&orig, NULL)) {
2313                        g_hash_table_remove (table, orig);
2314                        g_free (orig);
2315                }
2316                g_free (s);
2317        }
2318
2319        return TRUE;
2320}
2321
2322static int print_unresolved_forward_dcls (char *s, IDL_tree p)
2323{
2324        if (__IDL_flags & IDLF_PEDANTIC)
2325                IDL_tree_error (p, "Unresolved forward declaration `%s'", s);
2326        else
2327                IDL_tree_warning (p,
2328                        IDL_WARNING1, "Unresolved forward declaration `%s'", s);
2329        g_free (s);
2330
2331        return TRUE;
2332}
2333
2334void IDL_tree_process_forward_dcls (IDL_tree *p, IDL_ns ns)
2335{
2336        GHashTable *table = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal);
2337        gint total, resolved;
2338
2339        IDL_tree_walk_in_order (*p, (IDL_tree_func) load_forward_dcls, table);
2340        total = g_hash_table_size (table);
2341        IDL_tree_walk_in_order (*p, (IDL_tree_func) resolve_forward_dcls, table);
2342        resolved = total - g_hash_table_size (table);
2343        g_hash_table_foreach (table, (GHFunc) print_unresolved_forward_dcls, NULL);
2344        g_hash_table_destroy (table);
2345        if (__IDL_flags & IDLF_VERBOSE)
2346                g_message ("Forward declarations resolved: %d of %d", resolved, total);
2347}
2348
2349/* Inhibit Creation Removal */
2350static int load_inhibits (IDL_tree_func_data *tfd, GHashTable *table)
2351{
2352        IDL_tree p, q, *list_head;
2353
2354        p = tfd->tree;
2355
2356        if (p != NULL &&
2357            IDL_NODE_UP (p) &&
2358            IDL_NODE_TYPE (IDL_NODE_UP (p)) == IDLN_LIST &&
2359            IDL_NODE_DECLSPEC (p) & IDLF_DECLSPEC_INHIBIT &&
2360            !g_hash_table_lookup_extended (table, IDL_NODE_UP (p), NULL, NULL)) {
2361                list_head = NULL;
2362                q = IDL_NODE_UP (IDL_NODE_UP (p));
2363                if (q) {
2364                        switch (IDL_NODE_TYPE (q)) {
2365                        case IDLN_MODULE:
2366                                list_head = &IDL_MODULE (q).definition_list;
2367                                break;
2368
2369                        case IDLN_INTERFACE:
2370                                list_head = &IDL_INTERFACE (q).body;
2371                                break;
2372
2373                        default:
2374                                g_warning ("Unhandled node %s in load_inhibits",
2375                                           IDL_NODE_TYPE_NAME (q));
2376                                break;
2377                        }
2378                }
2379                g_hash_table_insert (table, IDL_NODE_UP (p), list_head);
2380
2381                return FALSE;
2382        }
2383
2384        return TRUE;
2385}
2386
2387void IDL_tree_remove_inhibits (IDL_tree *tree, IDL_ns ns)
2388{
2389        RemoveListNodeData data;
2390        GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal);
2391        gint removed;
2392
2393        g_return_if_fail (tree != NULL);
2394        g_return_if_fail (ns != NULL);
2395
2396        IDL_tree_walk_in_order (*tree, (IDL_tree_func) load_inhibits, table);
2397        removed = g_hash_table_size (table);
2398        data.root = tree;
2399        data.removed_nodes = IDL_NS (ns).inhibits;
2400        g_hash_table_foreach (table, (GHFunc) remove_list_node, &data);
2401        g_hash_table_destroy (table);
2402        if (__IDL_flags & IDLF_VERBOSE)
2403                g_message ("Inhibited nodes removed: %d", removed);
2404}
2405
2406/* Multi-Pass Empty Module Removal */
2407static int load_empty_modules (IDL_tree_func_data *tfd, GHashTable *table)
2408{
2409        IDL_tree p, q, *list_head;
2410
2411        p = tfd->tree;
2412
2413        if (IDL_NODE_TYPE (p) == IDLN_MODULE &&
2414            IDL_MODULE (p).definition_list == NULL &&
2415            IDL_NODE_UP (p) &&
2416            IDL_NODE_TYPE (IDL_NODE_UP (p)) == IDLN_LIST &&
2417            !g_hash_table_lookup_extended (table, IDL_NODE_UP (p), NULL, NULL)) {
2418
2419                list_head = NULL;
2420                q = IDL_NODE_UP (IDL_NODE_UP (p));
2421                if (q) {
2422                        assert (IDL_NODE_TYPE (q) == IDLN_MODULE);
2423                        list_head = &IDL_MODULE (q).definition_list;
2424                }
2425                g_hash_table_insert (table, IDL_NODE_UP (p), list_head);
2426        }
2427
2428        return TRUE;
2429}
2430
2431void IDL_tree_remove_empty_modules (IDL_tree *p, IDL_ns ns)
2432{
2433        RemoveListNodeData data;
2434        gboolean done = FALSE;
2435        gint removed = 0;
2436
2437        data.root = p;
2438        data.removed_nodes = NULL;
2439
2440        while (!done) {
2441                GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal);
2442                IDL_tree_walk_in_order (*p, (IDL_tree_func) load_empty_modules, table);
2443                removed += g_hash_table_size (table);
2444                done = g_hash_table_size (table) == 0;
2445                g_hash_table_foreach (table, (GHFunc) remove_list_node, &data);
2446                g_hash_table_destroy (table);
2447        }
2448        if (__IDL_flags & IDLF_VERBOSE)
2449                g_message ("Empty modules removed: %d", removed);
2450}
2451
2452/*
2453 * IDL_tree to IDL backend
2454 */
2455
2456#define DELIM_COMMA             ", "
2457#define DELIM_ARRAY             "]["
2458#define DELIM_SPACE             " "
2459
2460#define indent()                ++data->ilev
2461#define unindent()              --data->ilev
2462#define doindent()              do {                                    \
2463        int i;                                                          \
2464        if (!(data->flags & IDLF_OUTPUT_NO_NEWLINES))                   \
2465                for (i = 0; i < data->ilev; ++i) {                      \
2466                        switch (data->mode) {                           \
2467                        case OUTPUT_FILE:                               \
2468                                fputc ('\t', data->u.o);                \
2469                                break;                                  \
2470                                                                        \
2471                        case OUTPUT_STRING:                             \
2472                                g_string_append_c (data->u.s, '\t');    \
2473                                break;                                  \
2474                                                                        \
2475                        default:                                        \
2476                                break;                                  \
2477                        }                                               \
2478                }                                                       \
2479        else if (data->ilev > 0)                                        \
2480                dataf (data, DELIM_SPACE);                              \
2481} while (0)
2482#define nl()                    do {                            \
2483        if (!(data->flags & IDLF_OUTPUT_NO_NEWLINES)) {         \
2484                switch (data->mode) {                           \
2485                case OUTPUT_FILE:                               \
2486                        fputc ('\n', data->u.o);                \
2487                        break;                                  \
2488                                                                \
2489                case OUTPUT_STRING:                             \
2490                        g_string_append_c (data->u.s, '\n');    \
2491                        break;                                  \
2492                                                                \
2493                default:                                        \
2494                        break;                                  \
2495                }                                               \
2496        }                                                       \
2497} while (0)
2498#define save_flag(flagbit,val)  do {                            \
2499        tfd->data = GUINT_TO_POINTER (                          \
2500                GPOINTER_TO_UINT (tfd->data) |                  \
2501                (data->flagbit ? (1U << flagbit##bit) : 0));    \
2502        data->flagbit = val;                                    \
2503} while (0)
2504#define restore_flag(flagbit)   do {                    \
2505        data->flagbit = (GPOINTER_TO_UINT (             \
2506                tfd->data) >> flagbit##bit) & 1U;       \
2507} while (0)
2508
2509typedef struct {
2510        IDL_ns ns;
2511        enum {
2512                OUTPUT_FILE,
2513                OUTPUT_STRING
2514        } mode;
2515        union {
2516                FILE *o;
2517                GString *s;
2518        } u;
2519        int ilev;
2520        unsigned long flags;
2521
2522#define identsbit               0
2523        guint idents : 1;
2524
2525#define literalsbit             1
2526        guint literals : 1;
2527
2528#define inline_propsbit         2
2529        guint inline_props : 1;
2530
2531#define su_defbit               3
2532        guint su_def : 1;
2533} IDL_output_data;
2534
2535static void dataf (IDL_output_data *data, const char *fmt, ...)
2536G_GNUC_PRINTF (2, 3);
2537
2538static void idataf (IDL_output_data *data, const char *fmt, ...)
2539G_GNUC_PRINTF (2, 3);
2540
2541static void dataf (IDL_output_data *data, const char *fmt, ...)
2542{
2543        gchar *buffer;
2544        va_list args;
2545
2546        va_start (args, fmt);
2547        switch (data->mode) {
2548        case OUTPUT_FILE:
2549                vfprintf (data->u.o, fmt, args);
2550                break;
2551
2552        case OUTPUT_STRING:
2553                buffer = g_strdup_vprintf (fmt, args);
2554                g_string_append (data->u.s, buffer);
2555                g_free (buffer);
2556                break;
2557
2558        default:
2559                break;
2560        }
2561        va_end (args);
2562}
2563
2564static void idataf (IDL_output_data *data, const char *fmt, ...)
2565{
2566        gchar *buffer;
2567        va_list args;
2568
2569        va_start (args, fmt);
2570        doindent ();
2571        switch (data->mode) {
2572        case OUTPUT_FILE:
2573                vfprintf (data->u.o, fmt, args);
2574                break;
2575
2576        case OUTPUT_STRING:
2577                buffer = g_strdup_vprintf (fmt, args);
2578                g_string_append (data->u.s, buffer);
2579                g_free (buffer);
2580                break;
2581
2582        default:
2583                break;
2584        }
2585        va_end (args);
2586}
2587
2588static gboolean IDL_emit_node_pre_func (IDL_tree_func_data *tfd, IDL_output_data *data);
2589static gboolean IDL_emit_node_post_func (IDL_tree_func_data *tfd, IDL_output_data *data);
2590
2591typedef struct {
2592        IDL_tree_func pre_func;
2593        IDL_tree_func post_func;
2594        IDL_tree_type type, type2;
2595        gboolean limit;
2596        IDL_output_data *data;
2597        const char *delim;
2598        gboolean hit;
2599} IDL_output_delim_data;
2600
2601static gboolean IDL_output_delim_match (IDL_tree_func_data *tfd, IDL_output_delim_data *delim)
2602{
2603        return delim->type == IDLN_ANY ||
2604                IDL_NODE_TYPE (tfd->tree) == delim->type ||
2605                IDL_NODE_TYPE (tfd->tree) == delim->type2;
2606}
2607
2608static gboolean IDL_output_delim_pre (IDL_tree_func_data *tfd, IDL_output_delim_data *delim)
2609{
2610        if (IDL_output_delim_match (tfd, delim)) {
2611                if (delim->hit)
2612                        dataf (delim->data, delim->delim);
2613                else
2614                        delim->hit = TRUE;
2615                return delim->pre_func
2616                        ? (*delim->pre_func) (tfd, delim->data)
2617                        : TRUE;
2618        } else {
2619                if (!delim->limit)
2620                        return delim->pre_func
2621                                ? (*delim->pre_func) (tfd, delim->data)
2622                                : TRUE;
2623                else
2624                        return TRUE;
2625        }
2626}
2627
2628static gboolean IDL_output_delim_post (IDL_tree_func_data *tfd, IDL_output_delim_data *delim)
2629{
2630        if (delim->limit && !IDL_output_delim_match (tfd, delim))
2631                return TRUE;
2632
2633        return delim->post_func
2634                ? (*delim->post_func) (tfd, delim->data)
2635                : TRUE;
2636}
2637
2638static void IDL_output_delim (IDL_tree p, IDL_tree_func_data *current,
2639                              IDL_output_data *data,
2640                              IDL_tree_func pre_func, IDL_tree_func post_func,
2641                              IDL_tree_type type, IDL_tree_type type2,
2642                              gboolean limit,
2643                              const char *str)
2644{
2645        IDL_output_delim_data delim;
2646
2647        delim.pre_func = pre_func;
2648        delim.post_func = post_func;
2649        delim.type = type;
2650        delim.type2 = type2;
2651        delim.limit = limit;
2652        delim.data = data;
2653        delim.hit = FALSE;
2654        delim.delim = str;
2655
2656        IDL_tree_walk2 (p, current, /*flags*/0,
2657                       (IDL_tree_func) IDL_output_delim_pre,
2658                       (IDL_tree_func) IDL_output_delim_post,
2659                       &delim);
2660}
2661
2662typedef struct {
2663        IDL_output_data *data;
2664        gboolean hit;
2665} IDL_property_emit_data;
2666
2667static void IDL_emit_IDL_property (const char *key, const char *value,
2668                                   IDL_property_emit_data *emit_data)
2669{
2670        IDL_output_data *data = emit_data->data;
2671
2672        if (!emit_data->hit)
2673                emit_data->hit = TRUE;
2674        else
2675                dataf (emit_data->data, DELIM_COMMA);
2676        if (!data->inline_props) {
2677                nl ();
2678                doindent ();
2679        }
2680        if (value && *value)
2681                dataf (emit_data->data, "%s%s(%s)",
2682                       key, DELIM_SPACE, value);
2683        else
2684                dataf (emit_data->data, "%s", key);
2685}
2686
2687static gboolean IDL_emit_IDL_properties (IDL_tree p, IDL_output_data *data)
2688{
2689        IDL_property_emit_data emit_data;
2690
2691        if (IDL_NODE_PROPERTIES (p) &&
2692            data->flags & IDLF_OUTPUT_PROPERTIES &&
2693            g_hash_table_size (IDL_NODE_PROPERTIES (p)) > 0) {
2694                emit_data.data = data;
2695                emit_data.hit = FALSE;
2696                if (!data->inline_props)
2697                        idataf (data, "[" DELIM_SPACE);
2698                else
2699                        dataf (data, "[");
2700                indent ();
2701                g_hash_table_foreach (IDL_NODE_PROPERTIES (p),
2702                                      (GHFunc) IDL_emit_IDL_property,
2703                                      &emit_data);
2704                unindent ();
2705                if (!data->inline_props) {
2706                        nl ();
2707                        doindent ();
2708                }
2709                dataf (data, "]");
2710                if (!data->inline_props)
2711                        nl ();
2712                else
2713                        dataf (data, DELIM_SPACE);
2714        }
2715
2716        return TRUE;
2717}
2718
2719static gboolean IDL_emit_IDL_sc (IDL_tree_func_data *tfd, IDL_output_data *data)
2720{
2721        dataf (data, ";"); nl ();
2722
2723        return TRUE;
2724}
2725
2726static gboolean IDL_emit_IDL_indent (IDL_tree_func_data *tfd, IDL_output_data *data)
2727{
2728        doindent ();
2729
2730        return TRUE;
2731}
2732
2733static gboolean IDL_emit_IDL_curly_brace_open (IDL_tree_func_data *tfd, IDL_output_data *data)
2734{
2735        dataf (data, "{"); nl (); indent ();
2736
2737        return TRUE;
2738}
2739
2740static gboolean IDL_emit_IDL_curly_brace_close (IDL_tree_func_data *tfd, IDL_output_data *data)
2741{
2742        unindent (); idataf (data, "}");
2743
2744        return TRUE;
2745}
2746
2747static gboolean IDL_emit_IDL_curly_brace_close_sc (IDL_tree_func_data *tfd, IDL_output_data *data)
2748{
2749        IDL_emit_IDL_curly_brace_close (tfd, data);
2750        IDL_emit_IDL_sc (tfd, data);
2751
2752        return TRUE;
2753}
2754
2755static gboolean IDL_emit_IDL_ident_real (IDL_tree_func_data *tfd, IDL_output_data *data)
2756{
2757        IDL_tree_func_data *up_path;
2758        IDL_tree up_real, scope;
2759        char *s;
2760        int levels;
2761
2762        up_path = tfd;
2763        up_real = tfd->tree;
2764        while (up_path && up_real) {
2765                if (IDL_NODE_TYPE (up_path->tree) != IDL_NODE_TYPE (up_real))
2766                        break;
2767                up_path = up_path->up;
2768                up_real = IDL_NODE_UP (up_real);
2769        }
2770
2771        assert (IDL_NODE_TYPE (tfd->tree) == IDLN_IDENT);
2772
2773        if (!up_real || data->flags & IDLF_OUTPUT_NO_QUALIFY_IDENTS) {
2774                /* TODO: If the IDENT is also a keyword, escape it by
2775                   prepending an underscore. */
2776                dataf (data, "%s", IDL_IDENT (tfd->tree).str);
2777        } else {
2778                if ( up_path == 0 ) {
2779                    levels = 0;
2780                } else {
2781                    /* Determine minimal required levels of scoping */
2782                    scope = up_path->tree ? up_path->tree : up_real;
2783                    levels = IDL_ns_scope_levels_from_here (data->ns, tfd->tree, scope);
2784                }
2785                s = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (tfd->tree), "::", levels);
2786                dataf (data, "%s", s);
2787                g_free (s);
2788        }
2789
2790        return TRUE;
2791}
2792
2793static gboolean IDL_emit_IDL_ident_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
2794{
2795        if (data->idents)
2796                IDL_emit_IDL_ident_real (tfd, data);
2797
2798        return TRUE;
2799}
2800
2801static gboolean IDL_emit_IDL_ident_force_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
2802{
2803        IDL_emit_IDL_ident_real (tfd, data);
2804
2805        return TRUE;
2806}
2807
2808static gboolean IDL_emit_IDL_ident (IDL_tree ident, IDL_tree_func_data *tfd, IDL_output_data *data)
2809{
2810        IDL_tree_walk2 (ident, tfd, /*flags*/0,
2811                       (IDL_tree_func) IDL_emit_IDL_ident_real, NULL,
2812                       data);
2813
2814        return TRUE;
2815}
2816
2817static gboolean IDL_emit_IDL_literal (IDL_tree p, IDL_output_data *data)
2818{
2819        switch (IDL_NODE_TYPE (p)) {
2820        case IDLN_FLOAT:
2821                dataf (data, "%f", IDL_FLOAT (p).value);
2822                break;
2823
2824        case IDLN_INTEGER:
2825                /* FIXME: sign */
2826                dataf (data, "%" IDL_LL "d", IDL_INTEGER (p).value);
2827                break;
2828
2829        case IDLN_FIXED:
2830                dataf (data, "%s", IDL_FIXED (p).value);
2831                break;
2832
2833        case IDLN_CHAR:
2834                dataf (data, "'%s'", IDL_CHAR (p).value);
2835                break;
2836
2837        case IDLN_WIDE_CHAR:
2838/*              dataf (data, "'%s'", IDL_WIDE_CHAR (p).value); */
2839                g_warning ("IDL_emit_IDL_literal: %s is currently unhandled",
2840                           "Wide character output");
2841                break;
2842
2843        case IDLN_BOOLEAN:
2844                dataf (data, "%s", IDL_BOOLEAN (p).value ? "TRUE" : "FALSE");
2845                break;
2846
2847        case IDLN_STRING:
2848                dataf (data, "\"%s\"", IDL_STRING (p).value);
2849                break;
2850
2851        case IDLN_WIDE_STRING:
2852/*              dataf (data, "\"%s\"", IDL_STRING (p).value); */
2853                g_warning ("IDL_emit_IDL_literal: %s is currently unhandled",
2854                           "Wide string output");
2855                break;
2856
2857        default:
2858                g_warning ("Unhandled literal: %s", IDL_NODE_TYPE_NAME (p));
2859                break;
2860        }
2861
2862        return TRUE;
2863}
2864
2865static gboolean IDL_emit_IDL_literal_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
2866{
2867        if (data->literals)
2868                IDL_emit_IDL_literal (tfd->tree, data);
2869
2870        return TRUE;
2871}
2872
2873static gboolean IDL_emit_IDL_literal_force_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
2874{
2875        IDL_emit_IDL_literal (tfd->tree, data);
2876
2877        return TRUE;
2878}
2879
2880static gboolean IDL_emit_IDL_type_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
2881{
2882        IDL_tree p, q;
2883
2884        p = tfd->tree;
2885
2886        switch (IDL_NODE_TYPE (p)) {
2887        case IDLN_IDENT:
2888                IDL_emit_IDL_ident (p, tfd, data);
2889                break;
2890
2891        case IDLN_TYPE_CHAR:
2892                dataf (data, "char");
2893                break;
2894
2895        case IDLN_TYPE_WIDE_CHAR:
2896                dataf (data, "wchar");
2897                break;
2898
2899        case IDLN_TYPE_BOOLEAN:
2900                dataf (data, "boolean");
2901                break;
2902
2903        case IDLN_TYPE_OCTET:
2904                dataf (data, "octet");
2905                break;
2906
2907        case IDLN_TYPE_ANY:
2908                dataf (data, "any");
2909                break;
2910
2911        case IDLN_TYPE_OBJECT:
2912                dataf (data, "Object");
2913                break;
2914
2915        case IDLN_TYPE_TYPECODE:
2916                dataf (data, "TypeCode");
2917                break;
2918
2919        case IDLN_TYPE_FLOAT:
2920                switch (IDL_TYPE_FLOAT (p).f_type) {
2921                case IDL_FLOAT_TYPE_FLOAT: dataf (data, "float"); break;
2922                case IDL_FLOAT_TYPE_DOUBLE: dataf (data, "double"); break;
2923                case IDL_FLOAT_TYPE_LONGDOUBLE: dataf (data, "long" DELIM_SPACE "double"); break;
2924                }
2925                break;
2926
2927        case IDLN_TYPE_FIXED:
2928                dataf (data, "fixed<");
2929                IDL_emit_IDL_literal (IDL_TYPE_FIXED (p).positive_int_const, data);
2930                dataf (data, DELIM_COMMA);
2931                IDL_emit_IDL_literal (IDL_TYPE_FIXED (p).integer_lit, data);
2932                dataf (data, ">");
2933                return FALSE;
2934
2935        case IDLN_TYPE_INTEGER:
2936                if (!IDL_TYPE_INTEGER (p).f_signed)
2937                        dataf (data, "unsigned" DELIM_SPACE);
2938                switch (IDL_TYPE_INTEGER (p).f_type) {
2939                case IDL_INTEGER_TYPE_SHORT: dataf (data, "short"); break;
2940                case IDL_INTEGER_TYPE_LONG: dataf (data, "long"); break;
2941                case IDL_INTEGER_TYPE_LONGLONG: dataf (data, "long" DELIM_SPACE "long"); break;
2942                }
2943                break;
2944
2945        case IDLN_TYPE_STRING:
2946        case IDLN_TYPE_WIDE_STRING:
2947                if (IDL_NODE_TYPE (p) == IDLN_TYPE_STRING) {
2948                        dataf (data, "string");
2949                        q = IDL_TYPE_STRING (p).positive_int_const;
2950                } else {
2951                        dataf (data, "wstring");
2952                        q = IDL_TYPE_WIDE_STRING (p).positive_int_const;
2953                }
2954                if (q) {
2955                        dataf (data, "<");
2956                        if (IDL_NODE_TYPE (p) == IDLN_TYPE_STRING)
2957                                IDL_emit_IDL_literal (
2958                                        IDL_TYPE_STRING (p).positive_int_const, data);
2959                        else
2960                                IDL_emit_IDL_literal (
2961                                        IDL_TYPE_WIDE_STRING (p).positive_int_const, data);
2962                        dataf (data, ">");
2963                }
2964                return FALSE;
2965
2966        case IDLN_TYPE_ENUM:
2967                IDL_emit_IDL_indent (tfd, data);
2968                data->inline_props = TRUE;
2969                IDL_emit_IDL_properties (IDL_TYPE_ENUM (tfd->tree).ident, data);
2970                dataf (data, "enum" DELIM_SPACE);
2971                IDL_emit_IDL_ident (IDL_TYPE_ENUM (p).ident, tfd, data);
2972                dataf (data, DELIM_SPACE "{" DELIM_SPACE);
2973                IDL_output_delim (IDL_TYPE_ENUM (p).enumerator_list, tfd, data,
2974                                  (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL,
2975                                  IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA);
2976                dataf (data, DELIM_SPACE "};"); nl ();
2977                return FALSE;
2978
2979        case IDLN_TYPE_ARRAY:
2980                IDL_emit_IDL_ident (IDL_TYPE_ARRAY (p).ident, tfd, data);
2981                dataf (data, "[");
2982                IDL_output_delim (IDL_TYPE_ARRAY (p).size_list, tfd, data,
2983                                  (IDL_tree_func) IDL_emit_IDL_literal_force_pre, NULL,
2984                                  IDLN_INTEGER, IDLN_NONE, TRUE, DELIM_ARRAY);
2985                dataf (data, "]");
2986                return FALSE;
2987
2988        case IDLN_TYPE_SEQUENCE:
2989                dataf (data, "sequence<");
2990                save_flag (idents, TRUE);
2991                IDL_tree_walk2 (IDL_TYPE_SEQUENCE (tfd->tree).simple_type_spec, tfd,/*flags*/0,
2992                               (IDL_tree_func) IDL_emit_node_pre_func,
2993                               (IDL_tree_func) IDL_emit_node_post_func,
2994                               data);
2995                restore_flag (idents);
2996                if (IDL_TYPE_SEQUENCE (tfd->tree).positive_int_const) {
2997                        dataf (data, DELIM_COMMA);
2998                        IDL_emit_IDL_literal (
2999                                IDL_TYPE_SEQUENCE (tfd->tree).positive_int_const, data);
3000                }
3001                dataf (data, ">");
3002                return FALSE;
3003
3004        case IDLN_TYPE_STRUCT:
3005                if (!data->su_def)
3006                        doindent ();
3007                save_flag (su_def, TRUE);
3008                data->inline_props = TRUE;
3009                IDL_emit_IDL_properties (IDL_TYPE_STRUCT (tfd->tree).ident, data);
3010                dataf (data, "struct" DELIM_SPACE);
3011                IDL_emit_IDL_ident (IDL_TYPE_STRUCT (p).ident, tfd, data);
3012                dataf (data, DELIM_SPACE);
3013                IDL_emit_IDL_curly_brace_open (tfd, data);
3014                IDL_tree_walk2 (IDL_TYPE_STRUCT (p).member_list, tfd,/*flags*/0,
3015                               (IDL_tree_func) IDL_emit_node_pre_func,
3016                               (IDL_tree_func) IDL_emit_node_post_func,
3017                               data);
3018                restore_flag (su_def);
3019                if (data->su_def)
3020                        IDL_emit_IDL_curly_brace_close (tfd, data);
3021                else
3022                        IDL_emit_IDL_curly_brace_close_sc (tfd, data);
3023                return FALSE;
3024
3025        case IDLN_TYPE_UNION:
3026                if (!data->su_def)
3027                        doindent ();
3028                save_flag (su_def, TRUE);
3029                data->inline_props = TRUE;
3030                IDL_emit_IDL_properties (IDL_TYPE_UNION (tfd->tree).ident, data);
3031                dataf (data, "union" DELIM_SPACE);
3032                IDL_emit_IDL_ident (IDL_TYPE_UNION (p).ident, tfd, data);
3033                dataf (data, DELIM_SPACE);
3034                dataf (data, "switch" DELIM_SPACE "(");
3035                save_flag (idents, TRUE);
3036                IDL_tree_walk2 (IDL_TYPE_UNION (p).switch_type_spec, tfd,/*flags*/0,
3037                               (IDL_tree_func) IDL_emit_node_pre_func,
3038                               (IDL_tree_func) IDL_emit_node_post_func,
3039                               data);
3040                restore_flag (idents);
3041                dataf (data, ")" DELIM_SPACE "{"); nl ();
3042                IDL_tree_walk2 (IDL_TYPE_UNION (p).switch_body, tfd,/*flags*/0,
3043                               (IDL_tree_func) IDL_emit_node_pre_func,
3044                               (IDL_tree_func) IDL_emit_node_post_func,
3045                               data);
3046                restore_flag (su_def);
3047                if (data->su_def)
3048                        idataf (data, "}");
3049                else {
3050                        idataf (data, "};");
3051                        nl ();
3052                }
3053                return FALSE;
3054
3055        default:
3056                break;
3057        }
3058
3059        return TRUE;
3060}
3061
3062static gboolean IDL_emit_IDL_module_all (IDL_tree_func_data *tfd, IDL_output_data *data)
3063{
3064        if (tfd->step == 0) {
3065                idataf (data, "module" DELIM_SPACE);
3066                IDL_emit_IDL_ident (IDL_MODULE (tfd->tree).ident, tfd, data);
3067                dataf (data, DELIM_SPACE);
3068                IDL_emit_IDL_curly_brace_open (tfd, data);
3069                save_flag (idents, FALSE);
3070        } else {
3071                restore_flag (idents);
3072                IDL_emit_IDL_curly_brace_close_sc (tfd, data);
3073        }
3074
3075        return TRUE;
3076}
3077
3078static gboolean IDL_emit_IDL_interface_all (IDL_tree_func_data *tfd, IDL_output_data *data)
3079{
3080        if (tfd->step == 0) {
3081                data->inline_props = FALSE;
3082                IDL_emit_IDL_properties (IDL_INTERFACE (tfd->tree).ident, data);
3083                idataf (data, "interface" DELIM_SPACE);
3084                IDL_emit_IDL_ident (IDL_INTERFACE (tfd->tree).ident, tfd, data);
3085                dataf (data, DELIM_SPACE);
3086                if (IDL_INTERFACE (tfd->tree).inheritance_spec) {
3087                        dataf (data, ":" DELIM_SPACE);
3088                        IDL_output_delim (IDL_INTERFACE (tfd->tree).inheritance_spec, tfd, data,
3089                                          (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL,
3090                                          IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA);
3091                        dataf (data, DELIM_SPACE);
3092                }
3093                IDL_emit_IDL_curly_brace_open (tfd, data);
3094                save_flag (idents, FALSE);
3095        } else {
3096                restore_flag (idents);
3097                IDL_emit_IDL_curly_brace_close_sc (tfd, data);
3098        }
3099
3100        return TRUE;
3101}
3102
3103static gboolean IDL_emit_IDL_forward_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3104{
3105        idataf (data, "interface" DELIM_SPACE);
3106        IDL_emit_IDL_ident (IDL_FORWARD_DCL (tfd->tree).ident, tfd, data);
3107
3108        return TRUE;
3109}
3110
3111static gboolean IDL_emit_IDL_attr_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3112{
3113        IDL_emit_IDL_indent (tfd, data);
3114        data->inline_props = TRUE;
3115        IDL_emit_IDL_properties (IDL_LIST (IDL_ATTR_DCL (tfd->tree).simple_declarations).data,
3116                                 data);
3117        if (IDL_ATTR_DCL (tfd->tree).f_readonly) dataf (data, "readonly" DELIM_SPACE);
3118        dataf (data, "attribute" DELIM_SPACE);
3119        save_flag (idents, TRUE);
3120        IDL_tree_walk2 (IDL_ATTR_DCL (tfd->tree).param_type_spec, tfd,/*flags*/0,
3121                       (IDL_tree_func) IDL_emit_node_pre_func,
3122                       (IDL_tree_func) IDL_emit_node_post_func,
3123                       data);
3124        restore_flag (idents);
3125        dataf (data, DELIM_SPACE);
3126        IDL_output_delim (IDL_ATTR_DCL (tfd->tree).simple_declarations, tfd, data,
3127                          (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL,
3128                          IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA);
3129        IDL_emit_IDL_sc (tfd, data);
3130
3131        return FALSE;
3132}
3133
3134static gboolean IDL_emit_IDL_op_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3135{
3136        IDL_emit_IDL_indent (tfd, data);
3137        data->inline_props = TRUE;
3138        IDL_emit_IDL_properties (IDL_OP_DCL (tfd->tree).ident, data);
3139        if (IDL_OP_DCL (tfd->tree).f_oneway) dataf (data, "oneway" DELIM_SPACE);
3140        if (IDL_OP_DCL (tfd->tree).op_type_spec) {
3141                save_flag (idents, TRUE);
3142                IDL_tree_walk2 (IDL_OP_DCL (tfd->tree).op_type_spec, tfd,/*flags*/0,
3143                               (IDL_tree_func) IDL_emit_node_pre_func,
3144                               (IDL_tree_func) IDL_emit_node_post_func,
3145                               data);
3146                restore_flag (idents);
3147        } else
3148                dataf (data, "void");
3149        dataf (data, DELIM_SPACE "%s" DELIM_SPACE "(",
3150               IDL_IDENT (IDL_OP_DCL (tfd->tree).ident).str);
3151        if (IDL_OP_DCL (tfd->tree).parameter_dcls)
3152                IDL_output_delim (IDL_OP_DCL (tfd->tree).parameter_dcls, tfd, data,
3153                                  (IDL_tree_func) IDL_emit_node_pre_func,
3154                                  (IDL_tree_func) IDL_emit_node_post_func,
3155                                  IDLN_PARAM_DCL, IDLN_NONE, FALSE, DELIM_COMMA);
3156        if (IDL_OP_DCL (tfd->tree).f_varargs)
3157                dataf (data, DELIM_COMMA "...");
3158        dataf (data, ")");
3159        if (IDL_OP_DCL (tfd->tree).raises_expr) {
3160                nl (); indent ();
3161                idataf (data, DELIM_SPACE "raises" DELIM_SPACE "(");
3162                IDL_output_delim (IDL_OP_DCL (tfd->tree).raises_expr, tfd, data,
3163                                  (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL,
3164                                  IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA);
3165                dataf (data, ")");
3166                unindent ();
3167        }
3168        if (IDL_OP_DCL (tfd->tree).context_expr) {
3169                nl (); indent ();
3170                idataf (data, DELIM_SPACE "context" DELIM_SPACE "(");
3171                IDL_output_delim (IDL_OP_DCL (tfd->tree).context_expr, tfd, data,
3172                                  (IDL_tree_func) IDL_emit_IDL_literal_force_pre, NULL,
3173                                  IDLN_STRING, IDLN_NONE, TRUE, DELIM_COMMA);
3174                dataf (data, ")");
3175                unindent ();
3176        }
3177        IDL_emit_IDL_sc (tfd, data);
3178
3179        return FALSE;
3180}
3181
3182static gboolean IDL_emit_IDL_param_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3183{
3184        data->inline_props = TRUE;
3185        IDL_emit_IDL_properties (IDL_PARAM_DCL (tfd->tree).simple_declarator, data);
3186        switch (IDL_PARAM_DCL (tfd->tree).attr) {
3187        case IDL_PARAM_IN: dataf (data, "in" DELIM_SPACE); break;
3188        case IDL_PARAM_OUT: dataf (data, "out" DELIM_SPACE); break;
3189        case IDL_PARAM_INOUT: dataf (data, "inout" DELIM_SPACE); break;
3190        }
3191        save_flag (idents, TRUE);
3192        IDL_tree_walk2 (IDL_PARAM_DCL (tfd->tree).param_type_spec, tfd,/*flags*/0,
3193                       (IDL_tree_func) IDL_emit_node_pre_func,
3194                       (IDL_tree_func) IDL_emit_node_post_func,
3195                       data);
3196        restore_flag (idents);
3197        dataf (data, DELIM_SPACE);
3198        IDL_emit_IDL_ident (IDL_PARAM_DCL (tfd->tree).simple_declarator, tfd, data);
3199
3200        return FALSE;
3201}
3202
3203static gboolean IDL_emit_IDL_type_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3204{
3205        IDL_tree_func_data down_tfd;
3206        IDL_tree q;
3207
3208        IDL_emit_IDL_indent (tfd, data);
3209        data->inline_props = TRUE;
3210        IDL_emit_IDL_properties (IDL_LIST (IDL_TYPE_DCL (tfd->tree).dcls).data, data);
3211        dataf (data, "typedef" DELIM_SPACE);
3212        save_flag (idents, TRUE);
3213        save_flag (su_def, TRUE);
3214        IDL_tree_walk2 (IDL_TYPE_DCL (tfd->tree).type_spec, tfd,/*flags*/0,
3215                       (IDL_tree_func) IDL_emit_node_pre_func,
3216                       (IDL_tree_func) IDL_emit_node_post_func,
3217                       data);
3218        dataf (data, DELIM_SPACE);
3219        down_tfd = *tfd;
3220        down_tfd.up = tfd;
3221        for (q = IDL_TYPE_DCL (tfd->tree).dcls; q; q = IDL_LIST (q).next) {
3222                down_tfd.tree = q;
3223                IDL_tree_walk2 (IDL_LIST (q).data, &down_tfd,/*flags*/0,
3224                               (IDL_tree_func) IDL_emit_node_pre_func,
3225                               (IDL_tree_func) IDL_emit_node_post_func,
3226                               data);
3227                if (IDL_LIST (q).next)
3228                        dataf (data, DELIM_COMMA);
3229        }
3230        restore_flag (idents);
3231        restore_flag (su_def);
3232        IDL_emit_IDL_sc (tfd, data);
3233
3234        return FALSE;
3235}
3236
3237static gboolean IDL_emit_IDL_const_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3238{
3239        idataf (data, "const" DELIM_SPACE);
3240        save_flag (idents, TRUE);
3241        IDL_tree_walk2 (IDL_CONST_DCL (tfd->tree).const_type, tfd,/*flags*/0,
3242                       (IDL_tree_func) IDL_emit_node_pre_func,
3243                       (IDL_tree_func) IDL_emit_node_post_func,
3244                       data);
3245        restore_flag (idents);
3246        dataf (data, DELIM_SPACE);
3247        IDL_emit_IDL_ident (IDL_CONST_DCL (tfd->tree).ident, tfd, data);
3248        dataf (data, DELIM_SPACE "=" DELIM_SPACE);
3249        save_flag (literals, TRUE);
3250        IDL_tree_walk2 (IDL_CONST_DCL (tfd->tree).const_exp, tfd,/*flags*/0,
3251                       (IDL_tree_func) IDL_emit_node_pre_func,
3252                       (IDL_tree_func) IDL_emit_node_post_func,
3253                       data);
3254        restore_flag (literals);
3255        IDL_emit_IDL_sc (tfd, data);
3256
3257        return FALSE;
3258}
3259
3260static gboolean IDL_emit_IDL_except_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3261{
3262        idataf (data, "exception" DELIM_SPACE);
3263        IDL_emit_IDL_ident (IDL_EXCEPT_DCL (tfd->tree).ident, tfd, data);
3264        dataf (data, DELIM_SPACE);
3265        IDL_emit_IDL_curly_brace_open (tfd, data);
3266
3267        return TRUE;
3268}
3269
3270static gboolean IDL_emit_IDL_native_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3271{
3272        IDL_emit_IDL_indent (tfd, data);
3273        data->inline_props = TRUE;
3274        IDL_emit_IDL_properties (IDL_NATIVE (tfd->tree).ident, data);
3275        dataf (data, "native" DELIM_SPACE);
3276        IDL_emit_IDL_ident (IDL_NATIVE (tfd->tree).ident, tfd, data);
3277        if (IDL_NATIVE (tfd->tree).user_type)
3278                dataf (data, DELIM_SPACE "(%s)", IDL_NATIVE (tfd->tree).user_type);
3279        IDL_emit_IDL_sc (tfd, data);
3280
3281        return TRUE;
3282}
3283
3284static gboolean IDL_emit_IDL_case_stmt_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3285{
3286        IDL_tree_func_data down_tfd;
3287        IDL_tree q;
3288
3289        save_flag (idents, TRUE);
3290        save_flag (literals, TRUE);
3291        down_tfd = *tfd;
3292        down_tfd.up = tfd;
3293        for (q = IDL_CASE_STMT (tfd->tree).labels; q; q = IDL_LIST (q).next) {
3294                if (IDL_LIST (q).data) {
3295                        down_tfd.tree = q;
3296                        idataf (data, "case" DELIM_SPACE);
3297                        IDL_tree_walk2 (IDL_LIST (q).data, &down_tfd,/*flags*/0,
3298                                       (IDL_tree_func) IDL_emit_node_pre_func,
3299                                       (IDL_tree_func) IDL_emit_node_post_func,
3300                                       data);
3301                        dataf (data, ":");
3302                } else
3303                        idataf (data, "default:");
3304                nl ();
3305        }
3306        restore_flag (literals);
3307        restore_flag (idents);
3308        indent ();
3309
3310        return FALSE;
3311}
3312
3313static gboolean IDL_emit_IDL_case_stmt_post (IDL_tree_func_data *tfd, IDL_output_data *data)
3314{
3315        IDL_tree_walk2 (IDL_CASE_STMT (tfd->tree).element_spec, tfd, /*flags*/0,
3316                       (IDL_tree_func) IDL_emit_node_pre_func,
3317                       (IDL_tree_func) IDL_emit_node_post_func,
3318                       data);
3319        unindent ();
3320
3321        return FALSE;
3322}
3323
3324static gboolean IDL_emit_IDL_member_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3325{
3326        IDL_emit_IDL_indent (tfd, data);
3327        save_flag (idents, TRUE);
3328        IDL_tree_walk2 (IDL_MEMBER (tfd->tree).type_spec, tfd, /*flags*/0,
3329                       (IDL_tree_func) IDL_emit_node_pre_func,
3330                       (IDL_tree_func) IDL_emit_node_post_func,
3331                       data);
3332        restore_flag (idents);
3333
3334        return FALSE;
3335}
3336
3337static gboolean IDL_emit_IDL_member_post (IDL_tree_func_data *tfd, IDL_output_data *data)
3338{
3339        dataf (data, DELIM_SPACE);
3340        IDL_output_delim (IDL_MEMBER (tfd->tree).dcls, tfd, data,
3341                          (IDL_tree_func) IDL_emit_IDL_type_pre, NULL,
3342                          IDLN_IDENT, IDLN_TYPE_ARRAY, FALSE, DELIM_COMMA);
3343        IDL_emit_IDL_sc (tfd, data);
3344
3345        return TRUE;
3346}
3347
3348static gboolean IDL_emit_IDL_codefrag_pre (IDL_tree_func_data *tfd, IDL_output_data *data)
3349{
3350        if (data->flags & IDLF_OUTPUT_CODEFRAGS) {
3351                GSList *slist;
3352
3353                dataf (data, "%%{ %s", IDL_CODEFRAG (tfd->tree).desc); nl ();
3354                for (slist = IDL_CODEFRAG (tfd->tree).lines; slist; slist = slist->next) {
3355                        dataf (data, "%s", (char *) slist->data); nl ();
3356                }
3357                dataf (data, "%%}"); nl ();
3358        }
3359
3360        return TRUE;
3361}
3362
3363struct IDL_emit_node {
3364        IDL_tree_func pre;
3365        IDL_tree_func post;
3366};
3367
3368static const struct IDL_emit_node * const IDL_get_IDL_emission_table (void)
3369{
3370        static gboolean initialized = FALSE;
3371        static struct IDL_emit_node table[IDLN_LAST];
3372        struct IDL_emit_node *s;
3373
3374        if (!initialized) {
3375
3376                s = &table[IDLN_MODULE];
3377                s->pre = s->post = (IDL_tree_func) IDL_emit_IDL_module_all;
3378
3379                s = &table[IDLN_INTERFACE];
3380                s->pre = s->post = (IDL_tree_func) IDL_emit_IDL_interface_all;
3381
3382                s = &table[IDLN_FORWARD_DCL];
3383                s->pre = (IDL_tree_func) IDL_emit_IDL_forward_dcl_pre;
3384                s->post = (IDL_tree_func) IDL_emit_IDL_sc;
3385
3386                s = &table[IDLN_ATTR_DCL];
3387                s->pre = (IDL_tree_func) IDL_emit_IDL_attr_dcl_pre;
3388
3389                s = &table[IDLN_OP_DCL];
3390                s->pre = (IDL_tree_func) IDL_emit_IDL_op_dcl_pre;
3391
3392                s = &table[IDLN_PARAM_DCL];
3393                s->pre = (IDL_tree_func) IDL_emit_IDL_param_dcl_pre;
3394
3395                s = &table[IDLN_TYPE_DCL];
3396                s->pre = (IDL_tree_func) IDL_emit_IDL_type_dcl_pre;
3397
3398                s = &table[IDLN_CONST_DCL];
3399                s->pre = (IDL_tree_func) IDL_emit_IDL_const_dcl_pre;
3400
3401                s = &table[IDLN_EXCEPT_DCL];
3402                s->pre = (IDL_tree_func) IDL_emit_IDL_except_dcl_pre;
3403                s->post = (IDL_tree_func) IDL_emit_IDL_curly_brace_close_sc;
3404
3405                s = &table[IDLN_MEMBER];
3406                s->pre = (IDL_tree_func) IDL_emit_IDL_member_pre;
3407                s->post = (IDL_tree_func) IDL_emit_IDL_member_post;
3408
3409                s = &table[IDLN_NATIVE];
3410                s->pre = (IDL_tree_func) IDL_emit_IDL_native_pre;
3411
3412                s = &table[IDLN_CASE_STMT];
3413                s->pre = (IDL_tree_func) IDL_emit_IDL_case_stmt_pre;
3414                s->post = (IDL_tree_func) IDL_emit_IDL_case_stmt_post;
3415
3416                s = &table[IDLN_IDENT];
3417                s->pre = (IDL_tree_func) IDL_emit_IDL_ident_pre;
3418
3419                s = &table[IDLN_CODEFRAG];
3420                s->pre = (IDL_tree_func) IDL_emit_IDL_codefrag_pre;
3421
3422                table[IDLN_TYPE_FLOAT].pre =
3423                        table[IDLN_TYPE_CHAR].pre =
3424                        table[IDLN_TYPE_WIDE_CHAR].pre =
3425                        table[IDLN_TYPE_BOOLEAN].pre =
3426                        table[IDLN_TYPE_OCTET].pre =
3427                        table[IDLN_TYPE_ANY].pre =
3428                        table[IDLN_TYPE_OBJECT].pre =
3429                        table[IDLN_TYPE_TYPECODE].pre =
3430                        table[IDLN_TYPE_FIXED].pre =
3431                        table[IDLN_TYPE_INTEGER].pre =
3432                        table[IDLN_TYPE_STRING].pre =
3433                        table[IDLN_TYPE_WIDE_STRING].pre =
3434                        table[IDLN_TYPE_ENUM].pre =
3435                        table[IDLN_TYPE_ARRAY].pre =
3436                        table[IDLN_TYPE_SEQUENCE].pre =
3437                        table[IDLN_TYPE_STRUCT].pre =
3438                        table[IDLN_TYPE_UNION].pre = (IDL_tree_func) IDL_emit_IDL_type_pre;
3439
3440                table[IDLN_FLOAT].pre =
3441                        table[IDLN_INTEGER].pre =
3442                        table[IDLN_FIXED].pre =
3443                        table[IDLN_CHAR].pre =
3444                        table[IDLN_WIDE_CHAR].pre =
3445                        table[IDLN_BOOLEAN].pre =
3446                        table[IDLN_STRING].pre =
3447                        table[IDLN_WIDE_STRING].pre = (IDL_tree_func) IDL_emit_IDL_literal_pre;
3448
3449                initialized = TRUE;
3450        }
3451
3452        return table;
3453}
3454
3455static gboolean IDL_emit_node_pre_func (IDL_tree_func_data *tfd, IDL_output_data *data)
3456{
3457        const struct IDL_emit_node * const s =
3458                &IDL_get_IDL_emission_table () [IDL_NODE_TYPE (tfd->tree)];
3459
3460        if (s->pre)
3461                return (*s->pre) (tfd, data);
3462
3463        return TRUE;
3464}
3465
3466static gboolean IDL_emit_node_post_func (IDL_tree_func_data *tfd, IDL_output_data *data)
3467{
3468        const struct IDL_emit_node * const s =
3469                &IDL_get_IDL_emission_table () [IDL_NODE_TYPE (tfd->tree)];
3470
3471        if (s->post)
3472                return (*s->post) (tfd, data);
3473
3474        return TRUE;
3475}
3476
3477void IDL_tree_to_IDL (IDL_tree p, IDL_ns ns, FILE *output, unsigned long output_flags)
3478{
3479        IDL_output_data data;
3480
3481        g_return_if_fail (output != NULL);
3482
3483        data.ns = ns;
3484        data.mode = OUTPUT_FILE;
3485        data.u.o = output;
3486        data.flags = output_flags;
3487        data.ilev = 0;
3488        data.idents = TRUE;
3489        data.literals = TRUE;
3490        data.inline_props = TRUE;
3491        data.su_def = FALSE;
3492
3493        if (ns == NULL)
3494                data.flags |= IDLF_OUTPUT_NO_QUALIFY_IDENTS;
3495
3496        IDL_tree_walk2 (p, NULL, /*flags*/0,
3497                       (IDL_tree_func) IDL_emit_node_pre_func,
3498                       (IDL_tree_func) IDL_emit_node_post_func,
3499                       &data);
3500}
3501
3502GString *IDL_tree_to_IDL_string (IDL_tree p, IDL_ns ns, unsigned long output_flags)
3503{
3504        IDL_output_data data;
3505
3506        data.ns = ns;
3507        data.mode = OUTPUT_STRING;
3508        data.u.s = g_string_new (NULL);
3509        data.flags = output_flags;
3510        data.ilev = 0;
3511        data.idents = TRUE;
3512        data.literals = TRUE;
3513        data.inline_props = TRUE;
3514        data.su_def = FALSE;
3515
3516        if (ns == NULL)
3517                data.flags |= IDLF_OUTPUT_NO_QUALIFY_IDENTS;
3518
3519        IDL_tree_walk2 (p, NULL, /*flags*/0,
3520                       (IDL_tree_func) IDL_emit_node_pre_func,
3521                       (IDL_tree_func) IDL_emit_node_post_func,
3522                       &data);
3523
3524        return data.u.s;
3525}
3526
3527typedef struct {
3528    IDL_tree    searchNode;
3529    gboolean    found;
3530} ContainsNodeWalkerInfo;
3531
3532static gboolean
3533contains_node_walker (IDL_tree_func_data *tfd, gpointer data) {
3534        ContainsNodeWalkerInfo  *info = data;
3535        /* skip root! */
3536        if ( tfd->up!=0 && tfd->tree == info->searchNode ) {
3537                info->found = TRUE;
3538                return FALSE;
3539        }
3540        return TRUE;    /* continue walking */
3541}
3542
3543gboolean IDL_tree_contains_node(IDL_tree tree, IDL_tree node) {
3544        ContainsNodeWalkerInfo  info;
3545        info.searchNode = node;
3546        info.found = 0;
3547        IDL_tree_walk2 (tree, /*curwalk*/NULL, /*flags*/0,
3548          /*pre*/contains_node_walker, /*post*/NULL, &info);
3549        return info.found;
3550}
3551
3552struct IDL_recursive_walker_info {
3553        GSList   *ident_list;
3554        gboolean  recursive;
3555        };
3556
3557/*
3558 * IDL_tree_is_recursive_walker_pre:
3559 * @walk_frame: a #IDL_tree_func_data structure
3560 * @user_data: a #IDL_recursive_walker_info structure.
3561 *
3562 * If the current node in the parse tree is a structure or union
3563 * add its IDLN_IDENT to the ident list contained in @user_data;
3564 *
3565 * If the current node in the parse tree is a sequence, check to
3566 * see if the sequence element type is on the list of IDLN_IDENTs.
3567 *
3568 * Return value: %FALSE if recursion is detected - this stops the
3569 *               walk to the parse tree -, %TRUE otherwise.
3570 */
3571static gboolean
3572IDL_tree_is_recursive_walker_pre (IDL_tree_func_data *walk_frame,
3573                                  gpointer            user_data)
3574{
3575        struct IDL_recursive_walker_info *info = user_data;
3576        IDL_tree                          node = walk_frame->tree;
3577
3578        switch (IDL_NODE_TYPE (node)) {
3579        case IDLN_TYPE_STRUCT:
3580        case IDLN_TYPE_UNION:
3581                info->ident_list = g_slist_prepend (info->ident_list,
3582                                                    IDL_TYPE_STRUCT (node).ident);
3583                break;
3584        case IDLN_TYPE_SEQUENCE: {
3585                IDL_tree  seq_type = IDL_TYPE_SEQUENCE (node).simple_type_spec;
3586                GSList   *l = info->ident_list;
3587
3588                if (IDL_NODE_TYPE (seq_type) != IDLN_IDENT)
3589                        break;
3590
3591                g_assert (IDL_IDENT (seq_type).repo_id);
3592
3593                for (; l; l = l->next) {
3594                        IDL_tree n = (IDL_tree)l->data;
3595
3596                        g_assert (IDL_IDENT (n).repo_id);
3597
3598                        if (!strcmp (IDL_IDENT (n).repo_id,
3599                                     IDL_IDENT (seq_type).repo_id)) {
3600
3601                                info->recursive = TRUE;
3602                                return FALSE;
3603                        }
3604                }
3605                }
3606                break;
3607        default:
3608                break;
3609        }
3610
3611        return TRUE;
3612}
3613
3614/*
3615 * IDL_tree_is_recursive_walker_post:
3616 * @walk_frame: a #IDL_tree_func_data structure
3617 * @user_data: a #IDL_recursive_walker_info structure.
3618 *
3619 * If the current node in the parse tree is a structure or
3620 * union, remove the IDLN_IDENT from the ident list.
3621 *
3622 * Return value: %TRUE.
3623 */
3624static gboolean
3625IDL_tree_is_recursive_walker_post (IDL_tree_func_data *walk_frame,
3626                                   gpointer            user_data)
3627{
3628        struct IDL_recursive_walker_info *info = user_data;
3629        IDL_tree                          node = walk_frame->tree;
3630
3631        switch (IDL_NODE_TYPE (node)) {
3632        case IDLN_TYPE_STRUCT:
3633        case IDLN_TYPE_UNION: {
3634                GSList *link = info->ident_list;
3635
3636                g_assert (((IDL_tree)link->data) == IDL_TYPE_STRUCT (node).ident);
3637
3638                info->ident_list = g_slist_remove_link (info->ident_list,
3639                                                        link);
3640                g_slist_free_1 (link);
3641                }
3642                break;
3643        default:
3644                break;
3645        }
3646
3647        return TRUE;
3648}
3649
3650/*
3651 * IDL_tree_is_recursive:
3652 * @tree: a #IDL_tree.
3653 * @hasRecur: dummy argument, not used, deprecated, compatibility cruft.
3654 *
3655 * Checks whether or not @tree contains recursive types.
3656 *
3657 * Recursive types may only be constructed using structs/unions which
3658 * contain sequences that hold the parent struct/union type.
3659 *
3660 * Return value: %TRUE if @tree contains recursive types,
3661 *               %FALSE otherwise.
3662 */
3663gboolean
3664IDL_tree_is_recursive (IDL_tree tree, gpointer dummy)
3665{
3666        struct IDL_recursive_walker_info info;
3667
3668        info.ident_list = NULL;
3669        info.recursive  = FALSE;
3670
3671        IDL_tree_walk2 (tree, 0, IDL_WalkF_TypespecOnly,
3672                        IDL_tree_is_recursive_walker_pre,
3673                        IDL_tree_is_recursive_walker_post,
3674                        &info);
3675
3676        g_assert (!info.ident_list);
3677
3678        return info.recursive;
3679}
3680
3681/*
3682 * Local variables:
3683 * mode: C
3684 * c-basic-offset: 8
3685 * tab-width: 8
3686 * indent-tabs-mode: t
3687 * End:
3688 */
Note: See TracBrowser for help on using the repository browser.