Adds Solaris support (by Hady Zalek)

git-svn-id: http://googletest.googlecode.com/svn/trunk@371 861a406c-534a-0410-8894-cb66d6ee9925
diff --git a/include/gtest/gtest-typed-test.h b/include/gtest/gtest-typed-test.h
index 519edfe..1ec8eb8 100644
--- a/include/gtest/gtest-typed-test.h
+++ b/include/gtest/gtest-typed-test.h
@@ -159,8 +159,11 @@
 // given test case.
 #define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
 
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
 #define TYPED_TEST_CASE(CaseName, Types) \
-  typedef ::testing::internal::TypeList<Types>::type \
+  typedef ::testing::internal::TypeList< Types >::type \
       GTEST_TYPE_PARAMS_(CaseName)
 
 #define TYPED_TEST(CaseName, TestName) \
@@ -241,11 +244,14 @@
       GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
           __FILE__, __LINE__, #__VA_ARGS__)
 
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
 #define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
   bool gtest_##Prefix##_##CaseName = \
       ::testing::internal::TypeParameterizedTestCase<CaseName, \
           GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
-          ::testing::internal::TypeList<Types>::type>::Register(\
+          ::testing::internal::TypeList< Types >::type>::Register(\
               #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
 
 #endif  // GTEST_HAS_TYPED_TEST_P
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h
index d5e2e6b..c049a00 100644
--- a/include/gtest/internal/gtest-port.h
+++ b/include/gtest/internal/gtest-port.h
@@ -42,6 +42,8 @@
 //
 //   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
 //                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
 //   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
 //                              is/isn't available (some systems define
 //                              ::string, which is different to std::string).
@@ -242,9 +244,9 @@
 #endif  // GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC ||
         // GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS
 
-// Defines GTEST_HAS_EXCEPTIONS to 1 if exceptions are enabled, or 0
-// otherwise.
-
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 // MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
 // macro to enable exceptions, so we'll do the same.
@@ -253,16 +255,20 @@
 #define _HAS_EXCEPTIONS 1
 #endif  // _HAS_EXCEPTIONS
 #define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
-#else  // The compiler is not MSVC or C++Builder.
-// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.  For
-// other compilers, we assume exceptions are disabled to be
-// conservative.
-#if defined(__GNUC__) && __EXCEPTIONS
+#elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#define GTEST_HAS_EXCEPTIONS 1
+#elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
 #define GTEST_HAS_EXCEPTIONS 1
 #else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
 #define GTEST_HAS_EXCEPTIONS 0
-#endif  // defined(__GNUC__) && __EXCEPTIONS
 #endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
 
 #if !defined(GTEST_HAS_STD_STRING)
 // Even though we don't use this macro any longer, we keep it in case
@@ -340,7 +346,7 @@
 // Determines whether <pthread.h> is available.
 #ifndef GTEST_HAS_PTHREAD
 // The user didn't tell us, so we need to figure it out.
-#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC)
+#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_SOLARIS)
 #endif  // GTEST_HAS_PTHREAD
 
 // Determines whether Google Test can use tr1/tuple.  You can define
@@ -446,7 +452,7 @@
 // Google Test does not support death tests for VC 7.1 and earlier as
 // abort() in a VC 7.1 application compiled as GUI in debug config
 // pops up a dialog window that cannot be suppressed programmatically.
-#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || \
+#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
      (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || GTEST_OS_WINDOWS_MINGW)
 #define GTEST_HAS_DEATH_TEST 1
 #include <vector>  // NOLINT
@@ -462,12 +468,12 @@
 
 // Determines whether to support type-driven tests.
 
-// Typed tests need <typeinfo> and variadic macros, which gcc and VC
-// 8.0+ support.
-#if defined(__GNUC__) || (_MSC_VER >= 1400)
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0, and
+// Sun Pro CC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC)
 #define GTEST_HAS_TYPED_TEST 1
 #define GTEST_HAS_TYPED_TEST_P 1
-#endif  // defined(__GNUC__) || (_MSC_VER >= 1400)
+#endif
 
 // Determines whether to support Combine(). This only makes sense when
 // value-parameterized tests are enabled.
@@ -923,7 +929,7 @@
 #if GTEST_OS_WINDOWS_MOBILE
   // We are on Windows CE, which has no environment variables.
   return NULL;
-#elif defined(__BORLANDC__)
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
   // Environment variables which we programmatically clear will be set to the
   // empty string rather than unset (NULL).  Handle that case.
   const char* const env = getenv(name);
diff --git a/include/gtest/internal/gtest-tuple.h b/include/gtest/internal/gtest-tuple.h
index c201f5c..16178fc 100644
--- a/include/gtest/internal/gtest-tuple.h
+++ b/include/gtest/internal/gtest-tuple.h
@@ -42,7 +42,8 @@
 // tuple template as a friend (it complains that tuple is redefined).  This
 // hack bypasses the bug by declaring the members that should otherwise be
 // private as public.
-#if defined(__SYMBIAN32__)
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
 #define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
 #else
 #define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
diff --git a/include/gtest/internal/gtest-tuple.h.pump b/include/gtest/internal/gtest-tuple.h.pump
index 9e42423..85ebc80 100644
--- a/include/gtest/internal/gtest-tuple.h.pump
+++ b/include/gtest/internal/gtest-tuple.h.pump
@@ -43,7 +43,8 @@
 // tuple template as a friend (it complains that tuple is redefined).  This
 // hack bypasses the bug by declaring the members that should otherwise be
 // private as public.
-#if defined(__SYMBIAN32__)
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
 #define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
 #else
 #define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
diff --git a/src/gtest-filepath.cc b/src/gtest-filepath.cc
index 27a3342..c1ef918 100644
--- a/src/gtest-filepath.cc
+++ b/src/gtest-filepath.cc
@@ -342,9 +342,10 @@
       : *this;
 }
 
-// Normalize removes any redundant separators that might be in the pathname.
+// Removes any redundant separators that might be in the pathname.
 // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
 // redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
 void FilePath::Normalize() {
   if (pathname_.c_str() == NULL) {
     pathname_ = "";
diff --git a/src/gtest-port.cc b/src/gtest-port.cc
index 957595a..7d89e26 100644
--- a/src/gtest-port.cc
+++ b/src/gtest-port.cc
@@ -111,8 +111,14 @@
 // Implements RE.  Currently only needed for death tests.
 
 RE::~RE() {
-  regfree(&partial_regex_);
-  regfree(&full_regex_);
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
   free(const_cast<char*>(pattern_));
 }
 
@@ -152,9 +158,10 @@
   // Some implementation of POSIX regex (e.g. on at least some
   // versions of Cygwin) doesn't accept the empty string as a valid
   // regex.  We change it to an equivalent form "()" to be safe.
-  const char* const partial_regex = (*regex == '\0') ? "()" : regex;
-  is_valid_ = (regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0)
-      && is_valid_;
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
   EXPECT_TRUE(is_valid_)
       << "Regular expression \"" << regex
       << "\" is not a valid POSIX Extended regular expression.";
diff --git a/src/gtest-typed-test.cc b/src/gtest-typed-test.cc
index 4a0f657..3cc4b5d 100644
--- a/src/gtest-typed-test.cc
+++ b/src/gtest-typed-test.cc
@@ -37,6 +37,14 @@
 
 #if GTEST_HAS_TYPED_TEST_P
 
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (isspace(*str))
+    str++;
+  return str;
+}
+
 // Verifies that registered_tests match the test names in
 // defined_test_names_; returns registered_tests if successful, or
 // aborts the program otherwise.
@@ -45,6 +53,10 @@
   typedef ::std::set<const char*>::const_iterator DefinedTestIter;
   registered_ = true;
 
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
   Message errors;
   ::std::set<String> tests;
   for (const char* names = registered_tests; names != NULL;
diff --git a/test/gtest-filepath_test.cc b/test/gtest-filepath_test.cc
index 5706c8e..c5f58f4 100644
--- a/test/gtest-filepath_test.cc
+++ b/test/gtest-filepath_test.cc
@@ -153,31 +153,31 @@
 
 #if GTEST_HAS_ALT_PATH_SEP_
 
-// Test RemoveDirectory* functions with "/".
+// Tests that RemoveDirectoryName() works with the alternate separator
+// on Windows.
 
-// RemoveDirectoryName "/afile" -> "afile"
+// RemoveDirectoryName("/afile") -> "afile"
 TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
   EXPECT_STREQ("afile",
-      FilePath("/afile").RemoveDirectoryName().c_str());
+               FilePath("/afile").RemoveDirectoryName().c_str());
 }
 
-// RemoveDirectoryName "adir/" -> ""
+// RemoveDirectoryName("adir/") -> ""
 TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
   EXPECT_STREQ("",
-      FilePath("adir/").RemoveDirectoryName().c_str());
+               FilePath("adir/").RemoveDirectoryName().c_str());
 }
 
