/**************************************************************************
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 <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "rename.h"
#include "util.h"
#ifdef G_OS_WIN32
#include <fcntl.h>
#include <direct.h>
#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:
*/