/* * 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/sort.c,v 1.11 2005/11/05 12:03:15 stefanf Exp $ */ #include "config.h" #include "fmm.h" #include "msgcat.h" #include "tdf_types.h" #include "tdf_stream.h" #include "types.h" #include "ascii.h" #include "basic.h" #include "binding.h" #include "capsule.h" #include "file.h" #include "sort.h" #include "tree.h" #include "tdf.h" #include "unit.h" /* * WARN ABOUT UNDECLARED TOKENS */ BoolT warn_undeclared = FALSE; /* * DECODING TOKENS * * Simple TOKENs are represented by TDF integers. They may also be * tokenised themselves. */ object * de_token_aux(sortname s, char *nm) { word *w; long bits, t; object *obj = null; int ap = 1, simple = 1; int just_tok = (s == sort_unknown ? 1 : 0); /* Find the token number */ long n = de_token (); if (n == token_make_tok) { t = tdf_int (); } else { simple = 0; } /* Look up simple tokens */ if (simple) { SET (t); obj = find_binding (crt_binding, var_token, t); if (obj == null) { obj = new_object (var_token); set_binding (crt_binding, var_token, t, obj); } /* Check token sort */ if (res_sort (obj) == sort_unknown) { sortname is = implicit_sort (obj); if (is == sort_unknown && warn_undeclared) { MSG_token_used_before_it_is_declared ( object_name (var_token, t)); } if (is != sort_unknown && is != s) { sortid es; out (""); es = find_sort (s); MSG_implicit_sort_error ( object_name (var_token, t), es.name); } implicit_sort (obj) = s; } else if (res_sort (obj) != s && !just_tok) { sortid es; out (""); es = find_sort (s); MSG_sort_error (object_name (var_token, t), es.name); } /* Output token name if appropriate */ if (!dumb_mode) { if (obj->named) { if (obj->name.simple) { out_string (obj->name.val.str); ap = 0; } } else { char buff [50]; IGNORE sprintf (buff, "~token_%ld", obj->id); out_string (buff); ap = 0; } } } /* Output "apply_token" if appropriate */ if (ap) { if (just_tok) { out_string ("make_token"); } else { out_string ("apply_"); out_string (nm); out_string ("_token"); } w = new_word (VERT_BRACKETS); if (simple) { SET (t); out_object (t, obj, var_token); } else { if (n == token_token_apply_token) { object *subobj = de_token_aux (sort_token, "token"); if (subobj) obj = subobj->aux; } else { /* use_tokdef */ long len = tdf_int (); tdf_skip_bits (tdfr, len); out_string ("use_tokdef(....)"); IGNORE new_word (SIMPLE); } } } else { /* Applications of named tokens are indicated by "*" */ out_string ("*"); } /* Quit here if just reading token */ if (just_tok) { if (ap) { SET (w); end_word (w); } else { IGNORE new_word (SIMPLE); } return (obj); } /* Read length of token arguments */ bits = tdf_int (); /* Deal with tokens without arguments */ if (bits == 0) { if (obj && res_sort (obj) != sort_unknown) { char *ps = arg_sorts (obj); if (ps && *ps) { if (simple) { SET (t); MSG_token_arguments_missing_token ( object_name (var_token, t)); } else { MSG_token_arguments_missing (); } } } if (ap) { SET (w); end_word (w); } else { IGNORE new_word (SIMPLE); } return (obj); } /* Deal with tokens with arguments */ if (obj && res_sort (obj) != sort_unknown && !is_foreign (obj)) { /* Known token - decode arguments */ if (arg_sorts (obj)) { tdf_pos pos; pos = tdf_stream_tell (tdfr); if (!ap) w = new_word (VERT_BRACKETS); decode (arg_sorts (obj)); if (tdf_stream_tell(tdfr) != pos + bits) { if (simple) { SET (t); MSG_token_arguments_length_wrong_token ( object_name (var_token, t)); } else { MSG_token_arguments_length_wrong (); } } } else { if (ap) { SET (w); end_word (w); } else { IGNORE new_word (SIMPLE); } return (obj); } } else { /* Unknown token - step over arguments */ if (!ap) w = new_word (VERT_BRACKETS); out ("...."); tdf_skip_bits (tdfr, bits); } SET (w); end_word (w); return (obj); } /* * DECODING SIMPLE LABELS */ void de_make_label(long lab_no) { if (dumb_mode) { word *w; out_string ("label"); w = new_word (HORIZ_BRACKETS); out_int (lab_no); end_word (w); } else { out_string ("~label_"); out_int (lab_no); } if (lab_no < 0 || lab_no >= max_lab_no) { MSG_label_number_out_of_range (lab_no); } return; } /* * FORMATTING SIZE FOR TDF STRINGS * * A string will be split by de_format_string into sections of length * at most STRING_WIDTH. */ #define STRING_WIDTH 40 /* * DECODING FORMATTED STRINGS * * A TDF string is read and output in a formatted form. */ void de_tdfstring_format(void) { TDFSTRING ts; word *ptr1; size_t n; char *s; tdf_de_tdfstring(tdfr, &ts); if (ts.size != 8) { char sbuff [100]; IGNORE sprintf (sbuff, "make_string_%ld", (long)ts.size); out_string (sbuff); ptr1 = new_word (HORIZ_BRACKETS); } if (ts.size > 8) { TDFINTL i; for (i = 0; i < ts.number; i++) out_int (ts.ints.longs[i]); } else { s = tdf_string_format (&ts); n = strlen (s); if (n == 0) { out ("\"\""); return; } while (n) { size_t m = (n < STRING_WIDTH ? n : STRING_WIDTH); char *w = xmalloc_nof (char, m + 3); IGNORE memcpy (w + 1, s, (size_t) m); w [0] = QUOTE; w [m + 1] = QUOTE; w [m + 2] = 0; out (w); n -= m; s += m; } } if (ts.size != 8) { SET (ptr1); end_word (ptr1); } if (ts.number) xfree (ts.ints.chars); return; } /* * DECODING THE EXP "solve" (OR "labelled") * * This is tricky because it is encoded as : * * A1, ..., An, B, C1, ..., Cn * * where n is a TDF integer, Ai is given by the decode string str1, * B is given by str2, and Ci is given by str3, but we want to print * it in the order : * * B, A1, C1, ..., An, Cn * * so there is a certain amount of to-ing and fro-ing. */ void de_solve_fn(char *nm, char *str1, char *str2, char *str3, int ntwice) { long i, n; word *ptr1, *ptr2; tdf_pos posn1, posn2; int tempflag = printflag; out_string (nm); ptr1 = new_word (VERT_BRACKETS); /* Read the number of statements A1, ..., An */ check_list (); n = tdf_int (); /* Record the position of A1 */ posn1 = tdf_stream_tell (tdfr); /* Step over A1, ..., An */ printflag = 0; for (i = 0; i < n; i++) decode (str1); printflag = tempflag; /* Decode B */ decode (str2); if (ntwice) { /* Read and check the number of statements C1, ..., Cn */ long m; check_list (); m = tdf_int (); if (m != n) MSG_illegal_construct (nm); } for (i = 0; i < n; i++) { ptr2 = new_word (VERT_BRACKETS); /* Record the position of Ci */ posn2 = tdf_stream_tell (tdfr); /* Go back and read Ai */ tdf_stream_seek(tdfr, posn1); decode (str1); /* Record the position of A(i+1) */ posn1 = tdf_stream_tell (tdfr); /* Go forward and read Ci */ tdf_stream_seek(tdfr, posn2); decode (str3); end_word (ptr2); } end_word (ptr1); return; } /* * DECODING THE EXP "case" * * Only the layout makes this a special case. The general form is : * * A, L1, B1, ..., Ln, Bn * * where A is given by the decode string str1, Li is a label and Bi * is given by str2. */ void de_case_fn(char *nm, char *str1, char *str2) { long i, n; word *ptr1, *ptr2, *ptr3; out_string (nm); ptr1 = new_word (VERT_BRACKETS); decode (str1); ptr2 = new_word (VERT_BRACKETS); check_list (); n = tdf_int (); for (i = 0; i < n; i++) { ptr3 = new_word (HORIZ_NONE); IGNORE de_label (); out (":"); format (HORIZ_BRACKETS, "", str2); end_word (ptr3); } end_word (ptr2); end_word (ptr1); return; } /* * DECODING THE EXP "make_proc" * * The general form is : * * A, B1, ..., Bn, C * * where A is given by the decode string str1, B by str2 and C by str3. * However each Bi is grouped as a "make_proc_arg". */ void de_mk_proc_fn(char *nm, char *str1, char *str2, char *str3) { long i, n; word *ptr; out_string (nm); ptr = new_word (VERT_BRACKETS); decode (str1); check_list (); n = tdf_int (); if (n == 0) { out ("empty"); } else { for (i = 0; i < n; i++) { out_string (nm); format (VERT_BRACKETS, "_arg", str2); } } decode (str3); end_word (ptr); return; }