summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/option-parser.cc268
-rw-r--r--src/option-parser.h104
-rw-r--r--src/tools/wasm-interp.cc154
-rw-r--r--src/tools/wasm-link.cc92
-rw-r--r--src/tools/wasm-objdump.cc131
-rw-r--r--src/tools/wasm-opcodecnt.cc113
-rw-r--r--src/tools/wasm2wast.cc132
-rw-r--r--src/tools/wast-desugar.cc111
-rw-r--r--src/tools/wast2wasm.cc200
-rw-r--r--test/help/wasm-interp.txt14
-rw-r--r--test/help/wasm-link.txt14
-rw-r--r--test/help/wasm-objdump.txt20
-rw-r--r--test/help/wasm-opcodecnt.txt19
-rw-r--r--test/help/wasm2wast.txt (renamed from test/help/wasm-wast.txt)6
-rw-r--r--test/help/wast-desugar.txt23
-rw-r--r--test/help/wast2wasm.txt (renamed from test/help/sexpr-wasm.txt)10
-rw-r--r--test/too-many-arguments.txt6
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 ;;)