/* * 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/write.c,v 1.9 2005/09/21 21:18:35 stefanf Exp $ */ #include "config.h" #include #include "types.h" #include "file.h" #include "high.h" #include "names.h" #include "node.h" #include "shape.h" #include "table.h" #include "tdf.h" #include "utility.h" #include "write.h" /* * FLAGS CONTROLLING OUTPUT OF TOKENS ETC * * The output is in the fully expanded form if verbose is true. The * shape of each expression is printed if print_shapes is true. The * flag func_output controls whether the output should be lisp-like * (default) or c-like. */ BoolT verbose = 0; boolean print_shapes = 0; BoolT func_output = 0; /* * PRINT A NUMBER OF SPACES * * An indentation of d spaces is printed to the output file. */ static void print_spaces(int d) { int n = 2 * d; while (n >= 8) { IGNORE fputc ('\t', output); n -= 8; } while (n) { IGNORE fputc (' ', output); n--; } return; } /* * PRINT A NODE * * The node p is printed to the output file with an indentation of * d spaces. */ static boolean print_node(node *p, int d) { boolean negate = 0; boolean newline = 0; while (p) { construct *q = p->cons; sortname s = q->sortnum; long m = q->encoding; newline = 0; switch (s) { case SORT_tdfbool : { /* Set neg for subsequent number */ negate = (boolean) (m ? 1 : 0); break; } case SORT_bytestream : { /* Print a bytestream */ newline = print_node (p->son, d); break; } case SORT_completion : { /* Print a completion */ newline = print_node (p->son, d); break; } case SORT_small_tdfint : { /* Print a small number */ long n = q->encoding; print_spaces (d); if (negate) n = -n; IGNORE fprintf (output, "%ld", n); negate = 0; newline = 1; break; } case SORT_tdfint : { /* Print a number */ char *num = q->name; print_spaces (d); if (fits_ulong (num, 0)) { unsigned long n = octal_to_ulong (num); if (negate && n) IGNORE fputc ('-', output); IGNORE fprintf (output, "%lu", n); } else { if (negate) IGNORE fputc ('-', output); IGNORE fprintf (output, "0%s", num); } negate = 0; newline = 1; break; } case SORT_option : { /* Print an optional argument */ if (p->son) { newline = print_node (p->son, d); } else { print_spaces (d); IGNORE fputc ('-', output); newline = 1; } break; } case SORT_repeat : { /* Print a repeated argument */ if (m == 0) { print_spaces (d); IGNORE fputc ('|', output); newline = 1; } else { newline = print_node (p->son, d); if (func_output) IGNORE fputc (',', output); IGNORE fputs (" |", output); } break; } case SORT_tdfstring : { /* Print a string */ int i, n = (int) m; print_spaces (d); if (n == -1) { char *f = (func_output ? "%s (\n" : "(%s\n"); IGNORE fprintf (output, f, MAKE_STRING); newline = print_node (p->son, d + 1); IGNORE fputs (")", output); } else { IGNORE fputc ('"', output); for (i = 0 ; i < n ; i++) { int c = ((q->name [i]) & 0xff); if (isprint (c)) { if (c == '\\' || c == '"') { IGNORE fputc ('\\', output); } IGNORE fputc (c, output); } else { if (c == '\n') { IGNORE fputs ("\\n", output); } else if (c == '\t') { IGNORE fputs ("\\t", output); } else { unsigned co = (unsigned) c; IGNORE fprintf (output, "\\%03o", co); } } } IGNORE fputc ('"', output); newline = 1; } break; } case SORT_nat : { /* Print a nat */ if (m != ENC_make_nat) goto default_label; newline = print_node (p->son, d); break; } case SORT_signed_nat : { /* Print a signed_nat */ if (m != ENC_make_signed_nat) goto default_label; newline = print_node (p->son, d); break; } case SORT_string : { /* Print a string */ if (m != ENC_make_string) goto default_label; newline = print_node (p->son, d); break; } case SORT_al_tag : { /* Print an alignment tag */ if (verbose || m != ENC_make_al_tag || p->son == null) { goto default_label; } newline = print_node (p->son, d); break; } case SORT_label : { /* Print a label */ if (verbose || m != ENC_make_label || p->son == null) { goto default_label; } newline = print_node (p->son, d); break; } case SORT_tag : { /* Print a tag */ if (verbose || m != ENC_make_tag || p->son == null) { goto default_label; } newline = print_node (p->son, d); break; } case SORT_exp : { static node special_node; if (print_shapes && p->shape != &special_node) { /* Change exp to show shape */ node *z = new_node (); z->cons = &exp_shape; z->bro = p->bro; z->son = p; if (p->shape) { z->son->bro = copy_node (p->shape); } else { z->son->bro = new_node (); z->son->bro->cons = &unknown_cons; } p->shape = &special_node; p = z; q = p->cons; m = q->encoding; } goto default_label; } default : { /* Print a simple sort */ default_label : { if (!verbose && m == sort_tokens [s] && p->son && p->son->cons->sortnum == SORT_token) { newline = print_node (p->son, d); } else { print_spaces (d); if (p->son) { char *f = (func_output ? "%s (\n" : "(%s\n"); IGNORE fprintf (output, f, q->name); newline = print_node (p->son, d + 1); IGNORE fputs (")", output); } else { IGNORE fprintf (output, "%s", q->name); newline = 1; } } } break; } } p = p->bro; if (newline && p) { if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); newline = 0; } } return (newline); } /* * PRINT AN EXTERNAL NAME * * The start of a statement with name title concerning the construct * p is output. dec is true if this is the first statement concerning p. */ static void print_name(char *title, construct *p, int dec) { if (!func_output) IGNORE fputs ("(", output); if (p->ename == null) IGNORE fprintf (output, "%s ", LOCAL_DECL); IGNORE fprintf (output, "%s", title); if (func_output) IGNORE fputs (" (", output); if (p->ename && p->ename->cons->encoding && dec) { char *f = (func_output ? "\n %s (\n" : "\n (%s\n"); if (p->ename->son->cons->sortnum == SORT_tdfstring) { if (p->ename->son->bro == null) { IGNORE fprintf (output, f, MAKE_STRING_EXTERN); } else { IGNORE fprintf (output, f, MAKE_CHAIN_EXTERN); } } else { IGNORE fprintf (output, f, MAKE_UNIQUE_EXTERN); } IGNORE print_node (p->ename->son, 2); if (func_output) { IGNORE fputs ("),\n ", output); } else { IGNORE fputs (")\n ", output); } } else { IGNORE fputc (' ', output); } IGNORE fprintf (output, "%s", p->name); return; } /* * ALIGNMENT TAG DECLARATION AUXILIARY PRINTING ROUTINE * * Print the declaration of the alignment tag p. */ static void print_aldec(construct *p) { if (p->encoding == -1) return; print_name (MAKE_ALDEC, p, 1); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * ALIGNMENT TAG DEFINITION AUXILIARY PRINTING ROUTINE * * Print the definition of the alignment tag p. */ static void print_aldef(construct *p) { al_tag_info *info = get_al_tag_info (p); if (p->encoding == -1) return; if (info->def == null) return; print_name (MAKE_ALDEF, p, !show_aldecs); if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); IGNORE print_node (info->def, 1); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * TAG DECLARATION AUXILIARY PRINTING ROUTINE * * Print the declaration of the tag p. */ static void print_tagdec(construct *p) { tag_info *info = get_tag_info (p); if (p->encoding == -1 || info->dec == null) return; switch (info->var) { case 0 : print_name (MAKE_ID_TAGDEC, p, 1) ; break; case 1 : print_name (MAKE_VAR_TAGDEC, p, 1) ; break; case 2 : print_name (COMMON_TAGDEC, p, 1) ; break; } if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); IGNORE print_node (info->dec, 1); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * TAG DEFINITION AUXILIARY PRINTING ROUTINE * * Print the definition of the tag p. */ static void print_tagdef(construct *p) { char *instr; tag_info *info = get_tag_info (p); node *d = info->def; if (p->encoding == -1 || d == null) return; switch (info->var) EXHAUSTIVE { case 0 : instr = MAKE_ID_TAGDEF ; break; case 1 : instr = MAKE_VAR_TAGDEF ; break; case 2 : instr = COMMON_TAGDEF ; break; default: instr = "UNKNOWN TAGDEF"; } while (d) { /* Can have multiple definitions */ print_name (instr, p, !show_tagdecs); if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); IGNORE print_node (d->son, 1); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); d = d->bro; } return; } /* * TOKEN DECLARATION AUXILIARY PRINTING ROUTINE * * Print the declaration of the token p. */ static void print_tokdec(construct *p) { tok_info *info = get_tok_info (p); if (p->encoding == -1) return; if (!info->dec) return; print_name (MAKE_TOKDEC, p, 1); if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); if (info->sig) { IGNORE print_node (info->sig, 1); } else { print_spaces (1); IGNORE fputc ('-', output); } if (func_output) IGNORE fputc (',', output); IGNORE fputs ("\n ", output); if (info->args) { int n = 0; char *q = info->args; IGNORE fputs ("(", output); while (*q) { sortname s; q = find_sortname (q, &s); q++; if (n++ == 8) { IGNORE fputs ("\n ", output); n = 1; } IGNORE fputs (sort_name (s), output); if (func_output && *q) IGNORE fputc (',', output); IGNORE fputc (' ', output); } IGNORE fputs (") ", output); if (func_output) IGNORE fputs ("-> ", output); } IGNORE fputs (sort_name (info->res), output); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * TOKEN DEFINITION AUXILIARY PRINTING ROUTINE * * Print the definition of the token p. */ static void print_tokdef(construct *p) { tok_info *info = get_tok_info (p); if (p->encoding == -1) return; if (!info->dec) return; if (info->def == null) return; print_name (MAKE_TOKDEF, p, !show_tagdefs); if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); if (info->sig) { IGNORE print_node (info->sig, 1); } else { print_spaces (1); IGNORE fputc ('-', output); } if (func_output) IGNORE fputc (',', output); IGNORE fputs ("\n ", output); if (info->args) { int n = 0; construct **q = info->pars; IGNORE fputs ("(", output); while (*q) { tok_info *qinfo = get_tok_info (*q); if (n++ == 4) { IGNORE fputs ("\n ", output); n = 1; } IGNORE fprintf (output, "%s %s", sort_name (qinfo->res), (*q)->name); q++; if (func_output && *q) IGNORE fputc (',', output); IGNORE fputc (' ', output); } IGNORE fputs (") ", output); if (func_output) IGNORE fputs ("-> ", output); } IGNORE fputs (sort_name (info->res), output); if (func_output) IGNORE fputc (',', output); IGNORE fputc ('\n', output); IGNORE print_node (info->def, 1); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * PRINT A HIGH-LEVEL SORT * * This routine prints the high level sort h. */ static void print_high_sort(high_sort *h) { int i, n; if (h->id == SORT_unknown) return; if (func_output) { IGNORE fprintf (output, "%s (%s, ", MAKE_SORT, h->name); } else { IGNORE fprintf (output, "(%s %s ", MAKE_SORT, h->name); } n = h->no_args; if (n) { int m = 0; IGNORE fputs ("(", output); for (i = 0 ; i < n ; i++) { if (m++ == 8) { IGNORE fputs ("\n ", output); m = 1; } IGNORE fputs (sort_name (h->args [i]), output); if (func_output && i < n - 1) IGNORE fputc (',', output); IGNORE fputc (' ', output); } IGNORE fputs (") ", output); if (func_output) IGNORE fputs ("-> ", output); } IGNORE fputs (sort_name (h->res), output); IGNORE fputs ((func_output ? ") ;\n\n" : ")\n\n"), output); return; } /* * MAIN PRINTING ROUTINE * * This routine prints an entire capsule to the output file. */ void print_capsule(void) { if (high_sorts) { int i; IGNORE fputs ("# HIGH-LEVEL SORTS\n\n", output); for (i = 0 ; i < crt_high_sort ; i++) { print_high_sort (high_sorts + i); } IGNORE fputc ('\n', output); } if (show_tokdecs) { IGNORE fputs ("# TOKEN DECLARATIONS\n\n", output); apply_to_all (print_tokdec, SORT_token); IGNORE fputc ('\n', output); } if (show_aldecs) { IGNORE fputs ("# ALIGNMENT TAG DECLARATIONS\n\n", output); apply_to_all (print_aldec, SORT_al_tag); IGNORE fputc ('\n', output); } if (show_tagdecs) { IGNORE fputs ("# TAG DECLARATIONS\n\n", output); apply_to_all (print_tagdec, SORT_tag); IGNORE fputc ('\n', output); } if (show_tokdefs) { IGNORE fputs ("# TOKEN DEFINITIONS\n\n", output); apply_to_all (print_tokdef, SORT_token); IGNORE fputc ('\n', output); } if (show_aldefs) { IGNORE fputs ("# ALIGNMENT TAG DEFINITIONS\n\n", output); apply_to_all (print_aldef, SORT_al_tag); IGNORE fputc ('\n', output); } if (show_tagdefs) { IGNORE fputs ("# TAG DEFINITIONS\n\n", output); apply_to_all (print_tagdef, SORT_tag); IGNORE fputc ('\n', output); } return; }