diff options
-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 | ||||
-rw-r--r-- | test/help/wasm-interp.txt | 14 | ||||
-rw-r--r-- | test/help/wasm-link.txt | 14 | ||||
-rw-r--r-- | test/help/wasm-objdump.txt | 20 | ||||
-rw-r--r-- | test/help/wasm-opcodecnt.txt | 19 | ||||
-rw-r--r-- | test/help/wasm2wast.txt (renamed from test/help/wasm-wast.txt) | 6 | ||||
-rw-r--r-- | test/help/wast-desugar.txt | 23 | ||||
-rw-r--r-- | test/help/wast2wasm.txt (renamed from test/help/sexpr-wasm.txt) | 10 | ||||
-rw-r--r-- | test/too-many-arguments.txt | 6 |
17 files changed, 600 insertions, 817 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, diff --git a/test/help/wasm-interp.txt b/test/help/wasm-interp.txt index 1d2b95df..fde7bd96 100644 --- a/test/help/wasm-interp.txt +++ b/test/help/wasm-interp.txt @@ -24,11 +24,11 @@ examples: $ wasm-interp test.wasm -V 100 --run-all-exports options: - -v, --verbose use multiple times for more info - -h, --help print this help message - -V, --value-stack-size=SIZE size in elements of the value stack - -C, --call-stack-size=SIZE size in frames of the call stack - -t, --trace trace execution - --spec run spec tests (input file should be .json) - --run-all-exports run all the exported functions, in order. useful for testing + -v, --verbose Use multiple times for more info + -h, --help Print this help message + -V, --value-stack-size=SIZE Size in elements of the value stack + -C, --call-stack-size=SIZE Size in elements of the call stack + -t, --trace Trace execution + --spec Run spec tests (input file should be .json) + --run-all-exports Run all the exported functions, in order. Useful for testing ;;; STDOUT ;;) diff --git a/test/help/wasm-link.txt b/test/help/wasm-link.txt new file mode 100644 index 00000000..9f030d2d --- /dev/null +++ b/test/help/wasm-link.txt @@ -0,0 +1,14 @@ +;;; EXE: %(wasm-link)s +;;; FLAGS: --help +(;; STDOUT ;;; +usage: wasm-link [options] filename+ + + link one or more wasm binary modules into a single binary module. + $ wasm-link m1.wasm m2.wasm -o out.wasm + +options: + --debug Log extra information when reading and writing wasm files + -o, --output=FILE Output wasm binary file + -r, --relocatable Output a relocatable object file + -h, --help Print this help message +;;; STDOUT ;;) diff --git a/test/help/wasm-objdump.txt b/test/help/wasm-objdump.txt new file mode 100644 index 00000000..23548b22 --- /dev/null +++ b/test/help/wasm-objdump.txt @@ -0,0 +1,20 @@ +;;; EXE: %(wasm-objdump)s +;;; FLAGS: --help +(;; STDOUT ;;; +usage: wasm-objdump [options] filename+ + + Print information about the contents of wasm binaries. + +examples: + $ wasm-objdump test.wasm + +options: + -h, --headers Print headers + -j, --section=SECTION Select just one section + -s, --full-contents Print raw section contents + -d, --disassemble Disassemble function bodies + --debug Print extra debug information + -x, --details Show section details + -r, --reloc Show relocations inline with disassembly + -h, --help Print this help message +;;; STDOUT ;;) diff --git a/test/help/wasm-opcodecnt.txt b/test/help/wasm-opcodecnt.txt new file mode 100644 index 00000000..d8c3927d --- /dev/null +++ b/test/help/wasm-opcodecnt.txt @@ -0,0 +1,19 @@ +;;; EXE: %(wasm-opcodecnt)s +;;; FLAGS: --help +(;; STDOUT ;;; +usage: wasm-opcodecnt [options] filename+ + + Read a file in the wasm binary format, and count opcode usage for + instructions. + +examples: + # parse binary file test.wasm and write pcode dist file test.dist + $ wasm-opcodecnt test.wasm -o test.dist + +options: + -v, --verbose Use multiple times for more info + -h, --help Print this help message + -o, --output=FILENAME Output file for the opcode counts, by default use stdout + -c, --cutoff=N Cutoff for reporting counts less than N + -s, --separator=SEPARATOR Separator text between element and count when reporting counts +;;; STDOUT ;;) diff --git a/test/help/wasm-wast.txt b/test/help/wasm2wast.txt index 3b0ee185..08533d9d 100644 --- a/test/help/wasm-wast.txt +++ b/test/help/wasm2wast.txt @@ -14,9 +14,9 @@ examples: $ wasm2wast test.wasm --no-debug-names -o test.wast options: - -v, --verbose use multiple times for more info - -h, --help print this help message - -o, --output=FILENAME output file for the generated wast file, by default use stdout + -v, --verbose Use multiple times for more info + -h, --help Print this help message + -o, --output=FILENAME Output file for the generated wast file, by default use stdout -f, --fold-exprs Write folded expressions where possible --inline-exports Write all exports inline --no-debug-names Ignore debug names in the binary file diff --git a/test/help/wast-desugar.txt b/test/help/wast-desugar.txt new file mode 100644 index 00000000..5f9f1b11 --- /dev/null +++ b/test/help/wast-desugar.txt @@ -0,0 +1,23 @@ +;;; EXE: %(wast-desugar)s +;;; FLAGS: --help +(;; STDOUT ;;; +usage: wast-desugar [options] filename + + read a file in the wasm s-expression format and format it. + +examples: + # write output to stdout + $ wast-desugar test.wast + + # write output to test2.wast + $ wast-desugar test.wast -o test2.wast + + # generate names for indexed variables + $ wast-desugar --generate-names test.wast + +options: + -h, --help Print this help message + -o, --output=FILE Output file for the formatted file + -f, --fold-exprs Write folded expressions where possible + --generate-names Give auto-generated names to non-named functions, types, etc. +;;; STDOUT ;;) diff --git a/test/help/sexpr-wasm.txt b/test/help/wast2wasm.txt index dff7c894..f845ea1f 100644 --- a/test/help/sexpr-wasm.txt +++ b/test/help/wast2wasm.txt @@ -22,14 +22,14 @@ examples: $ wast2wasm spec-test.wast --spec -o spec-test.json options: - -v, --verbose use multiple times for more info - -h, --help print this help message + -v, --verbose Use multiple times for more info + -h, --help Print this help message --debug-parser Turn on debugging the parser of wast files - -d, --dump-module print a hexdump of the module to stdout + -d, --dump-module Print a hexdump of the module to stdout --future-exceptions Test future extension for exception handling -o, --output=FILE output wasm binary file - -r, create a relocatable wasm binary (suitable for linking with wasm-link) - --spec parse a file with multiple modules and assertions, like the spec tests + -r, --relocatable Create a relocatable wasm binary (suitable for linking with wasm-link) + --spec Parse a file with multiple modules and assertions, like the spec tests --no-canonicalize-leb128s Write all LEB128 sizes as 5-bytes instead of their minimal size --debug-names Write debug names to the generated binary file --no-check Don't check for invalid modules diff --git a/test/too-many-arguments.txt b/test/too-many-arguments.txt new file mode 100644 index 00000000..9189b729 --- /dev/null +++ b/test/too-many-arguments.txt @@ -0,0 +1,6 @@ +;;; EXE: %(wast2wasm)s +;;; FLAGS: foo.txt bar.txt +;;; ERROR: 1 +(;; STDERR ;;; +unexpected argument 'bar.txt' +;;; STDERR ;;) |