/*
* Copyright (c) 2002, The Tendra Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Crown Copyright (c) 1997
*
* This TenDRA(r) Computer Program is subject to Copyright
* owned by the United Kingdom Secretary of State for Defence
* acting through the Defence Evaluation and Research Agency
* (DERA). It is made available to Recipients with a
* royalty-free licence for its use, reproduction, transfer
* to other parties and amendment for any purpose not excluding
* product development provided that any such use et cetera
* shall be deemed to be acceptance of the following conditions:-
*
* (1) Its Recipients shall ensure that this Notice is
* reproduced upon any copies or amended versions of it;
*
* (2) Any amended version of it shall be clearly marked to
* show both the nature of and the organisation responsible
* for the relevant amendment or amendments;
*
* (3) Its onward transfer from a recipient to another
* party shall be deemed to be that party's acceptance of
* these conditions;
*
* (4) DERA gives no warranty or assurance as to its
* quality or suitability for any purpose and DERA accepts
* no liability whatsoever in relation to any use to which
* it may be put.
*
* $TenDRA: tendra/src/tools/tld/name-entry.c,v 1.12 2005/10/18 15:31:06 stefanf Exp $
*/
/*** name-entry.c --- Name table entry ADT.
*
** Author: Steve Folkes
*
*** Commentary:
*
* This file implements the name table entry routines used by the TDF
* linker.
*
*** Change Log:*/
/****************************************************************************/
#include "name-entry.h"
#include "capsule.h"
#include "debug.h"
#include "msgcat.h"
#include "library.h"
#include "name-table.h"
#include "ostream.h"
#include "shape-entry.h"
#include "shape-table.h"
#include "tdf.h"
#include "unit-table.h"
#include "solve-cycles.h"
/*--------------------------------------------------------------------------*/
NameEntryP
name_entry_create_direct(NameKeyP key, ShapeEntryP shape_entry)
{
NameEntryP entry = ALLOCATE (NameEntryT);
entry->next = NIL (NameEntryP);
name_key_copy (&(entry->key), key);
entry->type = NT_DIRECT;
entry->u.direct.id = shape_entry_next_id (shape_entry);
entry->u.direct.use = 0;
entry->u.direct.definition = NIL (CapsuleP);
entry->u.direct.lib_definition = NIL (LibCapsuleP);
shape_entry_add_to_list (shape_entry, entry);
return (entry);
}
NameEntryP
name_entry_create_indirect(NameKeyP key, NameEntryP indirect)
{
NameEntryP entry = ALLOCATE (NameEntryT);
entry->next = NIL (NameEntryP);
name_key_copy (&(entry->key), key);
entry->type = NT_INDIRECT;
entry->u.indirect = indirect;
return (entry);
}
NameEntryP
name_entry_create_place(NameKeyP key)
{
NameEntryP entry = ALLOCATE (NameEntryT);
entry->next = NIL (NameEntryP);
name_key_copy (&(entry->key), key);
entry->type = NT_PLACEHOLDER;
return (entry);
}
void
name_entry_make_direct(NameEntryP entry, ShapeEntryP shape_entry)
{
ASSERT (name_entry_is_place (entry));
entry->type = NT_DIRECT;
entry->u.direct.id = shape_entry_next_id (shape_entry);
entry->u.direct.use = 0;
entry->u.direct.definition = NIL (CapsuleP);
entry->u.direct.lib_definition = NIL (LibCapsuleP);
shape_entry_add_to_list (shape_entry, entry);
}
void
name_entry_make_indirect(NameEntryP entry, NameEntryP indirect)
{
ASSERT (name_entry_is_place (entry));
entry->type = NT_INDIRECT;
entry->u.indirect = indirect;
}
NameEntryP
name_entry_resolve_renames(NameEntryP entry, NStringP shape, BoolT report)
{
switch (entry->type) EXHAUSTIVE {
case NT_PLACEHOLDER:
case NT_DIRECT:
return (entry);
case NT_INDIRECT_DONE:
return (name_entry_get_indirect (entry));
case NT_INDIRECT_CYCLING:
if (report) {
MSG_rename_cycle (shape, name_entry_key (entry));
}
return (NIL (NameEntryP));
case NT_INDIRECT:
entry->type = NT_INDIRECT_CYCLING;
entry->u.indirect = name_entry_resolve_renames (entry->u.indirect,
shape, report);
entry->type = NT_INDIRECT_DONE;
return (name_entry_get_indirect (entry));
}
UNREACHED;
}
NameKeyP
name_entry_key(NameEntryP entry)
{
return (&(entry->key));
}
NameEntryP
name_entry_next(NameEntryP entry)
{
return (entry->next);
}
NameEntryP *
name_entry_next_ref(NameEntryP entry)
{
return (&(entry->next));
}
BoolT
name_entry_is_direct(NameEntryP entry)
{
return (entry->type == NT_DIRECT);
}
BoolT
name_entry_is_indirect(NameEntryP entry)
{
return ((entry->type == NT_INDIRECT) ||
(entry->type == NT_INDIRECT_CYCLING) ||
(entry->type == NT_INDIRECT_DONE));
}
BoolT
name_entry_is_place(NameEntryP entry)
{
return (entry->type == NT_PLACEHOLDER);
}
unsigned
name_entry_id(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (entry->u.direct.id);
}
void
name_entry_merge_use(NameEntryP entry, unsigned use)
{
ASSERT (name_entry_is_direct (entry));
entry->u.direct.use |= use;
}
unsigned
name_entry_get_use(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (entry->u.direct.use & (U_DEFD | U_DECD | U_MULT | U_USED));
}
void
name_entry_hide(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
entry->u.direct.use |= U_HIDE;
}
void
name_entry_unhide(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
entry->u.direct.use &= ~U_HIDE;
}
BoolT
name_entry_is_hidden(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return ((entry->u.direct.use & U_HIDE) == U_HIDE);
}
void
name_entry_set_definition(NameEntryP entry, CapsuleP capsule)
{
ASSERT (name_entry_is_direct (entry));
entry->u.direct.definition = capsule;
}
CapsuleP
name_entry_get_definition(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (entry->u.direct.definition);
}
void
name_entry_set_lib_definition(NameEntryP entry, LibCapsuleP capsule)
{
ASSERT (name_entry_is_direct (entry));
entry->u.direct.lib_definition = capsule;
}
LibCapsuleP
name_entry_get_lib_definition(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (entry->u.direct.lib_definition);
}
NameEntryP
name_entry_list_next(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (entry->u.direct.list_next);
}
NameEntryP *
name_entry_list_next_ref(NameEntryP entry)
{
ASSERT (name_entry_is_direct (entry));
return (&(entry->u.direct.list_next));
}
NameEntryP
name_entry_get_indirect(NameEntryP entry)
{
ASSERT (name_entry_is_indirect (entry));
return (entry->u.indirect);
}
NameEntryP
name_entry_deallocate(NameEntryP entry)
{
NameEntryP next = name_entry_next (entry);
name_key_destroy (name_entry_key (entry));
DEALLOCATE (entry);
return (next);
}
/*--------------------------------------------------------------------------*/
void
name_entry_do_count(NameEntryP entry, void *gclosure)
{
unsigned *count_ref = (unsigned *) gclosure;
if (!(name_entry_is_hidden (entry))) {
(*count_ref) ++;
}
}
void
name_entry_write_name(NameEntryP entry, void *gclosure)
{
if (!(name_entry_is_hidden (entry))) {
TDFWriterP writer = (TDFWriterP) gclosure;
NameKeyP key = name_entry_key (entry);
unsigned id = name_entry_id (entry);
debug_info_w_name (key, id);
tdf_write_int (writer, id);
tdf_write_name (writer, key);
}
}
void
name_entry_compute_tld_size(NameEntryP entry, void *gclosure)
{
unsigned *size_ref = (unsigned *) gclosure;
if (!name_entry_is_hidden (entry)) {
unsigned use = name_entry_get_use (entry);
(*size_ref) += tdf_int_size (use);
}
}
void
name_entry_write_tld(NameEntryP entry, void *gclosure)
{
TDFWriterP writer = (TDFWriterP) gclosure;
if (!(name_entry_is_hidden (entry))) {
unsigned use = name_entry_get_use (entry);
debug_info_w_usage (use, name_entry_key (entry));
tdf_write_int (writer, use);
}
}
void
name_entry_check_multi_defs(NameEntryP entry, void *gclosure)
{
NStringP shape_name = (NStringP) gclosure;
if ((name_entry_get_use (entry) & U_MULT) &&
(name_entry_get_definition (entry) == NIL (CapsuleP))) {
MSG_no_single_definition (shape_name, name_entry_key (entry));
}
}
void
name_entry_do_lib_count(NameEntryP entry, void *gclosure)
{
if (name_entry_get_definition (entry)) {
unsigned *num_names_ref = (unsigned *) gclosure;
(*num_names_ref) ++;
}
}
void
name_entry_do_lib_write(NameEntryP entry, void *gclosure)
{
CapsuleP definition = name_entry_get_definition (entry);
if (definition) {
TDFWriterP writer = (TDFWriterP) gclosure;
NameKeyP key = name_entry_key (entry);
unsigned use = name_entry_get_use (entry);
unsigned capsule_index = capsule_get_index (definition);
debug_info_w_index_entry (key, use, capsule_name (definition),
capsule_index);
tdf_write_name (writer, key);
tdf_write_int (writer, use);
tdf_write_int (writer, capsule_index);
}
}
void
name_entry_suppress(NameEntryP entry, void *gclosure)
{
NStringP shape = (NStringP) gclosure;
debug_info_l_suppress (shape, name_entry_key (entry));
name_entry_set_lib_definition (entry, NIL (LibCapsuleP));
}
void
name_entry_builder_suppress(NameEntryP entry, void *gclosure)
{
NStringP shape = (NStringP) gclosure;
debug_info_l_suppress (shape, name_entry_key (entry));
name_entry_set_definition (entry, NIL (CapsuleP));
}
BoolT
name_entry_resolve_undefined(NameEntryP entry, NameTableP table,
UnitTableP units, ShapeTableP shapes, NStringP shape_key)
{
unsigned use = name_entry_get_use (entry);
NameKeyP key = name_entry_key (entry);
if ((use & U_DEFD) || (!(use & U_USED))) {
debug_info_l_not_needed (key, shape_key, use);
return (FALSE);
} else if (table) {
NameEntryP lib_entry = name_table_get (table, key);
if (lib_entry) {
LibCapsuleP lib_def = name_entry_get_lib_definition (lib_entry);
unsigned lib_use = name_entry_get_use (lib_entry);
if (lib_def && (!lib_capsule_is_loaded (lib_def)) &&
((!(use & U_MULT)) || (lib_use & U_DEFD))) {
char *name = lib_capsule_full_name (lib_def);
NStringP contents = lib_capsule_contents (lib_def);
CapsuleP capsule;
debug_info_l_found (key, shape_key, use, name);
capsule = capsule_create_string_input (name, contents);
capsule_read (capsule, units, shapes);
capsule_close (capsule);
lib_capsule_loaded (lib_def);
return (TRUE);
}
}
}
MSG_no_definition_found (shape_key, key);
debug_info_l_not_found (key, shape_key, use);
return (FALSE);
}
void
name_entry_hide_defd(NameEntryP entry, void *gclosure)
{
if (name_entry_get_use (entry) & U_DEFD) {
NStringP shape = (NStringP) gclosure;
debug_info_l_hide (shape, name_entry_key (entry));
name_entry_hide (entry);
}
}
void
name_entry_keep(NameEntryP entry, void *gclosure)
{
NStringP shape = (NStringP) gclosure;
debug_info_l_keep (shape, name_entry_key (entry));
name_entry_unhide (entry);
}
void
name_entry_suppress_mult(NameEntryP entry, void *gclosure)
{
if ((name_entry_get_use (entry) & (U_DEFD | U_MULT)) == U_MULT) {
NStringP shape = (NStringP) gclosure;
debug_info_l_suppress (shape, name_entry_key (entry));
name_entry_set_definition (entry, NIL (CapsuleP));
}
}
void
name_entry_lib_suppress_mult(NameEntryP entry, void *gclosure)
{
if ((name_entry_get_use (entry) & (U_DEFD | U_MULT)) == U_MULT) {
NStringP shape = (NStringP) gclosure;
debug_info_l_suppress (shape, name_entry_key (entry));
name_entry_set_lib_definition (entry, NIL (LibCapsuleP));
}
}
void
name_entry_show_content(NameEntryP entry, void *gclosure)
{
LibCapsuleP capsule = name_entry_get_lib_definition (entry);
UNUSED (gclosure);
write_cstring (ostream_output, " ");
write_name_key (ostream_output, name_entry_key (entry));
write_char (ostream_output, ' ');
write_usage (ostream_output, name_entry_get_use (entry));
write_cstring (ostream_output, " '");
write_cstring (ostream_output, lib_capsule_name (capsule));
write_char (ostream_output, '\'');
write_newline (ostream_output);
}