-// RemoveDirectoryName "adir/afile" -> "afile"
+// RemoveDirectoryName("adir/afile") -> "afile"
 TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
   EXPECT_STREQ("afile",
-      FilePath("adir/afile").RemoveDirectoryName().c_str());
+               FilePath("adir/afile").RemoveDirectoryName().c_str());
 }
 
-// RemoveDirectoryName "adir/subdir/afile" -> "afile"
+// RemoveDirectoryName("adir/subdir/afile") -> "afile"
 TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
   EXPECT_STREQ("afile",
-      FilePath("adir/subdir/afile")
-      .RemoveDirectoryName().c_str());
+               FilePath("adir/subdir/afile").RemoveDirectoryName().c_str());
 }
 
 #endif
@@ -222,32 +222,31 @@
 
 #if GTEST_HAS_ALT_PATH_SEP_
 
-// Test RemoveFile* functions with "/".
+// Tests that RemoveFileName() works with the alternate separator on
+// Windows.
 
-// RemoveFileName "adir/" -> "adir/"
+// RemoveFileName("adir/") -> "adir/"
 TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
   EXPECT_STREQ("adir" GTEST_PATH_SEP_,
-      FilePath("adir/").RemoveFileName().c_str());
+               FilePath("adir/").RemoveFileName().c_str());
 }
 
