11be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Copyright 2008, Google Inc.
21be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// All rights reserved.
31be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
41be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Redistribution and use in source and binary forms, with or without
51be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// modification, are permitted provided that the following conditions are
61be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// met:
71be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
81be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//     * Redistributions of source code must retain the above copyright
91be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// notice, this list of conditions and the following disclaimer.
101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//     * Redistributions in binary form must reproduce the above
111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// copyright notice, this list of conditions and the following disclaimer
121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// in the documentation and/or other materials provided with the
131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// distribution.
141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//     * Neither the name of Google Inc. nor the names of its
151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// contributors may be used to endorse or promote products derived from
161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// this software without specific prior written permission.
171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Author: wan@google.com (Zhanyong Wan)
311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-port.h"
331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <limits.h>
351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdlib.h>
361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdio.h>
3741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <string.h>
381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE
4041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <windows.h>  // For TerminateProcess()
4141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_WINDOWS
4241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <io.h>
4341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <sys/stat.h>
441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else
4541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <unistd.h>
4641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_OS_WINDOWS_MOBILE
471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC
4941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/mach_init.h>
5041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/task.h>
5141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/vm_map.h>
5241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_OS_MAC
531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-spi.h"
5541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-message.h"
5641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-internal.h"
5741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-string.h"
581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Indicates that this translation unit is part of Google Test's
601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// implementation.  It must come before gtest-internal-inl.h is
611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// included, or there will be a compiler error.  This trick is to
621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// prevent a user from accidentally including gtest-internal-inl.h in
631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// his code.
641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#define GTEST_IMPLEMENTATION_ 1
651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include "src/gtest-internal-inl.h"
661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#undef GTEST_IMPLEMENTATION_
671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace testing {
691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace internal {
701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if defined(_MSC_VER) || defined(__BORLANDC__)
7241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
7341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = 1;
741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = 2;
751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else
7641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = STDOUT_FILENO;
771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = STDERR_FILENO;
7841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // _MSC_VER
7941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
8041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC
8141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
8241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Returns the number of threads running in the process, or 0 to indicate that
8341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// we cannot detect it.
8441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() {
8541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const task_t task = mach_task_self();
8641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  mach_msg_type_number_t thread_count;
8741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  thread_act_array_t thread_list;
8841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
8941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (status == KERN_SUCCESS) {
9041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // task_threads allocates resources in thread_list and we need to free them
9141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // to avoid leaks.
9241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    vm_deallocate(task,
9341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                  reinterpret_cast<vm_address_t>(thread_list),
9441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                  sizeof(thread_t) * thread_count);
9541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return static_cast<size_t>(thread_count);
9641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  } else {
9741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return 0;
9841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
9941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
10041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
10141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else
10241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
10341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() {
10441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // There's no portable way to detect the number of threads, so we just
10541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // return 0 to indicate that we cannot detect it.
10641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return 0;
10741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
10841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
10941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_OS_MAC
1101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_USES_POSIX_RE
1121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements RE.  Currently only needed for death tests.
1141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1151be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() {
11641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (is_valid_) {
11741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // regfree'ing an invalid regex might crash because the content
11841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // of the regex is undefined. Since the regex's are essentially
11941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // the same, one cannot be valid (or invalid) without the other
12041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // being so too.
12141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    regfree(&partial_regex_);
12241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    regfree(&full_regex_);
12341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
1241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  free(const_cast<char*>(pattern_));
1251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str.
1281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) {
1291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (!re.is_valid_) return false;
1301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  regmatch_t match;
1321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
1331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str
1361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself).
1371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) {
1381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (!re.is_valid_) return false;
1391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  regmatch_t match;
1411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
1421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation.
1451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) {
14641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  pattern_ = posix::StrDup(regex);
1471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Reserves enough bytes to hold the regular expression used for a
1491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // full match.
1501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const size_t full_regex_len = strlen(regex) + 10;
1511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  char* const full_pattern = new char[full_regex_len];
1521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
1541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
1551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // We want to call regcomp(&partial_regex_, ...) even if the
1561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // previous expression returns false.  Otherwise partial_regex_ may
1571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // not be properly initialized can may cause trouble when it's
1581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // freed.
1591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  //
1601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Some implementation of POSIX regex (e.g. on at least some
1611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // versions of Cygwin) doesn't accept the empty string as a valid
1621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // regex.  We change it to an equivalent form "()" to be safe.
16341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (is_valid_) {
16441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
16541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
16641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
1671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  EXPECT_TRUE(is_valid_)
1681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      << "Regular expression \"" << regex
1691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      << "\" is not a valid POSIX Extended regular expression.";
1701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  delete[] full_pattern;
1721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#elif GTEST_USES_SIMPLE_RE
1751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch appears anywhere in str (excluding the
1771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// terminating '\0' character).
1781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsInSet(char ch, const char* str) {
1791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return ch != '\0' && strchr(str, ch) != NULL;
1801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch belongs to the given classification.  Unlike
1831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// similar functions in <ctype.h>, these aren't affected by the
1841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// current locale.
18541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
18641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiPunct(char ch) {
1871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
1881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
19041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
19141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWordChar(char ch) {
1921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
1931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      ('0' <= ch && ch <= '9') || ch == '_';
1941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
1951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
1961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff "\\c" is a supported escape sequence.
1971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsValidEscape(char c) {
19841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
1991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
2001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff the given atom (specified by escaped and pattern)
2021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// matches ch.  The result is undefined if the atom is invalid.
2031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
2041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (escaped) {  // "\\p" where p is pattern_char.
2051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    switch (pattern_char) {
20641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 'd': return IsAsciiDigit(ch);
20741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 'D': return !IsAsciiDigit(ch);
2081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      case 'f': return ch == '\f';
2091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      case 'n': return ch == '\n';
2101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      case 'r': return ch == '\r';
21141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 's': return IsAsciiWhiteSpace(ch);
21241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 'S': return !IsAsciiWhiteSpace(ch);
2131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      case 't': return ch == '\t';
2141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      case 'v': return ch == '\v';
21541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 'w': return IsAsciiWordChar(ch);
21641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      case 'W': return !IsAsciiWordChar(ch);
2171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    }
21841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return IsAsciiPunct(pattern_char) && pattern_char == ch;
2191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
2201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
2221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
2231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Helper function used by ValidateRegex() to format error messages.
2251be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaString FormatRegexSyntaxError(const char* regex, int index) {
2261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return (Message() << "Syntax error at index " << index
2271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania          << " in simple regular expression \"" << regex << "\": ").GetString();
2281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
2291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Generates non-fatal failures and returns false if regex is invalid;
2311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// otherwise returns true.
2321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ValidateRegex(const char* regex) {
2331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (regex == NULL) {
2341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // TODO(wan@google.com): fix the source file location in the
2351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // assertion failures to match where the regex is used in user
2361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // code.
2371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
2381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return false;
2391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
2401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  bool is_valid = true;
2421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // True iff ?, *, or + can follow the previous atom.
2441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  bool prev_repeatable = false;
2451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  for (int i = 0; regex[i]; i++) {
2461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    if (regex[i] == '\\') {  // An escape sequence
2471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      i++;
2481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      if (regex[i] == '\0') {
2491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
2501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "'\\' cannot appear at the end.";
2511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        return false;
2521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      }
2531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      if (!IsValidEscape(regex[i])) {
2551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
2561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "invalid escape sequence \"\\" << regex[i] << "\".";
2571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        is_valid = false;
2581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      }
2591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      prev_repeatable = true;
2601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    } else {  // Not an escape sequence.
2611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      const char ch = regex[i];
2621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      if (ch == '^' && i > 0) {
2641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
2651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "'^' can only appear at the beginning.";
2661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        is_valid = false;
2671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      } else if (ch == '$' && regex[i + 1] != '\0') {
2681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
2691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "'$' can only appear at the end.";
2701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        is_valid = false;
2711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      } else if (IsInSet(ch, "()[]{}|")) {
2721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
2731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "'" << ch << "' is unsupported.";
2741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        is_valid = false;
2751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      } else if (IsRepeat(ch) && !prev_repeatable) {
2761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
2771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                      << "'" << ch << "' can only follow a repeatable token.";
2781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        is_valid = false;
2791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      }
2801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      prev_repeatable = !IsInSet(ch, "^$?*+");
2821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    }
2831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
2841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return is_valid;
2861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
2871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
2881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Matches a repeated regex atom followed by a valid simple regular
2891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// expression.  The regex atom is defined as c if escaped is false,
2901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or \c otherwise.  repeat is the repetition meta character (?, *,
2911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or +).  The behavior is undefined if str contains too many
2921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// characters to be indexable by size_t, in which case the test will
2931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// probably time out anyway.  We are fine with this limitation as
2941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// std::string has it too.
2951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRepetitionAndRegexAtHead(
2961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    bool escaped, char c, char repeat, const char* regex,
2971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    const char* str) {
2981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const size_t min_count = (repeat == '+') ? 1 : 0;
2991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const size_t max_count = (repeat == '?') ? 1 :
3001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      static_cast<size_t>(-1) - 1;
3011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // We cannot call numeric_limits::max() as it conflicts with the
3021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // max() macro on Windows.
3031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  for (size_t i = 0; i <= max_count; ++i) {
3051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // We know that the atom matches each of the first i characters in str.
3061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
3071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // We have enough matches at the head, and the tail matches too.
3081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // Since we only care about *whether* the pattern matches str
3091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // (as opposed to *how* it matches), there is no need to find a
3101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // greedy match.
3111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      return true;
3121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    }
3131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
3141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      return false;
3151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
3161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return false;
3171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches a prefix of str.  regex must be a
3201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// valid simple regular expression and not start with "^", or the
3211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// result is undefined.
3221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAtHead(const char* regex, const char* str) {
3231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (*regex == '\0')  // An empty regex matches a prefix of anything.
3241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return true;
3251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // "$" only matches the end of a string.  Note that regex being
3271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // valid guarantees that there's nothing after "$" in it.
3281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (*regex == '$')
3291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return *str == '\0';
3301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Is the first thing in regex an escape sequence?
3321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const bool escaped = *regex == '\\';
3331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (escaped)
3341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    ++regex;
3351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (IsRepeat(regex[1])) {
3361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
3371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // here's an indirect recursion.  It terminates as the regex gets
3381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // shorter in each recursion.
3391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return MatchRepetitionAndRegexAtHead(
3401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        escaped, regex[0], regex[1], regex + 2, str);
3411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  } else {
3421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // regex isn't empty, isn't "$", and doesn't start with a
3431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // repetition.  We match the first atom of regex with the first
3441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // character of str and recurse.
3451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
3461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        MatchRegexAtHead(regex + 1, str + 1);
3471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
3481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches any substring of str.  regex must be
3511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// a valid simple regular expression, or the result is undefined.
3521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
3531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The algorithm is recursive, but the recursion depth doesn't exceed
3541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the regex length, so we won't need to worry about running out of
3551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// stack space normally.  In rare cases the time complexity can be
3561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// exponential with respect to the regex length + the string length,
3571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// but usually it's must faster (often close to linear).
3581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAnywhere(const char* regex, const char* str) {
3591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (regex == NULL || str == NULL)
3601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return false;
3611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (*regex == '^')
3631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return MatchRegexAtHead(regex + 1, str);
3641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // A successful match can be anywhere in str.
3661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  do {
3671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    if (MatchRegexAtHead(regex, str))
3681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      return true;
3691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  } while (*str++ != '\0');
3701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return false;
3711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements the RE class.
3741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3751be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() {
3761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  free(const_cast<char*>(pattern_));
3771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  free(const_cast<char*>(full_pattern_));
3781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str.
3811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) {
3821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
3831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str
3861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself).
3871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) {
3881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
3891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
3901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation.
3921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) {
3931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  pattern_ = full_pattern_ = NULL;
3941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (regex != NULL) {
39541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    pattern_ = posix::StrDup(regex);
3961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
3971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
3981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  is_valid_ = ValidateRegex(regex);
3991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (!is_valid_) {
4001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // No need to calculate the full pattern when the regex is invalid.
4011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return;
4021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
4031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const size_t len = strlen(regex);
4051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Reserves enough bytes to hold the regular expression used for a
4061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // full match: we need space to prepend a '^', append a '$', and
4071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // terminate the string with '\0'.
4081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  char* buffer = static_cast<char*>(malloc(len + 3));
4091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  full_pattern_ = buffer;
4101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (*regex != '^')
4121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
4131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // We don't use snprintf or strncpy, as they trigger a warning when
4151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // compiled with VC++ 8.0.
4161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  memcpy(buffer, regex, len);
4171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  buffer += len;
4181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (len == 0 || regex[len - 1] != '$')
4201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
4211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  *buffer = '\0';
4231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
4241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif  // GTEST_USES_POSIX_RE
4261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
42741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst char kUnknownFile[] = "unknown file";
42841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
42941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a source file path and a line number as they would appear
43041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// in an error message from the compiler used to compile this code.
43141d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
43241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const char* const file_name = file == NULL ? kUnknownFile : file;
43341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
43441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (line < 0) {
43541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return String::Format("%s:", file_name).c_str();
43641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
43741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#ifdef _MSC_VER
43841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return String::Format("%s(%d):", file_name, line).c_str();
43941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else
44041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return String::Format("%s:%d:", file_name, line).c_str();
44141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // _MSC_VER
44241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
44341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
44441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a file location for compiler-independent XML output.
44541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Although this function is not platform dependent, we put it next to
44641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// FormatFileLocation in order to contrast the two functions.
44741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Note that FormatCompilerIndependentFileLocation() does NOT append colon
44841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// to the file location it produces, unlike FormatFileLocation().
44941d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
45041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const char* file, int line) {
45141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const char* const file_name = file == NULL ? kUnknownFile : file;
45241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
45341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (line < 0)
45441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return file_name;
45541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  else
45641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return String::Format("%s:%d", file_name, line).c_str();
45741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
45841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
45941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
46041d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
46141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    : severity_(severity) {
4621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const char* const marker =
4631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      severity == GTEST_INFO ?    "[  INFO ]" :
4641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      severity == GTEST_WARNING ? "[WARNING]" :
4651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
46641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  GetStream() << ::std::endl << marker << " "
46741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot              << FormatFileLocation(file, line).c_str() << ": ";
4681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
4691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
47041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
47141d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::~GTestLog() {
47241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  GetStream() << ::std::endl;
47341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (severity_ == GTEST_FATAL) {
47441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    fflush(stderr);
47541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    posix::Abort();
47641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
47741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
4781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Disable Microsoft deprecation warnings for POSIX functions called from
4791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// this class (creat, dup, dup2, and close)
4801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#ifdef _MSC_VER
48141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(push)
48241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(disable: 4996)
4831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif  // _MSC_VER
4841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
48541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_STREAM_REDIRECTION
4861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
48741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Object that captures an output stream (stdout/stderr).
48841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotclass CapturedStream {
4891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania public:
49041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // The ctor redirects the stream to a temporary file.
49141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
4921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
49341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# if GTEST_OS_WINDOWS
4941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
4951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
4961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
4971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
49841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const UINT success = ::GetTempFileNameA(temp_dir_path,
49941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                            "gtest_redir",
50041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                            0,  // Generate unique file name.
50141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                            temp_file_path);
50241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    GTEST_CHECK_(success != 0)
50341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        << "Unable to create a temporary file in " << temp_dir_path;
5041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
50541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
50641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                    << temp_file_path;
5071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    filename_ = temp_file_path;
50841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// ANDROID
50941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_LINUX_ANDROID
510344e5f3db17615cc853073a02968a603efd39109Stephen Hines    // Get $EXTERNAL_STORAGE from the environment, since this can change
511d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes    // for shell users (fallback is /data/nativetest, for emulator users).
512d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes    ::std::string external_storage = "/data/nativetest";
513344e5f3db17615cc853073a02968a603efd39109Stephen Hines    char *sdcard_path = getenv("EXTERNAL_STORAGE");
514d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes    if (sdcard_path != NULL) {
515d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes      // Check that $EXTERNAL_STORAGE exists and is writable before trying to use it.
516d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes      struct stat sb;
517d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes      if (stat(sdcard_path, &sb) != -1) {
518d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes        if ((sb.st_mode & S_IWUSR) != 0) {
519d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes          external_storage = sdcard_path;
520d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes        }
521d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes      }
522344e5f3db17615cc853073a02968a603efd39109Stephen Hines    }
523344e5f3db17615cc853073a02968a603efd39109Stephen Hines    external_storage += "/captured_stderr.XXXXXX";
524344e5f3db17615cc853073a02968a603efd39109Stephen Hines    char *name_template = strdup(external_storage.c_str());
52584190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania    const int captured_fd = mkstemp(name_template);
526d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
527d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes                                    << name_template;
52884190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania    filename_ = name_template;
529344e5f3db17615cc853073a02968a603efd39109Stephen Hines    free(name_template);
530344e5f3db17615cc853073a02968a603efd39109Stephen Hines    name_template = NULL;
53141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// END ANDROID
53241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# else
5331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // There's no guarantee that a test has write access to the
5341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // current directory, so we create the temporary file in the /tmp
5351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // directory instead.
53641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    char name_template[] = "/tmp/captured_stream.XXXXXX";
5371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    const int captured_fd = mkstemp(name_template);
5381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    filename_ = name_template;
53941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif  // GTEST_OS_WINDOWS
5401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    fflush(NULL);
54141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    dup2(captured_fd, fd_);
5421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    close(captured_fd);
5431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
5441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
54541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  ~CapturedStream() {
5461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    remove(filename_.c_str());
5471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
5481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
54941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  String GetCapturedString() {
55041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    if (uncaptured_fd_ != -1) {
55141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // Restores the original stream.
55241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      fflush(NULL);
55341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      dup2(uncaptured_fd_, fd_);
55441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      close(uncaptured_fd_);
55541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      uncaptured_fd_ = -1;
55641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    }
5571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
55841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    FILE* const file = posix::FOpen(filename_.c_str(), "r");
55941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const String content = ReadEntireFile(file);
56041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    posix::FClose(file);
56141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return content;
56241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
5631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania private:
56541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // Reads the entire content of a file as a String.
56641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  static String ReadEntireFile(FILE* file);
56741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
56841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // Returns the size (in bytes) of a file.
56941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  static size_t GetFileSize(FILE* file);
57041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
57141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const int fd_;  // A stream to capture.
5721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  int uncaptured_fd_;
57341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // Name of the temporary file holding the stderr output.
5741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  ::std::string filename_;
5751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
57641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
57741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot};
5781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the size (in bytes) of a file.
58041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t CapturedStream::GetFileSize(FILE* file) {
5811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  fseek(file, 0, SEEK_END);
5821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return static_cast<size_t>(ftell(file));
5831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
5841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads the entire content of a file as a string.
58641d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString CapturedStream::ReadEntireFile(FILE* file) {
5871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const size_t file_size = GetFileSize(file);
5881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  char* const buffer = new char[file_size];
5891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
5911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  size_t bytes_read = 0;       // # of bytes read so far
5921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  fseek(file, 0, SEEK_SET);
5941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
5951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Keeps reading the file until we cannot read further or the
5961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // pre-determined file size is reached.
5971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  do {
5981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
5991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    bytes_read += bytes_last_read;
6001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  } while (bytes_last_read > 0 && bytes_read < file_size);
6011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
60241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const String content(buffer, bytes_read);
6031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  delete[] buffer;
6041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return content;
6061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
6071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
60841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# ifdef _MSC_VER
60941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#  pragma warning(pop)
61041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif  // _MSC_VER
61141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
61241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stderr = NULL;
61341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stdout = NULL;
61441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
61541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing an output stream (stdout/stderr).
61641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
61741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (*stream != NULL) {
61841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    GTEST_LOG_(FATAL) << "Only one " << stream_name
61941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                      << " capturer can exist at a time.";
6201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
62141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *stream = new CapturedStream(fd);
6221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
6231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
62441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing the output stream and returns the captured string.
62541d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStream(CapturedStream** captured_stream) {
62641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const String content = (*captured_stream)->GetCapturedString();
6271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
62841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  delete *captured_stream;
62941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *captured_stream = NULL;
6301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return content;
6321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
6331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
63441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stdout.
63541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStdout() {
63641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
63741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
63841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
63941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stderr.
64041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStderr() {
64141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
64241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
64341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
64441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stdout and returns the captured string.
64541d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
64641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
64741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stderr and returns the captured string.
64841d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
64941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
65041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_HAS_STREAM_REDIRECTION
6511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_HAS_DEATH_TEST
6531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// A copy of all command line arguments.  Set by InitGoogleTest().
6551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania::std::vector<String> g_argvs;
6561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the command line as a vector of strings.
6581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst ::std::vector<String>& GetArgvs() { return g_argvs; }
6591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif  // GTEST_HAS_DEATH_TEST
6611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
66241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE
66341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace posix {
66441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid Abort() {
6651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  DebugBreak();
6661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  TerminateProcess(GetCurrentProcess(), 1);
6671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
66841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}  // namespace posix
66941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_OS_WINDOWS_MOBILE
6701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the name of the environment variable corresponding to the
6721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// given flag.  For example, FlagToEnvVar("foo") will return
6731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// "GTEST_FOO" in the open-source version.
6741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniastatic String FlagToEnvVar(const char* flag) {
6751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const String full_flag =
6761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
6771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  Message env_var;
67941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  for (size_t i = 0; i != full_flag.length(); i++) {
68041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    env_var << ToUpper(full_flag.c_str()[i]);
6811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
6821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return env_var.GetString();
6841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
6851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Parses 'str' for a 32-bit signed integer.  If successful, writes
6871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the result to *value and returns true; otherwise leaves *value
6881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// unchanged and returns false.
6891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ParseInt32(const Message& src_text, const char* str, Int32* value) {
6901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Parses the environment variable as a decimal integer.
6911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  char* end = NULL;
6921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const long long_value = strtol(str, &end, 10);  // NOLINT
6931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
6941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Has strtol() consumed all characters in the string?
6951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (*end != '\0') {
6961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // No - an invalid character was encountered.
6971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    Message msg;
6981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    msg << "WARNING: " << src_text
6991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        << " is expected to be a 32-bit integer, but actually"
7001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        << " has value \"" << str << "\".\n";
7011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    printf("%s", msg.GetString().c_str());
7021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    fflush(stdout);
7031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return false;
7041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
7051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  // Is the parsed value in the range of an Int32?
7071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const Int32 result = static_cast<Int32>(long_value);
7081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (long_value == LONG_MAX || long_value == LONG_MIN ||
7091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // The parsed value overflows as a long.  (strtol() returns
7101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // LONG_MAX or LONG_MIN when the input overflows.)
7111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      result != long_value
7121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      // The parsed value overflows as an Int32.
7131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      ) {
7141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    Message msg;
7151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    msg << "WARNING: " << src_text
7161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        << " is expected to be a 32-bit integer, but actually"
7171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania        << " has value " << str << ", which overflows.\n";
7181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    printf("%s", msg.GetString().c_str());
7191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    fflush(stdout);
7201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return false;
7211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
7221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  *value = result;
7241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return true;
7251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
7261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the Boolean environment variable corresponding to
7281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value.
7291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania//
7301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The value is considered true iff it's not "0".
7311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool BoolFromGTestEnv(const char* flag, bool default_value) {
7321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const String env_var = FlagToEnvVar(flag);
73341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const char* const string_value = posix::GetEnv(env_var.c_str());
7341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return string_value == NULL ?
7351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania      default_value : strcmp(string_value, "0") != 0;
7361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
7371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns a 32-bit integer stored in the environment
7391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// variable corresponding to the given flag; if it isn't set or
7401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// doesn't represent a valid 32-bit integer, returns default_value.
7411be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
7421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const String env_var = FlagToEnvVar(flag);
74341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const char* const string_value = posix::GetEnv(env_var.c_str());
7441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (string_value == NULL) {
7451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    // The environment variable is not set.
7461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return default_value;
7471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
7481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  Int32 result = default_value;
7501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  if (!ParseInt32(Message() << "Environment variable " << env_var,
7511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania                  string_value, &result)) {
7521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    printf("The default value %s is used.\n",
7531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania           (Message() << default_value).GetString().c_str());
7541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    fflush(stdout);
7551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania    return default_value;
7561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  }
7571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return result;
7591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
7601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the string environment variable corresponding to
7621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value.
7631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst char* StringFromGTestEnv(const char* flag, const char* default_value) {
7641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  const String env_var = FlagToEnvVar(flag);
76541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const char* const value = posix::GetEnv(env_var.c_str());
7661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania  return value == NULL ? default_value : value;
7671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}
7681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania
7691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}  // namespace internal
7701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania}  // namespace testing
771