/* * 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/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; }