/* * 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/tnc/decode.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 "eval.h" #include "file.h" #include "high.h" #include "node.h" #include "shape.h" #include "table.h" #include "tdf.h" #include "utility.h" /* * DECODE A TDF INTEGER * * A TDF integer is decoded and returned as a long (no overflow checks). */ long tdf_int(void) { return (long)tdf_de_tdfintl (tdfr); } /* * DECODE A TOKEN APPLICATION * * A token application returning sort s is appended to p. If s is * SORT_unknown a simple token (rather than a token application) is * read. */ construct * de_token(node *p, sortname s) { long bits; construct *t; tok_info *info; construct dummy; /* Find token type */ long n = de_token_bits (); if (n == ENC_make_tok) { long m = tdf_int (); t = find_binding (crt_binding, tok_var, m); info = get_tok_info (t); p->son = new_node (); p->son->cons = t; } else if (n == ENC_use_tokdef) { char *nm; t = make_construct (SORT_token); nm = xalloc (32); IGNORE sprintf (nm, "~~token_%ld", t->encoding); t->name = nm; if (add_to_var_hash (t, SORT_token)) MSG_FATAL_var_already_defined (nm); de_token_defn (t, (node *) null); info = get_tok_info (t); p->son = new_node (); p->son->cons = t; } else { high_sort *h; construct *tt; tt = de_token (p, SORT_token); info = get_tok_info (tt); h = high_sorts + high_no (info->res); dummy.name = "high level token"; dummy.u.tok_u.res = h->res; dummy.u.tok_u.args = find_decode_string (h); t = &dummy; info = &dummy.u.tok_u; } /* Quit here if only reading token */ if (s == SORT_unknown) { if (!text_output) { p->son->son = new_node (); p->son->son->cons = &token_cons; } return (null); } /* Find the length of the arguments */ bits = tdf_int (); if (info->res == SORT_unknown) { /* Unknown token */ if (bits) { /* Step over arguments */ char *args; if (streq (t->name, "~dg_exp")) { args = "xFF"; } else if (streq (t->name, "~exp_to_source")) { args = "xFF"; } else if (streq (t->name, "~diag_id_scope")) { args = "x$xF"; } else if (streq (t->name, "~diag_type_scope")) { args = "x$F"; } else if (streq (t->name, "~diag_tag_scope")) { args = "x$F"; } else { MSG_token_undeclared (t->name); args = "F"; } bits += tdf_stream_tell (tdfr); p->son->son = de_node (args); bits -= tdf_stream_tell (tdfr); if (bits < 0) MSG_FATAL_token_arguments_length_wrong (t->name); tdf_skip_bits (tdfr, bits); } else { /* No argument - can deduce token sort */ info->res = s; info->dec = 1; } } else { /* Known token */ if (s == SORT_token) { /* Must be high level */ if (!is_high (info->res)) MSG_FATAL_sort_error_in_token (t->name); } else if (info->res != s) { /* Result sort must match */ MSG_FATAL_sort_error_in_token (t->name); } if (info->args) { /* Decode arguments */ tdf_pos end_posn = tdf_stream_tell (tdfr) + bits; p->son->son = de_node (info->args); if (tdf_stream_tell (tdfr) != end_posn) MSG_FATAL_token_arguments_length_wrong (t->name); } else { /* No arguments */ if (bits) MSG_FATAL_token_arguments_length_wrong (t->name); } info->dec = 1; } /* Mark used tokens */ if (info->dec) adjust_token (t); return (t); } /* * DECODE A VARIABLE SORT * * A construct of the vth variable sort is decoded. */ node * de_var_sort(long v) { long n = tdf_int (); node *p = new_node (); p->cons = find_binding (crt_binding, v, n); return (p); } /* * DECODE A STRING OF DECODE CHARACTERS * * The string of decode character str is decoded. */ node * de_node(char *str) { char c; node *p, *q = null, *qe = null; while (c = *str, c != 0 && c != ']') { switch (c) { case '[' : case '{' : case '}' : case '&' : case '^' : { /* Ignore these cases */ p = null; break; } case '|' : { /* Align input stream */ tdf_de_align (tdfr); p = null; break; } case 'i' : { /* Decode an integer as a string of octal digits */ unsigned long d, n = 0; char buff [1000]; do { d = tdf_de_bits (tdfr, 4); buff [n] = (char) ('0' + (d & 7)); n++; } while (!(d & 8)); buff [n] = 0; p = new_node (); p->cons = new_construct (); if (fits_ulong (buff, 1)) { p->cons->sortnum = SORT_small_tdfint; p->cons->encoding = (long) octal_to_ulong (buff); } else { p->cons->sortnum = SORT_tdfint; p->cons->name = string_copy (buff); } break; } case 'j' : { /* Decode a bit */ p = new_node (); p->cons = (tdf_bool () ? &true_cons : &false_cons); break; } case '$' : { /* Decode a string */ unsigned long i, n = tdf_de_tdfintl (tdfr); if (n == 8) { char *s; n = tdf_de_tdfintl (tdfr); s = xalloc (n + 1); p = new_node (); p->cons = new_construct (); p->cons->sortnum = SORT_tdfstring; p->cons->encoding = n; p->cons->name = s; p->cons->next = null; for (i = 0 ; i < n ; i++) { s [i] = (char) tdf_de_bits (tdfr, 8) ; /* LINT */ } s [n] = 0; } else { unsigned long m; node *px; p = new_node (); p->cons = &string_cons; p->son = make_int (n); m = tdf_de_tdfintl (tdfr); px = new_node (); px->cons = new_construct (); px->cons->sortnum = SORT_repeat; px->cons->encoding = m; p->son->bro->bro = px; for (i = 0 ; i < m ; i++) { long v = tdf_de_bits (tdfr, n); if (i == 0) { px->son = make_int (v); px = px->son; } else { px->bro->bro = make_int (v); px = px->bro->bro; } } } break; } case '=' : { /* Decode an aligned string */ char *s; unsigned long i, n = tdf_de_tdfintl (tdfr); if (n != 8) MSG_FATAL_only_8bit_strings_allowed (); n = tdf_de_tdfintl (tdfr); tdf_de_align (tdfr); s = xalloc (n + 1); p = new_node (); p->cons = new_construct (); p->cons->sortnum = SORT_tdfstring; p->cons->encoding = n; p->cons->name = s; p->cons->next = null; for (i = 0 ; i < n ; i++) { s [i] = (char) tdf_de_bits (tdfr, 8) ; /* LINT */ } s [n] = 0; tdf_de_align (tdfr); break; } case '*' : { /* The following text is repeated n times */ de_list_start (); goto percent_case; } case '%' : percent_case : { /* The following text is repeated n times */ node *pe = null; long i, n = tdf_int (); p = new_node (); p->cons = new_construct (); p->cons->sortnum = SORT_repeat; p->cons->encoding = n; str += 2; for (i = 0 ; i < n ; i++) { node *pi = de_node (str); if (pe == null) { p->son = pi; } else { pe->bro = pi; } pe = pi; while (pe->bro) pe = pe->bro; } str = skip_text (str); break; } case '?' : { /* The following text is optional */ p = new_node (); p->cons = &optional_cons; str += 2; if (tdf_bool ()) { p->son = de_node (str); if (*str == '*' && p->son->cons->encoding == 0) { /* Get rid of optional empty lists */ p->son = null; } } str = skip_text (str); break; } case '@' : { /* The following text is a bitstream */ tdf_pos len, pos; str += 2; len = tdf_de_tdfintl (tdfr); pos = tdf_stream_tell (tdfr); p = new_node (); p->cons = &bytestream_cons; p->son = de_node (str); if (len + pos != tdf_stream_tell (tdfr)) MSG_FATAL_conditional_length_wrong (); str = skip_text (str); break; } case 'T' : { node dummy; str = find_sortname (str, (sortname *) null); IGNORE de_token (&dummy, SORT_unknown); p = dummy.son; break; } case 'F' : { /* Unknown sort */ p = new_node (); p->cons = &unknown_cons; break; } default : { /* Basic sorts */ sortname s = find_sort (c); p = (sort_decode [s]) (); break; } } if (p) { if (qe == null) { q = p; } else { qe->bro = p; } qe = p; while (qe->bro) qe = qe->bro; } str++; } return (q); }