/************************************************************************** util.c Copyright (C) 1998, 1999 Andrew T. Veliath This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id$ ***************************************************************************/ #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include "rename.h" #include "util.h" #ifdef G_OS_WIN32 #include #include #define popen _popen #define pclose _pclose #endif const char *IDL_tree_type_names[] = { "IDLN_NONE", "IDLN_ANY", "IDLN_LIST", "IDLN_GENTREE", "IDLN_INTEGER", "IDLN_STRING", "IDLN_WIDE_STRING", "IDLN_CHAR", "IDLN_WIDE_CHAR", "IDLN_FIXED", "IDLN_FLOAT", "IDLN_BOOLEAN", "IDLN_IDENT", "IDLN_TYPE_DCL", "IDLN_CONST_DCL", "IDLN_EXCEPT_DCL", "IDLN_ATTR_DCL", "IDLN_OP_DCL", "IDLN_PARAM_DCL", "IDLN_FORWARD_DCL", "IDLN_TYPE_INTEGER", "IDLN_TYPE_FLOAT", "IDLN_TYPE_FIXED", "IDLN_TYPE_CHAR", "IDLN_TYPE_WIDE_CHAR", "IDLN_TYPE_STRING", "IDLN_TYPE_WIDE_STRING", "IDLN_TYPE_BOOLEAN", "IDLN_TYPE_OCTET", "IDLN_TYPE_ANY", "IDLN_TYPE_OBJECT", "IDLN_TYPE_TYPECODE", "IDLN_TYPE_ENUM", "IDLN_TYPE_SEQUENCE", "IDLN_TYPE_ARRAY", "IDLN_TYPE_STRUCT", "IDLN_TYPE_UNION", "IDLN_MEMBER", "IDLN_NATIVE", "IDLN_CASE_STMT", "IDLN_INTERFACE", "IDLN_MODULE", "IDLN_BINOP", "IDLN_UNARYOP", "IDLN_CODEFRAG", /* IDLN_LAST */ }; int __IDL_check_type_casts = FALSE; #ifndef HAVE_CPP_PIPE_STDIN const char * __IDL_tmp_filename = NULL; #endif const char * __IDL_real_filename = NULL; char * __IDL_cur_filename = NULL; int __IDL_cur_line; GHashTable * __IDL_filename_hash; IDL_fileinfo * __IDL_cur_fileinfo; GHashTable * __IDL_structunion_ht; int __IDL_inhibits; int __IDL_typecodes_as_tok; int __IDL_pidl; IDL_tree __IDL_root; IDL_ns __IDL_root_ns; int __IDL_is_okay; int __IDL_is_parsing; unsigned long __IDL_flags; unsigned long __IDL_flagsi; gpointer __IDL_inputcb_user_data; IDL_input_callback __IDL_inputcb; GSList * __IDL_new_ident_comments; static int __IDL_max_msg_level; static int __IDL_nerrors, __IDL_nwarnings; static IDL_msg_callback __IDL_msgcb; /* Case-insensitive version of g_str_hash */ guint IDL_strcase_hash (gconstpointer v) { const char *p; guint h = 0, g; for (p = (char *) v; *p != '\0'; ++p) { h = (h << 4) + isupper ((int)*p) ? tolower (*p) : *p; if ((g = h & 0xf0000000)) { h = h ^ (g >> 24); h = h ^ g; } } return h /* % M */; } gint IDL_strcase_equal (gconstpointer a, gconstpointer b) { return g_ascii_strcasecmp (a, b) == 0; } gint IDL_strcase_cmp (gconstpointer a, gconstpointer b) { return g_ascii_strcasecmp (a, b); } static int my_strcmp (IDL_tree p, IDL_tree q) { const char *a = IDL_IDENT (p).str; const char *b = IDL_IDENT (q).str; int cmp = IDL_strcase_cmp (a, b); if (__IDL_is_parsing && cmp == 0 && strcmp (a, b) != 0 && !(IDL_IDENT (p)._flags & IDLF_IDENT_CASE_MISMATCH_HIT || IDL_IDENT (q)._flags & IDLF_IDENT_CASE_MISMATCH_HIT)) { IDL_tree_warning (p, IDL_WARNING1, "Case mismatch between `%s'", a); IDL_tree_warning (q, IDL_WARNING1, "and `%s'", b); yywarning (IDL_WARNING1, "(Identifiers should be case-consistent after initial declaration)"); IDL_IDENT (p)._flags |= IDLF_IDENT_CASE_MISMATCH_HIT; IDL_IDENT (q)._flags |= IDLF_IDENT_CASE_MISMATCH_HIT; } return cmp; } guint IDL_ident_hash (gconstpointer v) { return IDL_strcase_hash (IDL_IDENT ((IDL_tree) v).str); } gint IDL_ident_equal (gconstpointer a, gconstpointer b) { return my_strcmp ((IDL_tree) a, (IDL_tree) b) == 0; } gint IDL_ident_cmp (gconstpointer a, gconstpointer b) { return my_strcmp ((IDL_tree) a, (IDL_tree) b); } const char *IDL_get_libver_string (void) { return LIBIDL_VERSION; } const char *IDL_get_IDLver_string (void) { return "2.2"; } static void IDL_tree_optimize (IDL_tree *p, IDL_ns ns) { if (!(__IDL_flags & IDLF_IGNORE_FORWARDS)) IDL_tree_process_forward_dcls (p, ns); if (!(__IDL_flags & IDLF_INHIBIT_TAG_ONLY)) IDL_tree_remove_inhibits (p, ns); IDL_tree_remove_empty_modules (p, ns); } static void IDL_parse_setup(unsigned long parse_flags, int max_msg_level) { if (parse_flags & IDLF_XPIDL) parse_flags |= IDLF_PROPERTIES; __IDL_max_msg_level = max_msg_level; __IDL_nerrors = __IDL_nwarnings = 0; __IDL_inhibits = 0; __IDL_typecodes_as_tok = (parse_flags & IDLF_TYPECODES) ? 1 : 0; __IDL_pidl = (parse_flags & IDLF_XPIDL) ? 1 : 0; __IDL_flags = parse_flags; __IDL_flagsi = 0; __IDL_is_parsing = TRUE; __IDL_is_okay = TRUE; __IDL_new_ident_comments = NULL; } int IDL_parse_filename (const char *filename, const char *cpp_args, IDL_msg_callback msg_cb, IDL_tree *tree, IDL_ns *ns, unsigned long parse_flags, int max_msg_level) { extern void __IDL_lex_init (void); extern void __IDL_lex_cleanup (void); extern int yyparse (void); extern FILE *__IDL_in; FILE *input; char *cmd; #ifdef HAVE_CPP_PIPE_STDIN char *fmt = CPP_PROGRAM " - %s%s %s < \"%s\" %s"; char *wd; #else char *fmt = CPP_PROGRAM " -I%s %s \"%s\" %s"; char cwd[2048]; #ifdef HAVE_SYMLINK char *s, *tmpfilename; gchar *linkto; #else const char *tmpfilename; #endif #endif #ifndef G_OS_WIN32 char *cpperrs = (parse_flags & IDLF_SHOW_CPP_ERRORS) ? "" : "2>/dev/null"; #else char *cpperrs = ""; #endif GSList *slist; int rv; #if 0 && defined(YYDEBUG) { extern int __IDL_debug; __IDL_debug = 1; } #endif if (!filename || !tree) { errno = EINVAL; return -1; } #ifdef HAVE_ACCESS if (access (filename, R_OK)) return -1; #endif #ifdef HAVE_CPP_PIPE_STDIN wd = g_path_get_dirname (filename); cmd = g_strdup_printf (fmt, "-I", wd, cpp_args ? cpp_args : "", filename, cpperrs); g_free (wd); #else if (!getcwd (cwd, sizeof (cwd))) return -1; #ifdef HAVE_SYMLINK s = tmpnam (NULL); if (s == NULL) return -1; if (g_path_is_absolute (filename)) { linkto = g_strdup (filename); } else { linkto = g_strconcat (cwd, "/", filename, NULL); } tmpfilename = g_strconcat (s, ".c", NULL); if (symlink (linkto, tmpfilename) < 0) { g_free (linkto); g_free (tmpfilename); return -1; } g_free (linkto); #else tmpfilename = filename; #endif cmd = g_strdup_printf (fmt, cwd, cpp_args ? cpp_args : "", tmpfilename, cpperrs); #endif /* Many versions of cpp do evil translating internal * strings, producing bogus output, so clobber LC_ALL */ putenv ("LC_ALL=C"); #ifdef HAVE_POPEN #if defined (G_OS_WIN32) && !defined (_MSC_VER) if (!(parse_flags & IDLF_SHOW_CPP_ERRORS)) { int save_stderr = dup (2); int null = open ("NUL:", O_WRONLY); dup2 (null, 2); input = popen (cmd, "r"); close (2); close (null); dup2 (save_stderr, 2); close (save_stderr); } else input = popen (cmd, "r"); #else input = popen (cmd, "r"); #endif #else #error Must have popen #endif g_free (cmd); if (input == NULL || ferror (input)) { #if !defined (HAVE_CPP_PIPE_STDIN) && defined (HAVE_SYMLINK) g_free (tmpfilename); #endif return IDL_ERROR; } IDL_parse_setup(parse_flags, max_msg_level); __IDL_in = input; __IDL_msgcb = msg_cb; __IDL_root_ns = IDL_ns_new (); __IDL_lex_init (); __IDL_real_filename = filename; #ifndef HAVE_CPP_PIPE_STDIN __IDL_tmp_filename = tmpfilename; #endif __IDL_filename_hash = IDL_NS (__IDL_root_ns).filename_hash; __IDL_structunion_ht = g_hash_table_new (g_direct_hash, g_direct_equal); rv = yyparse (); g_hash_table_destroy (__IDL_structunion_ht); __IDL_is_parsing = FALSE; __IDL_lex_cleanup (); __IDL_parser_reset (); __IDL_real_filename = NULL; #ifndef HAVE_CPP_PIPE_STDIN __IDL_tmp_filename = NULL; #endif #ifdef HAVE_POPEN pclose (input); #else fclose (input); #endif #if !defined (HAVE_CPP_PIPE_STDIN) && defined (HAVE_SYMLINK) unlink (tmpfilename); g_free (tmpfilename); #endif for (slist = __IDL_new_ident_comments; slist; slist = slist->next) g_free (slist->data); g_slist_free (__IDL_new_ident_comments); if (__IDL_root != NULL) { IDL_tree_optimize (&__IDL_root, __IDL_root_ns); if (__IDL_root == NULL) yyerror ("File empty after optimization"); } __IDL_msgcb = NULL; if (rv != 0 || !__IDL_is_okay) { *tree = NULL; if (ns) *ns = NULL; return IDL_ERROR; } if (__IDL_flags & IDLF_PREFIX_FILENAME) IDL_ns_prefix (__IDL_root_ns, filename); *tree = __IDL_root; if (ns) *ns = __IDL_root_ns; else IDL_ns_free (__IDL_root_ns); return IDL_SUCCESS; } int IDL_parse_filename_with_input (const char *filename, IDL_input_callback input_cb, gpointer input_cb_user_data, IDL_msg_callback msg_cb, IDL_tree *tree, IDL_ns *ns, unsigned long parse_flags, int max_msg_level) { extern void __IDL_lex_init (void); extern void __IDL_lex_cleanup (void); extern int yyparse (void); union IDL_input_data data; GSList *slist; int rv; if (!filename || !input_cb || !tree) { errno = EINVAL; return -1; } IDL_parse_setup(parse_flags, max_msg_level); __IDL_msgcb = msg_cb; __IDL_root_ns = IDL_ns_new (); __IDL_lex_init (); __IDL_inputcb = input_cb; __IDL_inputcb_user_data = input_cb_user_data; __IDL_real_filename = filename; #ifndef HAVE_CPP_PIPE_STDIN __IDL_tmp_filename = NULL; #endif __IDL_filename_hash = IDL_NS (__IDL_root_ns).filename_hash; data.init.filename = filename; if ((*__IDL_inputcb) ( IDL_INPUT_REASON_INIT, &data, __IDL_inputcb_user_data)) { IDL_ns_free (__IDL_root_ns); __IDL_lex_cleanup (); __IDL_real_filename = NULL; return -1; } __IDL_structunion_ht = g_hash_table_new (g_direct_hash, g_direct_equal); rv = yyparse (); g_hash_table_destroy (__IDL_structunion_ht); __IDL_is_parsing = FALSE; __IDL_lex_cleanup (); __IDL_parser_reset (); __IDL_real_filename = NULL; for (slist = __IDL_new_ident_comments; slist; slist = slist->next) g_free (slist->data); g_slist_free (__IDL_new_ident_comments); if (__IDL_root != NULL) { IDL_tree_optimize (&__IDL_root, __IDL_root_ns); if (__IDL_root == NULL) yyerror ("File empty after optimization"); } __IDL_msgcb = NULL; if (rv != 0 || !__IDL_is_okay) { *tree = NULL; if (ns) *ns = NULL; (*__IDL_inputcb) ( IDL_INPUT_REASON_ABORT, NULL, __IDL_inputcb_user_data); return IDL_ERROR; } (*__IDL_inputcb) (IDL_INPUT_REASON_FINISH, NULL, __IDL_inputcb_user_data); if (__IDL_flags & IDLF_PREFIX_FILENAME) IDL_ns_prefix (__IDL_root_ns, filename); *tree = __IDL_root; if (ns) *ns = __IDL_root_ns; else IDL_ns_free (__IDL_root_ns); return IDL_SUCCESS; } void yyerrorl (const char *s, int ofs) { int line = __IDL_cur_line - 1 + ofs; gchar *freeme = NULL, *filename = NULL; if (__IDL_cur_filename) { #ifdef HAVE_CPP_PIPE_STDIN filename = __IDL_cur_filename; #else freeme = filename = g_path_get_basename (__IDL_cur_filename); #endif } else line = -1; ++__IDL_nerrors; __IDL_is_okay = FALSE; /* Errors are counted, even if not printed */ if (__IDL_max_msg_level < IDL_ERROR) { g_free (freeme); return; } if (__IDL_msgcb) (*__IDL_msgcb)(IDL_ERROR, __IDL_nerrors, line, filename, s); else { if (line > 0) fprintf (stderr, "%s:%d: Error: %s\n", filename, line, s); else fprintf (stderr, "Error: %s\n", s); } g_free (freeme); } void yywarningl (int level, const char *s, int ofs) { int line = __IDL_cur_line - 1 + ofs; gchar *freeme = NULL, *filename = NULL; /* Unprinted warnings are not counted */ if (__IDL_max_msg_level < level) return; if (__IDL_cur_filename) { #ifdef HAVE_CPP_PIPE_STDIN filename = __IDL_cur_filename; #else freeme = filename = g_path_get_basename (__IDL_cur_filename); #endif } else line = -1; ++__IDL_nwarnings; if (__IDL_msgcb) (*__IDL_msgcb)(level, __IDL_nwarnings, line, filename, s); else { if (line > 0) fprintf (stderr, "%s:%d: Warning: %s\n", filename, line, s); else fprintf (stderr, "Warning: %s\n", s); } g_free (freeme); } void yyerror (const char *s) { yyerrorl (s, 0); } void yywarning (int level, const char *s) { yywarningl (level, s, 0); } void yyerrorlv (const char *fmt, int ofs, ...) { gchar *msg; va_list args; va_start (args, ofs); msg = g_strdup_vprintf (fmt, args); yyerrorl (msg, ofs); va_end (args); g_free (msg); } void yywarninglv (int level, const char *fmt, int ofs, ...) { gchar *msg; va_list args; va_start (args, ofs); msg = g_strdup_vprintf (fmt, args); yywarningl (level, msg, ofs); va_end (args); g_free (msg); } void yyerrorv (const char *fmt, ...) { gchar *msg; va_list args; va_start (args, fmt); msg = g_strdup_vprintf (fmt, args); yyerror (msg); va_end (args); g_free (msg); } void yywarningv (int level, const char *fmt, ...) { gchar *msg; va_list args; va_start (args, fmt); msg = g_strdup_vprintf (fmt, args); yywarning (level, msg); va_end (args); g_free (msg); } void IDL_tree_error (IDL_tree p, const char *fmt, ...) { char *file_save = __IDL_cur_filename; int line_save = __IDL_cur_line; gchar *msg; va_list args; if (p) { __IDL_cur_filename = p->_file; __IDL_cur_line = p->_line; } else { __IDL_cur_filename = NULL; __IDL_cur_line = -1; } va_start (args, fmt); msg = g_strdup_vprintf (fmt, args); yyerror (msg); va_end (args); g_free (msg); __IDL_cur_filename = file_save; __IDL_cur_line = line_save; } void IDL_tree_warning (IDL_tree p, int level, const char *fmt, ...) { char *file_save = __IDL_cur_filename; int line_save = __IDL_cur_line; gchar *msg; va_list args; if (p) { __IDL_cur_filename = p->_file; __IDL_cur_line = p->_line; } else { __IDL_cur_filename = NULL; __IDL_cur_line = -1; } va_start (args, fmt); msg = g_strdup_vprintf (fmt, args); yywarning (level, msg); va_end (args); g_free (msg); __IDL_cur_filename = file_save; __IDL_cur_line = line_save; } int IDL_tree_get_node_info (IDL_tree p, char **what, char **who) { int dienow = 0; assert (what != NULL); assert (who != NULL); switch (IDL_NODE_TYPE (p)) { case IDLN_TYPE_STRUCT: *what = "structure definition"; *who = IDL_IDENT (IDL_TYPE_STRUCT (p).ident).str; break; case IDLN_TYPE_UNION: *what = "union definition"; *who = IDL_IDENT (IDL_TYPE_UNION (p).ident).str; break; case IDLN_TYPE_ARRAY: *what = "array"; *who = IDL_IDENT (IDL_TYPE_ARRAY (p).ident).str; break; case IDLN_TYPE_ENUM: *what = "enumeration definition"; *who = IDL_IDENT (IDL_TYPE_ENUM (p).ident).str; break; case IDLN_IDENT: *what = "identifier"; *who = IDL_IDENT (p).str; break; case IDLN_TYPE_DCL: *what = "type definition"; assert (IDL_TYPE_DCL (p).dcls != NULL); assert (IDL_NODE_TYPE (IDL_TYPE_DCL (p).dcls) == IDLN_LIST); assert (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail != NULL); assert (IDL_NODE_TYPE (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail) == IDLN_LIST); *who = IDL_IDENT (IDL_LIST (IDL_LIST (IDL_TYPE_DCL (p).dcls)._tail).data).str; break; case IDLN_MEMBER: *what = "member declaration"; assert (IDL_MEMBER (p).dcls != NULL); assert (IDL_NODE_TYPE (IDL_MEMBER (p).dcls) == IDLN_LIST); assert (IDL_LIST (IDL_MEMBER (p).dcls)._tail != NULL); assert (IDL_NODE_TYPE (IDL_LIST (IDL_MEMBER (p).dcls)._tail) == IDLN_LIST); *who = IDL_IDENT (IDL_LIST (IDL_LIST (IDL_MEMBER (p).dcls)._tail).data).str; break; case IDLN_NATIVE: *what = "native declaration"; assert (IDL_NATIVE (p).ident != NULL); assert (IDL_NODE_TYPE (IDL_NATIVE (p).ident) == IDLN_IDENT); *who = IDL_IDENT (IDL_NATIVE (p).ident).str; break; case IDLN_LIST: if (!IDL_LIST (p).data) break; dienow = IDL_tree_get_node_info (IDL_LIST (p).data, what, who); break; case IDLN_ATTR_DCL: *what = "interface attribute"; assert (IDL_ATTR_DCL (p).simple_declarations != NULL); assert (IDL_NODE_TYPE (IDL_ATTR_DCL (p).simple_declarations) == IDLN_LIST); assert (IDL_LIST (IDL_ATTR_DCL (p).simple_declarations)._tail != NULL); assert (IDL_NODE_TYPE (IDL_LIST ( IDL_ATTR_DCL (p).simple_declarations)._tail) == IDLN_LIST); *who = IDL_IDENT (IDL_LIST (IDL_LIST ( IDL_ATTR_DCL (p).simple_declarations)._tail).data).str; break; case IDLN_PARAM_DCL: *what = "operation parameter"; assert (IDL_PARAM_DCL (p).simple_declarator != NULL); assert (IDL_NODE_TYPE (IDL_PARAM_DCL (p).simple_declarator) == IDLN_IDENT); *who = IDL_IDENT (IDL_PARAM_DCL (p).simple_declarator).str; break; case IDLN_CONST_DCL: *what = "constant declaration for"; *who = IDL_IDENT (IDL_CONST_DCL (p).ident).str; break; case IDLN_EXCEPT_DCL: *what = "exception"; *who = IDL_IDENT (IDL_EXCEPT_DCL (p).ident).str; break; case IDLN_OP_DCL: *what = "interface operation"; *who = IDL_IDENT (IDL_OP_DCL (p).ident).str; break; case IDLN_MODULE: *what = "module"; *who = IDL_IDENT (IDL_MODULE (p).ident).str; break; case IDLN_FORWARD_DCL: *what = "forward declaration"; *who = IDL_IDENT (IDL_FORWARD_DCL (p).ident).str; break; case IDLN_INTERFACE: *what = "interface"; *who = IDL_IDENT (IDL_INTERFACE (p).ident).str; break; default: g_warning ("Node type: %s\n", IDL_NODE_TYPE_NAME (p)); *what = "unknown (internal error)"; break; } return dienow; } static IDL_tree IDL_node_new (IDL_tree_type type) { IDL_tree p; p = g_new0 (IDL_tree_node, 1); if (p == NULL) { yyerror ("IDL_node_new: memory exhausted"); return NULL; } IDL_NODE_TYPE (p) = type; IDL_NODE_REFS (p) = 1; p->_file = __IDL_cur_filename; p->_line = __IDL_cur_line; return p; } void __IDL_assign_up_node (IDL_tree up, IDL_tree node) { if (node == NULL) return; assert (node != up); switch (IDL_NODE_TYPE (node)) { case IDLN_LIST: if (IDL_NODE_UP (node) == NULL) for (; node != NULL; node = IDL_LIST (node).next) IDL_NODE_UP (node) = up; break; default: if (IDL_NODE_UP (node) == NULL) IDL_NODE_UP (node) = up; break; } } void __IDL_assign_location (IDL_tree node, IDL_tree from_node) { assert (node != NULL); if (from_node) { node->_file = from_node->_file; node->_line = from_node->_line; } } void __IDL_assign_this_location (IDL_tree node, char *filename, int line) { assert (node != NULL); node->_file = filename; node->_line = line; } IDL_tree IDL_list_new (IDL_tree data) { IDL_tree p = IDL_node_new (IDLN_LIST); __IDL_assign_up_node (p, data); IDL_LIST (p).data = data; IDL_LIST (p)._tail = p; return p; } IDL_tree IDL_list_concat (IDL_tree orig, IDL_tree append) { IDL_tree p; if (orig == NULL) return append; if (append == NULL) return orig; IDL_LIST (IDL_LIST (orig)._tail).next = append; IDL_LIST (append).prev = IDL_LIST (orig)._tail; IDL_LIST (orig)._tail = IDL_LIST (append)._tail; /* Set tails on original */ for (p = IDL_LIST (orig).next; p && p != append; p = IDL_LIST (p).next) IDL_LIST (p)._tail = IDL_LIST (orig)._tail; /* Set up nodes on appended list */ for (p = append; p; p = IDL_LIST (p).next) IDL_NODE_UP (p) = IDL_NODE_UP (orig); return orig; } IDL_tree IDL_list_remove (IDL_tree list, IDL_tree p) { IDL_tree new_list = list; if (IDL_LIST (p).prev == NULL) { assert (list == p); new_list = IDL_LIST (p).next; if (new_list) IDL_LIST (new_list).prev = NULL; } else { IDL_tree prev = IDL_LIST (p).prev; IDL_tree next = IDL_LIST (p).next; IDL_LIST (prev).next = next; if (next) IDL_LIST (next).prev = prev; } IDL_LIST (p).prev = NULL; IDL_LIST (p).next = NULL; IDL_LIST (p)._tail = p; /* Not all tails updated... */ return new_list; } IDL_tree IDL_gentree_new (GHashFunc hash_func, GCompareFunc key_compare_func, IDL_tree data) { IDL_tree p = IDL_node_new (IDLN_GENTREE); __IDL_assign_up_node (p, data); IDL_GENTREE (p).data = data; IDL_GENTREE (p).hash_func = hash_func; IDL_GENTREE (p).key_compare_func = key_compare_func; IDL_GENTREE (p).siblings = g_hash_table_new (hash_func, key_compare_func); IDL_GENTREE (p).children = g_hash_table_new (hash_func, key_compare_func); g_hash_table_insert (IDL_GENTREE (p).siblings, data, p); return p; } IDL_tree IDL_gentree_new_sibling (IDL_tree from, IDL_tree data) { IDL_tree p = IDL_node_new (IDLN_GENTREE); __IDL_assign_up_node (p, data); IDL_GENTREE (p).data = data; IDL_GENTREE (p).hash_func = IDL_GENTREE (from).hash_func; IDL_GENTREE (p).key_compare_func = IDL_GENTREE (from).key_compare_func; IDL_GENTREE (p).siblings = IDL_GENTREE (from).siblings; IDL_GENTREE (p).children = g_hash_table_new (IDL_GENTREE (from).hash_func, IDL_GENTREE (from).key_compare_func); return p; } IDL_tree IDL_integer_new (IDL_longlong_t value) { IDL_tree p = IDL_node_new (IDLN_INTEGER); IDL_INTEGER (p).value = value; return p; } IDL_tree IDL_string_new (char *value) { IDL_tree p = IDL_node_new (IDLN_STRING); IDL_STRING (p).value = value; return p; } IDL_tree IDL_wide_string_new (wchar_t *value) { IDL_tree p = IDL_node_new (IDLN_WIDE_STRING); IDL_WIDE_STRING (p).value = value; return p; } IDL_tree IDL_char_new (char *value) { IDL_tree p = IDL_node_new (IDLN_CHAR); IDL_CHAR (p).value = value; return p; } IDL_tree IDL_wide_char_new (wchar_t *value) { IDL_tree p = IDL_node_new (IDLN_WIDE_CHAR); IDL_WIDE_CHAR (p).value = value; return p; } IDL_tree IDL_fixed_new (char *value) { IDL_tree p = IDL_node_new (IDLN_FIXED); IDL_FIXED (p).value = value; return p; } IDL_tree IDL_float_new (double value) { IDL_tree p = IDL_node_new (IDLN_FLOAT); IDL_FLOAT (p).value = value; return p; } IDL_tree IDL_boolean_new (unsigned value) { IDL_tree p = IDL_node_new (IDLN_BOOLEAN); IDL_BOOLEAN (p).value = value; return p; } IDL_tree IDL_ident_new (char *str) { IDL_tree p = IDL_node_new (IDLN_IDENT); IDL_IDENT (p).str = str; return p; } IDL_tree IDL_member_new (IDL_tree type_spec, IDL_tree dcls) { IDL_tree p = IDL_node_new (IDLN_MEMBER); __IDL_assign_up_node (p, type_spec); __IDL_assign_up_node (p, dcls); IDL_MEMBER (p).type_spec = type_spec; IDL_MEMBER (p).dcls = dcls; return p; } IDL_tree IDL_native_new (IDL_tree ident) { IDL_tree p = IDL_node_new (IDLN_NATIVE); __IDL_assign_up_node (p, ident); __IDL_assign_location (p, ident); IDL_NATIVE (p).ident = ident; return p; } IDL_tree IDL_type_dcl_new (IDL_tree type_spec, IDL_tree dcls) { IDL_tree p = IDL_node_new (IDLN_TYPE_DCL); __IDL_assign_up_node (p, type_spec); __IDL_assign_up_node (p, dcls); __IDL_assign_location (p, IDL_LIST (dcls).data); IDL_TYPE_DCL (p).type_spec = type_spec; IDL_TYPE_DCL (p).dcls = dcls; return p; } IDL_tree IDL_type_float_new (enum IDL_float_type f_type) { IDL_tree p = IDL_node_new (IDLN_TYPE_FLOAT); IDL_TYPE_FLOAT (p).f_type = f_type; return p; } IDL_tree IDL_type_fixed_new (IDL_tree positive_int_const, IDL_tree integer_lit) { IDL_tree p = IDL_node_new (IDLN_TYPE_FIXED); __IDL_assign_up_node (p, positive_int_const); __IDL_assign_up_node (p, integer_lit); IDL_TYPE_FIXED (p).positive_int_const = positive_int_const; IDL_TYPE_FIXED (p).integer_lit = integer_lit; return p; } IDL_tree IDL_type_integer_new (unsigned f_signed, enum IDL_integer_type f_type) { IDL_tree p = IDL_node_new (IDLN_TYPE_INTEGER); IDL_TYPE_INTEGER (p).f_signed = f_signed; IDL_TYPE_INTEGER (p).f_type = f_type; return p; } IDL_tree IDL_type_char_new (void) { return IDL_node_new (IDLN_TYPE_CHAR); } IDL_tree IDL_type_wide_char_new (void) { return IDL_node_new (IDLN_TYPE_WIDE_CHAR); } IDL_tree IDL_type_boolean_new (void) { return IDL_node_new (IDLN_TYPE_BOOLEAN); } IDL_tree IDL_type_octet_new (void) { return IDL_node_new (IDLN_TYPE_OCTET); } IDL_tree IDL_type_any_new (void) { return IDL_node_new (IDLN_TYPE_ANY); } IDL_tree IDL_type_object_new (void) { return IDL_node_new (IDLN_TYPE_OBJECT); } IDL_tree IDL_type_typecode_new (void) { return IDL_node_new (IDLN_TYPE_TYPECODE); } IDL_tree IDL_type_string_new (IDL_tree positive_int_const) { IDL_tree p = IDL_node_new (IDLN_TYPE_STRING); __IDL_assign_up_node (p, positive_int_const); IDL_TYPE_STRING (p).positive_int_const = positive_int_const; return p; } IDL_tree IDL_type_wide_string_new (IDL_tree positive_int_const) { IDL_tree p = IDL_node_new (IDLN_TYPE_WIDE_STRING); __IDL_assign_up_node (p, positive_int_const); IDL_TYPE_WIDE_STRING (p).positive_int_const = positive_int_const; return p; } IDL_tree IDL_type_array_new (IDL_tree ident, IDL_tree size_list) { IDL_tree p = IDL_node_new (IDLN_TYPE_ARRAY); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, size_list); __IDL_assign_location (p, ident); IDL_TYPE_ARRAY (p).ident = ident; IDL_TYPE_ARRAY (p).size_list = size_list; return p; } IDL_tree IDL_type_sequence_new (IDL_tree simple_type_spec, IDL_tree positive_int_const) { IDL_tree p = IDL_node_new (IDLN_TYPE_SEQUENCE); __IDL_assign_up_node (p, simple_type_spec); __IDL_assign_up_node (p, positive_int_const); IDL_TYPE_SEQUENCE (p).simple_type_spec = simple_type_spec; IDL_TYPE_SEQUENCE (p).positive_int_const = positive_int_const; return p; } IDL_tree IDL_type_struct_new (IDL_tree ident, IDL_tree member_list) { IDL_tree p = IDL_node_new (IDLN_TYPE_STRUCT); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, member_list); __IDL_assign_location (p, ident); IDL_TYPE_STRUCT (p).ident = ident; IDL_TYPE_STRUCT (p).member_list = member_list; return p; } IDL_tree IDL_type_union_new (IDL_tree ident, IDL_tree switch_type_spec, IDL_tree switch_body) { IDL_tree p = IDL_node_new (IDLN_TYPE_UNION); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, switch_type_spec); __IDL_assign_up_node (p, switch_body); __IDL_assign_location (p, ident); IDL_TYPE_UNION (p).ident = ident; IDL_TYPE_UNION (p).switch_type_spec = switch_type_spec; IDL_TYPE_UNION (p).switch_body = switch_body; return p; } IDL_tree IDL_type_enum_new (IDL_tree ident, IDL_tree enumerator_list) { IDL_tree p = IDL_node_new (IDLN_TYPE_ENUM); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, enumerator_list); __IDL_assign_location (p, ident); IDL_TYPE_ENUM (p).ident = ident; IDL_TYPE_ENUM (p).enumerator_list = enumerator_list; return p; } IDL_tree IDL_case_stmt_new (IDL_tree labels, IDL_tree element_spec) { IDL_tree p = IDL_node_new (IDLN_CASE_STMT); __IDL_assign_up_node (p, labels); __IDL_assign_up_node (p, element_spec); IDL_CASE_STMT (p).labels = labels; IDL_CASE_STMT (p).element_spec = element_spec; return p; } IDL_tree IDL_interface_new (IDL_tree ident, IDL_tree inheritance_spec, IDL_tree body) { IDL_tree p = IDL_node_new (IDLN_INTERFACE); /* Make sure the up node points to the interface */ if (ident && IDL_NODE_UP (ident) && IDL_NODE_TYPE (IDL_NODE_UP (ident)) != IDLN_INTERFACE) IDL_NODE_UP (ident) = NULL; __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, inheritance_spec); __IDL_assign_up_node (p, body); IDL_INTERFACE (p).ident = ident; IDL_INTERFACE (p).inheritance_spec = inheritance_spec; IDL_INTERFACE (p).body = body; return p; } IDL_tree IDL_module_new (IDL_tree ident, IDL_tree definition_list) { IDL_tree p = IDL_node_new (IDLN_MODULE); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, definition_list); __IDL_assign_location (p, ident); IDL_MODULE (p).ident = ident; IDL_MODULE (p).definition_list = definition_list; return p; } IDL_tree IDL_binop_new (enum IDL_binop op, IDL_tree left, IDL_tree right) { IDL_tree p = IDL_node_new (IDLN_BINOP); __IDL_assign_up_node (p, left); __IDL_assign_up_node (p, right); IDL_BINOP (p).op = op; IDL_BINOP (p).left = left; IDL_BINOP (p).right = right; return p; } IDL_tree IDL_unaryop_new (enum IDL_unaryop op, IDL_tree operand) { IDL_tree p = IDL_node_new (IDLN_UNARYOP); __IDL_assign_up_node (p, operand); IDL_UNARYOP (p).op = op; IDL_UNARYOP (p).operand = operand; return p; } IDL_tree IDL_codefrag_new (char *desc, GSList *lines) { IDL_tree p = IDL_node_new (IDLN_CODEFRAG); IDL_CODEFRAG (p).desc = desc; IDL_CODEFRAG (p).lines = lines; return p; } IDL_tree IDL_srcfile_new (char *filename, int seenCnt, gboolean isTop, gboolean wasInhibit) { IDL_tree p = IDL_node_new (IDLN_SRCFILE); IDL_SRCFILE (p).filename = filename; IDL_SRCFILE (p).seenCnt = seenCnt; IDL_SRCFILE (p).isTop = isTop; IDL_SRCFILE (p).wasInhibit = wasInhibit; return p; } IDL_tree IDL_const_dcl_new (IDL_tree const_type, IDL_tree ident, IDL_tree const_exp) { IDL_tree p = IDL_node_new (IDLN_CONST_DCL); __IDL_assign_up_node (p, const_type); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, const_exp); __IDL_assign_location (p, ident); IDL_CONST_DCL (p).const_type = const_type; IDL_CONST_DCL (p).ident = ident; IDL_CONST_DCL (p).const_exp = const_exp; return p; } IDL_tree IDL_except_dcl_new (IDL_tree ident, IDL_tree members) { IDL_tree p = IDL_node_new (IDLN_EXCEPT_DCL); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, members); __IDL_assign_location (p, ident); IDL_EXCEPT_DCL (p).ident = ident; IDL_EXCEPT_DCL (p).members = members; return p; } IDL_tree IDL_attr_dcl_new (unsigned f_readonly, IDL_tree param_type_spec, IDL_tree simple_declarations) { IDL_tree p = IDL_node_new (IDLN_ATTR_DCL); __IDL_assign_up_node (p, param_type_spec); __IDL_assign_up_node (p, simple_declarations); __IDL_assign_location (p, IDL_LIST (simple_declarations).data); IDL_ATTR_DCL (p).f_readonly = f_readonly; IDL_ATTR_DCL (p).param_type_spec = param_type_spec; IDL_ATTR_DCL (p).simple_declarations = simple_declarations; return p; } IDL_tree IDL_op_dcl_new (unsigned f_oneway, IDL_tree op_type_spec, IDL_tree ident, IDL_tree parameter_dcls, IDL_tree raises_expr, IDL_tree context_expr) { IDL_tree p = IDL_node_new (IDLN_OP_DCL); __IDL_assign_up_node (p, op_type_spec); __IDL_assign_up_node (p, ident); __IDL_assign_up_node (p, parameter_dcls); __IDL_assign_up_node (p, raises_expr); __IDL_assign_up_node (p, context_expr); __IDL_assign_location (p, ident); IDL_OP_DCL (p).f_oneway = f_oneway; IDL_OP_DCL (p).op_type_spec = op_type_spec; IDL_OP_DCL (p).ident = ident; IDL_OP_DCL (p).parameter_dcls = parameter_dcls; IDL_OP_DCL (p).raises_expr = raises_expr; IDL_OP_DCL (p).context_expr = context_expr; return p; } IDL_tree IDL_param_dcl_new (enum IDL_param_attr attr, IDL_tree param_type_spec, IDL_tree simple_declarator) { IDL_tree p = IDL_node_new (IDLN_PARAM_DCL); __IDL_assign_up_node (p, param_type_spec); __IDL_assign_up_node (p, simple_declarator); __IDL_assign_location (p, simple_declarator); IDL_PARAM_DCL (p).attr = attr; IDL_PARAM_DCL (p).param_type_spec = param_type_spec; IDL_PARAM_DCL (p).simple_declarator = simple_declarator; return p; } IDL_tree IDL_forward_dcl_new (IDL_tree ident) { IDL_tree p = IDL_node_new (IDLN_FORWARD_DCL); __IDL_assign_up_node (p, ident); __IDL_assign_location (p, ident); IDL_FORWARD_DCL (p).ident = ident; return p; } IDL_tree IDL_check_type_cast (const IDL_tree tree, IDL_tree_type type, const char *file, int line, const char *function) { if (__IDL_check_type_casts) { if (tree == NULL) { g_warning ("file %s: line %d: (%s) invalid type cast attempt," " NULL tree to %s\n", file, line, function, IDL_tree_type_names[type]); } else if (IDL_NODE_TYPE (tree) != type) { g_warning ("file %s: line %d: (%s) expected IDL tree type %s," " but got %s\n", file, line, function, IDL_tree_type_names[type], IDL_NODE_TYPE_NAME (tree)); } } return tree; } IDL_tree IDL_gentree_chain_sibling (IDL_tree from, IDL_tree data) { IDL_tree p; if (from == NULL) return NULL; p = IDL_gentree_new_sibling (from, data); IDL_NODE_UP (p) = IDL_NODE_UP (from); return p; } IDL_tree IDL_gentree_chain_child (IDL_tree from, IDL_tree data) { IDL_tree p; if (from == NULL) return NULL; p = IDL_gentree_new (IDL_GENTREE (from).hash_func, IDL_GENTREE (from).key_compare_func, data); IDL_NODE_UP (p) = from; g_hash_table_insert (IDL_GENTREE (from).children, data, p); return p; } IDL_tree IDL_get_parent_node (IDL_tree p, IDL_tree_type type, int *levels) { int count = 0; if (p == NULL) return NULL; if (type == IDLN_ANY) return IDL_NODE_UP (p); while (p != NULL && IDL_NODE_TYPE (p) != type) { if (IDL_NODE_IS_SCOPED (p)) ++count; p = IDL_NODE_UP (p); } if (p != NULL) if (levels != NULL) *levels = count; return p; } IDL_tree IDL_tree_get_scope (IDL_tree p) { g_return_val_if_fail (p != NULL, NULL); if (IDL_NODE_TYPE (p) == IDLN_GENTREE) return p; if (!IDL_NODE_IS_SCOPED (p)) { g_warning ("Node type %s isn't scoped", IDL_NODE_TYPE_NAME (p)); return NULL; } switch (IDL_NODE_TYPE (p)) { case IDLN_IDENT: return IDL_IDENT_TO_NS (p); case IDLN_INTERFACE: return IDL_IDENT_TO_NS (IDL_INTERFACE (p).ident); case IDLN_MODULE: return IDL_IDENT_TO_NS (IDL_MODULE (p).ident); case IDLN_EXCEPT_DCL: return IDL_IDENT_TO_NS (IDL_EXCEPT_DCL (p).ident); case IDLN_OP_DCL: return IDL_IDENT_TO_NS (IDL_OP_DCL (p).ident); case IDLN_TYPE_ENUM: return IDL_IDENT_TO_NS (IDL_TYPE_ENUM (p).ident); case IDLN_TYPE_STRUCT: return IDL_IDENT_TO_NS (IDL_TYPE_STRUCT (p).ident); case IDLN_TYPE_UNION: return IDL_IDENT_TO_NS (IDL_TYPE_UNION (p).ident); default: return NULL; } } typedef struct { IDL_tree_func pre_tree_func; IDL_tree_func post_tree_func; gpointer user_data; } IDLTreeWalkRealData; static void IDL_tree_walk_real (IDL_tree_func_data *tfd, IDLTreeWalkRealData *data) { IDL_tree_func_data down_tfd; gboolean recurse = TRUE; IDL_tree p, q; if (tfd->tree == NULL) return; tfd->state->bottom = tfd; tfd->step = 0; tfd->data = NULL; if (data->pre_tree_func) recurse = (*data->pre_tree_func) (tfd, data->user_data); ++tfd->step; down_tfd.state = tfd->state; down_tfd.up = tfd; down_tfd.level = tfd->level + 1; p = tfd->tree; if (recurse) switch (IDL_NODE_TYPE (p)) { case IDLN_INTEGER: case IDLN_STRING: case IDLN_CHAR: case IDLN_FIXED: case IDLN_FLOAT: case IDLN_BOOLEAN: case IDLN_IDENT: case IDLN_TYPE_WIDE_CHAR: case IDLN_TYPE_BOOLEAN: case IDLN_TYPE_OCTET: case IDLN_TYPE_ANY: case IDLN_TYPE_OBJECT: case IDLN_TYPE_TYPECODE: case IDLN_TYPE_FLOAT: case IDLN_TYPE_INTEGER: case IDLN_TYPE_CHAR: case IDLN_CODEFRAG: case IDLN_SRCFILE: break; case IDLN_LIST: for (q = p; q; q = IDL_LIST (q).next) { down_tfd.tree = IDL_LIST (q).data; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_GENTREE: g_error ("IDLN_GENTREE walk not implemented!"); break; case IDLN_MEMBER: down_tfd.tree = IDL_MEMBER (p).type_spec; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_MEMBER (p).dcls; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_NATIVE: down_tfd.tree = IDL_NATIVE (p).ident; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_TYPE_DCL: down_tfd.tree = IDL_TYPE_DCL (p).type_spec; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_DCL (p).dcls; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_CONST_DCL: down_tfd.tree = IDL_CONST_DCL (p).const_type; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_CONST_DCL (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_CONST_DCL (p).const_exp; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_EXCEPT_DCL: if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_EXCEPT_DCL (p).ident; IDL_tree_walk_real (&down_tfd, data); } down_tfd.tree = IDL_EXCEPT_DCL (p).members; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_ATTR_DCL: down_tfd.tree = IDL_ATTR_DCL (p).param_type_spec; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_ATTR_DCL (p).simple_declarations; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_OP_DCL: down_tfd.tree = IDL_OP_DCL (p).op_type_spec; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_OP_DCL (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_OP_DCL (p).parameter_dcls; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_OP_DCL (p).raises_expr; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_OP_DCL (p).context_expr; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_PARAM_DCL: down_tfd.tree = IDL_PARAM_DCL (p).param_type_spec; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_PARAM_DCL (p).simple_declarator; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_FORWARD_DCL: down_tfd.tree = IDL_FORWARD_DCL (p).ident; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_TYPE_FIXED: if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_FIXED (p).positive_int_const; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_TYPE_FIXED (p).integer_lit; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_STRING: if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_STRING (p).positive_int_const; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_WIDE_STRING: if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_WIDE_STRING (p).positive_int_const; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_ENUM: if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_ENUM (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_TYPE_ENUM (p).enumerator_list; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_SEQUENCE: down_tfd.tree = IDL_TYPE_SEQUENCE (p).simple_type_spec; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_SEQUENCE (p).positive_int_const; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_ARRAY: down_tfd.tree = IDL_TYPE_ARRAY (p).ident; IDL_tree_walk_real (&down_tfd, data); if ( (tfd->state->flags & IDL_WalkF_TypespecOnly)==0 ) { down_tfd.tree = IDL_TYPE_ARRAY (p).size_list; IDL_tree_walk_real (&down_tfd, data); } break; case IDLN_TYPE_STRUCT: down_tfd.tree = IDL_TYPE_STRUCT (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_TYPE_STRUCT (p).member_list; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_TYPE_UNION: down_tfd.tree = IDL_TYPE_UNION (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_TYPE_UNION (p).switch_type_spec; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_TYPE_UNION (p).switch_body; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_CASE_STMT: down_tfd.tree = IDL_CASE_STMT (p).labels; IDL_tree_walk_real (&down_tfd, data); /* FIXME */ down_tfd.tree = IDL_CASE_STMT (p).element_spec; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_INTERFACE: down_tfd.tree = IDL_INTERFACE (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_INTERFACE (p).inheritance_spec; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_INTERFACE (p).body; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_MODULE: down_tfd.tree = IDL_MODULE (p).ident; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_MODULE (p).definition_list; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_BINOP: down_tfd.tree = IDL_BINOP (p).left; IDL_tree_walk_real (&down_tfd, data); down_tfd.tree = IDL_BINOP (p).right; IDL_tree_walk_real (&down_tfd, data); break; case IDLN_UNARYOP: down_tfd.tree = IDL_UNARYOP (p).operand; IDL_tree_walk_real (&down_tfd, data); break; default: g_warning ("IDL_tree_walk_real: unknown node type %s\n", IDL_NODE_TYPE_NAME (p)); break; } if (data->post_tree_func) (void) (*data->post_tree_func) (tfd, data->user_data); tfd->state->bottom = tfd->up; } void IDL_tree_walk2 (IDL_tree p, IDL_tree_func_data *current, glong flags, IDL_tree_func pre_tree_func, IDL_tree_func post_tree_func, gpointer user_data) { IDLTreeWalkRealData data; IDL_tree_func_state tfs; IDL_tree_func_data tfd; g_return_if_fail (!(pre_tree_func == NULL && post_tree_func == NULL)); data.pre_tree_func = pre_tree_func; data.post_tree_func = post_tree_func; data.user_data = user_data; tfs.up = current ? current->state : NULL; tfs.start = p; tfs.flags = flags; tfd.level = 0; if (current) { tfd = *current; tfd.level = ((tfd.level / 1000)+1) * 1000; } tfd.state = &tfs; tfd.up = current; tfd.tree = p; IDL_tree_walk_real (&tfd, &data); } void IDL_tree_walk (IDL_tree p, IDL_tree_func_data *current, IDL_tree_func pre_tree_func, IDL_tree_func post_tree_func, gpointer user_data) { IDL_tree_walk2 (p, current, /*flags*/0, pre_tree_func, post_tree_func, user_data); } void IDL_tree_walk_in_order (IDL_tree p, IDL_tree_func tree_func, gpointer user_data) { IDL_tree_walk2 (p, NULL, /*flags*/0, tree_func, NULL, user_data); } static void __IDL_tree_free (IDL_tree p); static int tree_free_but_this (IDL_tree data, IDL_tree p, IDL_tree this_one) { if (p == this_one) return TRUE; __IDL_tree_free (p); return TRUE; } static void property_free (char *key, char *value) { g_free (key); g_free (value); } void __IDL_free_properties (GHashTable *table) { if (table) { g_hash_table_foreach (table, (GHFunc) property_free, NULL); g_hash_table_destroy (table); } } /* Free associated node data, regardless of refcounts */ static void IDL_tree_free_real (IDL_tree p) { GSList *slist; assert (p != NULL); switch (IDL_NODE_TYPE (p)) { case IDLN_GENTREE: g_hash_table_foreach (IDL_GENTREE (p).children, (GHFunc) tree_free_but_this, NULL); g_hash_table_destroy (IDL_GENTREE (p).children); break; case IDLN_FIXED: g_free (IDL_FIXED (p).value); break; case IDLN_STRING: g_free (IDL_STRING (p).value); break; case IDLN_WIDE_STRING: g_free (IDL_WIDE_STRING (p).value); break; case IDLN_CHAR: g_free (IDL_CHAR (p).value); break; case IDLN_WIDE_CHAR: g_free (IDL_WIDE_CHAR (p).value); break; case IDLN_IDENT: g_free (IDL_IDENT (p).str); g_free (IDL_IDENT_REPO_ID (p)); for (slist = IDL_IDENT (p).comments; slist; slist = slist->next) g_free (slist->data); g_slist_free (IDL_IDENT (p).comments); break; case IDLN_NATIVE: g_free (IDL_NATIVE (p).user_type); break; case IDLN_INTERFACE: break; case IDLN_CODEFRAG: g_free (IDL_CODEFRAG (p).desc); for (slist = IDL_CODEFRAG (p).lines; slist; slist = slist->next) g_free (slist->data); g_slist_free (IDL_CODEFRAG (p).lines); break; default: break; } __IDL_free_properties (IDL_NODE_PROPERTIES (p)); g_free (p); } /* Free node taking into account refcounts */ static void __IDL_tree_free (IDL_tree p) { if (p == NULL) return; if (--IDL_NODE_REFS (p) <= 0) IDL_tree_free_real (p); } /* Free a set of references of an entire tree */ void IDL_tree_free (IDL_tree p) { IDL_tree q; if (p == NULL) return; switch (IDL_NODE_TYPE (p)) { case IDLN_INTEGER: case IDLN_FLOAT: case IDLN_BOOLEAN: case IDLN_TYPE_FLOAT: case IDLN_TYPE_INTEGER: case IDLN_TYPE_CHAR: case IDLN_TYPE_WIDE_CHAR: case IDLN_TYPE_BOOLEAN: case IDLN_TYPE_OCTET: case IDLN_TYPE_ANY: case IDLN_TYPE_OBJECT: case IDLN_TYPE_TYPECODE: case IDLN_FIXED: case IDLN_STRING: case IDLN_WIDE_STRING: case IDLN_CHAR: case IDLN_WIDE_CHAR: case IDLN_IDENT: case IDLN_CODEFRAG: case IDLN_SRCFILE: __IDL_tree_free (p); break; case IDLN_LIST: while (p) { IDL_tree_free (IDL_LIST (p).data); q = IDL_LIST (p).next; __IDL_tree_free (p); p = q; } break; case IDLN_GENTREE: g_hash_table_foreach (IDL_GENTREE (p).siblings, (GHFunc) tree_free_but_this, p); g_hash_table_destroy (IDL_GENTREE (p).siblings); __IDL_tree_free (p); break; case IDLN_MEMBER: IDL_tree_free (IDL_MEMBER (p).type_spec); IDL_tree_free (IDL_MEMBER (p).dcls); __IDL_tree_free (p); break; case IDLN_NATIVE: IDL_tree_free (IDL_NATIVE (p).ident); __IDL_tree_free (p); break; case IDLN_TYPE_ENUM: IDL_tree_free (IDL_TYPE_ENUM (p).ident); IDL_tree_free (IDL_TYPE_ENUM (p).enumerator_list); __IDL_tree_free (p); break; case IDLN_TYPE_SEQUENCE: IDL_tree_free (IDL_TYPE_SEQUENCE (p).simple_type_spec); IDL_tree_free (IDL_TYPE_SEQUENCE (p).positive_int_const); __IDL_tree_free (p); break; case IDLN_TYPE_ARRAY: IDL_tree_free (IDL_TYPE_ARRAY (p).ident); IDL_tree_free (IDL_TYPE_ARRAY (p).size_list); __IDL_tree_free (p); break; case IDLN_TYPE_STRUCT: IDL_tree_free (IDL_TYPE_STRUCT (p).ident); IDL_tree_free (IDL_TYPE_STRUCT (p).member_list); __IDL_tree_free (p); break; case IDLN_TYPE_UNION: IDL_tree_free (IDL_TYPE_UNION (p).ident); IDL_tree_free (IDL_TYPE_UNION (p).switch_type_spec); IDL_tree_free (IDL_TYPE_UNION (p).switch_body); __IDL_tree_free (p); break; case IDLN_TYPE_DCL: IDL_tree_free (IDL_TYPE_DCL (p).type_spec); IDL_tree_free (IDL_TYPE_DCL (p).dcls); __IDL_tree_free (p); break; case IDLN_CONST_DCL: IDL_tree_free (IDL_CONST_DCL (p).const_type); IDL_tree_free (IDL_CONST_DCL (p).ident); IDL_tree_free (IDL_CONST_DCL (p).const_exp); __IDL_tree_free (p); break; case IDLN_EXCEPT_DCL: IDL_tree_free (IDL_EXCEPT_DCL (p).ident); IDL_tree_free (IDL_EXCEPT_DCL (p).members); __IDL_tree_free (p); break; case IDLN_ATTR_DCL: IDL_tree_free (IDL_ATTR_DCL (p).param_type_spec); IDL_tree_free (IDL_ATTR_DCL (p).simple_declarations); __IDL_tree_free (p); break; case IDLN_OP_DCL: IDL_tree_free (IDL_OP_DCL (p).op_type_spec); IDL_tree_free (IDL_OP_DCL (p).ident); IDL_tree_free (IDL_OP_DCL (p).parameter_dcls); IDL_tree_free (IDL_OP_DCL (p).raises_expr); IDL_tree_free (IDL_OP_DCL (p).context_expr); __IDL_tree_free (p); break; case IDLN_PARAM_DCL: IDL_tree_free (IDL_PARAM_DCL (p).param_type_spec); IDL_tree_free (IDL_PARAM_DCL (p).simple_declarator); __IDL_tree_free (p); break; case IDLN_FORWARD_DCL: IDL_tree_free (IDL_FORWARD_DCL (p).ident); __IDL_tree_free (p); break; case IDLN_TYPE_STRING: IDL_tree_free (IDL_TYPE_STRING (p).positive_int_const); __IDL_tree_free (p); break; case IDLN_TYPE_WIDE_STRING: IDL_tree_free (IDL_TYPE_WIDE_STRING (p).positive_int_const); __IDL_tree_free (p); break; case IDLN_TYPE_FIXED: IDL_tree_free (IDL_TYPE_FIXED (p).positive_int_const); IDL_tree_free (IDL_TYPE_FIXED (p).integer_lit); __IDL_tree_free (p); break; case IDLN_CASE_STMT: IDL_tree_free (IDL_CASE_STMT (p).labels); IDL_tree_free (IDL_CASE_STMT (p).element_spec); __IDL_tree_free (p); break; case IDLN_INTERFACE: IDL_tree_free (IDL_INTERFACE (p).ident); IDL_tree_free (IDL_INTERFACE (p).inheritance_spec); IDL_tree_free (IDL_INTERFACE (p).body); __IDL_tree_free (p); break; case IDLN_MODULE: IDL_tree_free (IDL_MODULE (p).ident); IDL_tree_free (IDL_MODULE (p).definition_list); __IDL_tree_free (p); break; case IDLN_BINOP: IDL_tree_free (IDL_BINOP (p).left); IDL_tree_free (IDL_BINOP (p).right); __IDL_tree_free (p); break; case IDLN_UNARYOP: IDL_tree_free (IDL_UNARYOP (p).operand); __IDL_tree_free (p); break; default: g_warning ("Free unknown node: %d\n", IDL_NODE_TYPE (p)); break; } } #define C_ESC(a,b) case a: *p++ = b; ++s; break gchar *IDL_do_escapes (const char *s) { char *p, *q; if (!s) return NULL; p = q = g_malloc (strlen (s) + 1); while (*s) { if (*s != '\\') { *p++ = *s++; continue; } ++s; if (*s == 'x') { char hex[3]; int n; hex[0] = 0; ++s; sscanf (s, "%2[0-9a-fA-F]", hex); s += strlen (hex); sscanf (hex, "%x", &n); *p++ = n; continue; } if (*s >= '0' && *s <= '7') { char oct[4]; int n; oct[0] = 0; sscanf (s, "%3[0-7]", oct); s += strlen (oct); sscanf (oct, "%o", &n); *p++ = n; continue; } switch (*s) { C_ESC ('n','\n'); C_ESC ('t','\t'); C_ESC ('v','\v'); C_ESC ('b','\b'); C_ESC ('r','\r'); C_ESC ('f','\f'); C_ESC ('a','\a'); C_ESC ('\\','\\'); C_ESC ('?','?'); C_ESC ('\'','\''); C_ESC ('"','"'); } } *p = 0; return q; } int IDL_list_length (IDL_tree list) { IDL_tree curitem; int length; for (curitem = list, length = 0; curitem; curitem = IDL_LIST (curitem).next) length++; return length; } IDL_tree IDL_list_nth (IDL_tree list, int n) { IDL_tree curitem; int i; for (curitem = list, i = 0; i < n && curitem; curitem = IDL_LIST (curitem).next, i++) ; return curitem; } const char *IDL_tree_property_get (IDL_tree tree, const char *key) { g_return_val_if_fail (tree != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); if (!IDL_NODE_PROPERTIES (tree)) return NULL; return g_hash_table_lookup (IDL_NODE_PROPERTIES (tree), key); } void IDL_tree_property_set (IDL_tree tree, const char *key, const char *value) { g_return_if_fail (tree != NULL); g_return_if_fail (key != NULL); if (!IDL_NODE_PROPERTIES (tree)) IDL_NODE_PROPERTIES (tree) = g_hash_table_new ( IDL_strcase_hash, IDL_strcase_equal); else if (IDL_tree_property_get (tree, key)) IDL_tree_property_remove (tree, key); g_hash_table_insert (IDL_NODE_PROPERTIES (tree), g_strdup (key), g_strdup (value)); } gboolean IDL_tree_property_remove (IDL_tree tree, const char *key) { gboolean removed = FALSE; char *val; g_return_val_if_fail (tree != NULL, FALSE); g_return_val_if_fail (key != NULL, FALSE); if (!IDL_NODE_PROPERTIES (tree)) return FALSE; if ((val = g_hash_table_lookup (IDL_NODE_PROPERTIES (tree), key))) { g_hash_table_remove (IDL_NODE_PROPERTIES (tree), key); g_free (val); removed = TRUE; } return removed; } static void property_set (char *key, char *value, IDL_tree tree) { IDL_tree_property_set (tree, key, value); } void IDL_tree_properties_copy (IDL_tree from_tree, IDL_tree to_tree) { g_return_if_fail (from_tree != NULL); g_return_if_fail (to_tree != NULL); if (IDL_NODE_PROPERTIES (from_tree)) g_hash_table_foreach (IDL_NODE_PROPERTIES (from_tree), (GHFunc) property_set, to_tree); } typedef struct { IDL_tree *root; GHashTable *removed_nodes; } RemoveListNodeData; static int remove_list_node (IDL_tree p, IDL_tree *list_head, RemoveListNodeData *data) { assert (p != NULL); assert (IDL_NODE_TYPE (p) == IDLN_LIST); if (list_head) *list_head = IDL_list_remove (*list_head, p); else *data->root = IDL_list_remove (*data->root, p); if (data->removed_nodes) { if (!g_hash_table_lookup_extended (data->removed_nodes, p, NULL, NULL)) g_hash_table_insert (data->removed_nodes, p, p); /* We shouldn't need this since we have removed it from the tree, but we might need it for multiple declspec (inhibits) in the same subtree. IDL_tree_walk_in_order (p, (IDL_tree_func) inc_node_ref, NULL); */ } else IDL_tree_free (p); return TRUE; } /* Forward Declaration Resolution */ static int load_forward_dcls (IDL_tree_func_data *tfd, GHashTable *table) { if (IDL_NODE_TYPE (tfd->tree) == IDLN_FORWARD_DCL) { char *s = IDL_ns_ident_to_qstring (IDL_FORWARD_DCL (tfd->tree).ident, "::", 0); if (!g_hash_table_lookup_extended (table, s, NULL, NULL)) g_hash_table_insert (table, s, tfd->tree); else g_free (s); } return TRUE; } static int resolve_forward_dcls (IDL_tree_func_data *tfd, GHashTable *table) { if (IDL_NODE_TYPE (tfd->tree) == IDLN_INTERFACE) { char *orig, *s = IDL_ns_ident_to_qstring (IDL_INTERFACE (tfd->tree).ident, "::", 0); if (g_hash_table_lookup_extended (table, s, (gpointer)&orig, NULL)) { g_hash_table_remove (table, orig); g_free (orig); } g_free (s); } return TRUE; } static int print_unresolved_forward_dcls (char *s, IDL_tree p) { if (__IDL_flags & IDLF_PEDANTIC) IDL_tree_error (p, "Unresolved forward declaration `%s'", s); else IDL_tree_warning (p, IDL_WARNING1, "Unresolved forward declaration `%s'", s); g_free (s); return TRUE; } void IDL_tree_process_forward_dcls (IDL_tree *p, IDL_ns ns) { GHashTable *table = g_hash_table_new (IDL_strcase_hash, IDL_strcase_equal); gint total, resolved; IDL_tree_walk_in_order (*p, (IDL_tree_func) load_forward_dcls, table); total = g_hash_table_size (table); IDL_tree_walk_in_order (*p, (IDL_tree_func) resolve_forward_dcls, table); resolved = total - g_hash_table_size (table); g_hash_table_foreach (table, (GHFunc) print_unresolved_forward_dcls, NULL); g_hash_table_destroy (table); if (__IDL_flags & IDLF_VERBOSE) g_message ("Forward declarations resolved: %d of %d", resolved, total); } /* Inhibit Creation Removal */ static int load_inhibits (IDL_tree_func_data *tfd, GHashTable *table) { IDL_tree p, q, *list_head; p = tfd->tree; if (p != NULL && IDL_NODE_UP (p) && IDL_NODE_TYPE (IDL_NODE_UP (p)) == IDLN_LIST && IDL_NODE_DECLSPEC (p) & IDLF_DECLSPEC_INHIBIT && !g_hash_table_lookup_extended (table, IDL_NODE_UP (p), NULL, NULL)) { list_head = NULL; q = IDL_NODE_UP (IDL_NODE_UP (p)); if (q) { switch (IDL_NODE_TYPE (q)) { case IDLN_MODULE: list_head = &IDL_MODULE (q).definition_list; break; case IDLN_INTERFACE: list_head = &IDL_INTERFACE (q).body; break; default: g_warning ("Unhandled node %s in load_inhibits", IDL_NODE_TYPE_NAME (q)); break; } } g_hash_table_insert (table, IDL_NODE_UP (p), list_head); return FALSE; } return TRUE; } void IDL_tree_remove_inhibits (IDL_tree *tree, IDL_ns ns) { RemoveListNodeData data; GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal); gint removed; g_return_if_fail (tree != NULL); g_return_if_fail (ns != NULL); IDL_tree_walk_in_order (*tree, (IDL_tree_func) load_inhibits, table); removed = g_hash_table_size (table); data.root = tree; data.removed_nodes = IDL_NS (ns).inhibits; g_hash_table_foreach (table, (GHFunc) remove_list_node, &data); g_hash_table_destroy (table); if (__IDL_flags & IDLF_VERBOSE) g_message ("Inhibited nodes removed: %d", removed); } /* Multi-Pass Empty Module Removal */ static int load_empty_modules (IDL_tree_func_data *tfd, GHashTable *table) { IDL_tree p, q, *list_head; p = tfd->tree; if (IDL_NODE_TYPE (p) == IDLN_MODULE && IDL_MODULE (p).definition_list == NULL && IDL_NODE_UP (p) && IDL_NODE_TYPE (IDL_NODE_UP (p)) == IDLN_LIST && !g_hash_table_lookup_extended (table, IDL_NODE_UP (p), NULL, NULL)) { list_head = NULL; q = IDL_NODE_UP (IDL_NODE_UP (p)); if (q) { assert (IDL_NODE_TYPE (q) == IDLN_MODULE); list_head = &IDL_MODULE (q).definition_list; } g_hash_table_insert (table, IDL_NODE_UP (p), list_head); } return TRUE; } void IDL_tree_remove_empty_modules (IDL_tree *p, IDL_ns ns) { RemoveListNodeData data; gboolean done = FALSE; gint removed = 0; data.root = p; data.removed_nodes = NULL; while (!done) { GHashTable *table = g_hash_table_new (g_direct_hash, g_direct_equal); IDL_tree_walk_in_order (*p, (IDL_tree_func) load_empty_modules, table); removed += g_hash_table_size (table); done = g_hash_table_size (table) == 0; g_hash_table_foreach (table, (GHFunc) remove_list_node, &data); g_hash_table_destroy (table); } if (__IDL_flags & IDLF_VERBOSE) g_message ("Empty modules removed: %d", removed); } /* * IDL_tree to IDL backend */ #define DELIM_COMMA ", " #define DELIM_ARRAY "][" #define DELIM_SPACE " " #define indent() ++data->ilev #define unindent() --data->ilev #define doindent() do { \ int i; \ if (!(data->flags & IDLF_OUTPUT_NO_NEWLINES)) \ for (i = 0; i < data->ilev; ++i) { \ switch (data->mode) { \ case OUTPUT_FILE: \ fputc ('\t', data->u.o); \ break; \ \ case OUTPUT_STRING: \ g_string_append_c (data->u.s, '\t'); \ break; \ \ default: \ break; \ } \ } \ else if (data->ilev > 0) \ dataf (data, DELIM_SPACE); \ } while (0) #define nl() do { \ if (!(data->flags & IDLF_OUTPUT_NO_NEWLINES)) { \ switch (data->mode) { \ case OUTPUT_FILE: \ fputc ('\n', data->u.o); \ break; \ \ case OUTPUT_STRING: \ g_string_append_c (data->u.s, '\n'); \ break; \ \ default: \ break; \ } \ } \ } while (0) #define save_flag(flagbit,val) do { \ tfd->data = GUINT_TO_POINTER ( \ GPOINTER_TO_UINT (tfd->data) | \ (data->flagbit ? (1U << flagbit##bit) : 0)); \ data->flagbit = val; \ } while (0) #define restore_flag(flagbit) do { \ data->flagbit = (GPOINTER_TO_UINT ( \ tfd->data) >> flagbit##bit) & 1U; \ } while (0) typedef struct { IDL_ns ns; enum { OUTPUT_FILE, OUTPUT_STRING } mode; union { FILE *o; GString *s; } u; int ilev; unsigned long flags; #define identsbit 0 guint idents : 1; #define literalsbit 1 guint literals : 1; #define inline_propsbit 2 guint inline_props : 1; #define su_defbit 3 guint su_def : 1; } IDL_output_data; static void dataf (IDL_output_data *data, const char *fmt, ...) G_GNUC_PRINTF (2, 3); static void idataf (IDL_output_data *data, const char *fmt, ...) G_GNUC_PRINTF (2, 3); static void dataf (IDL_output_data *data, const char *fmt, ...) { gchar *buffer; va_list args; va_start (args, fmt); switch (data->mode) { case OUTPUT_FILE: vfprintf (data->u.o, fmt, args); break; case OUTPUT_STRING: buffer = g_strdup_vprintf (fmt, args); g_string_append (data->u.s, buffer); g_free (buffer); break; default: break; } va_end (args); } static void idataf (IDL_output_data *data, const char *fmt, ...) { gchar *buffer; va_list args; va_start (args, fmt); doindent (); switch (data->mode) { case OUTPUT_FILE: vfprintf (data->u.o, fmt, args); break; case OUTPUT_STRING: buffer = g_strdup_vprintf (fmt, args); g_string_append (data->u.s, buffer); g_free (buffer); break; default: break; } va_end (args); } static gboolean IDL_emit_node_pre_func (IDL_tree_func_data *tfd, IDL_output_data *data); static gboolean IDL_emit_node_post_func (IDL_tree_func_data *tfd, IDL_output_data *data); typedef struct { IDL_tree_func pre_func; IDL_tree_func post_func; IDL_tree_type type, type2; gboolean limit; IDL_output_data *data; const char *delim; gboolean hit; } IDL_output_delim_data; static gboolean IDL_output_delim_match (IDL_tree_func_data *tfd, IDL_output_delim_data *delim) { return delim->type == IDLN_ANY || IDL_NODE_TYPE (tfd->tree) == delim->type || IDL_NODE_TYPE (tfd->tree) == delim->type2; } static gboolean IDL_output_delim_pre (IDL_tree_func_data *tfd, IDL_output_delim_data *delim) { if (IDL_output_delim_match (tfd, delim)) { if (delim->hit) dataf (delim->data, "%s", delim->delim); else delim->hit = TRUE; return delim->pre_func ? (*delim->pre_func) (tfd, delim->data) : TRUE; } else { if (!delim->limit) return delim->pre_func ? (*delim->pre_func) (tfd, delim->data) : TRUE; else return TRUE; } } static gboolean IDL_output_delim_post (IDL_tree_func_data *tfd, IDL_output_delim_data *delim) { if (delim->limit && !IDL_output_delim_match (tfd, delim)) return TRUE; return delim->post_func ? (*delim->post_func) (tfd, delim->data) : TRUE; } static void IDL_output_delim (IDL_tree p, IDL_tree_func_data *current, IDL_output_data *data, IDL_tree_func pre_func, IDL_tree_func post_func, IDL_tree_type type, IDL_tree_type type2, gboolean limit, const char *str) { IDL_output_delim_data delim; delim.pre_func = pre_func; delim.post_func = post_func; delim.type = type; delim.type2 = type2; delim.limit = limit; delim.data = data; delim.hit = FALSE; delim.delim = str; IDL_tree_walk2 (p, current, /*flags*/0, (IDL_tree_func) IDL_output_delim_pre, (IDL_tree_func) IDL_output_delim_post, &delim); } typedef struct { IDL_output_data *data; gboolean hit; } IDL_property_emit_data; static void IDL_emit_IDL_property (const char *key, const char *value, IDL_property_emit_data *emit_data) { IDL_output_data *data = emit_data->data; if (!emit_data->hit) emit_data->hit = TRUE; else dataf (emit_data->data, DELIM_COMMA); if (!data->inline_props) { nl (); doindent (); } if (value && *value) dataf (emit_data->data, "%s%s(%s)", key, DELIM_SPACE, value); else dataf (emit_data->data, "%s", key); } static gboolean IDL_emit_IDL_properties (IDL_tree p, IDL_output_data *data) { IDL_property_emit_data emit_data; if (IDL_NODE_PROPERTIES (p) && data->flags & IDLF_OUTPUT_PROPERTIES && g_hash_table_size (IDL_NODE_PROPERTIES (p)) > 0) { emit_data.data = data; emit_data.hit = FALSE; if (!data->inline_props) idataf (data, "[" DELIM_SPACE); else dataf (data, "["); indent (); g_hash_table_foreach (IDL_NODE_PROPERTIES (p), (GHFunc) IDL_emit_IDL_property, &emit_data); unindent (); if (!data->inline_props) { nl (); doindent (); } dataf (data, "]"); if (!data->inline_props) nl (); else dataf (data, DELIM_SPACE); } return TRUE; } static gboolean IDL_emit_IDL_sc (IDL_tree_func_data *tfd, IDL_output_data *data) { dataf (data, ";"); nl (); return TRUE; } static gboolean IDL_emit_IDL_indent (IDL_tree_func_data *tfd, IDL_output_data *data) { doindent (); return TRUE; } static gboolean IDL_emit_IDL_curly_brace_open (IDL_tree_func_data *tfd, IDL_output_data *data) { dataf (data, "{"); nl (); indent (); return TRUE; } static gboolean IDL_emit_IDL_curly_brace_close (IDL_tree_func_data *tfd, IDL_output_data *data) { unindent (); idataf (data, "}"); return TRUE; } static gboolean IDL_emit_IDL_curly_brace_close_sc (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_curly_brace_close (tfd, data); IDL_emit_IDL_sc (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_ident_real (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree_func_data *up_path; IDL_tree up_real, scope; char *s; int levels; up_path = tfd; up_real = tfd->tree; while (up_path && up_real) { if (IDL_NODE_TYPE (up_path->tree) != IDL_NODE_TYPE (up_real)) break; up_path = up_path->up; up_real = IDL_NODE_UP (up_real); } assert (IDL_NODE_TYPE (tfd->tree) == IDLN_IDENT); if (!up_real || data->flags & IDLF_OUTPUT_NO_QUALIFY_IDENTS) { /* TODO: If the IDENT is also a keyword, escape it by prepending an underscore. */ dataf (data, "%s", IDL_IDENT (tfd->tree).str); } else { if (up_path == NULL) { levels = 0; } else { /* Determine minimal required levels of scoping */ scope = up_path->tree ? up_path->tree : up_real; levels = IDL_ns_scope_levels_from_here (data->ns, tfd->tree, scope); } s = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (tfd->tree), "::", levels); dataf (data, "%s", s); g_free (s); } return TRUE; } static gboolean IDL_emit_IDL_ident_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { if (data->idents) IDL_emit_IDL_ident_real (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_ident_force_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_ident_real (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_ident (IDL_tree ident, IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree_walk2 (ident, tfd, /*flags*/0, (IDL_tree_func) IDL_emit_IDL_ident_real, NULL, data); return TRUE; } static gboolean IDL_emit_IDL_literal (IDL_tree p, IDL_output_data *data) { switch (IDL_NODE_TYPE (p)) { case IDLN_FLOAT: dataf (data, "%f", IDL_FLOAT (p).value); break; case IDLN_INTEGER: /* FIXME: sign */ dataf (data, "%" IDL_LL "d", IDL_INTEGER (p).value); break; case IDLN_FIXED: dataf (data, "%s", IDL_FIXED (p).value); break; case IDLN_CHAR: dataf (data, "'%s'", IDL_CHAR (p).value); break; case IDLN_WIDE_CHAR: /* dataf (data, "'%s'", IDL_WIDE_CHAR (p).value); */ g_warning ("IDL_emit_IDL_literal: %s is currently unhandled", "Wide character output"); break; case IDLN_BOOLEAN: dataf (data, "%s", IDL_BOOLEAN (p).value ? "TRUE" : "FALSE"); break; case IDLN_STRING: dataf (data, "\"%s\"", IDL_STRING (p).value); break; case IDLN_WIDE_STRING: /* dataf (data, "\"%s\"", IDL_STRING (p).value); */ g_warning ("IDL_emit_IDL_literal: %s is currently unhandled", "Wide string output"); break; default: g_warning ("Unhandled literal: %s", IDL_NODE_TYPE_NAME (p)); break; } return TRUE; } static gboolean IDL_emit_IDL_literal_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { if (data->literals) IDL_emit_IDL_literal (tfd->tree, data); return TRUE; } static gboolean IDL_emit_IDL_literal_force_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_literal (tfd->tree, data); return TRUE; } static gboolean IDL_emit_IDL_type_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree p, q; p = tfd->tree; switch (IDL_NODE_TYPE (p)) { case IDLN_IDENT: IDL_emit_IDL_ident (p, tfd, data); break; case IDLN_TYPE_CHAR: dataf (data, "char"); break; case IDLN_TYPE_WIDE_CHAR: dataf (data, "wchar"); break; case IDLN_TYPE_BOOLEAN: dataf (data, "boolean"); break; case IDLN_TYPE_OCTET: dataf (data, "octet"); break; case IDLN_TYPE_ANY: dataf (data, "any"); break; case IDLN_TYPE_OBJECT: dataf (data, "Object"); break; case IDLN_TYPE_TYPECODE: dataf (data, "TypeCode"); break; case IDLN_TYPE_FLOAT: switch (IDL_TYPE_FLOAT (p).f_type) { case IDL_FLOAT_TYPE_FLOAT: dataf (data, "float"); break; case IDL_FLOAT_TYPE_DOUBLE: dataf (data, "double"); break; case IDL_FLOAT_TYPE_LONGDOUBLE: dataf (data, "long" DELIM_SPACE "double"); break; } break; case IDLN_TYPE_FIXED: dataf (data, "fixed<"); IDL_emit_IDL_literal (IDL_TYPE_FIXED (p).positive_int_const, data); dataf (data, DELIM_COMMA); IDL_emit_IDL_literal (IDL_TYPE_FIXED (p).integer_lit, data); dataf (data, ">"); return FALSE; case IDLN_TYPE_INTEGER: if (!IDL_TYPE_INTEGER (p).f_signed) dataf (data, "unsigned" DELIM_SPACE); switch (IDL_TYPE_INTEGER (p).f_type) { case IDL_INTEGER_TYPE_SHORT: dataf (data, "short"); break; case IDL_INTEGER_TYPE_LONG: dataf (data, "long"); break; case IDL_INTEGER_TYPE_LONGLONG: dataf (data, "long" DELIM_SPACE "long"); break; } break; case IDLN_TYPE_STRING: case IDLN_TYPE_WIDE_STRING: if (IDL_NODE_TYPE (p) == IDLN_TYPE_STRING) { dataf (data, "string"); q = IDL_TYPE_STRING (p).positive_int_const; } else { dataf (data, "wstring"); q = IDL_TYPE_WIDE_STRING (p).positive_int_const; } if (q) { dataf (data, "<"); if (IDL_NODE_TYPE (p) == IDLN_TYPE_STRING) IDL_emit_IDL_literal ( IDL_TYPE_STRING (p).positive_int_const, data); else IDL_emit_IDL_literal ( IDL_TYPE_WIDE_STRING (p).positive_int_const, data); dataf (data, ">"); } return FALSE; case IDLN_TYPE_ENUM: IDL_emit_IDL_indent (tfd, data); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_TYPE_ENUM (tfd->tree).ident, data); dataf (data, "enum" DELIM_SPACE); IDL_emit_IDL_ident (IDL_TYPE_ENUM (p).ident, tfd, data); dataf (data, DELIM_SPACE "{" DELIM_SPACE); IDL_output_delim (IDL_TYPE_ENUM (p).enumerator_list, tfd, data, (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL, IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA); dataf (data, DELIM_SPACE "};"); nl (); return FALSE; case IDLN_TYPE_ARRAY: IDL_emit_IDL_ident (IDL_TYPE_ARRAY (p).ident, tfd, data); dataf (data, "["); IDL_output_delim (IDL_TYPE_ARRAY (p).size_list, tfd, data, (IDL_tree_func) IDL_emit_IDL_literal_force_pre, NULL, IDLN_INTEGER, IDLN_NONE, TRUE, DELIM_ARRAY); dataf (data, "]"); return FALSE; case IDLN_TYPE_SEQUENCE: dataf (data, "sequence<"); save_flag (idents, TRUE); IDL_tree_walk2 (IDL_TYPE_SEQUENCE (tfd->tree).simple_type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); if (IDL_TYPE_SEQUENCE (tfd->tree).positive_int_const) { dataf (data, DELIM_COMMA); IDL_emit_IDL_literal ( IDL_TYPE_SEQUENCE (tfd->tree).positive_int_const, data); } dataf (data, ">"); return FALSE; case IDLN_TYPE_STRUCT: if (!data->su_def) doindent (); save_flag (su_def, TRUE); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_TYPE_STRUCT (tfd->tree).ident, data); dataf (data, "struct" DELIM_SPACE); IDL_emit_IDL_ident (IDL_TYPE_STRUCT (p).ident, tfd, data); dataf (data, DELIM_SPACE); IDL_emit_IDL_curly_brace_open (tfd, data); IDL_tree_walk2 (IDL_TYPE_STRUCT (p).member_list, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (su_def); if (data->su_def) IDL_emit_IDL_curly_brace_close (tfd, data); else IDL_emit_IDL_curly_brace_close_sc (tfd, data); return FALSE; case IDLN_TYPE_UNION: if (!data->su_def) doindent (); save_flag (su_def, TRUE); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_TYPE_UNION (tfd->tree).ident, data); dataf (data, "union" DELIM_SPACE); IDL_emit_IDL_ident (IDL_TYPE_UNION (p).ident, tfd, data); dataf (data, DELIM_SPACE); dataf (data, "switch" DELIM_SPACE "("); save_flag (idents, TRUE); IDL_tree_walk2 (IDL_TYPE_UNION (p).switch_type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); dataf (data, ")" DELIM_SPACE "{"); nl (); IDL_tree_walk2 (IDL_TYPE_UNION (p).switch_body, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (su_def); if (data->su_def) idataf (data, "}"); else { idataf (data, "};"); nl (); } return FALSE; default: break; } return TRUE; } static gboolean IDL_emit_IDL_module_all (IDL_tree_func_data *tfd, IDL_output_data *data) { if (tfd->step == 0) { idataf (data, "module" DELIM_SPACE); IDL_emit_IDL_ident (IDL_MODULE (tfd->tree).ident, tfd, data); dataf (data, DELIM_SPACE); IDL_emit_IDL_curly_brace_open (tfd, data); save_flag (idents, FALSE); } else { restore_flag (idents); IDL_emit_IDL_curly_brace_close_sc (tfd, data); } return TRUE; } static gboolean IDL_emit_IDL_interface_all (IDL_tree_func_data *tfd, IDL_output_data *data) { if (tfd->step == 0) { data->inline_props = FALSE; IDL_emit_IDL_properties (IDL_INTERFACE (tfd->tree).ident, data); idataf (data, "interface" DELIM_SPACE); IDL_emit_IDL_ident (IDL_INTERFACE (tfd->tree).ident, tfd, data); dataf (data, DELIM_SPACE); if (IDL_INTERFACE (tfd->tree).inheritance_spec) { dataf (data, ":" DELIM_SPACE); IDL_output_delim (IDL_INTERFACE (tfd->tree).inheritance_spec, tfd, data, (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL, IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA); dataf (data, DELIM_SPACE); } IDL_emit_IDL_curly_brace_open (tfd, data); save_flag (idents, FALSE); } else { restore_flag (idents); IDL_emit_IDL_curly_brace_close_sc (tfd, data); } return TRUE; } static gboolean IDL_emit_IDL_forward_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { idataf (data, "interface" DELIM_SPACE); IDL_emit_IDL_ident (IDL_FORWARD_DCL (tfd->tree).ident, tfd, data); return TRUE; } static gboolean IDL_emit_IDL_attr_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_indent (tfd, data); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_LIST (IDL_ATTR_DCL (tfd->tree).simple_declarations).data, data); if (IDL_ATTR_DCL (tfd->tree).f_readonly) dataf (data, "readonly" DELIM_SPACE); dataf (data, "attribute" DELIM_SPACE); save_flag (idents, TRUE); IDL_tree_walk2 (IDL_ATTR_DCL (tfd->tree).param_type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); dataf (data, DELIM_SPACE); IDL_output_delim (IDL_ATTR_DCL (tfd->tree).simple_declarations, tfd, data, (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL, IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA); IDL_emit_IDL_sc (tfd, data); return FALSE; } static gboolean IDL_emit_IDL_op_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_indent (tfd, data); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_OP_DCL (tfd->tree).ident, data); if (IDL_OP_DCL (tfd->tree).f_oneway) dataf (data, "oneway" DELIM_SPACE); if (IDL_OP_DCL (tfd->tree).op_type_spec) { save_flag (idents, TRUE); IDL_tree_walk2 (IDL_OP_DCL (tfd->tree).op_type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); } else dataf (data, "void"); dataf (data, DELIM_SPACE "%s" DELIM_SPACE "(", IDL_IDENT (IDL_OP_DCL (tfd->tree).ident).str); if (IDL_OP_DCL (tfd->tree).parameter_dcls) IDL_output_delim (IDL_OP_DCL (tfd->tree).parameter_dcls, tfd, data, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, IDLN_PARAM_DCL, IDLN_NONE, FALSE, DELIM_COMMA); if (IDL_OP_DCL (tfd->tree).f_varargs) dataf (data, DELIM_COMMA "..."); dataf (data, ")"); if (IDL_OP_DCL (tfd->tree).raises_expr) { nl (); indent (); idataf (data, DELIM_SPACE "raises" DELIM_SPACE "("); IDL_output_delim (IDL_OP_DCL (tfd->tree).raises_expr, tfd, data, (IDL_tree_func) IDL_emit_IDL_ident_force_pre, NULL, IDLN_IDENT, IDLN_NONE, TRUE, DELIM_COMMA); dataf (data, ")"); unindent (); } if (IDL_OP_DCL (tfd->tree).context_expr) { nl (); indent (); idataf (data, DELIM_SPACE "context" DELIM_SPACE "("); IDL_output_delim (IDL_OP_DCL (tfd->tree).context_expr, tfd, data, (IDL_tree_func) IDL_emit_IDL_literal_force_pre, NULL, IDLN_STRING, IDLN_NONE, TRUE, DELIM_COMMA); dataf (data, ")"); unindent (); } IDL_emit_IDL_sc (tfd, data); return FALSE; } static gboolean IDL_emit_IDL_param_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_PARAM_DCL (tfd->tree).simple_declarator, data); switch (IDL_PARAM_DCL (tfd->tree).attr) { case IDL_PARAM_IN: dataf (data, "in" DELIM_SPACE); break; case IDL_PARAM_OUT: dataf (data, "out" DELIM_SPACE); break; case IDL_PARAM_INOUT: dataf (data, "inout" DELIM_SPACE); break; } save_flag (idents, TRUE); IDL_tree_walk2 (IDL_PARAM_DCL (tfd->tree).param_type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); dataf (data, DELIM_SPACE); IDL_emit_IDL_ident (IDL_PARAM_DCL (tfd->tree).simple_declarator, tfd, data); return FALSE; } static gboolean IDL_emit_IDL_type_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree_func_data down_tfd; IDL_tree q; IDL_emit_IDL_indent (tfd, data); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_LIST (IDL_TYPE_DCL (tfd->tree).dcls).data, data); dataf (data, "typedef" DELIM_SPACE); save_flag (idents, TRUE); save_flag (su_def, TRUE); IDL_tree_walk2 (IDL_TYPE_DCL (tfd->tree).type_spec, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); dataf (data, DELIM_SPACE); down_tfd = *tfd; down_tfd.up = tfd; for (q = IDL_TYPE_DCL (tfd->tree).dcls; q; q = IDL_LIST (q).next) { down_tfd.tree = q; IDL_tree_walk2 (IDL_LIST (q).data, &down_tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); if (IDL_LIST (q).next) dataf (data, DELIM_COMMA); } restore_flag (idents); restore_flag (su_def); IDL_emit_IDL_sc (tfd, data); return FALSE; } static gboolean IDL_emit_IDL_const_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { idataf (data, "const" DELIM_SPACE); save_flag (idents, TRUE); IDL_tree_walk2 (IDL_CONST_DCL (tfd->tree).const_type, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); dataf (data, DELIM_SPACE); IDL_emit_IDL_ident (IDL_CONST_DCL (tfd->tree).ident, tfd, data); dataf (data, DELIM_SPACE "=" DELIM_SPACE); save_flag (literals, TRUE); IDL_tree_walk2 (IDL_CONST_DCL (tfd->tree).const_exp, tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (literals); IDL_emit_IDL_sc (tfd, data); return FALSE; } static gboolean IDL_emit_IDL_except_dcl_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { idataf (data, "exception" DELIM_SPACE); IDL_emit_IDL_ident (IDL_EXCEPT_DCL (tfd->tree).ident, tfd, data); dataf (data, DELIM_SPACE); IDL_emit_IDL_curly_brace_open (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_native_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_indent (tfd, data); data->inline_props = TRUE; IDL_emit_IDL_properties (IDL_NATIVE (tfd->tree).ident, data); dataf (data, "native" DELIM_SPACE); IDL_emit_IDL_ident (IDL_NATIVE (tfd->tree).ident, tfd, data); if (IDL_NATIVE (tfd->tree).user_type) dataf (data, DELIM_SPACE "(%s)", IDL_NATIVE (tfd->tree).user_type); IDL_emit_IDL_sc (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_case_stmt_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree_func_data down_tfd; IDL_tree q; save_flag (idents, TRUE); save_flag (literals, TRUE); down_tfd = *tfd; down_tfd.up = tfd; for (q = IDL_CASE_STMT (tfd->tree).labels; q; q = IDL_LIST (q).next) { if (IDL_LIST (q).data) { down_tfd.tree = q; idataf (data, "case" DELIM_SPACE); IDL_tree_walk2 (IDL_LIST (q).data, &down_tfd,/*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); dataf (data, ":"); } else idataf (data, "default:"); nl (); } restore_flag (literals); restore_flag (idents); indent (); return FALSE; } static gboolean IDL_emit_IDL_case_stmt_post (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_tree_walk2 (IDL_CASE_STMT (tfd->tree).element_spec, tfd, /*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); unindent (); return FALSE; } static gboolean IDL_emit_IDL_member_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { IDL_emit_IDL_indent (tfd, data); save_flag (idents, TRUE); IDL_tree_walk2 (IDL_MEMBER (tfd->tree).type_spec, tfd, /*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, data); restore_flag (idents); return FALSE; } static gboolean IDL_emit_IDL_member_post (IDL_tree_func_data *tfd, IDL_output_data *data) { dataf (data, DELIM_SPACE); IDL_output_delim (IDL_MEMBER (tfd->tree).dcls, tfd, data, (IDL_tree_func) IDL_emit_IDL_type_pre, NULL, IDLN_IDENT, IDLN_TYPE_ARRAY, FALSE, DELIM_COMMA); IDL_emit_IDL_sc (tfd, data); return TRUE; } static gboolean IDL_emit_IDL_codefrag_pre (IDL_tree_func_data *tfd, IDL_output_data *data) { if (data->flags & IDLF_OUTPUT_CODEFRAGS) { GSList *slist; dataf (data, "%%{ %s", IDL_CODEFRAG (tfd->tree).desc); nl (); for (slist = IDL_CODEFRAG (tfd->tree).lines; slist; slist = slist->next) { dataf (data, "%s", (char *) slist->data); nl (); } dataf (data, "%%}"); nl (); } return TRUE; } struct IDL_emit_node { IDL_tree_func pre; IDL_tree_func post; }; static struct IDL_emit_node * IDL_get_IDL_emission_table (void) { static gboolean initialized = FALSE; static struct IDL_emit_node table[IDLN_LAST]; struct IDL_emit_node *s; if (!initialized) { s = &table[IDLN_MODULE]; s->pre = s->post = (IDL_tree_func) IDL_emit_IDL_module_all; s = &table[IDLN_INTERFACE]; s->pre = s->post = (IDL_tree_func) IDL_emit_IDL_interface_all; s = &table[IDLN_FORWARD_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_forward_dcl_pre; s->post = (IDL_tree_func) IDL_emit_IDL_sc; s = &table[IDLN_ATTR_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_attr_dcl_pre; s = &table[IDLN_OP_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_op_dcl_pre; s = &table[IDLN_PARAM_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_param_dcl_pre; s = &table[IDLN_TYPE_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_type_dcl_pre; s = &table[IDLN_CONST_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_const_dcl_pre; s = &table[IDLN_EXCEPT_DCL]; s->pre = (IDL_tree_func) IDL_emit_IDL_except_dcl_pre; s->post = (IDL_tree_func) IDL_emit_IDL_curly_brace_close_sc; s = &table[IDLN_MEMBER]; s->pre = (IDL_tree_func) IDL_emit_IDL_member_pre; s->post = (IDL_tree_func) IDL_emit_IDL_member_post; s = &table[IDLN_NATIVE]; s->pre = (IDL_tree_func) IDL_emit_IDL_native_pre; s = &table[IDLN_CASE_STMT]; s->pre = (IDL_tree_func) IDL_emit_IDL_case_stmt_pre; s->post = (IDL_tree_func) IDL_emit_IDL_case_stmt_post; s = &table[IDLN_IDENT]; s->pre = (IDL_tree_func) IDL_emit_IDL_ident_pre; s = &table[IDLN_CODEFRAG]; s->pre = (IDL_tree_func) IDL_emit_IDL_codefrag_pre; table[IDLN_TYPE_FLOAT].pre = table[IDLN_TYPE_CHAR].pre = table[IDLN_TYPE_WIDE_CHAR].pre = table[IDLN_TYPE_BOOLEAN].pre = table[IDLN_TYPE_OCTET].pre = table[IDLN_TYPE_ANY].pre = table[IDLN_TYPE_OBJECT].pre = table[IDLN_TYPE_TYPECODE].pre = table[IDLN_TYPE_FIXED].pre = table[IDLN_TYPE_INTEGER].pre = table[IDLN_TYPE_STRING].pre = table[IDLN_TYPE_WIDE_STRING].pre = table[IDLN_TYPE_ENUM].pre = table[IDLN_TYPE_ARRAY].pre = table[IDLN_TYPE_SEQUENCE].pre = table[IDLN_TYPE_STRUCT].pre = table[IDLN_TYPE_UNION].pre = (IDL_tree_func) IDL_emit_IDL_type_pre; table[IDLN_FLOAT].pre = table[IDLN_INTEGER].pre = table[IDLN_FIXED].pre = table[IDLN_CHAR].pre = table[IDLN_WIDE_CHAR].pre = table[IDLN_BOOLEAN].pre = table[IDLN_STRING].pre = table[IDLN_WIDE_STRING].pre = (IDL_tree_func) IDL_emit_IDL_literal_pre; initialized = TRUE; } return table; } static gboolean IDL_emit_node_pre_func (IDL_tree_func_data *tfd, IDL_output_data *data) { const struct IDL_emit_node * const s = &IDL_get_IDL_emission_table () [IDL_NODE_TYPE (tfd->tree)]; if (s->pre) return (*s->pre) (tfd, data); return TRUE; } static gboolean IDL_emit_node_post_func (IDL_tree_func_data *tfd, IDL_output_data *data) { const struct IDL_emit_node * const s = &IDL_get_IDL_emission_table () [IDL_NODE_TYPE (tfd->tree)]; if (s->post) return (*s->post) (tfd, data); return TRUE; } void IDL_tree_to_IDL (IDL_tree p, IDL_ns ns, FILE *output, unsigned long output_flags) { IDL_output_data data; g_return_if_fail (output != NULL); data.ns = ns; data.mode = OUTPUT_FILE; data.u.o = output; data.flags = output_flags; data.ilev = 0; data.idents = TRUE; data.literals = TRUE; data.inline_props = TRUE; data.su_def = FALSE; if (ns == NULL) data.flags |= IDLF_OUTPUT_NO_QUALIFY_IDENTS; IDL_tree_walk2 (p, NULL, /*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, &data); } GString *IDL_tree_to_IDL_string (IDL_tree p, IDL_ns ns, unsigned long output_flags) { IDL_output_data data; data.ns = ns; data.mode = OUTPUT_STRING; data.u.s = g_string_new (NULL); data.flags = output_flags; data.ilev = 0; data.idents = TRUE; data.literals = TRUE; data.inline_props = TRUE; data.su_def = FALSE; if (ns == NULL) data.flags |= IDLF_OUTPUT_NO_QUALIFY_IDENTS; IDL_tree_walk2 (p, NULL, /*flags*/0, (IDL_tree_func) IDL_emit_node_pre_func, (IDL_tree_func) IDL_emit_node_post_func, &data); return data.u.s; } typedef struct { IDL_tree searchNode; gboolean found; } ContainsNodeWalkerInfo; static gboolean contains_node_walker (IDL_tree_func_data *tfd, gpointer data) { ContainsNodeWalkerInfo *info = data; /* skip root! */ if (tfd->up != NULL && tfd->tree == info->searchNode) { info->found = TRUE; return FALSE; } return TRUE; /* continue walking */ } gboolean IDL_tree_contains_node(IDL_tree tree, IDL_tree node) { ContainsNodeWalkerInfo info; info.searchNode = node; info.found = 0; IDL_tree_walk2 (tree, /*curwalk*/NULL, /*flags*/0, /*pre*/contains_node_walker, /*post*/NULL, &info); return info.found; } struct IDL_recursive_walker_info { GSList *ident_list; gboolean recursive; }; /* * IDL_tree_is_recursive_walker_pre: * @walk_frame: a #IDL_tree_func_data structure * @user_data: a #IDL_recursive_walker_info structure. * * If the current node in the parse tree is a structure or union * add its IDLN_IDENT to the ident list contained in @user_data; * * If the current node in the parse tree is a sequence, check to * see if the sequence element type is on the list of IDLN_IDENTs. * * Return value: %FALSE if recursion is detected - this stops the * walk to the parse tree -, %TRUE otherwise. */ static gboolean IDL_tree_is_recursive_walker_pre (IDL_tree_func_data *walk_frame, gpointer user_data) { struct IDL_recursive_walker_info *info = user_data; IDL_tree node = walk_frame->tree; switch (IDL_NODE_TYPE (node)) { case IDLN_TYPE_STRUCT: case IDLN_TYPE_UNION: info->ident_list = g_slist_prepend (info->ident_list, IDL_TYPE_STRUCT (node).ident); break; case IDLN_TYPE_SEQUENCE: { IDL_tree seq_type = IDL_TYPE_SEQUENCE (node).simple_type_spec; GSList *l = info->ident_list; if (IDL_NODE_TYPE (seq_type) != IDLN_IDENT) break; g_assert (IDL_IDENT (seq_type).repo_id); for (; l; l = l->next) { IDL_tree n = (IDL_tree)l->data; g_assert (IDL_IDENT (n).repo_id); if (!strcmp (IDL_IDENT (n).repo_id, IDL_IDENT (seq_type).repo_id)) { info->recursive = TRUE; return FALSE; } } } break; default: break; } return TRUE; } /* * IDL_tree_is_recursive_walker_post: * @walk_frame: a #IDL_tree_func_data structure * @user_data: a #IDL_recursive_walker_info structure. * * If the current node in the parse tree is a structure or * union, remove the IDLN_IDENT from the ident list. * * Return value: %TRUE. */ static gboolean IDL_tree_is_recursive_walker_post (IDL_tree_func_data *walk_frame, gpointer user_data) { struct IDL_recursive_walker_info *info = user_data; IDL_tree node = walk_frame->tree; switch (IDL_NODE_TYPE (node)) { case IDLN_TYPE_STRUCT: case IDLN_TYPE_UNION: { GSList *link = info->ident_list; g_assert (((IDL_tree)link->data) == IDL_TYPE_STRUCT (node).ident); info->ident_list = g_slist_remove_link (info->ident_list, link); g_slist_free_1 (link); } break; default: break; } return TRUE; } /* * IDL_tree_is_recursive: * @tree: a #IDL_tree. * @hasRecur: dummy argument, not used, deprecated, compatibility cruft. * * Checks whether or not @tree contains recursive types. * * Recursive types may only be constructed using structs/unions which * contain sequences that hold the parent struct/union type. * * Return value: %TRUE if @tree contains recursive types, * %FALSE otherwise. */ gboolean IDL_tree_is_recursive (IDL_tree tree, gpointer dummy) { struct IDL_recursive_walker_info info; info.ident_list = NULL; info.recursive = FALSE; IDL_tree_walk2 (tree, NULL, IDL_WalkF_TypespecOnly, IDL_tree_is_recursive_walker_pre, IDL_tree_is_recursive_walker_post, &info); g_assert (!info.ident_list); return info.recursive; } /* * Local variables: * mode: C * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: */