|
Packit |
4a5d52 |
/***************************************************************************
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
ns.c (libIDL namespace functions)
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
Copyright (C) 1998, 1999 Andrew T. Veliath
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
This library is free software; you can redistribute it and/or
|
|
Packit |
4a5d52 |
modify it under the terms of the GNU Library General Public
|
|
Packit |
4a5d52 |
License as published by the Free Software Foundation; either
|
|
Packit |
4a5d52 |
version 2 of the License, or (at your option) any later version.
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
4a5d52 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4a5d52 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
4a5d52 |
Library General Public License for more details.
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
You should have received a copy of the GNU Library General Public
|
|
Packit |
4a5d52 |
License along with this library; if not, write to the Free
|
|
Packit |
4a5d52 |
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
$Id$
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
***************************************************************************/
|
|
Packit |
4a5d52 |
#include <assert.h>
|
|
Packit |
4a5d52 |
#include <stdarg.h>
|
|
Packit |
4a5d52 |
#include <stdio.h>
|
|
Packit |
4a5d52 |
#include <stdlib.h>
|
|
Packit |
4a5d52 |
#include <ctype.h>
|
|
Packit |
4a5d52 |
#include <string.h>
|
|
Packit |
4a5d52 |
#include <errno.h>
|
|
Packit |
4a5d52 |
#include "rename.h"
|
|
Packit |
4a5d52 |
#include "util.h"
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static int is_inheritance_conflict (IDL_tree p);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_ns IDL_ns_new (void)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_ns ns;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
ns = g_new0 (struct _IDL_ns, 1);
|
|
Packit |
4a5d52 |
if (ns == NULL) {
|
|
Packit |
4a5d52 |
yyerror ("IDL_ns_new: memory exhausted");
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS (ns).global = IDL_gentree_new (IDL_ident_hash,
|
|
Packit |
4a5d52 |
IDL_ident_equal,
|
|
Packit |
4a5d52 |
IDL_ident_new (""));
|
|
Packit |
4a5d52 |
IDL_NS (ns).file = IDL_NS (ns).current = IDL_NS (ns).global;
|
|
Packit |
4a5d52 |
IDL_NS (ns).inhibits = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
Packit |
4a5d52 |
IDL_NS (ns).filename_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return ns;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static void filename_hash_free (char *filename, IDL_fileinfo *fi)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
g_free (fi->name);
|
|
Packit |
4a5d52 |
g_free (fi);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
void IDL_ns_free (IDL_ns ns)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
assert (ns != NULL);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_hash_table_foreach (IDL_NS (ns).inhibits, (GHFunc)IDL_tree_free, NULL);
|
|
Packit |
4a5d52 |
g_hash_table_destroy (IDL_NS (ns).inhibits);
|
|
Packit |
4a5d52 |
g_hash_table_foreach (IDL_NS (ns).filename_hash, (GHFunc) filename_hash_free, NULL);
|
|
Packit |
4a5d52 |
g_hash_table_destroy (IDL_NS (ns).filename_hash);
|
|
Packit |
4a5d52 |
IDL_tree_free (IDL_NS (ns).global);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_free (ns);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
#define IDL_NS_ASSERTS do { \
|
|
Packit |
4a5d52 |
assert (ns != NULL); \
|
|
Packit |
4a5d52 |
if (__IDL_is_parsing) { \
|
|
Packit |
4a5d52 |
assert (IDL_NS (ns).global != NULL); \
|
|
Packit |
4a5d52 |
assert (IDL_NS (ns).file != NULL); \
|
|
Packit |
4a5d52 |
assert (IDL_NS (ns).current != NULL); \
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_NS (ns).global) == IDLN_GENTREE); \
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_NS (ns).file) == IDLN_GENTREE); \
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_NS (ns).current) == IDLN_GENTREE); \
|
|
Packit |
4a5d52 |
} \
|
|
Packit |
4a5d52 |
} while (0)
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
int IDL_ns_prefix (IDL_ns ns, const char *s)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
char *r;
|
|
Packit |
4a5d52 |
int l;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (s == NULL)
|
|
Packit |
4a5d52 |
return FALSE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (*s == '"')
|
|
Packit |
4a5d52 |
r = g_strdup (s + 1);
|
|
Packit |
4a5d52 |
else
|
|
Packit |
4a5d52 |
r = g_strdup (s);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
l = strlen (r);
|
|
Packit |
4a5d52 |
if (l && r[l - 1] == '"')
|
|
Packit |
4a5d52 |
r[l - 1] = 0;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (IDL_GENTREE (IDL_NS (ns).current)._cur_prefix)
|
|
Packit |
4a5d52 |
g_free (IDL_GENTREE (IDL_NS (ns).current)._cur_prefix);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_GENTREE (IDL_NS (ns).current)._cur_prefix = r;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return TRUE;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_resolve_this_scope_ident (IDL_ns ns, IDL_tree scope, IDL_tree ident)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree p, q;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
p = scope;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
while (p != NULL) {
|
|
Packit |
4a5d52 |
q = IDL_ns_lookup_this_scope (ns, p, ident, NULL);
|
|
Packit |
4a5d52 |
if (q != NULL)
|
|
Packit |
4a5d52 |
return q;
|
|
Packit |
4a5d52 |
p = IDL_NODE_UP (p);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return p;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_resolve_ident (IDL_ns ns, IDL_tree ident)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
return IDL_ns_resolve_this_scope_ident (ns, IDL_NS (ns).current, ident);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_lookup_this_scope (IDL_ns ns, IDL_tree scope, IDL_tree ident, gboolean *conflict)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree p, q;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (conflict)
|
|
Packit |
4a5d52 |
*conflict = TRUE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (scope == NULL)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Search this namespace */
|
|
Packit |
4a5d52 |
if (g_hash_table_lookup_extended (
|
|
Packit |
4a5d52 |
IDL_GENTREE (scope).children, ident, NULL, (gpointer)&p)) {
|
|
Packit |
4a5d52 |
assert (IDL_GENTREE (p).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
return p;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* If there are inherited namespaces, look in those before giving up */
|
|
Packit |
4a5d52 |
q = IDL_GENTREE (scope)._import;
|
|
Packit |
4a5d52 |
if (!q)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (q) == IDLN_LIST);
|
|
Packit |
4a5d52 |
for (; q != NULL; q = IDL_LIST (q).next) {
|
|
Packit |
4a5d52 |
IDL_tree r;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_LIST (q).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_LIST (q).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
assert (IDL_IDENT_TO_NS (IDL_LIST (q).data) != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_IDENT_TO_NS (IDL_LIST (q).data)) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Search imported namespace scope q */
|
|
Packit |
4a5d52 |
if (g_hash_table_lookup_extended (
|
|
Packit |
4a5d52 |
IDL_GENTREE (IDL_IDENT_TO_NS (IDL_LIST (q).data)).children,
|
|
Packit |
4a5d52 |
ident, NULL, (gpointer)&p)) {
|
|
Packit |
4a5d52 |
assert (IDL_GENTREE (p).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* This needs more work, it won't do full ambiguity detection */
|
|
Packit |
4a5d52 |
if (conflict && !is_inheritance_conflict (p))
|
|
Packit |
4a5d52 |
*conflict = FALSE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return p;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Search up one level */
|
|
Packit |
4a5d52 |
if (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (q).data)) == IDLN_INTERFACE &&
|
|
Packit |
4a5d52 |
(r = IDL_ns_lookup_this_scope (
|
|
Packit |
4a5d52 |
ns, IDL_IDENT_TO_NS (IDL_LIST (q).data), ident, conflict)))
|
|
Packit |
4a5d52 |
return r;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_lookup_cur_scope (IDL_ns ns, IDL_tree ident, gboolean *conflict)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
return IDL_ns_lookup_this_scope (ns, IDL_NS (ns).current, ident, conflict);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_place_new (IDL_ns ns, IDL_tree ident)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree p, up_save;
|
|
Packit |
4a5d52 |
gboolean does_conflict;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
p = IDL_ns_lookup_cur_scope (ns, ident, &does_conflict);
|
|
Packit |
4a5d52 |
if (p != NULL && does_conflict)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* The namespace tree is separate from the primary parse tree,
|
|
Packit |
4a5d52 |
so keep the primary tree node's parent the same */
|
|
Packit |
4a5d52 |
up_save = IDL_NODE_UP (ident);
|
|
Packit |
4a5d52 |
p = IDL_gentree_chain_child (IDL_NS (ns).current, ident);
|
|
Packit |
4a5d52 |
IDL_NODE_UP (ident) = up_save;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (p == NULL)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (p) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_IDENT_TO_NS (ident) = p;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_UP (IDL_IDENT_TO_NS (ident)) == IDL_NS (ns).current);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Generate default repository ID */
|
|
Packit |
4a5d52 |
IDL_IDENT_REPO_ID (ident) =
|
|
Packit |
4a5d52 |
IDL_ns_ident_make_repo_id (__IDL_root_ns, p, NULL, NULL, NULL);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return p;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
void IDL_ns_push_scope (IDL_ns ns, IDL_tree ns_ident)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (ns_ident) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (ns_ident).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
assert (IDL_NS (ns).current == IDL_NODE_UP (ns_ident));
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_NS (ns).current = ns_ident;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
void IDL_ns_pop_scope (IDL_ns ns)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_NS_ASSERTS;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (IDL_NODE_UP (IDL_NS (ns).current) != NULL)
|
|
Packit |
4a5d52 |
IDL_NS (ns).current = IDL_NODE_UP (IDL_NS (ns).current);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree IDL_ns_qualified_ident_new (IDL_tree nsid)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree l = NULL, item;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
while (nsid != NULL) {
|
|
Packit |
4a5d52 |
if (IDL_GENTREE (nsid).data == NULL) {
|
|
Packit |
4a5d52 |
nsid = IDL_NODE_UP (nsid);
|
|
Packit |
4a5d52 |
continue;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
assert (IDL_GENTREE (nsid).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (nsid).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
item = IDL_list_new (IDL_ident_new (
|
|
Packit |
4a5d52 |
g_strdup (IDL_IDENT (IDL_GENTREE (nsid).data).str)));
|
|
Packit |
4a5d52 |
l = IDL_list_concat (item, l);
|
|
Packit |
4a5d52 |
nsid = IDL_NODE_UP (nsid);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return l;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
gchar *IDL_ns_ident_to_qstring (IDL_tree ns_ident, const char *join, int levels)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree l, q;
|
|
Packit |
4a5d52 |
int len, joinlen;
|
|
Packit |
4a5d52 |
char *s;
|
|
Packit |
4a5d52 |
int count = 0, start_level;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (levels < 0 || levels > 64)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (ns_ident == NULL)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (IDL_NODE_TYPE (ns_ident) == IDLN_IDENT)
|
|
Packit |
4a5d52 |
ns_ident = IDL_IDENT_TO_NS (ns_ident);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (ns_ident) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
l = IDL_ns_qualified_ident_new (ns_ident);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (l == NULL)
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (join == NULL)
|
|
Packit |
4a5d52 |
join = "";
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
joinlen = strlen (join);
|
|
Packit |
4a5d52 |
for (len = 0, q = l; q != NULL; q = IDL_LIST (q).next) {
|
|
Packit |
4a5d52 |
IDL_tree i = IDL_LIST (q).data;
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (q) == IDLN_LIST);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (i) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
if (IDL_IDENT (i).str != NULL)
|
|
Packit |
4a5d52 |
len += strlen (IDL_IDENT (i).str) + joinlen;
|
|
Packit |
4a5d52 |
++count;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (levels == 0)
|
|
Packit |
4a5d52 |
start_level = 0;
|
|
Packit |
4a5d52 |
else
|
|
Packit |
4a5d52 |
start_level = count - levels;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (start_level >= 0 && start_level < count);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
s = g_malloc (len + 1);
|
|
Packit |
4a5d52 |
if (s == NULL) {
|
|
Packit |
4a5d52 |
IDL_tree_free (l);
|
|
Packit |
4a5d52 |
return NULL;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
s[0] = '\0';
|
|
Packit |
4a5d52 |
for (q = l; q != NULL; q = IDL_LIST (q).next) {
|
|
Packit |
4a5d52 |
IDL_tree i = IDL_LIST (q).data;
|
|
Packit |
4a5d52 |
if (start_level > 0) {
|
|
Packit |
4a5d52 |
--start_level;
|
|
Packit |
4a5d52 |
continue;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
if (s[0] != '\0')
|
|
Packit |
4a5d52 |
strcat (s, join);
|
|
Packit |
4a5d52 |
strcat (s, IDL_IDENT (i).str);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
IDL_tree_free (l);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return s;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
int IDL_ns_scope_levels_from_here (IDL_ns ns, IDL_tree ident, IDL_tree parent)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree p, scope_here, scope_ident;
|
|
Packit |
4a5d52 |
int levels;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_return_val_if_fail (ns != NULL, 1);
|
|
Packit |
4a5d52 |
g_return_val_if_fail (ident != NULL, 1);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
while (parent && !IDL_NODE_IS_SCOPED (parent))
|
|
Packit |
4a5d52 |
parent = IDL_NODE_UP (parent);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (parent == NULL)
|
|
Packit |
4a5d52 |
return 1;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if ((scope_here = IDL_tree_get_scope (parent)) == NULL ||
|
|
Packit |
4a5d52 |
(scope_ident = IDL_tree_get_scope (ident)) == NULL)
|
|
Packit |
4a5d52 |
return 1;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope_here) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope_ident) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
for (levels = 1; scope_ident;
|
|
Packit |
4a5d52 |
++levels, scope_ident = IDL_NODE_UP (scope_ident)) {
|
|
Packit |
4a5d52 |
p = IDL_ns_resolve_this_scope_ident (
|
|
Packit |
4a5d52 |
ns, scope_here, IDL_GENTREE (scope_ident).data);
|
|
Packit |
4a5d52 |
if (p == scope_ident)
|
|
Packit |
4a5d52 |
return levels;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return 1;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* If insertion was made, return true, else there was a collision */
|
|
Packit |
4a5d52 |
static gboolean heap_insert_ident (IDL_tree interface_ident, GTree *heap, IDL_tree any)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree p;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (any != NULL);
|
|
Packit |
4a5d52 |
assert (heap != NULL);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if ((p = g_tree_lookup (heap, any))) {
|
|
Packit |
4a5d52 |
char *newi;
|
|
Packit |
4a5d52 |
char *i1, *i2;
|
|
Packit |
4a5d52 |
char *what1 = "identifier", *what2 = what1;
|
|
Packit |
4a5d52 |
char *who1, *who2;
|
|
Packit |
4a5d52 |
IDL_tree q;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (p) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
newi = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (interface_ident), "::", 0);
|
|
Packit |
4a5d52 |
i1 = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (p), "::", 0);
|
|
Packit |
4a5d52 |
i2 = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (any), "::", 0);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
q = p;
|
|
Packit |
4a5d52 |
while (q && (IDL_NODE_TYPE (q) == IDLN_IDENT || IDL_NODE_TYPE (q) == IDLN_LIST))
|
|
Packit |
4a5d52 |
q = IDL_NODE_UP (q);
|
|
Packit |
4a5d52 |
assert (q != NULL);
|
|
Packit |
4a5d52 |
IDL_tree_get_node_info (q, &what1, &who1);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
q = any;
|
|
Packit |
4a5d52 |
while (q && (IDL_NODE_TYPE (q) == IDLN_IDENT || IDL_NODE_TYPE (q) == IDLN_LIST))
|
|
Packit |
4a5d52 |
q = IDL_NODE_UP (q);
|
|
Packit |
4a5d52 |
assert (q != NULL);
|
|
Packit |
4a5d52 |
IDL_tree_get_node_info (q, &what2, &who2);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
yyerrorv ("Ambiguous inheritance in interface `%s' from %s `%s' and %s `%s'",
|
|
Packit |
4a5d52 |
newi, what1, i1, what2, i2);
|
|
Packit |
4a5d52 |
IDL_tree_error (p, "%s `%s' conflicts with", what1, i1);
|
|
Packit |
4a5d52 |
IDL_tree_error (any, "%s `%s'", what2, i2);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_free (newi); g_free (i1); g_free (i2);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return FALSE;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_tree_insert (heap, any, any);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return TRUE;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static int is_visited_interface (GHashTable *visited_interfaces, IDL_tree scope)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
assert (scope != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
/* If already visited, do not visit again */
|
|
Packit |
4a5d52 |
return g_hash_table_lookup_extended (visited_interfaces, scope, NULL, NULL);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static void mark_visited_interface (GHashTable *visited_interfaces, IDL_tree scope)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
assert (scope != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
g_hash_table_insert (visited_interfaces, scope, scope);
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static int is_inheritance_conflict (IDL_tree p)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
if (IDL_GENTREE (p).data == NULL)
|
|
Packit |
4a5d52 |
return FALSE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (p).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (IDL_NODE_UP (IDL_GENTREE (p).data) == NULL)
|
|
Packit |
4a5d52 |
return FALSE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (!(IDL_NODE_TYPE (IDL_NODE_UP (IDL_GENTREE (p).data)) == IDLN_OP_DCL ||
|
|
Packit |
4a5d52 |
(IDL_NODE_UP (IDL_GENTREE (p).data) &&
|
|
Packit |
4a5d52 |
IDL_NODE_TYPE (IDL_NODE_UP (IDL_NODE_UP (IDL_GENTREE (p).data))) == IDLN_ATTR_DCL)))
|
|
Packit |
4a5d52 |
return FALSE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return TRUE;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
typedef struct {
|
|
Packit |
4a5d52 |
IDL_tree interface_ident;
|
|
Packit |
4a5d52 |
GTree *ident_heap;
|
|
Packit |
4a5d52 |
int insert_conflict;
|
|
Packit |
4a5d52 |
} InsertHeapData;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
static void insert_heap_cb (IDL_tree ident, IDL_tree p, InsertHeapData *data)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
if (!is_inheritance_conflict (p))
|
|
Packit |
4a5d52 |
return;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (!heap_insert_ident (
|
|
Packit |
4a5d52 |
data->interface_ident, data->ident_heap, IDL_GENTREE (p).data))
|
|
Packit |
4a5d52 |
data->insert_conflict = 1;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Return true if adds went okay */
|
|
Packit |
4a5d52 |
static int IDL_ns_load_idents_to_tables (IDL_tree interface_ident, IDL_tree ident_scope,
|
|
Packit |
4a5d52 |
GTree *ident_heap, GHashTable *visited_interfaces)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
IDL_tree q, scope;
|
|
Packit |
4a5d52 |
InsertHeapData data;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (ident_scope != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (ident_scope) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
scope = IDL_IDENT_TO_NS (ident_scope);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (!scope)
|
|
Packit |
4a5d52 |
return TRUE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (scope) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
assert (IDL_GENTREE (scope).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_GENTREE (scope).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_UP (IDL_GENTREE (scope).data) != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_NODE_UP (IDL_GENTREE (scope).data)) == IDLN_INTERFACE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (is_visited_interface (visited_interfaces, scope))
|
|
Packit |
4a5d52 |
return TRUE;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Search this namespace */
|
|
Packit |
4a5d52 |
data.interface_ident = interface_ident;
|
|
Packit |
4a5d52 |
data.ident_heap = ident_heap;
|
|
Packit |
4a5d52 |
data.insert_conflict = 0;
|
|
Packit |
4a5d52 |
g_hash_table_foreach (IDL_GENTREE (scope).children, (GHFunc)insert_heap_cb, &data);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* If there are inherited namespaces, look in those before giving up */
|
|
Packit |
4a5d52 |
q = IDL_GENTREE (scope)._import;
|
|
Packit |
4a5d52 |
if (!q)
|
|
Packit |
4a5d52 |
data.insert_conflict = 0;
|
|
Packit |
4a5d52 |
else
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (q) == IDLN_LIST);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/* Add inherited namespace identifiers into heap */
|
|
Packit |
4a5d52 |
for (; q != NULL; q = IDL_LIST (q).next) {
|
|
Packit |
4a5d52 |
int r;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_LIST (q).data != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_LIST (q).data) == IDLN_IDENT);
|
|
Packit |
4a5d52 |
assert (IDL_IDENT_TO_NS (IDL_LIST (q).data) != NULL);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_IDENT_TO_NS (IDL_LIST (q).data)) == IDLN_GENTREE);
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (IDL_NODE_UP (IDL_LIST (q).data)) == IDLN_INTERFACE);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (!(r = IDL_ns_load_idents_to_tables (interface_ident, IDL_LIST (q).data,
|
|
Packit |
4a5d52 |
ident_heap, visited_interfaces)))
|
|
Packit |
4a5d52 |
data.insert_conflict = 1;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
mark_visited_interface (visited_interfaces, scope);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return data.insert_conflict == 0;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
int IDL_ns_check_for_ambiguous_inheritance (IDL_tree interface_ident, IDL_tree p)
|
|
Packit |
4a5d52 |
{
|
|
Packit |
4a5d52 |
/* We use a sorted heap to check for namespace collisions,
|
|
Packit |
4a5d52 |
since we must do case-insensitive collision checks.
|
|
Packit |
4a5d52 |
visited_interfaces is a hash of visited interface nodes, so
|
|
Packit |
4a5d52 |
we only visit common ancestors once. */
|
|
Packit |
4a5d52 |
GTree *ident_heap;
|
|
Packit |
4a5d52 |
GHashTable *visited_interfaces;
|
|
Packit |
4a5d52 |
int is_ambiguous = 0;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
if (!p)
|
|
Packit |
4a5d52 |
return 0;
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
ident_heap = g_tree_new (IDL_ident_cmp);
|
|
Packit |
4a5d52 |
visited_interfaces = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
assert (IDL_NODE_TYPE (p) == IDLN_LIST);
|
|
Packit |
4a5d52 |
for (; p; p = IDL_LIST (p).next) {
|
|
Packit |
4a5d52 |
if (!IDL_ns_load_idents_to_tables (interface_ident, IDL_LIST (p).data,
|
|
Packit |
4a5d52 |
ident_heap, visited_interfaces))
|
|
Packit |
4a5d52 |
is_ambiguous = 1;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
g_tree_destroy (ident_heap);
|
|
Packit |
4a5d52 |
g_hash_table_destroy (visited_interfaces);
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
return is_ambiguous;
|
|
Packit |
4a5d52 |
}
|
|
Packit |
4a5d52 |
|
|
Packit |
4a5d52 |
/*
|
|
Packit |
4a5d52 |
* Local variables:
|
|
Packit |
4a5d52 |
* mode: C
|
|
Packit |
4a5d52 |
* c-basic-offset: 8
|
|
Packit |
4a5d52 |
* tab-width: 8
|
|
Packit |
4a5d52 |
* indent-tabs-mode: t
|
|
Packit |
4a5d52 |
* End:
|
|
Packit |
4a5d52 |
*/
|