From c65c429e2b91e73939ea0153ffc8121c314c066a Mon Sep 17 00:00:00 2001 From: Chris Leary Date: Mon, 29 Aug 2011 12:19:19 -0700 Subject: [PATCH] Bug 679138: argv past script argument should not be interpreted as options. (r=dvander) --- js/src/methodjit/Compiler.cpp | 4 ++-- js/src/shell/js.cpp | 2 ++ js/src/shell/jsoptparse.cpp | 25 ++++++++++++++++++++----- js/src/shell/jsoptparse.h | 11 ++++++++--- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 62721cbcd4b..6e027f717f8 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -225,8 +225,8 @@ mjit::Compiler::performCompilation(JITScript **jitp) JaegerSpew(JSpew_Prof, "compilation took %d us\n", prof.time_us()); #endif - JaegerSpew(JSpew_Scripts, "successfully compiled (code \"%p\") (size \"%ld\")\n", - (*jitp)->code.m_code.executableAddress(), (*jitp)->code.m_size); + JaegerSpew(JSpew_Scripts, "successfully compiled (code \"%p\") (size \"%u\")\n", + (*jitp)->code.m_code.executableAddress(), unsigned((*jitp)->code.m_size)); return Compile_Okay; } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 4c158f44c36..fe1d705ff01 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5608,6 +5608,8 @@ main(int argc, char **argv, char **envp) return EXIT_FAILURE; } + op.setArgTerminatesOptions("script", true); + switch (op.parseArgs(argc, argv)) { case OptionParser::ParseHelp: return EXIT_SUCCESS; diff --git a/js/src/shell/jsoptparse.cpp b/js/src/shell/jsoptparse.cpp index 938b6b0d2ef..3be80491012 100644 --- a/js/src/shell/jsoptparse.cpp +++ b/js/src/shell/jsoptparse.cpp @@ -84,6 +84,12 @@ OPTION_CONVERT_IMPL(String) OPTION_CONVERT_IMPL(Int) OPTION_CONVERT_IMPL(MultiString) +void +OptionParser::setArgTerminatesOptions(const char *name, bool enabled) +{ + findArgument(name)->setTerminatesOptions(enabled); +} + OptionParser::Result OptionParser::error(const char *fmt, ...) { @@ -284,8 +290,11 @@ OptionParser::extractValue(size_t argc, char **argv, size_t *i, char **value) } OptionParser::Result -OptionParser::handleOption(Option *opt, size_t argc, char **argv, size_t *i) +OptionParser::handleOption(Option *opt, size_t argc, char **argv, size_t *i, bool *optionsAllowed) { + if (opt->getTerminatesOptions()) + *optionsAllowed = false; + switch (opt->kind) { case OptionKindBool: { @@ -329,12 +338,16 @@ OptionParser::handleOption(Option *opt, size_t argc, char **argv, size_t *i) } OptionParser::Result -OptionParser::handleArg(size_t argc, char **argv, size_t *i) +OptionParser::handleArg(size_t argc, char **argv, size_t *i, bool *optionsAllowed) { if (nextArgument >= arguments.length()) return error("Too many arguments provided"); Option *arg = arguments[nextArgument]; + + if (arg->getTerminatesOptions()) + *optionsAllowed = false; + switch (arg->kind) { case OptionKindString: arg->asStringOption()->value = argv[*i]; @@ -357,11 +370,13 @@ OptionParser::parseArgs(int inputArgc, char **argv) { JS_ASSERT(inputArgc >= 0); size_t argc = inputArgc; + /* Permit a "no more options" capability, like |--| offers in many shell interfaces. */ + bool optionsAllowed = true; for (size_t i = 1; i < argc; ++i) { char *arg = argv[i]; Result r; - if (arg[0] == '-') { + if (arg[0] == '-' && optionsAllowed) { /* Option. */ size_t arglen = strlen(arg); if (arglen < 2) /* Do not permit solo dash option. */ @@ -382,10 +397,10 @@ OptionParser::parseArgs(int inputArgc, char **argv) return error("Invalid short option: %s", arg); } - r = handleOption(opt, argc, argv, &i); + r = handleOption(opt, argc, argv, &i, &optionsAllowed); } else { /* Argument. */ - r = handleArg(argc, argv, &i); + r = handleArg(argc, argv, &i, &optionsAllowed); } switch (r) { case Okay: diff --git a/js/src/shell/jsoptparse.h b/js/src/shell/jsoptparse.h index f3f131219fd..0a9b9b792b9 100644 --- a/js/src/shell/jsoptparse.h +++ b/js/src/shell/jsoptparse.h @@ -70,13 +70,17 @@ struct Option const char *help; OptionKind kind; char shortflag; + bool terminatesOptions; Option(OptionKind kind, char shortflag, const char *longflag, const char *help) - : longflag(longflag), help(help), kind(kind), shortflag(shortflag) + : longflag(longflag), help(help), kind(kind), shortflag(shortflag), terminatesOptions(false) {} virtual ~Option() = 0; + void setTerminatesOptions(bool enabled) { terminatesOptions = enabled; } + bool getTerminatesOptions() const { return terminatesOptions; } + virtual bool isValued() const { return false; } /* Only some valued options are variadic (like MultiStringOptions). */ @@ -248,8 +252,8 @@ class OptionParser Result error(const char *fmt, ...); Result extractValue(size_t argc, char **argv, size_t *i, char **value); - Result handleArg(size_t argc, char **argv, size_t *i); - Result handleOption(Option *opt, size_t argc, char **argv, size_t *i); + Result handleArg(size_t argc, char **argv, size_t *i, bool *optsAllowed); + Result handleOption(Option *opt, size_t argc, char **argv, size_t *i, bool *optsAllowed); public: explicit OptionParser(const char *usage) @@ -269,6 +273,7 @@ class OptionParser void setDescriptionWidth(size_t width) { descrWidth = width; } void setDescription(const char *description) { descr = description; } void setHelpOption(char shortflag, const char *longflag, const char *help); + void setArgTerminatesOptions(const char *name, bool enabled); /* Arguments: no further arguments may be added after a variadic argument. */