-// RemoveFileName "adir/afile" -> "adir/"
+// RemoveFileName("adir/afile") -> "adir/"
 TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
   EXPECT_STREQ("adir" GTEST_PATH_SEP_,
-      FilePath("adir/afile")
-      .RemoveFileName().c_str());
+               FilePath("adir/afile").RemoveFileName().c_str());
 }
 
-// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
+// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
 TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
   EXPECT_STREQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
-      FilePath("adir/subdir/afile")
-      .RemoveFileName().c_str());
+               FilePath("adir/subdir/afile").RemoveFileName().c_str());
 }
 
-// RemoveFileName "/afile" -> "\"
+// RemoveFileName("/afile") -> "\"
 TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
   EXPECT_STREQ(GTEST_PATH_SEP_,
-      FilePath("/afile").RemoveFileName().c_str());
+               FilePath("/afile").RemoveFileName().c_str());
 }
 
 #endif
@@ -357,9 +356,8 @@
       "foo",
       FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().c_str());
 #if GTEST_HAS_ALT_PATH_SEP_
-  EXPECT_STREQ(
-      "foo",
-      FilePath("foo/").RemoveTrailingPathSeparator().c_str());
+  EXPECT_STREQ("foo",
+               FilePath("foo/").RemoveTrailingPathSeparator().c_str());
 #endif
 }
 
@@ -465,7 +463,9 @@
 
 #if GTEST_HAS_ALT_PATH_SEP_
 
-// "foo\" =="foo/\" == "foo\\/"
+// Tests that separators at the end of the string are normalized
+// regardless of their combination (e.g. "foo\" =="foo/\" ==
+// "foo\\/").
 TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
   EXPECT_STREQ("foo" GTEST_PATH_SEP_,
                FilePath("foo/").c_str());
