|
| 1 | +/******************************************************************\ |
| 2 | +
|
| 3 | +Module: symtab2gb_parse_options |
| 4 | +
|
| 5 | +Author: Diffblue Ltd. |
| 6 | +
|
| 7 | +\******************************************************************/ |
| 8 | + |
| 9 | +#include "symtab2gb_parse_options.h" |
| 10 | + |
| 11 | +#include <fstream> |
| 12 | +#include <iostream> |
| 13 | +#include <string> |
| 14 | + |
| 15 | +#include <goto-programs/goto_convert_functions.h> |
| 16 | +#include <goto-programs/goto_model.h> |
| 17 | +#include <goto-programs/link_goto_model.h> |
| 18 | +#include <goto-programs/write_goto_binary.h> |
| 19 | +#include <json-symtab-language/json_symtab_language.h> |
| 20 | +#include <util/exception_utils.h> |
| 21 | +#include <util/exit_codes.h> |
| 22 | +#include <util/invariant.h> |
| 23 | +#include <util/optional.h> |
| 24 | +#include <util/version.h> |
| 25 | + |
| 26 | +symtab2gb_parse_optionst::symtab2gb_parse_optionst(int argc, const char *argv[]) |
| 27 | + : parse_options_baset{SYMTAB2GB_OPTIONS, |
| 28 | + argc, |
| 29 | + argv, |
| 30 | + std::string("SYMTAB2GB ") + CBMC_VERSION} |
| 31 | +{ |
| 32 | +} |
| 33 | + |
| 34 | +static inline bool failed(bool error_indicator) |
| 35 | +{ |
| 36 | + return error_indicator; |
| 37 | +} |
| 38 | + |
| 39 | +static void run_symtab2gb( |
| 40 | + const std::vector<std::string> &symtab_filenames, |
| 41 | + const std::string &gb_filename) |
| 42 | +{ |
| 43 | + // try opening all the files first to make sure we can |
| 44 | + // even read/write what we want |
| 45 | + std::ofstream out_file{gb_filename}; |
| 46 | + if(!out_file.is_open()) |
| 47 | + { |
| 48 | + throw system_exceptiont{"couldn't open output file `" + gb_filename + "'"}; |
| 49 | + } |
| 50 | + std::vector<std::ifstream> symtab_files; |
| 51 | + for(auto const &symtab_filename : symtab_filenames) |
| 52 | + { |
| 53 | + std::ifstream symtab_file{symtab_filename}; |
| 54 | + if(!symtab_file.is_open()) |
| 55 | + { |
| 56 | + throw system_exceptiont{"couldn't open input file `" + symtab_filename + |
| 57 | + "'"}; |
| 58 | + } |
| 59 | + symtab_files.emplace_back(std::move(symtab_file)); |
| 60 | + } |
| 61 | + |
| 62 | + stream_message_handlert message_handler{std::cerr}; |
| 63 | + |
| 64 | + auto const symtab_language = new_json_symtab_language(); |
| 65 | + symtab_language->set_message_handler(message_handler); |
| 66 | + |
| 67 | + goto_modelt linked_goto_model{}; |
| 68 | + |
| 69 | + for(std::size_t ix = 0; ix < symtab_files.size(); ++ix) |
| 70 | + { |
| 71 | + auto const &symtab_filename = symtab_filenames[ix]; |
| 72 | + auto &symtab_file = symtab_files[ix]; |
| 73 | + if(failed(symtab_language->parse(symtab_file, symtab_filename))) |
| 74 | + { |
| 75 | + throw invalid_source_file_exceptiont{ |
| 76 | + "failed to parse symbol table from file `" + symtab_filename + "'"}; |
| 77 | + } |
| 78 | + symbol_tablet symtab{}; |
| 79 | + if(failed(symtab_language->typecheck(symtab, "<unused>"))) |
| 80 | + { |
| 81 | + throw invalid_source_file_exceptiont{ |
| 82 | + "failed to typecheck symbol table from file `" + symtab_filename + "'"}; |
| 83 | + } |
| 84 | + goto_modelt goto_model{}; |
| 85 | + goto_model.symbol_table = symtab; |
| 86 | + goto_convert(goto_model, message_handler); |
| 87 | + link_goto_model(linked_goto_model, goto_model, message_handler); |
| 88 | + } |
| 89 | + if(failed(write_goto_binary(out_file, linked_goto_model))) |
| 90 | + { |
| 91 | + throw system_exceptiont{"failed to write goto binary to " + gb_filename}; |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +int symtab2gb_parse_optionst::doit() |
| 96 | +{ |
| 97 | + if(cmdline.isset("version")) |
| 98 | + { |
| 99 | + log.status() << CBMC_VERSION << '\n'; |
| 100 | + return CPROVER_EXIT_SUCCESS; |
| 101 | + } |
| 102 | + if(cmdline.args.empty()) |
| 103 | + { |
| 104 | + throw invalid_command_line_argument_exceptiont{ |
| 105 | + "expect at least one input file", "<json-symtab-file>"}; |
| 106 | + } |
| 107 | + std::vector<std::string> symtab_filenames = cmdline.args; |
| 108 | + std::string gb_filename = "a.out"; |
| 109 | + if(cmdline.isset(SYMTAB2GB_OUT_FILE_OPT)) |
| 110 | + { |
| 111 | + gb_filename = cmdline.get_value(SYMTAB2GB_OUT_FILE_OPT); |
| 112 | + } |
| 113 | + run_symtab2gb(symtab_filenames, gb_filename); |
| 114 | + return CPROVER_EXIT_SUCCESS; |
| 115 | +} |
| 116 | + |
| 117 | +void symtab2gb_parse_optionst::help() |
| 118 | +{ |
| 119 | + log.status() |
| 120 | + << '\n' |
| 121 | + << banner_string("symtab2gb", CBMC_VERSION) << '\n' |
| 122 | + << align_center_with_border("Copyright (C) 2019") << '\n' |
| 123 | + << align_center_with_border("Diffblue Ltd.") << '\n' |
| 124 | + << align_center_with_border( "[email protected]") << '\n' |
| 125 | + << '\n' |
| 126 | + << "Usage: Purpose:\n" |
| 127 | + << '\n' |
| 128 | + << "symtab2gb [-?] [-h] [--help] show help\n" |
| 129 | + "symtab2gb compile .json_symtabs\n" |
| 130 | + " <json-symtab-file>+ to a single goto-binary\n" |
| 131 | + " [--out <outfile>]\n\n" |
| 132 | + "<json-symtab-file> a CBMC symbol table in\n" |
| 133 | + " JSON format\n" |
| 134 | + "--out <outfile> specify the filename of\n" |
| 135 | + " the resulting binary\n" |
| 136 | + " (default: a.out)\n" |
| 137 | + << messaget::eom; |
| 138 | +} |
0 commit comments