summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/command_line.cc141
-rw-r--r--base/command_line.h8
-rw-r--r--base/command_line_unittest.cc21
3 files changed, 130 insertions, 40 deletions
diff --git a/base/command_line.cc b/base/command_line.cc
index 7755578..a142f95 100644
--- a/base/command_line.cc
+++ b/base/command_line.cc
@@ -27,17 +27,30 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include "base/command_line.h"
+
+#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
+#endif
#include <algorithm>
-#include "base/command_line.h"
-
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"
+extern "C" {
+#if defined(OS_MACOSX)
+const char** NXArgv;
+int NXArgc;
+#elif defined(OS_LINUX)
+extern "C" {
+const char** __libc_argv;
+int __libc_argv;
+#endif
+} // extern "C"
+
using namespace std;
// Since we use a lazy match, make sure that longer versions (like L"--")
@@ -46,8 +59,15 @@ const wchar_t* const CommandLine::kSwitchPrefixes[] = {L"--", L"-", L"/"};
const wchar_t CommandLine::kSwitchValueSeparator[] = L"=";
+// Needed to avoid a typecast on the tolower() function pointer in Lowercase().
+// MSVC accepts it as-is but GCC requires the typecast.
+static int ToLower(int c) {
+ return tolower(c);
+}
+
static void Lowercase(wstring* parameter) {
- transform(parameter->begin(), parameter->end(), parameter->begin(), tolower);
+ transform(parameter->begin(), parameter->end(), parameter->begin(),
+ ToLower);
}
// CommandLine::Data
@@ -61,13 +81,85 @@ static void Lowercase(wstring* parameter) {
// Do NOT add any non-const methods to this object. You have been warned.
class CommandLine::Data {
public:
- Data() {
+#if defined(OS_WIN)
+ Data() {
Init(GetCommandLineW());
}
+#elif defined(OS_MACOSX)
+ Data() {
+ Init(NXArgc, NXArgv);
+ }
+#elif defined(OS_LINUX)
+ Data() {
+ Init(__gnuc_argc, __gnuc_argv);
+ }
+#endif
+#if defined(OS_WIN)
Data(const wstring& command_line) {
Init(command_line);
}
+#elif defined(OS_POSIX)
+ Data(const int argc, const char* argv[]) {
+ Init(argc, argv);
+ }
+#endif
+
+#if defined(OS_WIN)
+ // Does the actual parsing of the command line.
+ void Init(const std::wstring& command_line) {
+ TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
+
+ if (command_line_string_.empty())
+ return;
+
+ int num_args = 0;
+ wchar_t** args = NULL;
+
+ args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
+
+ // Populate program_ with the trimmed version of the first arg.
+ TrimWhitespace(args[0], TRIM_ALL, &program_);
+
+ for (int i = 1; i < num_args; ++i) {
+ wstring arg;
+ TrimWhitespace(args[i], TRIM_ALL, &arg);
+
+ wstring switch_string;
+ wstring switch_value;
+ if (IsSwitch(arg, &switch_string, &switch_value)) {
+ switches_[switch_string] = switch_value;
+ } else {
+ loose_values_.push_back(arg);
+ }
+ }
+
+ if (args)
+ LocalFree(args);
+ }
+#elif defined(OS_POSIX) // Does the actual parsing of the command line.
+ void Init(int argc, const char* argv[]) {
+ if (argc <= 1)
+ return;
+
+ program_ = NativeMBToWide(argv[0]);
+ command_line_string_ = program_;
+
+ for (int i = 1; i < argc; ++i) {
+ std::wstring arg = NativeMBToWide(argv[i]);
+ command_line_string_.append(L" ");
+ command_line_string_.append(arg);
+
+ wstring switch_string;
+ wstring switch_value;
+ if (IsSwitch(arg, &switch_string, &switch_value)) {
+ switches_[switch_string] = switch_value;
+ } else {
+ loose_values_.push_back(arg);
+ }
+ }
+ }
+#endif
const std::wstring& command_line_string() const {
return command_line_string_;
@@ -119,44 +211,12 @@ class CommandLine::Data {
return false;
}
- // Does the actual parsing of the command line.
- void Init(const std::wstring& command_line) {
- TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
-
- if (command_line_string_.empty())
- return;
-
- int num_args = 0;
- wchar_t** args = NULL;
-
- args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
-
- // Populate program_ with the trimmed version of the first arg.
- TrimWhitespace(args[0], TRIM_ALL, &program_);
-
- for (int i = 1; i < num_args; ++i) {
- wstring arg;
- TrimWhitespace(args[i], TRIM_ALL, &arg);
-
- wstring switch_string;
- wstring switch_value;
- if (IsSwitch(arg, &switch_string, &switch_value)) {
- switches_[switch_string] = switch_value;
- } else {
- loose_values_.push_back(arg);
- }
- }
-
- if (args)
- LocalFree(args);
- }
-
std::wstring command_line_string_;
std::wstring program_;
std::map<std::wstring, std::wstring> switches_;
std::vector<std::wstring> loose_values_;
- DISALLOW_EVIL_CONSTRUCTORS(CommandLine::Data);
+ DISALLOW_EVIL_CONSTRUCTORS(Data);
};
CommandLine::CommandLine()
@@ -164,10 +224,17 @@ CommandLine::CommandLine()
data_(Singleton<Data>::get()) {
}
+#if defined(OS_WIN)
CommandLine::CommandLine(const wstring& command_line)
: we_own_data_(true),
data_(new Data(command_line)) {
}
+#elif defined(OS_POSIX)
+CommandLine::CommandLine(const int argc, const char* argv[])
+ : we_own_data_(true),
+ data_(new Data(argc, argv)) {
+}
+#endif
CommandLine::~CommandLine() {
if (we_own_data_)
diff --git a/base/command_line.h b/base/command_line.h
index f1b7ade..4f24f26 100644
--- a/base/command_line.h
+++ b/base/command_line.h
@@ -50,9 +50,13 @@ class CommandLine {
// the current process.
CommandLine();
+#if defined(OS_WIN)
// Creates a parsed version of the given command-line string.
- // The program name is assumed to be the first item in the string.
+ // The program name is assumed to be the first item in the string.
CommandLine(const std::wstring& command_line);
+#elif defined(OS_POSIX)
+ CommandLine(int argc, const char** argv);
+#endif
~CommandLine();
@@ -112,7 +116,7 @@ class CommandLine {
// A pointer to the parsed version of the command line.
Data* data_;
-
+
DISALLOW_EVIL_CONSTRUCTORS(CommandLine);
};
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
index dbcf06f..6a0a62c 100644
--- a/base/command_line_unittest.cc
+++ b/base/command_line_unittest.cc
@@ -31,6 +31,7 @@
#include <vector>
#include "base/command_line.h"
+#include "base/basictypes.h"
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,12 +41,21 @@ namespace {
};
TEST(CommandLineTest, CommandLineConstructor) {
+#ifdef OS_WIN
CommandLine cl(L"program --foo= -bAr /Spaetzel=pierogi /Baz flim "
L"--other-switches=\"--dog=canine --cat=feline\" "
L"-spaetzle=Crepe -=loosevalue flan "
L"--input-translation=\"45\"--output-rotation "
L"\"in the time of submarines...\"");
-
+#elif OS_POSIX
+ const char* argv[] = {"program", "--foo=", "-bAr",
+ "/Spaetzel=pierogi /Baz flim",
+ "--other-switches=\"--dog=canine --cat=feline\"",
+ "-spaetzle=Crepe", "-=loosevalue", "flan",
+ "--input-translation=\"45\"--output-rotation",
+ "\"in the time of submarines...\""};
+ CommandLine cl(arraysize(argv), argv);
+#endif
EXPECT_FALSE(cl.command_line_string().empty());
EXPECT_FALSE(cl.HasSwitch(L"cruller"));
EXPECT_FALSE(cl.HasSwitch(L"flim"));
@@ -92,13 +102,21 @@ TEST(CommandLineTest, DefaultConstructor) {
// Tests behavior with an empty input string.
TEST(CommandLineTest, EmptyString) {
+#if defined(OS_WIN)
CommandLine cl(L"");
+#elif defined(OS_POSIX)
+ const char* argv[] = {};
+ CommandLine cl(ARRAYSIZE_UNSAFE(argv), argv);
+#endif
EXPECT_TRUE(cl.command_line_string().empty());
EXPECT_TRUE(cl.program().empty());
EXPECT_EQ(0, cl.GetLooseValueCount());
}
// Test static functions for appending switches to a command line.
+// TODO(pinkerton): non-windows platforms don't have the requisite ctor here, so
+// we need something that tests AppendSwitches in another way (if even desired).
+#if defined(OS_WIN)
TEST(CommandLineTest, AppendSwitches) {
std::wstring cl_string = L"Program";
std::wstring switch1 = L"switch1";
@@ -123,3 +141,4 @@ TEST(CommandLineTest, AppendSwitches) {
EXPECT_TRUE(cl.HasSwitch(switch2));
EXPECT_EQ(value4.substr(1, value4.length() - 2), cl.GetSwitchValue(switch4));
}
+#endif