@@ -678,6 +678,7 @@
   EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
 #else
   EXPECT_TRUE(FilePath("/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("//").IsRootDirectory());
   EXPECT_FALSE(FilePath("").IsRootDirectory());
   EXPECT_FALSE(FilePath("\\").IsRootDirectory());
   EXPECT_FALSE(FilePath("/x").IsRootDirectory());
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index a593494..55313e3 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -74,9 +74,7 @@
 #include <pthread.h>
 #endif  // GTEST_HAS_PTHREAD
 
-#ifdef __BORLANDC__
 #include <map>
-#endif
 
 namespace testing {
 namespace internal {
@@ -1388,12 +1386,16 @@
   EXPECT_STREQ("hello", dest.c_str());
 }
 
+// Sun Studio < 12 incorrectly rejects this code due to an overloading
+// ambiguity.
+#if !(defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
 // Tests streaming a String.
 TEST(StringTest, Streams) {
   EXPECT_EQ(StreamableToString(String()), "(null)");
   EXPECT_EQ(StreamableToString(String("")), "");
   EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
 }
+#endif
 
 // Tests that String::Format() works.
 TEST(StringTest, FormatWorks) {
@@ -2050,7 +2052,7 @@
 #if GTEST_OS_WINDOWS_MOBILE
   // Environment variables are not supported on Windows CE.
   return;
-#elif defined(__BORLANDC__)
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
   // C++Builder's putenv only stores a pointer to its parameter; we have to
   // ensure that the string remains valid as long as it might be needed.
   // We use an std::map to do so.
@@ -2063,7 +2065,11 @@
     prev_env = added_env[name];
   }
   added_env[name] = new String((Message() << name << "=" << value).GetString());
-  putenv(added_env[name]->c_str());
+
+  // The standard signature of putenv accepts a 'char*' argument. Other
+  // implementations, like C++Builder's, accept a 'const char*'.
+  // We cast away the 'const' since that would work for both variants.
+  putenv(const_cast<char*>(added_env[name]->c_str()));
   delete prev_env;
 #elif GTEST_OS_WINDOWS  // If we are on Windows proper.
   _putenv((Message() << name << "=" << value).GetString().c_str());
@@ -3013,7 +3019,10 @@
   // In C++Builder, names within local classes (such as used by
   // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
   // scoping class.  Use a static local alias as a workaround.
-  static const FloatTest::TestValues& v(this->values_);
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
 
   EXPECT_FLOAT_EQ(0.0, v.close_to_positive_zero);
   EXPECT_FLOAT_EQ(-0.0, v.close_to_negative_zero);
@@ -3065,7 +3074,10 @@
   // In C++Builder, names within local classes (such as used by
   // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
   // scoping class.  Use a static local alias as a workaround.
-  static const FloatTest::TestValues& v(this->values_);
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
 
   EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1),
                           "v.nan1");
@@ -3180,7 +3192,10 @@
   // In C++Builder, names within local classes (such as used by
   // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
   // scoping class.  Use a static local alias as a workaround.
-  static const DoubleTest::TestValues& v(this->values_);
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
 
   EXPECT_DOUBLE_EQ(0.0, v.close_to_positive_zero);
   EXPECT_DOUBLE_EQ(-0.0, v.close_to_negative_zero);
@@ -3230,7 +3245,10 @@
   // In C++Builder, names within local classes (such as used by
   // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
   // scoping class.  Use a static local alias as a workaround.
-  static const DoubleTest::TestValues& v(this->values_);
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
 
   // Nokia's STLport crashes if we try to output infinity or NaN.
   EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1),
@@ -4015,7 +4033,8 @@
 // The version of gcc used in XCode 2.2 has a bug and doesn't allow
 // anonymous enums in assertions.  Therefore the following test is not
 // done on Mac.
-#if !GTEST_OS_MAC
+// Sun Studio also rejects this code.
+#if !GTEST_OS_MAC && !defined(__SUNPRO_CC)
 
 // Tests using assertions with anonymous enums.
 enum {
@@ -4060,7 +4079,7 @@
                        "Value of: CASE_B");
 }
 
-#endif  // !GTEST_OS_MAC
+#endif  // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
 
 #if GTEST_OS_WINDOWS