/* * 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/enc_cap.c,v 1.9 2005/09/21 20:30:00 stefanf Exp $ */ #include "config.h" #include "tdf_types.h" #include "tdf_stream.h" #include "file.h" #include "types.h" #include "enc_cap.h" #include "encode.h" #include "names.h" #include "node.h" #include "table.h" #include "tdf.h" #include "utility.h" /* * CURRENT BITSTREAM * * This is the main bitstream. */ static struct tdf_stream *crt_bitstream; /* * NUMBERS OF EQUATIONS AND VARIABLE SORTS * * The number of equation types and variable sorts in the output capsule. */ static unsigned long eqn_total, var_total; /* * LINKAGE INFORMATION ENCODING VARIABLES * * The tld2 unit gives information on the use, declaration and * definition of the externally named tags and tokens. */ static struct tdf_stream *tld_bs; /* * ALIGNMENT TAG ENCODING VARIABLES * * The alignment tag definitions are formed in the bitstream al_tag_defs_bs. * There are al_tag_total alignment tags, of which al_tag_external have * external names and al_tag_defs are defined. */ static unsigned long al_tag_total = 0; static unsigned long al_tag_external = 0; static unsigned long al_tag_defs = 0; static struct tdf_stream *al_tag_defs_bs; /* * AUXILIARY ALIGNMENT TAG ENCODING ROUTINE * * The alignment tag encoding variables are modified according to the * construct p. */ static void enc_al_tag_aux(construct *p) { al_tag_info *info = get_al_tag_info (p); al_tag_total++; if (p->ename) { al_tag_external++; tdf_en_tdfintl (tld_bs, (unsigned long)(info->def ? 5 : 1)); } if (info->def == null) return; al_tag_defs++; enc_aldef (al_tag_defs_bs, p); return; } /* * AUXILIARY ROUTINE FOR ENCODING ALIGNMENT TAG NAMES * * The external name (if any) of the alignment tag construct p is encoded. */ static void enc_al_tag_names(construct *p) { if (p->ename == null) return; enc_external (crt_bitstream, p); return; } /* * TAG ENCODING VARIABLES * * The tag declarations are formed in the bitstream tag_decs_bs and * the definitions in tag_defs_bs. There are tag_total tags, of * which tag_external have external names, tag_decs have declarations * and tag_defs have definitions. */ static unsigned long tag_total = 0; static unsigned long tag_external = 0; static unsigned long tag_decs = 0; static unsigned long tag_defs = 0; static struct tdf_stream *tag_decs_bs; static struct tdf_stream *tag_defs_bs; /* * AUXILIARY TAG ENCODING ROUTINE * * The tag encoding variables are modified according to the construct p. */ static void enc_tag_aux(construct *p) { tag_info *info = get_tag_info (p); tag_total++; if (info->var == 3) return; if (p->ename) { tag_external++; tdf_en_tdfintl (tld_bs, (unsigned long)(info->def ? 7 : 3)); } tag_decs++; enc_tagdec (tag_decs_bs, p); if (info->def == null) return; tag_defs += enc_tagdef (tag_defs_bs, p); return; } /* * AUXILIARY ROUTINE FOR ENCODING TAG NAMES * * The external name (if any) of the tag construct p is encoded. */ static void enc_tag_names(construct *p) { tag_info *info = get_tag_info (p); if (info->var == 3) return; if (p->ename == null) return; enc_external (crt_bitstream, p); return; } /* * TOKEN ENCODING VARIABLES * * The token declarations are formed in the bitstream tok_decs_bs and * the definitions in tok_defs_bs. There are tok_total tokens, of * which tok_external have external names, tok_decs have declarations * and tok_defs have definitions. */ static unsigned long tok_total = 0; static unsigned long tok_external = 0; static unsigned long tok_decs = 0; static unsigned long tok_defs = 0; static struct tdf_stream *tok_decs_bs; static struct tdf_stream *tok_defs_bs; /* * AUXILIARY TOKEN ENCODING ROUTINE * * The token encoding variables are modified according to the construct p. */ static void enc_token_aux(construct *p) { tok_info *info = get_tok_info (p); if (p->encoding == -1) return; tok_total++; if (info->dec == 0) return; if (p->ename) { tok_external++; if (info->def) { tdf_en_tdfintl (tld_bs, 5); } else { tdf_en_tdfintl (tld_bs, 3); } } if (info->def == null || !show_tokdefs) { if (info->args) { tok_decs++; enc_tokdec (tok_decs_bs, p); } } else { tok_defs++; enc_tokdef (tok_defs_bs, p); } return; } /* * AUXILIARY ROUTINE FOR ENCODING TOKEN NAMES * * The external name (if any) of the token construct p is encoded. */ static void enc_token_names(construct *p) { tok_info *info = get_tok_info (p); if (p->encoding == -1) return; if (info->dec == 0) return; if (p->ename == null) return; enc_external (crt_bitstream, p); return; } /* * LABEL ENCODING VARIABLES * * There are lab_total labels. */ static unsigned long lab_total = 0; /* * AUXILIARY LABEL ENCODING ROUTINE * * The label encoding variables are modified according to the construct p. */ /*ARGSUSED*/ static void enc_label_aux(construct *p) { UNUSED (p); lab_total++; return; } /* * ENCODE A SET OF LINKS * * A set of ntok token link, nalign alignment tag links and ntag tag * nlinks are encoded into the bitstream p. Since the same numbers * are used for variable sorts in all the encoded units these links * are identities. */ static void enc_links(struct tdf_stream *p, unsigned long ntok, unsigned long nalign, unsigned long ntag) { unsigned long i; tdf_en_tdfintl (p, var_total); if (tok_total) tdf_en_tdfintl (p, ntok); if (al_tag_total) tdf_en_tdfintl (p, nalign); if (tag_total) tdf_en_tdfintl (p, ntag); tdf_en_tdfintl (p, var_total); /* Token links */ if (tok_total) { tdf_en_tdfintl (p, ntok); for (i = 0 ; i < ntok ; i++) { tdf_en_tdfintl (p, i); tdf_en_tdfintl (p, i); } } /* Alignment tag links */ if (al_tag_total) { tdf_en_tdfintl (p, nalign); for (i = 0 ; i < nalign ; i++) { tdf_en_tdfintl (p, i); tdf_en_tdfintl (p, i); } } /* Tag links */ if (tag_total) { tdf_en_tdfintl (p, ntag); for (i = 0 ; i < ntag ; i++) { tdf_en_tdfintl (p, i); tdf_en_tdfintl (p, i); } } return; } /* * EQUATION TYPES */ #define EQN_VERS 0 #define EQN_TLD 1 #define EQN_TOKDEC 2 #define EQN_TOKDEF 3 #define EQN_ALDEF 4 #define EQN_TAGDEC 5 #define EQN_TAGDEF 6 /* * ENCODE AN EQUATION * * The ne equations of type t (see above) given in the bitstream q are * encoded into the bitstream p. */ static void enc_equation(struct tdf_stream *p, unsigned long ne, struct tdf_stream *q, int t) { unsigned long n; struct tdf_stream *u; if (ne == 0) { /* There are no sets of equations */ tdf_en_tdfintl (p, 0); return; } /* There is one set of equations */ tdf_en_tdfintl (p, 1); u = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); /* Encode the links */ switch (t) { case EQN_VERS : { enc_links (p, (long) 0, (long) 0, (long) 0); tdf_en_tdfintl (u, ne); break; } case EQN_TLD : { tdf_en_tdfintl (p, 0); tdf_en_tdfintl (p, 0); break; } case EQN_TOKDEC : { enc_links (p, tok_total, (long) 0, (unsigned long) 0); tdf_en_tdfintl (u, ne); break; } default : { enc_links (p, tok_total, al_tag_total, tag_total); tdf_en_tdfintl (u, lab_total); tdf_en_tdfintl (u, ne); break; } } /* Append the body to the links */ (void)tdf_en_stream (u, q); tdf_en_align (u); /* Precede links and body by their length in bytes */ n = u->ts_pos; tdf_en_tdfintl (p, n / BYTESIZE); tdf_en_align (p); (void)tdf_en_stream (p, u); return; } /* * VERSION NUMBERS * * These variables give the major and minor version numbers. */ static char *magic_number = VERSION_capsule; static unsigned long version_major = VERSION_major; static unsigned long version_minor = VERSION_minor; /* * ENCODE A CAPSULE * * A complete capsule is encoded. */ void enc_capsule(void) { unsigned long n; struct tdf_stream *vers_bs; char *m = magic_number; struct tdf_stream *p = tdf_bs_create (output, TDFS_MODE_WRITE, NULL); /* Map to lowest applicable version number */ if (version_major == 4) { if (version_minor == 1) version_minor = 0; } /* Initialize the equation bitstreams */ tld_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); tok_decs_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); tok_defs_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); al_tag_defs_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); tag_decs_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); tag_defs_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); /* Analyse all the tags, tokens etc */ tdf_en_tdfintl (tld_bs, 1); apply_to_all (enc_label_aux, SORT_label); apply_to_all (enc_token_aux, SORT_token); apply_to_all (enc_al_tag_aux, SORT_al_tag); apply_to_all (enc_tag_aux, SORT_tag); /* Check on output options */ if (!show_tokdecs) tok_decs = 0; if (!show_tokdefs) tok_defs = 0; if (!show_aldefs) al_tag_defs = 0; if (!show_tagdecs) tag_decs = 0; if (!show_tagdefs) tag_defs = 0; /* Output equation types */ eqn_total = 2; if (tok_decs) eqn_total++; if (tok_defs) eqn_total++; if (al_tag_defs) eqn_total++; if (tag_decs) eqn_total++; if (tag_defs) eqn_total++; while (n = (unsigned char) *(m++), n != 0) { tdf_en_bits (p, 8, n); } tdf_en_tdfintl (p, version_major); tdf_en_tdfintl (p, version_minor); tdf_en_align (p); tdf_en_tdfintl (p, eqn_total); enc_aligned_string (p, LINK_tld_props, (long) -1); enc_aligned_string (p, LINK_version_props, (long) -1); if (tok_decs) { enc_aligned_string (p, LINK_tokdec_props, (long) -1); } if (tok_defs) { enc_aligned_string (p, LINK_tokdef_props, (long) -1); } if (al_tag_defs) { enc_aligned_string (p, LINK_al_tagdef_props, (long) -1); } if (tag_decs) { enc_aligned_string (p, LINK_tagdec_props, (long) -1); } if (tag_defs) { enc_aligned_string (p, LINK_tagdef_props, (long) -1); } /* Adjust totals for removed variables */ tok_total += sort_removed [ SORT_token ]; tag_total += sort_removed [ SORT_tag ]; al_tag_total += sort_removed [ SORT_al_tag ]; lab_total += sort_removed [ SORT_label ]; /* Output variable sorts */ var_total = 0; if (tok_total) var_total++; if (al_tag_total) var_total++; if (tag_total) var_total++; tdf_en_tdfintl (p, var_total); if (tok_total) { enc_aligned_string (p, LINK_token, (long) -1); tdf_en_tdfintl (p, tok_total); } if (al_tag_total) { enc_aligned_string (p, LINK_al_tag, (long) -1); tdf_en_tdfintl (p, al_tag_total); } if (tag_total) { enc_aligned_string (p, LINK_tag, (long) -1); tdf_en_tdfintl (p, tag_total); } /* Output external names */ tdf_en_tdfintl (p, var_total); crt_bitstream = p; if (tok_total) { tdf_en_tdfintl (p, tok_external); apply_to_all (enc_token_names, SORT_token); } if (al_tag_total) { tdf_en_tdfintl (p, al_tag_external); apply_to_all (enc_al_tag_names, SORT_al_tag); } if (tag_total) { tdf_en_tdfintl (p, tag_external); apply_to_all (enc_tag_names, SORT_tag); } /* Output equations */ tdf_en_tdfintl (p, eqn_total); enc_equation (p, (long) 1, tld_bs, EQN_TLD); vers_bs = tdf_bs_create (NULL, TDFS_MODE_WRITE, NULL); enc_version_bits (vers_bs, ENC_make_version); tdf_en_tdfintl (vers_bs, version_major); tdf_en_tdfintl (vers_bs, version_minor); enc_equation (p, (long) 1, vers_bs, EQN_VERS); if (tok_decs) enc_equation (p, tok_decs, tok_decs_bs, EQN_TOKDEC); if (tok_defs) enc_equation (p, tok_defs, tok_defs_bs, EQN_TOKDEF); if (al_tag_defs) { enc_equation (p, al_tag_defs, al_tag_defs_bs, EQN_ALDEF); } if (tag_decs) enc_equation (p, tag_decs, tag_decs_bs, EQN_TAGDEC); if (tag_defs) enc_equation (p, tag_defs, tag_defs_bs, EQN_TAGDEF); tdf_stream_destroy (p); return; }