/*
* Copyright (c) 2002, The Tendra Project <http://www.ten15.org/>
* 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/disp/unit.c,v 1.14 2005/11/05 15:27:52 stefanf Exp $
*/
#include "config.h"
#include "fmm.h"
#include "msgcat.h"
#include "tdf_types.h"
#include "tdf_stream.h"
#include "types.h"
#include "basic.h"
#include "binding.h"
#include "capsule.h"
#include "file.h"
#include "sort.h"
#include "tdf.h"
#include "tree.h"
#include "unit.h"
/*
* CURRENT MAXIMUM LABEL NUMBER
*
* This gives the number of labels in the current unit.
*/
long max_lab_no = 0;
/*
* READ NUMBER OF LABELS
*
* This routine reads the number of labels in a unit.
*/
static void
read_no_labs(void)
{
long n = tdf_int ();
if (show_stuff) {
word *w = new_word (HORIZ_NONE);
out_string ("label x ");
out_int (n);
end_word (w);
blank_line ();
}
max_lab_no = n;
return;
}
/*
* SET TOKEN SORTS, CHECKING FOR COMPATIBILITY
*
* The token t (with number n) is set to have result sort rs and
* argument sorts args. If t has already been initialized these values
* are checked against the existing values. This routine also sets
* the foreign field of t.
*/
void
token_sort(object *t, sortname rs, char *args, long n)
{
sortid s;
s = find_sort (rs);
if (s.decode == 'F') is_foreign (t) = 1;
if (args) {
char *p;
for (p = args; *p; p++) {
if (*p == 'F') is_foreign (t) = 1;
}
}
if (res_sort (t) == sort_unknown) {
sortname is = implicit_sort (t);
if (is != sort_unknown && is != rs) {
MSG_token_inconsistent_with_previous_use (
object_name (var_token, n));
}
} else {
int good = 1;
if (res_sort (t) != rs) good = 0;
if (args) {
if (arg_sorts (t)) {
good = streq (args, arg_sorts (t));
} else {
good = 0;
}
} else {
if (arg_sorts (t)) good = 0;
}
if (!good) {
MSG_token_declared_inconsistently (
object_name (var_token, n));
}
}
res_sort (t) = rs;
arg_sorts (t) = args;
return;
}
/*
* DECODE A TOKEN DECLARATION
*
* A single token declaration is decoded.
*/
static void
de_tokdec_aux(void)
{
long t;
sortid s;
object *obj;
char *args = null;
word *w = new_word (HORIZ_NONE);
/* Find declaration type */
IGNORE de_tokdec ();
/* Find token number */
t = tdf_int ();
obj = find_binding (crt_binding, var_token, t);
if (obj == null) {
obj = new_object (var_token);
set_binding (crt_binding, var_token, t, obj);
}
out_object (t, obj, var_token);
out (":");
/* Deal with signature */
out ("[");
decode ("?[X]");
out ("] :");
/* Decode token sort */
s = de_sort_name (0);
if (s.res == sort_token) {
long i, m;
s = de_sort_name (1);
check_list ();
m = tdf_int ();
if (m == 0) {
out ("()");
args = "";
} else {
word *wp = new_word (HORIZ_BRACKETS);
args = xmalloc_nof (char, m + 1);
for (i = 0; i < m; i++) {
sortid p;
p = de_sort_name (1);
args [i] = p.decode;
out (p.name);
}
args [m] = 0;
end_word (wp);
}
out_string ("-> ");
}
out (s.name);
end_word (w);
if (obj) token_sort (obj, s.res, args, t);
return;
}
/*
* DECODE A TOKEN DEFINITION
*
* A single token definition is decoded. If skipping is true then only
* the declaration information will be extracted.
*/
static void
de_tokdef_aux(void)
{
tdf_pos end;
long t;
sortid s;
char *args;
object *obj;
long m;
word *w = new_word (HORIZ_NONE);
/* Find definition type */
IGNORE de_tokdef ();
/* Find token number */
t = tdf_int ();
obj = find_binding (crt_binding, var_token, t);
if (obj == null) {
obj = new_object (var_token);
set_binding (crt_binding, var_token, t, obj);
}
out_object (t, obj, var_token);
out (":");
/* Deal with signature */
out ("[");
decode ("?[X]");
out ("] :");
/* Read definition length and work out end */
end = tdf_int ();
end += tdf_stream_tell (tdfr);
/* Find definition type */
IGNORE de_token_defn ();
/* Decode token sort */
s = de_sort_name (1);
check_list ();
m = tdf_int ();
if (m == 0) {
out ("()");
args = "";
} else {
long i;
word *wp = new_word (HORIZ_BRACKETS);
args = xmalloc_nof (char, m + 1);
for (i = 0; i < m; i++) {
long pn;
sortid p;
object *tp;
p = de_sort_name (1);
pn = tdf_int ();
tp = find_binding (crt_binding, var_token, pn);
if (tp == null) {
tp = new_object (var_token);
set_binding (crt_binding, var_token, pn, tp);
}
res_sort (tp) = p.res;
arg_sorts (tp) = null;
if (p.res == sort_token) {
object *tpa = xmalloc_nof (object, 1);
*tpa = *tp;
res_sort (tpa) = p.res;
arg_sorts (tpa) = p.args;
tp->aux = tpa;
}
args [i] = p.decode;
if (!dumb_mode && !(tp->named)) {
tp->named = 1;
tp->name.simple = 1;
tp->name.val.str = xmalloc_nof (char, 10);
IGNORE sprintf (tp->name.val.str, "~par_%ld", i);
}
out_string (p.name);
out_string (" ");
out_object (pn, tp, var_token);
}
args [m] = 0;
end_word (wp);
}
out_string ("-> ");
/* Set result sort */
out (s.name);
end_word (w);
token_sort (obj, s.res, args, t);
/* Main definition body */
out ("Definition :");
if (skipping || is_foreign (obj)) {
tdf_pos pos = tdf_stream_tell (tdfr);
out ("....");
if (pos > end) {
MSG_token_definition_size_wrong ();
} else {
tdf_skip_bits (tdfr, end - pos);
}
} else {
char buff [2];
buff [0] = s.decode;
buff [1] = 0;
decode (buff);
if (tdf_stream_tell (tdfr) != end) {
MSG_token_definition_size_wrong ();
}
}
return;
}
/*
* DECODE A TAG DECLARATION
*
* A single tag declaration is decoded.
*/
static void
de_tagdec_aux(void)
{
long t;
char m;
word *wa;
object *obj;
word *w = new_word (HORIZ_NONE);
/* Find declaration type */
long n = de_tagdec ();
/* Get tag number */
t = tdf_int ();
obj = find_binding (crt_binding, var_tag, t);
if (obj == null) {
obj = new_object (var_tag);
set_binding (crt_binding, var_tag, t, obj);
}
out_object (t, obj, var_tag);
/* Check consistency */
switch (n) {
case tagdec_make_var_tagdec :
out ("(variable)");
m = 0;
break;
case tagdec_make_id_tagdec :
out ("(identity)");
m = 1;
break;
case tagdec_common_tagdec :
out ("(common)");
m = 2;
break;
}
if (obj) {
if (var (obj) != m && var (obj) != 3) {
string s = object_name (var_tag, t);
MSG_tag_declared_inconsistently (s);
}
var (obj) = m;
}
/* Decode declaration body */
wa = new_word (VERT_NONE);
format (HORIZ_NONE, "has access : ", "?[u]");
format (HORIZ_NONE, " and signature : ", "?[X]");
format (HORIZ_NONE, " and shape : ", "S");
end_word (wa);
end_word (w);
return;
}
/*
* DECODE A TAG DEFINITION
*
* A single tag definition is decoded.
*/
static void
de_tagdef_aux(void)
{
long t;
char m;
object *obj;
word *w = new_word (HORIZ_NONE);
/* Find definition type */
long n = de_tagdef ();
/* Get tag number */
t = tdf_int ();
obj = find_binding (crt_binding, var_tag, t);
if (obj == null) {
MSG_tag_defined_but_not_declared (object_name (var_tag, t));
obj = new_object (var_tag);
set_binding (crt_binding, var_tag, t, obj);
}
out_object (t, obj, var_tag);
/* Check consistency */
switch (n) {
case tagdef_make_var_tagdef :
out ("(variable)");
m = 0;
break;
case tagdef_make_id_tagdef :
out ("(identity)");
m = 1;
break;
case tagdef_common_tagdef :
out ("(common)");
m = 2;
break;
}
if (obj) {
if (var (obj) != m && var (obj) != 3) {
MSG_tag_declared_inconsistently (
object_name (var_tag, t));
}
var (obj) = m;
}
/* Decode definition body */
out ("is :");
end_word (w);
if (m != 1) format (HORIZ_NONE, "access : ", "?[u]");
format (HORIZ_NONE, "signature : ", "?[X]");
IGNORE de_exp ();
return;
}
/*
* DECODE AN ALIGNMENT TAG DEFINITION
*
* A single alignment tag definition is decoded.
*/
static void
de_al_tagdef_aux(void)
{
long t;
object *obj;
word *w = new_word (HORIZ_NONE);
/* Find definition type */
IGNORE de_al_tagdef ();
/* Get alignment tag number */
t = tdf_int ();
obj = find_binding (crt_binding, var_al_tag, t);
if (obj == null) {
obj = new_object (var_al_tag);
set_binding (crt_binding, var_al_tag, t, obj);
}
out_object (t, obj, var_al_tag);
/* Decode alignment body */
out ("is :");
end_word (w);
IGNORE de_alignment ();
return;
}
/*
* DECODE A TOKEN DECLARATION UNIT
*
* This routine decodes a list of token declarations.
*/
void
de_tokdec_props(void)
{
long i;
long n = tdf_int ();
for (i = 0; i < n; i++) {
de_tokdec_aux ();
blank_lines = 0;
}
total += n;
return;
}
/*
* DECODE A TOKEN DEFINITION UNIT
*
* This routine decodes a list of token definitions.
*/
void
de_tokdef_props(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
de_tokdef_aux ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
/*
* DECODE A TAG DECLARATION UNIT
*
* This routine decodes a list of tag declarations.
*/
void
de_tagdec_props(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
de_tagdec_aux ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
/*
* DECODE A TAG DEFINITION UNIT
*
* This routine decodes a list of tag definitions.
*/
void
de_tagdef_props(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
de_tagdef_aux ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
/*
* DECODE AN ALIGNMENT TAG DEFINITION UNIT
*
* This routine decodes a list of alignment tag definitions.
*/
void
de_al_tagdef_props(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
de_al_tagdef_aux ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
/*
* FLAGS FOR LINKER INFORMATION AND DIAGNOSTICS
*
* These flags control the output of the various non-core units.
*/
BoolT show_usage = FALSE;
BoolT diagnostics = FALSE;
int versions = 1;
/*
* OUTPUT USAGE INFORMATION
*
* Given a usage n this routine outputs the corresponding usage
* information.
*/
static void
out_usage(long n)
{
static char *usage_info [] = {
"used", "declared", "defined", "multiply-defined"
};
int i;
int used = 0;
word *w = new_word (HORIZ_BRACKETS);
for (i = 0; i < 4; i++) {
if (n & (1 << i)) {
out (usage_info [i]);
used = 1;
}
}
if (!used) out ("unused");
end_word (w);
return;
}
/*
* DECODE USAGE INFORMATION
*
* This routine decodes the usage information for the external variables
* of type v. This consists of a set of usage values in 1-1 correspondence
* with the externally named objects of this type.
*/
static void
de_usage(long v)
{
object **p;
long i, n;
binding *b;
long total_ext = 0, max_ext = -1;
if (v < 0 || v >= no_variables) return;
b = crt_binding + v;
n = b->sz;
if (n == 0) return;
p = xmalloc_nof (object *, n);
for (i = 0; i < n; i++) {
object *q = b->table [i];
long rank = (q ? q->order : -1);
if (rank != -1 && b->table [i]->named) {
p [rank] = b->table [i];
if (rank >= max_ext) max_ext = rank;
total_ext++;
}
}
if (total_ext != max_ext + 1) {
MSG_usage_information_wrong ();
return;
}
if (total_ext) {
out_string (var_types [v]);
out (" Usage Information");
blank_line ();
for (i = 0; i < total_ext; i++) {
long use = tdf_int ();
word *w = new_word (HORIZ_NONE);
if (p [i]->name.simple) {
out (p [i]->name.val.str);
} else {
out_unique (p [i]->name.val.uniq);
}
out_usage (use);
end_word (w);
}
blank_line ();
blank_line ();
blank_lines = 2;
total += total_ext;
}
xfree (p);
return;
}
/*
* DECODE LINKER INFORMATION
*
* This routine decodes the linker information (tld2) units. These are
* used to give the linker information on the usage of tokens and tags.
*/
void
de_tld2_unit(void)
{
de_usage (var_token);
de_usage (var_tag);
return;
}
/*
* DECODE LINKER INFORMATION - NEW VERSION
*
* This routine decodes the linker information (tld) units. These are
* used to give the linker information on the usage of the externally
* named objects.
*/
void
de_tld_unit(void)
{
long n = tdf_int ();
switch (n) {
case 0 : {
de_tld2_unit ();
break;
}
case 1 : {
long v;
for (v = 0; v < no_variables; v++) de_usage (v);
break;
}
default : {
MSG_illegal_tld_version_number (n);
break;
}
}
return;
}
/*
* DECODE A DIAGNOSTIC TAG DEFINITION
*
* This routine decodes a single diagnostic tag definition.
*/
#ifdef HAVE_diag_type_unit
static void
de_diag_tagdef_aux(void)
{
long t;
object *obj;
word *w = new_word (HORIZ_NONE);
IGNORE de_diag_tagdef ();
/* Get alignment tag number */
t = tdf_int ();
obj = find_binding (crt_binding, var_diag_tag, t);
if (obj == null) {
obj = new_object (var_diag_tag);
set_binding (crt_binding, var_diag_tag, t, obj);
}
out_object (t, obj, var_diag_tag);
/* Decode body */
out ("is :");
end_word (w);
IGNORE de_diag_type ();
return;
}
#endif
/*
* DECODE DIAGNOSTIC TYPE INFORMATION
*
* This routine decodes a diagnostic type unit.
*/
#ifdef HAVE_diag_type_unit
void
de_diag_type_unit(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
de_diag_tagdef_aux ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
#endif
/*
* DECODE DIAGNOSTIC INFORMATION
*
* This routine decodes a diagnostic unit.
*/
#ifdef HAVE_diag_unit
void
de_diag_unit(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
IGNORE de_diag_descriptor ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
#endif
/*
* DECODE NEW DIAGNOSTIC INFORMATION
*
* This routine decodes a new diagnostic unit.
*/
#ifdef HAVE_dg_comp_props
void
de_dg_comp_props(void)
{
long i, n;
read_no_labs ();
IGNORE de_dg_compilation ();
blank_line ();
blank_lines = 1;
n = tdf_int ();
for (i = 0; i < n; i++) {
IGNORE de_dg_append ();
blank_line ();
blank_lines = 1;
}
total += (n + 1);
return;
}
#endif
/*
* DECODE LINKING INFORMATION
*
* This routine decode a linkage information unit.
*/
#ifdef HAVE_linkinfo_props
void
de_linkinfo_props(void)
{
long i, n;
read_no_labs ();
n = tdf_int ();
for (i = 0; i < n; i++) {
IGNORE de_linkinfo ();
blank_line ();
blank_lines = 1;
}
total += n;
return;
}
#endif
/*
* PREVIOUS VERSION NUMBER
*
* These variables are used to store the last version number read so
* that duplicate version numbers can be suppressed.
*/
static struct tdf_version lastver = {-1, -1};
/*
* DECODE A VERSION NUMBER
*
* This routine decodes a version number for an s construct.
*/
void
de_make_version(char *s)
{
struct tdf_version v;
tdf_de_make_version (tdfr, &v);
if (v.major != lastver.major || v.minor != v.minor || dumb_mode) {
word *w;
out_string (s);
w = new_word (HORIZ_BRACKETS);
out_int (v.major);
out_int (v.minor);
end_word (w);
lastver = v;
}
if (v.major != version_major || v.minor > version_minor) {
MSG_illegal_version_number (v.major, v.minor, version_major, version_minor);
}
return;
}
/*
* DECODE A VERSION UNIT
*
* This routine decodes a list of version numbers.
*/
#ifdef HAVE_version_props
void
de_version_props(void)
{
long i, n;
n = tdf_int ();
for (i = 0; i < n; i++) {
IGNORE de_version ();
blank_lines = 0;
}
total += n;
return;
}
#endif
/*
* DECODE A MAGIC NUMBER
*
* This routine reads the magic number s.
*/
void
de_magic(char *s)
{
tdf_de_magic (tdfr, s);
de_make_version (s);
lastver.major = -1;
lastver.minor = -1;
tdf_de_align (tdfr);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1