Initialize the bootstrap class path from standard sources.

Change-Id: Ib49d21f98fd76504e5d3675fc731261426ca84ed
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 56b5db2..f92bc09 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -82,6 +82,7 @@
 	src/dex_instruction_visitor_test.cc \
 	src/jni_compiler_test.cc.arm \
 	src/object_test.cc \
+	src/runtime_test.cc \
 	src/space_test.cc
 
 TEST_TARGET_SRC_FILES := \
diff --git a/src/heap.cc b/src/heap.cc
index 6ec6aac..bc54a82 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -8,6 +8,7 @@
 #include "mark_sweep.h"
 #include "object.h"
 #include "space.h"
+#include "scoped_ptr.h"
 #include "stl_util.h"
 
 namespace art {
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 6c6f493..6aa5c77 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -7,6 +7,8 @@
 
 #include "logging.h"
 #include "runtime.h"
+#include "scoped_ptr.h"
+#include "stringpiece.h"
 #include "thread.h"
 
 namespace art {
@@ -32,7 +34,8 @@
   Runtime::Options options;
   for (int i = 0; i < args->nOptions; ++i) {
     JavaVMOption* option = &args->options[i];
-    options.push_back(std::make_pair(option->optionString, option->extraInfo));
+    options.push_back(std::make_pair(StringPiece(option->optionString),
+                                     option->extraInfo));
   }
   bool ignore_unrecognized = args->ignoreUnrecognized;
   scoped_ptr<Runtime> runtime(Runtime::Create(options, ignore_unrecognized));
diff --git a/src/runtime.cc b/src/runtime.cc
index f03157f..18b001e 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8,6 +8,7 @@
 
 #include "class_linker.h"
 #include "heap.h"
+#include "scoped_ptr.h"
 #include "thread.h"
 
 namespace art {
@@ -50,9 +51,61 @@
   // notreached
 }
 
+void ParseClassPath(const char* class_path, std::vector<std::string>* vec) {
+  CHECK(vec != NULL);
+  scoped_ptr_malloc<char> tmp(strdup(class_path));
+  char* full = tmp.get();
+  char* p = full;
+  while (p) {
+    p = strpbrk(full, ":");
+    if (p != NULL) {
+      p[0] = '\0';
+    }
+    if (full[0] != '\0') {
+      vec->push_back(std::string(full));
+    }
+    if (p) {
+      full = p + 1;
+    }
+  }
+}
+
+// TODO: move option processing elsewhere.
+const char* FindBootClassPath(const Runtime::Options& options) {
+  const char* boot_class_path = getenv("BOOTCLASSPATH");
+  const char* flag = "-Xbootclasspath:";
+  for (size_t i = 0; i < options.size(); ++i) {
+    const StringPiece& option = options[i].first;
+    if (option.starts_with(flag)) {
+      boot_class_path = option.substr(strlen(flag)).data();
+    }
+  }
+  if (boot_class_path == NULL) {
+    return "";
+  } else {
+    return boot_class_path;
+  }
+}
+
+void CreateBootClassPath(const Runtime::Options& options,
+                         std::vector<DexFile*>* boot_class_path) {
+  CHECK(boot_class_path != NULL);
+  const char* str = FindBootClassPath(options);
+  std::vector<std::string> parsed;
+  ParseClassPath(str, &parsed);
+  for (size_t i = 0; i < parsed.size(); ++i) {
+    DexFile* dex_file = DexFile::OpenFile(parsed[i].c_str());
+    if (dex_file != NULL) {
+      boot_class_path->push_back(dex_file);
+    }
+  }
+}
+
+// TODO: do something with ignore_unrecognized when we parse the option
+// strings for real.
 Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) {
-  // TODO: parse arguments
-  std::vector<DexFile*> boot_class_path;  // empty
+  std::vector<DexFile*> boot_class_path;
+  CreateBootClassPath(options, &boot_class_path);
   return Runtime::Create(boot_class_path);
 }
 
diff --git a/src/runtime.h b/src/runtime.h
index 9ff532c..7a1a504 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -4,22 +4,23 @@
 #define ART_SRC_RUNTIME_H_
 
 #include <vector>
+#include <utility>
 
 #include "globals.h"
 #include "macros.h"
-#include "dex_file.h"
 #include "stringpiece.h"
 
 namespace art {
 
 class ClassLinker;
+class DexFile;
 class Heap;
 class JniEnvironment;
 class ThreadList;
 
 class Runtime {
  public:
-  typedef std::vector<std::pair<const char*, void*> > Options;
+  typedef std::vector<std::pair<StringPiece, void*> > Options;
 
   // Creates and initializes a new runtime.
   static Runtime* Create(const Options& options, bool ignore_unrecognized);
diff --git a/src/runtime_test.cc b/src/runtime_test.cc
new file mode 100644
index 0000000..4b59cb3
--- /dev/null
+++ b/src/runtime_test.cc
@@ -0,0 +1,69 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "src/runtime.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+void ParseClassPath(const char* class_path, std::vector<std::string>* vec);
+}
+
+namespace {
+
+TEST(RuntimeTest, ParseClassPath) {
+  std::vector<std::string> vec;
+
+  art::ParseClassPath("", &vec);
+  EXPECT_EQ(0U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":", &vec);
+  EXPECT_EQ(0U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo", &vec);
+  EXPECT_EQ(1U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath("foo:", &vec);
+  EXPECT_EQ(1U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo:", &vec);
+  EXPECT_EQ(1U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath("foo:bar", &vec);
+  EXPECT_EQ(2U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo:bar", &vec);
+  EXPECT_EQ(2U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath("foo:bar:", &vec);
+  EXPECT_EQ(2U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo:bar:", &vec);
+  EXPECT_EQ(2U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath("foo:bar:baz", &vec);
+  EXPECT_EQ(3U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo:bar:baz", &vec);
+  EXPECT_EQ(3U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath("foo:bar:baz:", &vec);
+  EXPECT_EQ(3U, vec.size());
+  vec.clear();
+
+  art::ParseClassPath(":foo:bar:baz:", &vec);
+  EXPECT_EQ(3U, vec.size());
+  vec.clear();
+}
+
+}  // namespace