/*
* 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/basic.c,v 1.9 2005/11/05 12:03:14 stefanf Exp $
*/
#include "config.h"
#include "fmm.h"
#include "msgcat.h"
#include "tdf_types.h"
#include "tdf_stream.h"
#include "ascii.h"
#include "types.h"
#include "basic.h"
#include "capsule.h"
#include "file.h"
#include "sort.h"
#include "tdf.h"
#include "tree.h"
TDFINTL
tdf_int(void)
{
return tdf_de_tdfintl(tdfr);
}
int tdf_int_digits;
/*
* READ A TDF INTEGER AS A STRING OF OCTAL DIGITS
*
* A TDF integer is read into the buffer, with its length being
* recorded in tdf_int_digits.
*/
char *
tdf_int_str(void)
{
ByteT *bp;
bp = tdf_de_tdfintstr (tdfr);
tdf_int_digits = tdfr->ts_tdfintlen;
return (char*)bp;
}
/*
* Format TDFSTRING
*
* Only strings consisting of 8-bit characters are actually dealt with
* at the moment. This routine decodes such a string,
* translating any unprintable characters into escape sequences.
*/
char *
tdf_string_format(TDFSTRING *sp)
{
TDFINTL i, n;
int c;
char *s, *p;
n = 0;
for (i = 0; i < sp->number; i++) {
c = sp->ints.chars[i];
if (printable (c)) {
if (c == SLASH || c == QUOTE)
n++;
n++;
} else {
n++;
if (c == NEWLINE || c == TAB) {
n++;
} else {
n += 3;
}
}
}
p = s = xmalloc (n + 1);
for (i = 0; i < sp->number; i++) {
c = sp->ints.chars[i];
if (printable (c)) {
if (c == SLASH || c == QUOTE) *p++ = SLASH;
*p++ = (char) c;
} else {
*p++ = SLASH;
if (c == NEWLINE) {
*p++ = 'n';
} else if (c == TAB) {
*p++ = 't';
} else {
*p++ = charact (c / 64);
*p++ = charact ((c % 64) / 8);
*p++ = charact (c % 8);
}
}
}
*p++ = 0;
return (s);
}
/*
* DECODE A TDF STRING
*
* A TDF string is read and returned. This consists of the number
* of bits per character and the string length followed by the
* appropriate number of characters. If the character size is not 8
* or the string is too long, it is deemed to be unprintable.
*/
char *
de_tdfstring(void)
{
TDFSTRING ts;
char *s;
tdf_de_tdfstring(tdfr, &ts);
if (ts.size == 8 && ts.number < 1000) {
s = tdf_string_format (&ts);
} else {
s = "";
}
if (ts.number)
xfree (ts.ints.chars);
return (s);
}
/*
* DECODE AN ALIGNED TDF STRING
*
* This routine is identical to that above except that there are a
* couple of alignments. This is used by de_extern_name.
*/
char *
de_tdfstring_align(void)
{
TDFIDENT ti;
char *s;
tdf_de_tdfident(tdfr, &ti);
if (ti.size == 8 && ti.number < 1000) {
s = tdf_string_format (&ti);
} else {
s = "";
}
if (ti.number)
xfree (ti.ints.chars);
return (s);
}
/*
* DECODE A UNIQUE IDENTIFIER
*
* A unique consists of an array of strings. The end of the array is marked
* by a null string.
*/
unique
de_unique(void)
{
long i, n;
unique u;
n = tdf_int ();
u = xmalloc_nof (string, n + 1);
for (i = 0; i < n; i++) u [i] = de_tdfstring_align ();
u [n] = null;
return (u);
}
/*
* DECODE AN EXTERNAL NAME
*
* A number of bits are read and, according to their value, either a
* string or a unique is decoded.
*/
external
de_extern_name(void)
{
external e;
long n = de_external ();
tdf_de_align (tdfr);
switch (n) {
case external_string_extern : {
e.simple = 1;
e.val.str = de_tdfstring_align ();
break;
}
case external_unique_extern : {
e.simple = 0;
e.val.uniq = de_unique ();
break;
}
case external_chain_extern : {
e.simple = 1;
e.val.str = de_tdfstring_align ();
IGNORE tdf_int ();
break;
}
default : {
e.simple = 1;
e.val.str = "";
break;
}
}
return (e);
}
/*
* ARRAY OF FOREIGN SORTS
*
* Foreign sorts are identified by means of strings. This array gives all
* the foreign sorts known to the program.
*/
int do_foreign_sorts = 0;
long no_foreign_sorts = 0;
sortid *foreign_sorts = null;
static long fs_size = 0;
/*
* ADD A FOREIGN SORT
*
* The foreign sort with name nm, foreign name fnm and decode letter c is
* added to the array of foreign sorts.
*/
void
add_foreign_sort(char *nm, char *fnm, int c)
{
long n = no_foreign_sorts++;
if (n >= fs_size) {
fs_size += 20;
foreign_sorts = xrealloc (foreign_sorts, sizeof(sortid) * fs_size);
}
foreign_sorts [n].name = nm;
foreign_sorts [n].fname = fnm;
foreign_sorts [n].decode = (char) c;
foreign_sorts [n].res = (sortname) (extra_sorts + n);
foreign_sorts [n].args = null;
return;
}
/*
* DECODE A COMPLEX SORT AS A STRING
*/
static sortid
de_complex_sort(sortname sn)
{
sortid cs;
if (sn == sort_token) {
long i, n;
sortid cp, cr;
char buff [1000];
char *p = buff;
/* Decode result of token sort */
cr = de_sort_name (0);
cs.res = cr.res;
cr = de_complex_sort (cs.res);
/* Start decoding token sort */
cs.decode = 'T';
check_list ();
n = tdf_int ();
cs.args = xmalloc_nof (char, n + 1);
IGNORE strcpy (p, "TOKEN(");
p = p + strlen (p);
/* Decode arguments of token sort */
for (i = 0; i < n; i++) {
cp = de_sort_name (0);
cp = de_complex_sort (cp.res);
if (i) *(p++) = ',';
IGNORE strcpy (p, cp.name);
p = p + strlen (p);
cs.args [i] = cp.decode;
}
cs.args [n] = 0;
IGNORE strcpy (p, ")->");
p = p + strlen (p);
/* Copy token sort */
IGNORE strcpy (p, cr.name);
p = xmalloc_nof (char, (int) strlen (buff) + 1);
IGNORE strcpy (p, buff);
cs.name = p;
} else {
/* Non-token sorts are simple */
cs = find_sort (sn);
}
return (cs);
}
/*
* DECODE A SORTNAME
*
* A value representing a sort is read and returned. If expand is true
* then the parameters and result of any high-level sort are read but
* discarded.
*/
sortid
de_sort_name(int expand)
{
sortname sn = (sortname) de_sortname ();
if (sn == sort_token && expand) {
return (de_complex_sort (sn));
}
if (sn == sort_foreign) {
long i;
string nm;
#if string_ext
long n = tdf_de_tdfextint (tdfr, string_bits);
#else
long n = tdf_de_bits(tdfr, string_bits);
#endif
if (n != string_make_string) {
MSG_unknown_foreign_sort ();
}
nm = de_tdfstring ();
for (i = 0; i < no_foreign_sorts; i++) {
if (streq (nm, foreign_sorts [i].fname)) {
return (foreign_sorts [i]);
}
}
add_foreign_sort (nm, nm, 'F');
return (foreign_sorts [i]);
}
return (find_sort (sn));
}