/*
* 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/tnc/de_unit.c,v 1.9 2005/09/21 20:30:00 stefanf Exp $
*/
#include "config.h"
#include "cstring.h"
#include "fmm.h"
#include "msgcat.h"
#include "tdf_types.h"
#include "tdf_stream.h"
#include "types.h"
#include "check.h"
#include "de_types.h"
#include "de_capsule.h"
#include "de_unit.h"
#include "decode.h"
#include "file.h"
#include "high.h"
#include "node.h"
#include "table.h"
#include "tdf.h"
#include "utility.h"
/*
* ARRAY OF ALL LABELS
*
* The labels in a unit are held in the table labels of size max_lab_no.
*/
static long max_lab_no = 0;
static construct *labels;
/*
* SET UP LABELS
*
* A table of n labels is allocated and initialized.
*/
static void
set_up_labels(long n)
{
long i;
static long lno = 0;
max_lab_no = n;
labels = xalloc (sizeof (construct) * n);
for (i = 0 ; i < n ; i++) {
char *nm = xalloc (32);
IGNORE sprintf (nm, "~~label_%ld", lno);
labels [i].sortnum = SORT_label;
labels [i].encoding = lno++;
labels [i].name = nm;
labels [i].alias = null;
labels [i].next = null;
if (add_to_var_hash (labels + i, SORT_label))
MSG_FATAL_label_already_defined (nm);
}
return;
}
/*
* FIND A LABEL
*
* The nth label in the current unit is returned.
*/
construct *
find_label(long n)
{
if (n < 0 || n >= max_lab_no)
MSG_FATAL_label_number_too_big (n);
return (labels + n);
}
/*
* DECODE A SORT NAME
*
* A sortname is decoded. If expand is true the arguments of any high
* level sort will be stepped over.
*/
static sortname
de_sortname(boolean expand)
{
long n = de_sortname_bits ();
if (n == SORT_token && expand) {
long i, m;
high_sort h, *hp;
static int made_up_sorts = 0;
h.res = de_sortname (1);
de_list_start ();
m = tdf_int ();
h.no_args = (int) m;
h.args = xalloc (sizeof (sortname) * m);
h.name = xalloc (32);
IGNORE sprintf (h.name, "~~sort_%d", made_up_sorts++);
for (i = 0 ; i < m ; i++) {
h.args [i] = de_sortname (1);
}
hp = new_high_sort (&h);
hp = unique_high_sort (hp);
return (hp->id);
}
if (n == SORT_foreign) {
MSG_foreign_sorts_not_supported ();
IGNORE de_node ("X");
return (SORT_unknown);
}
return ((sortname) n);
}
/*
* DECODE AN ALIGNMENT TAG DEFINITION UNIT
*
* A number of alignment tag definitions are decoded.
*/
void
de_aldef(void)
{
long i, n = tdf_int ();
set_up_labels (n);
n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long t;
node *d;
construct *p;
al_tag_info *info;
/* Find the definition type */
IGNORE de_al_tagdef_bits ();
/* Find the alignment tag */
t = tdf_int ();
p = find_binding (crt_binding, al_tag_var, t);
info = get_al_tag_info (p);
/* Decode the definition (an alignment) */
d = completion (de_alignment ());
if (info->def) {
if (!eq_node (info->def, d))
MSG_alignment_tag_defined_inconsistently (p->name);
free_node (d);
} else {
info->def = d;
}
}
return;
}
/*
* DECODE A TAG DECLARATION UNIT
*
* A number of tag declarations are decoded.
*/
void
de_tagdec(void)
{
long i, n = tdf_int ();
set_up_labels (n);
n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long t;
node *d;
boolean is_var;
construct *p;
tag_info *info;
/* Find the declaration type */
long m = de_tagdec_bits ();
if (m == ENC_make_id_tagdec) {
is_var = 0;
} else if (m == ENC_make_var_tagdec) {
is_var = 1;
} else {
is_var = 2;
}
/* Find the tag */
t = tdf_int ();
p = find_binding (crt_binding, tag_var, t);
set_tag_type (p, is_var);
info = get_tag_info (p);
/* Declaration = optional access + optional string + shape from 4.0 */
d = completion (de_node ("?[u]?[X]S"));
info->var = is_var;
if (info->dec) {
if (!eq_node (info->dec, d))
MSG_tag_declared_inconsistently (p->name);
free_node (d);
} else {
info->dec = d;
}
}
return;
}
/*
* DECODE A TAG DEFINITION UNIT
*
* A number of tag definitions are decoded.
*/
void
de_tagdef(void)
{
long i, n = tdf_int ();
set_up_labels (n);
n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long t;
node *d;
construct *p;
tag_info *info;
boolean is_var;
/* Find the definition type */
long m = de_tagdef_bits ();
if (m == ENC_make_id_tagdef) {
is_var = 0;
} else if (m == ENC_make_var_tagdef) {
is_var = 1;
} else {
is_var = 2;
}
/* Find the tag */
t = tdf_int ();
p = find_binding (crt_binding, tag_var, t);
info = get_tag_info (p);
if (info->dec == null)
MSG_FATAL_tag_defined_but_not_declared (p->name);
set_tag_type (p, is_var);
/* Added signature in 4.0 */
d = completion (de_node (is_var ? "?[u]?[X]x" : "?[X]x"));
info->var = is_var;
if (info->def) {
if (is_var == 2) {
node *dp = info->def;
while (dp->bro) dp = dp->bro;
dp->bro = d;
} else {
if (!eq_node (info->def, d))
MSG_tag_defined_inconsistently (p->name);
free_node (d);
}
} else {
info->def = d;
if (do_check) check_tagdef (p);
}
}
return;
}
/*
* DECODE A TOKEN DECLARATION UNIT
*
* A number of token declarations are decoded.
*/
void
de_tokdec(void)
{
long i, n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long t;
node *sig;
char *args;
sortname rs;
construct *p;
tok_info *info;
/* Find the declaration type */
IGNORE de_tokdec_bits ();
/* Find the token */
t = tdf_int ();
p = find_binding (crt_binding, tok_var, t);
info = get_tok_info (p);
/* Deal with signature */
sig = de_node ("?[X]");
/* Decode token sort */
rs = de_sortname (0);
if (rs == SORT_token) {
long m;
rs = de_sortname (1);
de_list_start ();
m = tdf_int ();
if (m == 0) {
args = null;
} else {
long j;
char abuff [100], *a = abuff;
for (j = 0 ; j < m ; j++) {
sortname ps = de_sortname (1);
if (is_high (ps)) {
sprint_high_sort (a, ps);
while (*a) a++;
} else {
*(a++) = sort_letters [ps];
}
}
*a = 0;
args = string_copy (abuff);
}
} else {
args = null;
}
if (is_high (rs))
MSG_FATAL_token_has_high_level_result_sort (p->name);
set_token_sort (p, rs, args, sig);
info->dec = 1;
}
return;
}
/*
* DECODE A TOKEN DEFINITION BODY
*
* The actual body of a token definition is decoded.
*/
void
de_token_defn(construct *p, node *sig)
{
long m;
node *d;
char *args;
sortname rs;
tok_info *info = get_tok_info (p);
construct **old_pars = info->pars;
/* Find the end of the definition */
tdf_pos end_posn = tdf_de_tdfintl (tdfr);
end_posn += tdf_stream_tell (tdfr);
/* Find the definition type */
IGNORE de_token_defn_bits ();
/* Decode the token sort */
rs = de_sortname (1);
de_list_start ();
m = tdf_int ();
if (m == 0) {
args = null;
} else {
long j;
char abuff [100], *a = abuff;
if (!in_skip_pass) {
info->pars = xalloc (sizeof (construct *) * (m + 1));
}
for (j = 0 ; j < m ; j++) {
/* Decode the token arguments */
sortname ps = de_sortname (1);
long pn = tdf_int ();
construct *q = find_binding (crt_binding, tok_var, pn);
set_token_sort (q, ps, (char *) null, (node *) null);
if (is_high (ps)) {
sprint_high_sort (a, ps);
while (*a) a++;
} else {
*(a++) = sort_letters [ps];
}
if (!in_skip_pass) info->pars [j] = q;
}
*a = 0;
args = string_copy (abuff);
if (!in_skip_pass) info->pars [j] = null;
}
if (is_high (rs))
MSG_FATAL_token_has_high_level_result_sort (p->name);
set_token_sort (p, rs, args, sig);
info->dec = 1;
/* Decode the actual definition */
if (in_skip_pass) {
tdf_pos bits = end_posn - tdf_stream_tell (tdfr);
tdf_skip_bits (tdfr, bits);
} else {
char buff [2];
buff [0] = sort_letters [rs];
buff [1] = 0;
d = completion (de_node (buff));
if (info->def) {
if (!eq_node (info->def, d)) {
MSG_token_defined_inconsistently (p->name);
}
free_node (d);
info->pars = old_pars;
} else {
info->def = d;
}
if (rs == SORT_unknown) {
tdf_pos bits = end_posn - tdf_stream_tell (tdfr);
tdf_skip_bits (tdfr, bits);
}
if (tdf_stream_tell (tdfr) != end_posn)
MSG_FATAL_token_definition_length_wrong (p->name);
if (info->pars) {
/* Mark the formal arguments as unused */
construct **ps;
for (ps = info->pars ; *ps ; ps++) {
info = get_tok_info (*ps);
info->dec = 0;
}
}
}
return;
}
/*
* DECODE A TOKEN DEFINITION UNIT
*
* A number of token definitions are decoded.
*/
void
de_tokdef(void)
{
long i, n = tdf_int ();
set_up_labels (n);
n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long t;
node *sig;
construct *p;
/* Find the definition type */
IGNORE de_tokdef_bits ();
/* Find the token */
t = tdf_int ();
p = find_binding (crt_binding, tok_var, t);
/* Deal with signature */
sig = de_node ("?[X]");
/* Decode token definition */
de_token_defn (p, sig);
}
return;
}
/*
* FLAG
*
* Has a version number been read?
*/
int have_version = 0;
/*
* CHECK A VERSION NUMBER
*
* This routine reads and checks a version number.
*/
static void
de_version_number(void)
{
struct tdf_version v;
tdf_de_make_version (tdfr, &v);
if (v.major != VERSION_major || v.minor > VERSION_minor)
MSG_FATAL_illegal_version_number (v.major, v.minor);
have_version = 1;
return;
}
/*
* DECODE A VERSION UNIT
*
* A number of TDF version numbers are decoded. These were only
* introduced for version 2.1 of the TDF specification.
*/
void
de_version(void)
{
long i, n = tdf_int ();
for (i = 0 ; i < n ; i++) {
long m = de_version_bits ();
if (m == ENC_make_version) {
de_version_number ();
} else if (m == ENC_user_info) {
IGNORE de_node ("X");
}
}
return;
}
/*
* DECODE A MAGIC NUMBER
*/
void
de_magic(const char *m)
{
tdf_de_magic (tdfr, m);
de_version_number ();
tdf_de_align (tdfr);
return;
}
syntax highlighted by Code2HTML, v. 0.9.1