diff options
author | Ben Smith <binjimin@gmail.com> | 2017-06-14 01:07:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-14 01:07:48 -0700 |
commit | 0b789eaa02755a0082f454090f8bbae7f1418e12 (patch) | |
tree | a3b6114daa4bbd164a678bacd26ba04b0f87e858 /src | |
parent | 013802ca01035365e2459c70f0508481393ac075 (diff) | |
download | wabt-0b789eaa02755a0082f454090f8bbae7f1418e12.tar.gz wabt-0b789eaa02755a0082f454090f8bbae7f1418e12.tar.bz2 wabt-0b789eaa02755a0082f454090f8bbae7f1418e12.zip |
Make OptionParser into C++ class (#497)
Added a new feature where you can specify how many arguments are
allowed. It is an error to provide too many or too few.
Also add "help" tests for all of the other tools.
Diffstat (limited to 'src')
-rw-r--r-- | src/option-parser.cc | 268 | ||||
-rw-r--r-- | src/option-parser.h | 104 | ||||
-rw-r--r-- | src/tools/wasm-interp.cc | 154 | ||||
-rw-r--r-- | src/tools/wasm-link.cc | 92 | ||||
-rw-r--r-- | src/tools/wasm-objdump.cc | 131 | ||||
-rw-r--r-- | src/tools/wasm-opcodecnt.cc | 113 | ||||
-rw-r--r-- | src/tools/wasm2wast.cc | 132 | ||||
-rw-r--r-- | src/tools/wast-desugar.cc | 111 | ||||
-rw-r--r-- | src/tools/wast2wasm.cc | 200 |
9 files changed, 503 insertions, 802 deletions
diff --git a/src/option-parser.cc b/src/option-parser.cc index 173c5f54..e3eefeb2 100644 --- a/src/option-parser.cc +++ b/src/option-parser.cc @@ -28,20 +28,89 @@ namespace wabt { -static int option_match(const char* s, - const char* full, - HasArgument has_argument) { +OptionParser::Option::Option(char short_name, + const std::string& long_name, + const std::string& metavar, + HasArgument has_argument, + const std::string& help, + const Callback& callback) + : short_name(short_name), + long_name(long_name), + metavar(metavar), + has_argument(has_argument == HasArgument::Yes), + help(help), + callback(callback) {} + +OptionParser::Argument::Argument(const std::string& name, + ArgumentCount count, + const Callback& callback) + : name(name), count(count), callback(callback) {} + +OptionParser::OptionParser(const char* program_name, const char* description) + : program_name_(program_name), + description_(description), + on_error_([this](const std::string& message) { DefaultError(message); }) { +} + +void OptionParser::AddOption(const Option& option) { + options_.emplace_back(option); +} + +void OptionParser::AddArgument(const std::string& name, + ArgumentCount count, + const Callback& callback) { + arguments_.emplace_back(name, count, callback); +} + +void OptionParser::AddOption(char short_name, + const char* long_name, + const char* help, + const NullCallback& callback) { + Option option(short_name, long_name, std::string(), HasArgument::No, help, + [callback](const char*) { callback(); }); + AddOption(option); +} + +void OptionParser::AddOption(const char* long_name, + const char* help, + const NullCallback& callback){ + Option option('\0', long_name, std::string(), HasArgument::No, help, + [callback](const char*) { callback(); }); + AddOption(option); +} + +void OptionParser::AddOption(char short_name, + const char* long_name, + const char* metavar, + const char* help, + const Callback& callback) { + Option option(short_name, long_name, metavar, HasArgument::Yes, help, + callback); + AddOption(option); +} + +void OptionParser::AddHelpOption() { + AddOption('h', "help", "Print this help message", [this]() { + PrintHelp(); + exit(0); + }); +} + +// static +int OptionParser::Match(const char* s, + const std::string& full, + bool has_argument) { int i; for (i = 0;; i++) { if (full[i] == '\0') { - /* perfect match. return +1, so it will be preferred over a longer option - * with the same prefix */ + // Perfect match. Return +1, so it will be preferred over a longer option + // with the same prefix. if (s[i] == '\0') return i + 1; - /* we want to fail if s is longer than full, e.g. --foobar vs. --foo. - * However, if s ends with an '=', it's OK. */ - if (!(has_argument == HasArgument::Yes && s[i] == '=')) + // We want to fail if s is longer than full, e.g. --foobar vs. --foo. + // However, if s ends with an '=', it's OK. + if (!(has_argument && s[i] == '=')) return -1; break; } @@ -53,28 +122,45 @@ static int option_match(const char* s, return i; } -static void WABT_PRINTF_FORMAT(2, 3) - error(OptionParser* parser, const char* format, ...) { +void OptionParser::Errorf(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - parser->on_error(parser, buffer); + on_error_(buffer); +} + +void OptionParser::DefaultError(const std::string& message) { + WABT_FATAL("%s\n", message.c_str()); } -void parse_options(OptionParser* parser, int argc, char** argv) { - parser->argv0 = argv[0]; +void OptionParser::HandleArgument(size_t* arg_index, const char* arg_value) { + if (*arg_index >= arguments_.size()) { + Errorf("unexpected argument '%s'", arg_value); + return; + } + Argument& argument = arguments_[*arg_index]; + argument.callback(arg_value); + argument.handled_count++; + + if (argument.count == ArgumentCount::One) { + (*arg_index)++; + } +} + +void OptionParser::Parse(int argc, char* argv[]) { + size_t arg_index = 0; for (int i = 1; i < argc; ++i) { - char* arg = argv[i]; + const char* arg = argv[i]; if (arg[0] == '-') { if (arg[1] == '-') { - /* long option */ + // Long option. int best_index = -1; int best_length = 0; int best_count = 0; - for (int j = 0; j < parser->num_options; ++j) { - Option* option = &parser->options[j]; - if (option->long_name) { + for (size_t j = 0; j < options_.size(); ++j) { + const Option& option = options_[j]; + if (!option.long_name.empty()) { int match_length = - option_match(&arg[2], option->long_name, option->has_argument); + Match(&arg[2], option.long_name, option.has_argument); if (match_length > best_length) { best_index = j; best_length = match_length; @@ -86,97 +172,115 @@ void parse_options(OptionParser* parser, int argc, char** argv) { } if (best_count > 1) { - error(parser, "ambiguous option \"%s\"", arg); + Errorf("ambiguous option '%s'", arg); continue; } else if (best_count == 0) { - error(parser, "unknown option \"%s\"", arg); + Errorf("unknown option '%s'", arg); continue; } - Option* best_option = &parser->options[best_index]; + const Option& best_option = options_[best_index]; const char* option_argument = nullptr; - if (best_option->has_argument == HasArgument::Yes) { + if (best_option.has_argument) { if (arg[best_length] == '=') { option_argument = &arg[best_length + 1]; } else { if (i + 1 == argc || argv[i + 1][0] == '-') { - error(parser, "option \"--%s\" requires argument", - best_option->long_name); + Errorf("option '--%s' requires argument", + best_option.long_name.c_str()); continue; } ++i; option_argument = argv[i]; } } - parser->on_option(parser, best_option, option_argument); + best_option.callback(option_argument); } else { - /* short option */ + // Short option. if (arg[1] == '\0') { - /* just "-" */ - parser->on_argument(parser, arg); + // Just "-". + HandleArgument(&arg_index, arg); continue; } - /* allow short names to be combined, e.g. "-d -v" => "-dv" */ + // Allow short names to be combined, e.g. "-d -v" => "-dv". for (int k = 1; arg[k]; ++k) { bool matched = false; - for (int j = 0; j < parser->num_options; ++j) { - Option* option = &parser->options[j]; - if (option->short_name && arg[k] == option->short_name) { + for (const Option& option: options_) { + if (option.short_name && arg[k] == option.short_name) { const char* option_argument = nullptr; - if (option->has_argument == HasArgument::Yes) { - /* a short option with a required argument cannot be followed - * by other short options */ + if (option.has_argument) { + // A short option with a required argument cannot be followed + // by other short options_. if (arg[k + 1] != '\0') { - error(parser, "option \"-%c\" requires argument", - option->short_name); + Errorf("option '-%c' requires argument", option.short_name); break; } if (i + 1 == argc || argv[i + 1][0] == '-') { - error(parser, "option \"-%c\" requires argument", - option->short_name); + Errorf("option '-%c' requires argument", option.short_name); break; } ++i; option_argument = argv[i]; } - parser->on_option(parser, option, option_argument); + option.callback(option_argument); matched = true; break; } } if (!matched) { - error(parser, "unknown option \"-%c\"", arg[k]); + Errorf("unknown option '-%c'", arg[k]); continue; } } } } else { - /* non-option argument */ - parser->on_argument(parser, arg); + // Non-option argument. + HandleArgument(&arg_index, arg); + } + } + + // For now, all arguments must be provided. Check that the last Argument was + // handled at least once. + if (!arguments_.empty() && arguments_.back().handled_count == 0) { + PrintHelp(); + for (size_t i = arg_index; i < arguments_.size(); ++i) { + Errorf("expected %s argument.\n", arguments_[i].name.c_str()); } } } -void print_help(OptionParser* parser, const char* program_name) { - /* TODO(binji): do something more generic for filename here */ - printf("usage: %s [options] filename\n\n", program_name); - printf("%s\n", parser->description); +void OptionParser::PrintHelp() { + printf("usage: %s [options]", program_name_.c_str()); + + for (size_t i = 0; i < arguments_.size(); ++i) { + Argument& argument = arguments_[i]; + switch (argument.count) { + case ArgumentCount::One: + printf(" %s", argument.name.c_str()); + break; + + case ArgumentCount::OneOrMore: + printf(" %s+", argument.name.c_str()); + break; + } + } + + printf("\n\n"); + printf("%s\n", description_.c_str()); printf("options:\n"); - const int extra_space = 8; - int longest_name_length = 0; - for (int i = 0; i < parser->num_options; ++i) { - Option* option = &parser->options[i]; - int length; - if (option->long_name) { - if (option->metavar) { - length = - snprintf(nullptr, 0, "%s=%s", option->long_name, option->metavar); - } else { - length = snprintf(nullptr, 0, "%s", option->long_name); + const size_t kExtraSpace = 8; + size_t longest_name_length = 0; + for (const Option& option: options_) { + size_t length; + if (!option.long_name.empty()) { + length = option.long_name.size(); + if (!option.metavar.empty()) { + // +1 for '='. + length += option.metavar.size() + 1; } } else { continue; @@ -186,41 +290,33 @@ void print_help(OptionParser* parser, const char* program_name) { longest_name_length = length; } - size_t buffer_size = longest_name_length + 1; - char* buffer = static_cast<char*>(alloca(buffer_size)); - - for (int i = 0; i < parser->num_options; ++i) { - Option* option = &parser->options[i]; - if (!option->short_name && !option->long_name) + for (const Option& option: options_) { + if (!option.short_name && option.long_name.empty()) continue; - if (option->short_name) - printf(" -%c, ", option->short_name); + std::string line; + if (option.short_name) + line += std::string(" -") + option.short_name + ", "; else - printf(" "); - - char format[20]; - if (option->long_name) { - snprintf(format, sizeof(format), "--%%-%ds", - longest_name_length + extra_space); + line += " "; - if (option->metavar) { - snprintf(buffer, buffer_size, "%s=%s", option->long_name, - option->metavar); - printf(format, buffer); + std::string flag; + if (!option.long_name.empty()) { + flag = "--"; + if (!option.metavar.empty()) { + flag += option.long_name + '=' + option.metavar; } else { - printf(format, option->long_name); + flag += option.long_name; } - } else { - /* +2 for the extra "--" above */ - snprintf(format, sizeof(format), "%%-%ds", - longest_name_length + extra_space + 2); - printf(format, ""); } - if (option->help) - printf("%s", option->help); - printf("\n"); + // +2 for "--" of the long flag name. + size_t remaining = longest_name_length + kExtraSpace + 2 - flag.size(); + line += flag + std::string(remaining, ' '); + + if (!option.help.empty()) + line += option.help; + printf("%s\n", line.c_str()); } } diff --git a/src/option-parser.h b/src/option-parser.h index 9406748d..883e5f30 100644 --- a/src/option-parser.h +++ b/src/option-parser.h @@ -17,47 +17,83 @@ #ifndef WABT_OPTION_PARSER_H_ #define WABT_OPTION_PARSER_H_ +#include <functional> +#include <string> +#include <vector> + #include "common.h" namespace wabt { -enum class HasArgument { - No = 0, - Yes = 1, -}; +class OptionParser { + public: + enum class HasArgument { No, Yes }; + enum class ArgumentCount { One, OneOrMore }; -struct Option; -struct OptionParser; -typedef void (*OptionCallback)(struct OptionParser*, - struct Option*, - const char* argument); -typedef void (*ArgumentCallback)(struct OptionParser*, const char* argument); -typedef void (*OptionErrorCallback)(struct OptionParser*, const char* message); - -struct Option { - int id; - char short_name; - const char* long_name; - const char* metavar; - HasArgument has_argument; - const char* help; -}; + struct Option; + typedef std::function<void(const char*)> Callback; + typedef std::function<void()> NullCallback; -struct OptionParser { - const char* description; - Option* options; - int num_options; - OptionCallback on_option; - ArgumentCallback on_argument; - OptionErrorCallback on_error; - void* user_data; - - /* cached after call to parse_options */ - char* argv0; -}; + struct Option { + Option(char short_name, + const std::string& long_name, + const std::string& metavar, + HasArgument has_argument, + const std::string& help, + const Callback&); + + char short_name; + std::string long_name; + std::string metavar; + bool has_argument; + std::string help; + Callback callback; + }; + + struct Argument { + Argument(const std::string& name, ArgumentCount, const Callback&); + + std::string name; + ArgumentCount count; + Callback callback; + int handled_count = 0; + }; -void parse_options(OptionParser* parser, int argc, char** argv); -void print_help(OptionParser* parser, const char* program_name); + explicit OptionParser(const char* program_name, const char* description); + + void AddOption(const Option&); + void AddArgument(const std::string& name, ArgumentCount, const Callback&); + void SetErrorCallback(const Callback&); + void Parse(int argc, char* argv[]); + void PrintHelp(); + + // Helper functions. + void AddOption(char short_name, + const char* long_name, + const char* help, + const NullCallback&); + void AddOption(const char* long_name, const char* help, const NullCallback&); + void AddOption(char short_name, + const char* long_name, + const char* metavar, + const char* help, + const Callback&); + void AddHelpOption(); + + private: + static int Match(const char* s, const std::string& full, bool has_argument); + void WABT_PRINTF_FORMAT(2, 3) Errorf(const char* format, ...); + void HandleArgument(size_t* arg_index, const char* arg_value); + + // Print the error and exit(1). + void DefaultError(const std::string&); + + std::string program_name_; + std::string description_; + std::vector<Option> options_; + std::vector<Argument> arguments_; + Callback on_error_; +}; } // namespace wabt diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc index 2e27d5af..2ef89804 100644 --- a/src/tools/wasm-interp.cc +++ b/src/tools/wasm-interp.cc @@ -20,6 +20,7 @@ #include <cstdio> #include <cstdlib> #include <memory> +#include <string> #include <vector> #include "binary-error-handler.h" @@ -33,8 +34,6 @@ #include "wast-lexer.h" #include "wast-parser.h" -#define PROGRAM_NAME "wasm-interp" - using namespace wabt; using namespace wabt::interpreter; @@ -54,127 +53,68 @@ static bool s_run_all_exports; static std::unique_ptr<FileStream> s_log_stream; static std::unique_ptr<FileStream> s_stdout_stream; -#define NOPE HasArgument::No -#define YEP HasArgument::Yes - enum class RunVerbosity { Quiet = 0, Verbose = 1, }; -enum { - FLAG_VERBOSE, - FLAG_HELP, - FLAG_VALUE_STACK_SIZE, - FLAG_CALL_STACK_SIZE, - FLAG_TRACE, - FLAG_SPEC, - FLAG_RUN_ALL_EXPORTS, - NUM_FLAGS -}; - static const char s_description[] = - " read a file in the wasm binary format, and run in it a stack-based\n" - " interpreter.\n" - "\n" - "examples:\n" - " # parse binary file test.wasm, and type-check it\n" - " $ wasm-interp test.wasm\n" - "\n" - " # parse test.wasm and run all its exported functions\n" - " $ wasm-interp test.wasm --run-all-exports\n" - "\n" - " # parse test.wasm, run the exported functions and trace the output\n" - " $ wasm-interp test.wasm --run-all-exports --trace\n" - "\n" - " # parse test.json and run the spec tests\n" - " $ wasm-interp test.json --spec\n" - "\n" - " # parse test.wasm and run all its exported functions, setting the\n" - " # value stack size to 100 elements\n" - " $ wasm-interp test.wasm -V 100 --run-all-exports\n"; - -static Option s_options[] = { - {FLAG_VERBOSE, 'v', "verbose", nullptr, NOPE, - "use multiple times for more info"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, - {FLAG_VALUE_STACK_SIZE, 'V', "value-stack-size", "SIZE", YEP, - "size in elements of the value stack"}, - {FLAG_CALL_STACK_SIZE, 'C', "call-stack-size", "SIZE", YEP, - "size in frames of the call stack"}, - {FLAG_TRACE, 't', "trace", nullptr, NOPE, "trace execution"}, - {FLAG_SPEC, 0, "spec", nullptr, NOPE, - "run spec tests (input file should be .json)"}, - {FLAG_RUN_ALL_EXPORTS, 0, "run-all-exports", nullptr, NOPE, - "run all the exported functions, in order. useful for testing"}, -}; -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); - -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_VERBOSE: - s_verbose++; - s_log_stream = FileStream::CreateStdout(); - s_read_binary_options.log_stream = s_log_stream.get(); - break; +R"( read a file in the wasm binary format, and run in it a stack-based + interpreter. - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; +examples: + # parse binary file test.wasm, and type-check it + $ wasm-interp test.wasm - case FLAG_VALUE_STACK_SIZE: - /* TODO(binji): validate */ - s_thread_options.value_stack_size = atoi(argument); - break; + # parse test.wasm and run all its exported functions + $ wasm-interp test.wasm --run-all-exports - case FLAG_CALL_STACK_SIZE: - /* TODO(binji): validate */ - s_thread_options.call_stack_size = atoi(argument); - break; + # parse test.wasm, run the exported functions and trace the output + $ wasm-interp test.wasm --run-all-exports --trace - case FLAG_TRACE: - s_trace = true; - break; + # parse test.json and run the spec tests + $ wasm-interp test.json --spec - case FLAG_SPEC: - s_spec = true; - break; - - case FLAG_RUN_ALL_EXPORTS: - s_run_all_exports = true; - break; - } -} - -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infile = argument; -} - -static void on_option_error(struct OptionParser* parser, const char* message) { - WABT_FATAL("%s\n", message); -} + # parse test.wasm and run all its exported functions, setting the + # value stack size to 100 elements + $ wasm-interp test.wasm -V 100 --run-all-exports +)"; static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); + OptionParser parser("wasm-interp", s_description); + + parser.AddOption('v', "verbose", "Use multiple times for more info", []() { + s_verbose++; + s_log_stream = FileStream::CreateStdout(); + s_read_binary_options.log_stream = s_log_stream.get(); + }); + parser.AddHelpOption(); + parser.AddOption('V', "value-stack-size", "SIZE", + "Size in elements of the value stack", + [](const std::string& argument) { + // TODO(binji): validate. + s_thread_options.value_stack_size = atoi(argument.c_str()); + }); + parser.AddOption('C', "call-stack-size", "SIZE", + "Size in elements of the call stack", + [](const std::string& argument) { + // TODO(binji): validate. + s_thread_options.call_stack_size = atoi(argument.c_str()); + }); + parser.AddOption('t', "trace", "Trace execution", []() { s_trace = true; }); + parser.AddOption("spec", "Run spec tests (input file should be .json)", + []() { s_spec = true; }); + parser.AddOption( + "run-all-exports", + "Run all the exported functions, in order. Useful for testing", + []() { s_run_all_exports = true; }); + + parser.AddArgument("filename", OptionParser::ArgumentCount::One, + [](const char* argument) { s_infile = argument; }); + parser.Parse(argc, argv); if (s_spec && s_run_all_exports) WABT_FATAL("--spec and --run-all-exports are incompatible.\n"); - - if (!s_infile) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } } enum class ModuleType { diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc index c2a953e4..522982c9 100644 --- a/src/tools/wasm-link.cc +++ b/src/tools/wasm-link.cc @@ -16,6 +16,9 @@ #include "wasm-link.h" +#include <memory> +#include <vector> + #include "binary-reader.h" #include "binding-hash.h" #include "binary-writer.h" @@ -24,34 +27,16 @@ #include "writer.h" #include "binary-reader-linker.h" -#include <memory> -#include <vector> - -#define PROGRAM_NAME "wasm-link" -#define NOPE HasArgument::No -#define YEP HasArgument::Yes #define FIRST_KNOWN_SECTION static_cast<size_t>(BinarySection::Type) #define LOG_DEBUG(fmt, ...) if (s_debug) s_log_stream->Writef(fmt, __VA_ARGS__); using namespace wabt; using namespace wabt::link; -enum { FLAG_DEBUG, FLAG_OUTPUT, FLAG_RELOCATABLE, FLAG_HELP, NUM_FLAGS }; - static const char s_description[] = - " link one or more wasm binary modules into a single binary module." - "\n" - " $ wasm-link m1.wasm m2.wasm -o out.wasm\n"; - -static Option s_options[] = { - {FLAG_DEBUG, '\0', "debug", nullptr, NOPE, - "log extra information when reading and writing wasm files"}, - {FLAG_OUTPUT, 'o', "output", "FILE", YEP, "output wasm binary file"}, - {FLAG_RELOCATABLE, 'r', "relocatable", nullptr, NOPE, - "output a relocatable object file"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, -}; -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); +R"( link one or more wasm binary modules into a single binary module. + $ wasm-link m1.wasm m2.wasm -o out.wasm +)"; static bool s_debug; static bool s_relocatable; @@ -68,53 +53,26 @@ struct Context { ssize_t current_section_payload_offset = 0; }; -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_DEBUG: - s_debug = true; - s_log_stream = FileStream::CreateStdout(); - break; - - case FLAG_OUTPUT: - s_outfile = argument; - break; - - case FLAG_RELOCATABLE: - s_relocatable = true; - break; - - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; - } -} - -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infiles.emplace_back(argument); -} - -static void on_option_error(struct OptionParser* parser, const char* message) { - WABT_FATAL("%s\n", message); -} - static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (!s_infiles.size()) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No inputs files specified.\n"); - } + OptionParser parser("wasm-link", s_description); + + parser.AddOption("debug", + "Log extra information when reading and writing wasm files", + []() { + s_debug = true; + s_log_stream = FileStream::CreateStdout(); + }); + parser.AddOption('o', "output", "FILE", "Output wasm binary file", + [](const char* argument) { s_outfile = argument; }); + parser.AddOption('r', "relocatable", "Output a relocatable object file", + []() { s_relocatable = true; }); + parser.AddHelpOption(); + + parser.AddArgument( + "filename", OptionParser::ArgumentCount::OneOrMore, + [](const std::string& argument) { s_infiles.emplace_back(argument); }); + + parser.Parse(argc, argv); } Section::Section() diff --git a/src/tools/wasm-objdump.cc b/src/tools/wasm-objdump.cc index eaa9ece7..ec967c4e 100644 --- a/src/tools/wasm-objdump.cc +++ b/src/tools/wasm-objdump.cc @@ -25,46 +25,14 @@ #include "binary-reader.h" #include "binary-reader-objdump.h" -#define PROGRAM_NAME "wasm-objdump" - -#define NOPE HasArgument::No -#define YEP HasArgument::Yes - using namespace wabt; -enum { - FLAG_HEADERS, - FLAG_SECTION, - FLAG_RAW, - FLAG_DISASSEMBLE, - FLAG_DEBUG, - FLAG_DETAILS, - FLAG_RELOCS, - FLAG_HELP, - NUM_FLAGS -}; - static const char s_description[] = - " Print information about the contents of wasm binaries.\n" - "\n" - "examples:\n" - " $ wasm-objdump test.wasm\n"; - -static Option s_options[] = { - {FLAG_HEADERS, 'h', "headers", nullptr, NOPE, "print headers"}, - {FLAG_SECTION, 'j', "section", nullptr, YEP, "select just one section"}, - {FLAG_RAW, 's', "full-contents", nullptr, NOPE, - "print raw section contents"}, - {FLAG_DISASSEMBLE, 'd', "disassemble", nullptr, NOPE, - "disassemble function bodies"}, - {FLAG_DEBUG, '\0', "debug", nullptr, NOPE, "print extra debug information"}, - {FLAG_DETAILS, 'x', "details", nullptr, NOPE, "Show section details"}, - {FLAG_RELOCS, 'r', "reloc", nullptr, NOPE, - "show relocations inline with disassembly"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, -}; - -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); +R"( Print information about the contents of wasm binaries. + +examples: + $ wasm-objdump test.wasm +)"; static ObjdumpOptions s_objdump_options; @@ -72,70 +40,33 @@ static std::vector<const char*> s_infiles; static std::unique_ptr<FileStream> s_log_stream; -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infiles.push_back(argument); -} - -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_HEADERS: - s_objdump_options.headers = true; - break; - - case FLAG_RAW: - s_objdump_options.raw = true; - break; - - case FLAG_DEBUG: - s_objdump_options.debug = true; - s_log_stream = FileStream::CreateStdout(); - s_objdump_options.log_stream = s_log_stream.get(); - break; - - case FLAG_DISASSEMBLE: - s_objdump_options.disassemble = true; - break; - - case FLAG_DETAILS: - s_objdump_options.details = true; - break; - - case FLAG_RELOCS: - s_objdump_options.relocs = true; - break; - - case FLAG_SECTION: - s_objdump_options.section_name = argument; - break; - - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; - } -} - -static void on_option_error(struct OptionParser* parser, const char* message) { - WABT_FATAL("%s\n", message); -} - static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (s_infiles.size() == 0) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } + OptionParser parser("wasm-objdump", s_description); + + parser.AddOption('h', "headers", "Print headers", + []() { s_objdump_options.headers = true; }); + parser.AddOption( + 'j', "section", "SECTION", "Select just one section", + [](const char* argument) { s_objdump_options.section_name = argument; }); + parser.AddOption('s', "full-contents", "Print raw section contents", + []() { s_objdump_options.raw = true; }); + parser.AddOption('d', "disassemble", "Disassemble function bodies", + []() { s_objdump_options.disassemble = true; }); + parser.AddOption("debug", "Print extra debug information", []() { + s_objdump_options.debug = true; + s_log_stream = FileStream::CreateStdout(); + s_objdump_options.log_stream = s_log_stream.get(); + }); + parser.AddOption('x', "details", "Show section details", + []() { s_objdump_options.details = true; }); + parser.AddOption('r', "reloc", "Show relocations inline with disassembly", + []() { s_objdump_options.relocs = true; }); + parser.AddHelpOption(); + parser.AddArgument( + "filename", OptionParser::ArgumentCount::OneOrMore, + [](const char* argument) { s_infiles.push_back(argument); }); + + parser.Parse(argc, argv); } Result dump_file(const char* filename) { diff --git a/src/tools/wasm-opcodecnt.cc b/src/tools/wasm-opcodecnt.cc index 2ff37d72..3571871e 100644 --- a/src/tools/wasm-opcodecnt.cc +++ b/src/tools/wasm-opcodecnt.cc @@ -26,8 +26,6 @@ #include "option-parser.h" #include "stream.h" -#define PROGRAM_NAME "wasm-opcodecnt" - #define ERROR(fmt, ...) \ fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) @@ -44,91 +42,40 @@ static ReadBinaryOptions s_read_binary_options = static std::unique_ptr<FileStream> s_log_stream; -#define NOPE HasArgument::No -#define YEP HasArgument::Yes - -enum { - FLAG_VERBOSE, - FLAG_HELP, - FLAG_OUTPUT, - FLAG_CUTOFF, - FLAG_SEPARATOR, - NUM_FLAGS -}; - static const char s_description[] = - " Read a file in the wasm binary format, and count opcode usage for\n" - " instructions.\n" - "\n" - "examples:\n" - " # parse binary file test.wasm and write pcode dist file test.dist\n" - " $ wasm-opcodecnt test.wasm -o test.dist\n"; - -static Option s_options[] = { - {FLAG_VERBOSE, 'v', "verbose", nullptr, NOPE, - "use multiple times for more info"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, - {FLAG_OUTPUT, 'o', "output", "FILENAME", YEP, - "output file for the opcode counts, by default use stdout"}, - {FLAG_CUTOFF, 'c', "cutoff", "N", YEP, - "cutoff for reporting counts less than N"}, - {FLAG_SEPARATOR, 's', "separator", "SEPARATOR", YEP, - "Separator text between element and count when reporting counts"}}; - -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); +R"( Read a file in the wasm binary format, and count opcode usage for + instructions. -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_VERBOSE: - s_verbose++; - s_log_stream = FileStream::CreateStdout(); - s_read_binary_options.log_stream = s_log_stream.get(); - break; - - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; - - case FLAG_OUTPUT: - s_outfile = argument; - break; - - case FLAG_CUTOFF: - s_cutoff = atol(argument); - break; - - case FLAG_SEPARATOR: - s_separator = argument; - break; - } -} - -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infile = argument; -} - -static void on_option_error(struct OptionParser* parser, const char* message) { - WABT_FATAL("%s\n", message); -} +examples: + # parse binary file test.wasm and write pcode dist file test.dist + $ wasm-opcodecnt test.wasm -o test.dist +)"; static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (!s_infile) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } + OptionParser parser("wasm-opcodecnt", s_description); + + parser.AddOption('v', "verbose", "Use multiple times for more info", []() { + s_verbose++; + s_log_stream = FileStream::CreateStdout(); + s_read_binary_options.log_stream = s_log_stream.get(); + }); + parser.AddOption('h', "help", "Print this help message", [&parser]() { + parser.PrintHelp(); + exit(0); + }); + parser.AddOption('o', "output", "FILENAME", + "Output file for the opcode counts, by default use stdout", + [](const char* argument) { s_outfile = argument; }); + parser.AddOption( + 'c', "cutoff", "N", "Cutoff for reporting counts less than N", + [](const std::string& argument) { s_cutoff = atol(argument.c_str()); }); + parser.AddOption( + 's', "separator", "SEPARATOR", + "Separator text between element and count when reporting counts", + [](const char* argument) { s_separator = argument; }); + parser.AddArgument("filename", OptionParser::ArgumentCount::OneOrMore, + [](const char* argument) { s_infile = argument; }); + parser.Parse(argc, argv); } typedef int(int_counter_lt_fcn)(const IntCounter&, const IntCounter&); diff --git a/src/tools/wasm2wast.cc b/src/tools/wasm2wast.cc index 91092d34..45ce4bcd 100644 --- a/src/tools/wasm2wast.cc +++ b/src/tools/wasm2wast.cc @@ -30,8 +30,6 @@ #include "wat-writer.h" #include "writer.h" -#define PROGRAM_NAME "wasm2wast" - using namespace wabt; static int s_verbose; @@ -42,108 +40,44 @@ static WriteWatOptions s_write_wat_options; static bool s_generate_names; static std::unique_ptr<FileStream> s_log_stream; -#define NOPE HasArgument::No -#define YEP HasArgument::Yes - -enum { - FLAG_VERBOSE, - FLAG_HELP, - FLAG_OUTPUT, - FLAG_NO_DEBUG_NAMES, - FLAG_GENERATE_NAMES, - FLAG_FOLD_EXPRS, - FLAG_INLINE_EXPORTS, - NUM_FLAGS -}; - static const char s_description[] = - " read a file in the wasm binary format, and convert it to the wasm\n" - " s-expression file format.\n" - "\n" - "examples:\n" - " # parse binary file test.wasm and write s-expression file test.wast\n" - " $ wasm2wast test.wasm -o test.wast\n" - "\n" - " # parse test.wasm, write test.wast, but ignore the debug names, if any\n" - " $ wasm2wast test.wasm --no-debug-names -o test.wast\n"; - -static Option s_options[] = { - {FLAG_VERBOSE, 'v', "verbose", nullptr, NOPE, - "use multiple times for more info"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, - {FLAG_OUTPUT, 'o', "output", "FILENAME", YEP, - "output file for the generated wast file, by default use stdout"}, - {FLAG_FOLD_EXPRS, 'f', "fold-exprs", nullptr, NOPE, - "Write folded expressions where possible"}, - {FLAG_INLINE_EXPORTS, 0, "inline-exports", nullptr, NOPE, - "Write all exports inline"}, - {FLAG_NO_DEBUG_NAMES, 0, "no-debug-names", nullptr, NOPE, - "Ignore debug names in the binary file"}, - {FLAG_GENERATE_NAMES, 0, "generate-names", nullptr, NOPE, - "Give auto-generated names to non-named functions, types, etc."}, -}; -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); - -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_VERBOSE: - s_verbose++; - s_log_stream = FileStream::CreateStdout(); - s_read_binary_options.log_stream = s_log_stream.get(); - break; +R"( read a file in the wasm binary format, and convert it to the wasm + s-expression file format. - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; +examples: + # parse binary file test.wasm and write s-expression file test.wast + $ wasm2wast test.wasm -o test.wast - case FLAG_OUTPUT: - s_outfile = argument; - break; - - case FLAG_FOLD_EXPRS: - s_write_wat_options.fold_exprs = true; - break; - - case FLAG_INLINE_EXPORTS: - s_write_wat_options.inline_export = true; - break; - - case FLAG_NO_DEBUG_NAMES: - s_read_binary_options.read_debug_names = false; - break; - - case FLAG_GENERATE_NAMES: - s_generate_names = true; - break; - } -} - -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infile = argument; -} - -static void on_option_error(struct OptionParser* parser, const char* message) { - WABT_FATAL("%s\n", message); -} + # parse test.wasm, write test.wast, but ignore the debug names, if any + $ wasm2wast test.wasm --no-debug-names -o test.wast +)"; static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (!s_infile) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } + OptionParser parser("wasm2wast", s_description); + + parser.AddOption('v', "verbose", "Use multiple times for more info", []() { + s_verbose++; + s_log_stream = FileStream::CreateStdout(); + s_read_binary_options.log_stream = s_log_stream.get(); + }); + parser.AddHelpOption(); + parser.AddOption( + 'o', "output", "FILENAME", + "Output file for the generated wast file, by default use stdout", + [](const char* argument) { s_outfile = argument; }); + parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", + []() { s_write_wat_options.fold_exprs = true; }); + parser.AddOption("inline-exports", "Write all exports inline", + []() { s_write_wat_options.inline_export = true; }); + parser.AddOption("no-debug-names", "Ignore debug names in the binary file", + []() { s_read_binary_options.read_debug_names = false; }); + parser.AddOption( + "generate-names", + "Give auto-generated names to non-named functions, types, etc.", + []() { s_generate_names = true; }); + parser.AddArgument("filename", OptionParser::ArgumentCount::One, + [](const char* argument) { s_infile = argument; }); + parser.Parse(argc, argv); } int ProgramMain(int argc, char** argv) { diff --git a/src/tools/wast-desugar.cc b/src/tools/wast-desugar.cc index 441a928b..55caf7d0 100644 --- a/src/tools/wast-desugar.cc +++ b/src/tools/wast-desugar.cc @@ -32,8 +32,6 @@ #include "wat-writer.h" #include "writer.h" -#define PROGRAM_NAME "wast-desugar" - using namespace wabt; static const char* s_infile; @@ -41,97 +39,38 @@ static const char* s_outfile; static WriteWatOptions s_write_wat_options; static bool s_generate_names; -enum { - FLAG_HELP, - FLAG_OUTPUT, - FLAG_FOLD_EXPRS, - FLAG_GENERATE_NAMES, - NUM_FLAGS -}; - static const char s_description[] = - " read a file in the wasm s-expression format and format it.\n" - "\n" - "examples:\n" - " # write output to stdout\n" - " $ wast-desugar test.wast\n" - "\n" - " # write output to test2.wast\n" - " $ wast-desugar test.wast -o test2.wast\n" - "\n" - " # generate names for indexed variables\n" - " $ wast-desugar --generate-names test.wast\n"; - -static Option s_options[] = { - {FLAG_HELP, 'h', "help", nullptr, HasArgument::No, - "print this help message"}, - {FLAG_OUTPUT, 'o', "output", "FILE", HasArgument::Yes, - "output file for the formatted file"}, - {FLAG_FOLD_EXPRS, 'f', "fold-exprs", nullptr, HasArgument::No, - "Write folded expressions where possible"}, - {FLAG_GENERATE_NAMES, 0, "generate-names", nullptr, HasArgument::No, - "Give auto-generated names to non-named functions, types, etc."}, -}; -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); - -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; - - case FLAG_OUTPUT: - s_outfile = argument; - break; - - case FLAG_FOLD_EXPRS: - s_write_wat_options.fold_exprs = true; - break; - - case FLAG_GENERATE_NAMES: - s_generate_names = true; - break; - } -} +R"( read a file in the wasm s-expression format and format it. -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infile = argument; -} +examples: + # write output to stdout + $ wast-desugar test.wast -static void on_option_error(struct OptionParser* parser, - const char* message) { - WABT_FATAL("%s\n", message); -} + # write output to test2.wast + $ wast-desugar test.wast -o test2.wast + + # generate names for indexed variables + $ wast-desugar --generate-names test.wast +)"; static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (!s_infile) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } + OptionParser parser("wast-desugar", s_description); + + parser.AddHelpOption(); + parser.AddOption('o', "output", "FILE", "Output file for the formatted file", + [](const char* argument) { s_outfile = argument; }); + parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", + []() { s_write_wat_options.fold_exprs = true; }); + parser.AddOption( + "generate-names", + "Give auto-generated names to non-named functions, types, etc.", + []() { s_generate_names = true; }); + + parser.AddArgument("filename", OptionParser::ArgumentCount::One, + [](const char* argument) { s_infile = argument; }); + parser.Parse(argc, argv); } -struct Context { - MemoryWriter json_writer; - MemoryWriter module_writer; - Stream json_stream; - StringSlice output_filename_noext; - char* module_filename; - Result result; -}; - int ProgramMain(int argc, char** argv) { init_stdio(); parse_options(argc, argv); diff --git a/src/tools/wast2wasm.cc b/src/tools/wast2wasm.cc index eb5ea041..4bfc2e7c 100644 --- a/src/tools/wast2wasm.cc +++ b/src/tools/wast2wasm.cc @@ -19,6 +19,7 @@ #include <cstdint> #include <cstdlib> #include <cstdio> +#include <string> #include "config.h" @@ -34,8 +35,6 @@ #include "wast-parser.h" #include "writer.h" -#define PROGRAM_NAME "wast2wasm" - using namespace wabt; static const char* s_infile; @@ -52,145 +51,66 @@ static WastParseOptions s_parse_options; static std::unique_ptr<FileStream> s_log_stream; -#define NOPE HasArgument::No -#define YEP HasArgument::Yes - -enum { - FLAG_VERBOSE, - FLAG_HELP, - FLAG_DUMP_MODULE, - FLAG_OUTPUT, - FLAG_RELOCATABLE, - FLAG_SPEC, - FLAG_NO_CANONICALIZE_LEB128S, - FLAG_DEBUG_NAMES, - FLAG_NO_CHECK, - FLAG_EXCEPTIONS, - FLAG_DEBUG_PARSER, - NUM_FLAGS -}; - static const char s_description[] = - " read a file in the wasm s-expression format, check it for errors, and\n" - " convert it to the wasm binary format.\n" - "\n" - "examples:\n" - " # parse and typecheck test.wast\n" - " $ wast2wasm test.wast\n" - "\n" - " # parse test.wast and write to binary file test.wasm\n" - " $ wast2wasm test.wast -o test.wasm\n" - "\n" - " # parse spec-test.wast, and write verbose output to stdout (including\n" - " # the meaning of every byte)\n" - " $ wast2wasm spec-test.wast -v\n" - "\n" - " # parse spec-test.wast, and write files to spec-test.json. Modules are\n" - " # written to spec-test.0.wasm, spec-test.1.wasm, etc.\n" - " $ wast2wasm spec-test.wast --spec -o spec-test.json\n"; - -static Option s_options[] = { - {FLAG_VERBOSE, 'v', "verbose", nullptr, NOPE, - "use multiple times for more info"}, - {FLAG_HELP, 'h', "help", nullptr, NOPE, "print this help message"}, - {FLAG_DEBUG_PARSER, 0, "debug-parser", nullptr, NOPE, - "Turn on debugging the parser of wast files"}, - {FLAG_DUMP_MODULE, 'd', "dump-module", nullptr, NOPE, - "print a hexdump of the module to stdout"}, - {FLAG_EXCEPTIONS, 0, "future-exceptions", nullptr, NOPE, - "Test future extension for exception handling"}, - {FLAG_OUTPUT, 'o', "output", "FILE", YEP, "output wasm binary file"}, - {FLAG_RELOCATABLE, 'r', nullptr, nullptr, NOPE, - "create a relocatable wasm binary (suitable for linking with wasm-link)"}, - {FLAG_SPEC, 0, "spec", nullptr, NOPE, - "parse a file with multiple modules and assertions, like the spec " - "tests"}, - {FLAG_NO_CANONICALIZE_LEB128S, 0, "no-canonicalize-leb128s", nullptr, NOPE, - "Write all LEB128 sizes as 5-bytes instead of their minimal size"}, - {FLAG_DEBUG_NAMES, 0, "debug-names", nullptr, NOPE, - "Write debug names to the generated binary file"}, - {FLAG_NO_CHECK, 0, "no-check", nullptr, NOPE, - "Don't check for invalid modules"} -}; -WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options)); - -static void on_option(struct OptionParser* parser, - struct Option* option, - const char* argument) { - switch (option->id) { - case FLAG_VERBOSE: - s_verbose++; - s_log_stream = FileStream::CreateStdout(); - s_write_binary_options.log_stream = s_log_stream.get(); - break; - - case FLAG_HELP: - print_help(parser, PROGRAM_NAME); - exit(0); - break; - - case FLAG_DUMP_MODULE: - s_dump_module = true; - break; - - case FLAG_OUTPUT: - s_outfile = argument; - break; - - case FLAG_RELOCATABLE: - s_write_binary_options.relocatable = true; - break; - - case FLAG_SPEC: - s_spec = true; - break; - - case FLAG_NO_CANONICALIZE_LEB128S: - s_write_binary_options.canonicalize_lebs = false; - break; - - case FLAG_DEBUG_NAMES: - s_write_binary_options.write_debug_names = true; - break; - - case FLAG_NO_CHECK: - s_validate = false; - break; - - case FLAG_EXCEPTIONS: - s_parse_options.allow_exceptions = true; - break; - - case FLAG_DEBUG_PARSER: - s_parse_options.debug_parsing = true; - break; - } -} - -static void on_argument(struct OptionParser* parser, const char* argument) { - s_infile = argument; -} - -static void on_option_error(struct OptionParser* parser, - const char* message) { - WABT_FATAL("%s\n", message); -} - -static void parse_options(int argc, char** argv) { - OptionParser parser; - WABT_ZERO_MEMORY(parser); - parser.description = s_description; - parser.options = s_options; - parser.num_options = WABT_ARRAY_SIZE(s_options); - parser.on_option = on_option; - parser.on_argument = on_argument; - parser.on_error = on_option_error; - parse_options(&parser, argc, argv); - - if (!s_infile) { - print_help(&parser, PROGRAM_NAME); - WABT_FATAL("No filename given.\n"); - } +R"( read a file in the wasm s-expression format, check it for errors, and + convert it to the wasm binary format. + +examples: + # parse and typecheck test.wast + $ wast2wasm test.wast + + # parse test.wast and write to binary file test.wasm + $ wast2wasm test.wast -o test.wasm + + # parse spec-test.wast, and write verbose output to stdout (including + # the meaning of every byte) + $ wast2wasm spec-test.wast -v + + # parse spec-test.wast, and write files to spec-test.json. Modules are + # written to spec-test.0.wasm, spec-test.1.wasm, etc. + $ wast2wasm spec-test.wast --spec -o spec-test.json +)"; + +static void parse_options(int argc, char* argv[]) { + OptionParser parser("wast2wasm", s_description); + + parser.AddOption('v', "verbose", "Use multiple times for more info", []() { + s_verbose++; + s_log_stream = FileStream::CreateStdout(); + s_write_binary_options.log_stream = s_log_stream.get(); + }); + parser.AddHelpOption(); + parser.AddOption("debug-parser", "Turn on debugging the parser of wast files", + []() { s_parse_options.debug_parsing = true; }); + parser.AddOption('d', "dump-module", + "Print a hexdump of the module to stdout", + []() { s_dump_module = true; }); + parser.AddOption("future-exceptions", + "Test future extension for exception handling", + []() { s_parse_options.allow_exceptions = true; }); + parser.AddOption('o', "output", "FILE", "output wasm binary file", + [](const char* argument) { s_outfile = argument; }); + parser.AddOption( + 'r', "relocatable", + "Create a relocatable wasm binary (suitable for linking with wasm-link)", + []() { s_write_binary_options.relocatable = true; }); + parser.AddOption( + "spec", + "Parse a file with multiple modules and assertions, like the spec tests", + []() { s_spec = true; }); + parser.AddOption( + "no-canonicalize-leb128s", + "Write all LEB128 sizes as 5-bytes instead of their minimal size", + []() { s_write_binary_options.canonicalize_lebs = false; }); + parser.AddOption("debug-names", + "Write debug names to the generated binary file", + []() { s_write_binary_options.write_debug_names = true; }); + parser.AddOption("no-check", "Don't check for invalid modules", + []() { s_validate = false; }); + parser.AddArgument("filename", OptionParser::ArgumentCount::One, + [](const char* argument) { s_infile = argument; }); + + parser.Parse(argc, argv); } static void write_buffer_to_file(const char* filename, |