/* * 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/tld/main.c,v 1.20 2005/10/18 16:06:53 stefanf Exp $ */ /*** main.c --- tld program main routine. * ** Author: Steve Folkes * *** Commentary: * * This file contains the main routine for the TDF linker. It performs * argument parsing, and then calls one of "builder_main", "contents_main", * "extract_main" or "linker_main" to do the actual work. See the files in * the "frontends" directory for more details. * *** Change Log:*/ /****************************************************************************/ #include "config.h" #include "argparse.h" #include "release.h" #include "arg-data.h" #include "builder.h" #include "contents.h" #include "debug.h" #include "exception.h" #include "extract.h" #include "istream.h" #include "msgcat.h" #include "catstdn.h" #include "linker.h" #include "rename-file.h" #include "tenapp.h" #include "solve-cycles.h" /*--------------------------------------------------------------------------*/ typedef enum { MODE_BUILDER, MODE_CONTENTS, MODE_EXTRACT, MODE_LINKER } ModeT; /*--------------------------------------------------------------------------*/ static BoolT main_used_one_off = FALSE; static BoolT main_used_other = FALSE; static ArgDataT main_arg_data; static ModeT mode = MODE_LINKER; /*--------------------------------------------------------------------------*/ static void main_handle_all(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_extract_all (&main_arg_data, enable); } static void main_handle_all_hide_defd(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_all_hide_defd (&main_arg_data, enable); } static void main_handle_basename(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_extract_basename (&main_arg_data, enable); } static void main_handle_debug_file(char *option, void *gclosure, char *debug_file) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_debug_file (&main_arg_data, debug_file); } static void main_handle_hide(char *option, void *gclosure, char *shape, char *name) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_hide (&main_arg_data, shape, name); } static void main_handle_hide_defined(char *option, void *gclosure, char *shape) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_hide_defined (&main_arg_data, shape); } static void main_handle_index(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_content_index (&main_arg_data, enable); } static void main_handle_info(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; msg_sev_set(MSG_SEV_INFO, enable); } static void main_handle_keep(char *option, void *gclosure, char *shape, char *name) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_keep (&main_arg_data, shape, name); } static void main_handle_keep_all(char *option, void *gclosure, char *shape) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_keep_all (&main_arg_data, shape); } static void main_handle_library_file(char *option, void *gclosure, char *library_file) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_library_file (&main_arg_data, library_file); } static void main_handle_match_base(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_extract_match_base (&main_arg_data, enable); } static void main_handle_output_file(char *option, void *gclosure, char *output_file) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_output_file (&main_arg_data, output_file); } static void main_handle_library_path(char *option, void *gclosure, char *directory) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_library_path (&main_arg_data, directory); } static void main_handle_rename(char *option, void *gclosure, char *shape, char *from, char *to) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_parse_rename (&main_arg_data, shape, from, to); } static void main_handle_rename_file(char *option, void *gclosure, char *name) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; rename_file_parse (name, &main_arg_data); } static void main_handle_size(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_content_size (&main_arg_data, enable); } static void main_handle_suppress(char *option, void *gclosure, char *shape, char *name) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_suppress (&main_arg_data, shape, name); } static void main_handle_suppress_all(char *option, void *gclosure, char *shape) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_add_suppress_all (&main_arg_data, shape); } static void main_handle_suppress_mult(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_suppress_mult (&main_arg_data, enable); } static void main_handle_tdf_version(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_content_version (&main_arg_data, enable); } static void main_handle_unit_file(char *option, void *gclosure, char *unit_file) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; arg_data_set_unit_file (&main_arg_data, unit_file); } static void main_handle_version(char *option, void *gclosure) { UNUSED (option); UNUSED (gclosure); main_used_one_off = TRUE; tenapp_report_version(); } static void main_handle_warning(char *option, void *gclosure, BoolT enable) { UNUSED (option); UNUSED (gclosure); main_used_other = TRUE; msg_sev_set(MSG_SEV_WARNING, enable); } static void main_handle_mode(char *option, void *closure, char *arg) { UNUSED(closure); if (arg[1]) MSG_bad_mode (option); switch (arg[0]) { case 'c': mode = MODE_BUILDER; break; case 't': mode = MODE_CONTENTS; break; case 'x': mode = MODE_EXTRACT; break; case 'l': break; default: MSG_bad_mode (option); UNREACHED; } } static void main_handle_root_help (char *, void *); static void main_handle_builder_help (char *, void *); static void main_handle_contents_help (char *, void *); static void main_handle_extract_help (char *, void *); static void main_handle_linker_help (char *, void *); /*--------------------------------------------------------------------------*/ /* * Top level options */ static ArgListT main_opts[] = { AP_OPT_EMPTY (help, 'h', NULL, main_handle_root_help), AP_OPT_IMMEDIATE(mode, 'm', NULL, main_handle_mode), AP_OPT_EMPTY (version, 'V', NULL, main_handle_version), AP_OPT_EOL }; static ArgListT main_builder_arg_list[] = { AP_OPT_FOLLOWING(debug_file, 'd', "debug-file", main_handle_debug_file), AP_OPT_EMPTY (help, 'h', "help", main_handle_builder_help), AP_OPT_FOLLOWING(include_library,'i',"include-library", main_handle_library_file), AP_OPT_FOLLOWING(output_file, 'o', "output-file",main_handle_output_file), AP_OPT_FOLLOWING2(suppress, 's', "suppress", main_handle_suppress), AP_OPT_FOLLOWING(suppress_all, 'S', "suppress-all", main_handle_suppress_all), AP_OPT_PROC_SW (suppress_mult, 'M', "suppress-mult", main_handle_suppress_mult), AP_OPT_FOLLOWING(unit_file, 'u', "unit-file", main_handle_unit_file), AP_OPT_EMPTY (version, 'V', "version", main_handle_version), AP_OPT_EOL }; static ArgListT main_contents_arg_list[] = { AP_OPT_FOLLOWING(debug_file, 'd', "debug-file", main_handle_debug_file), AP_OPT_EMPTY (help, 'h', "help", main_handle_contents_help), AP_OPT_PROC_SW (index, 'i', "index", main_handle_index), AP_OPT_PROC_SW (size, 's', "size", main_handle_size), AP_OPT_PROC_SW (tdf_version, 't', "tdf-version", main_handle_tdf_version), AP_OPT_EMPTY (version, 'V', "version", main_handle_version), AP_OPT_EOL }; static ArgListT main_extract_arg_list[] = { AP_OPT_PROC_SW (all, 'a', "all", main_handle_all), AP_OPT_PROC_SW (basename, 'b', "basename", main_handle_basename), AP_OPT_FOLLOWING(debug_file, 'd', "debug-file", main_handle_debug_file), AP_OPT_EMPTY (help, 'h', "help", main_handle_extract_help), AP_OPT_PROC_SW (info, 'i', "info", main_handle_info), AP_OPT_PROC_SW (match_basename,'m', "match-basename", main_handle_match_base), AP_OPT_EMPTY (version, 'V', "version", main_handle_version), AP_OPT_EOL }; static ArgListT main_linker_arg_list[] = { AP_OPT_PROC_SW (all_hide_defined,'a', "all-hide-defined", main_handle_all_hide_defd), AP_OPT_FOLLOWING(debug_file, 'd', "debug-file", main_handle_debug_file), AP_OPT_EMPTY (help, '\0', "help", main_handle_linker_help), AP_OPT_FOLLOWING2(hide, 'h', "hide", main_handle_hide), AP_OPT_FOLLOWING(hide_defined, 'H', "hide-defined", main_handle_hide_defined), AP_OPT_FOLLOWING2(keep, 'k', "keep", main_handle_keep), AP_OPT_FOLLOWING(keep_all, 'K', "keep-all", main_handle_keep_all), AP_OPT_EITHER (library_file, 'l', "library", main_handle_library_file), AP_OPT_FOLLOWING(output_file, 'o', "output-file", main_handle_output_file), AP_OPT_EITHER (path, 'L', "path", main_handle_library_path), AP_OPT_FOLLOWING3(rename, 'r', "rename", main_handle_rename), AP_OPT_FOLLOWING(rename_file, 'R', "rename-file", main_handle_rename_file), AP_OPT_FOLLOWING2(suppress, 's', "suppress", main_handle_suppress), AP_OPT_FOLLOWING(suppress_all, 'S', "suppress-all", main_handle_suppress_all), AP_OPT_PROC_SW (suppress_mult, 'M', "suppress-mult", main_handle_suppress_mult), AP_OPT_FOLLOWING(unit_file, 'u', "unit-file", main_handle_unit_file), AP_OPT_EMPTY (version, 'V', "version", main_handle_version), AP_OPT_PROC_SW (warning, 'w', "warnings", main_handle_warning), AP_OPT_EOL }; static void main_handle_root_help(char *option, void *closure) { UNUSED(option); UNUSED(closure); MSG_root_usage (); arg_print_usage (main_opts); msg_append_newline (); } static void main_handle_builder_help(char *option, void *closure) { UNUSED(option); UNUSED(closure); MSG_builder_usage (); arg_print_usage (main_builder_arg_list); msg_append_newline (); } static void main_handle_contents_help(char *option, void *closure) { UNUSED(option); UNUSED(closure); MSG_contents_usage (); arg_print_usage (main_contents_arg_list); msg_append_newline (); } static void main_handle_extract_help(char *option, void *closure) { UNUSED(option); UNUSED(closure); MSG_extract_usage (); arg_print_usage (main_extract_arg_list); msg_append_newline (); } static void main_handle_linker_help(char *option, void *closure) { UNUSED(option); UNUSED(closure); MSG_linker_usage (); arg_print_usage (main_linker_arg_list); msg_append_newline (); } /*--------------------------------------------------------------------------*/ /* * Handlers for tld specific message objects */ static void msg_uh_NStringP(char ch, void *pp) { NStringP nstring = (NStringP)pp; UNUSED(ch); msg_append_nstring(nstring->ns_contents, nstring_length(nstring)); } static void msg_uh_NameKeyP(char ch, void *pp) { UNUSED(ch); write_name_key(msg_stream, (NameKeyP)pp); } static void msg_uh_capsule_offset(char ch, void *pp) { CapsuleP capsule = pp; UNUSED(ch); write_fmt(msg_stream, "%s: %lu: ", capsule_name(capsule), (unsigned long)capsule_byte(capsule)); } static void msg_uh_library_offset(char ch, void *pp) { LibraryP lib = pp; UNUSED(ch); write_fmt(msg_stream, "%s: %lu: ", library_name(lib), (unsigned long)library_byte(lib)); } static void msg_uh_istream_line(char ch, void *pp) { IStreamP is = pp; UNUSED(ch); write_fmt(msg_stream, "%s: %lu: ", istream_name(is), (unsigned long)istream_line(is)); } static void msg_uh_tdfr_offset(char ch, void *pp) { TDFReaderP tdfr = pp; UNUSED(ch); write_fmt(msg_stream, "%s: %lu: ", tdf_reader_name(tdfr), (unsigned long)tdf_reader_byte(tdfr)); } static void msg_uh_ExceptionName(char ch, void *pp) { UNUSED(ch); msg_append_string(exception_name((ExceptionP)pp)); } static void msg_uh_libcapfullname(char ch, void *pp) { UNUSED(ch); write_lib_capsule_full_name(msg_stream, (LibCapsuleP)pp); } static ModeT main_init(int argc, char **argv) { ArgListT *arg_list; int skip; msg_uh_add(MSG_KEY_NStringP, msg_uh_NStringP); msg_uh_add(MSG_KEY_NameKeyP, msg_uh_NameKeyP); msg_uh_add(MSG_KEY_capsule_offset, msg_uh_capsule_offset); msg_uh_add(MSG_KEY_library_offset, msg_uh_library_offset); msg_uh_add(MSG_KEY_istream_line, msg_uh_istream_line); msg_uh_add(MSG_KEY_tdfr_offset, msg_uh_tdfr_offset); msg_uh_add(MSG_KEY_ExceptionName, msg_uh_ExceptionName); msg_uh_add(MSG_KEY_libcapfullname, msg_uh_libcapfullname); argc--; argv++; if (argc <= 0) { main_handle_root_help (NULL, NULL); return (EXIT_FAILURE); } if (argv[0][0] == '-') { switch (argv[0][1]) { case 'h': case 'm': case 'V': skip = arg_parse_arguments (main_opts, 1, argv); argc -= skip; argv += skip; break; } } switch (mode) { case MODE_BUILDER: arg_list = main_builder_arg_list; arg_data_init (&main_arg_data, "library.tl"); break; case MODE_CONTENTS: arg_list = main_contents_arg_list; arg_data_init (&main_arg_data, NULL); break; case MODE_EXTRACT: arg_list = main_extract_arg_list; arg_data_init (&main_arg_data, NULL); break; case MODE_LINKER: arg_list = main_linker_arg_list; arg_data_init (&main_arg_data, "capsule.j"); } skip = arg_parse_arguments (arg_list, argc, argv); argc -= skip; argv += skip; if (main_used_one_off && (!main_used_other) && (argc == 0)) { exit (EXIT_SUCCESS); UNREACHED; } else if (argc == 0) { MSG_missing_files (); UNREACHED; } arg_data_set_files (&main_arg_data, argc, argv); arg_data_vector_libraries (&main_arg_data); debug_set_file (arg_data_get_debug_file (&main_arg_data)); return (mode); } /*--------------------------------------------------------------------------*/ int main(int argc, char **argv) { HANDLE { istream_setup (); tenapp_init(argc, argv, "TDF linker", "4.0#8"); msg_sev_set(MSG_SEV_WARNING, 0); switch (main_init (argc, argv)) EXHAUSTIVE { case MODE_BUILDER: builder_main (&main_arg_data); break; case MODE_CONTENTS: contents_main (&main_arg_data); break; case MODE_EXTRACT: extract_main (&main_arg_data); break; case MODE_LINKER: linker_main (&main_arg_data); break; } } WITH { ExceptionP exception = EXCEPTION_EXCEPTION (); if (exception == XX_dalloc_no_memory) { MSG_no_memory (); UNREACHED; } else if ((exception == XX_istream_read_error) || (exception == XX_bistream_read_error)) { char *file = (char *) EXCEPTION_VALUE (); MSG_file_read_error (file); UNREACHED; } else if (exception == XX_bostream_write_error) { char *file = (char *) EXCEPTION_VALUE (); MSG_file_write_error (file); UNREACHED; } else { RETHROW (); UNREACHED; } } END_HANDLE exit (EXIT_SUCCESS); UNREACHED; }