17ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Copyright 2008, Google Inc.
27ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// All rights reserved.
37ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
47ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Redistribution and use in source and binary forms, with or without
57ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// modification, are permitted provided that the following conditions are
67ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// met:
77ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
87ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//     * Redistributions of source code must retain the above copyright
97ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// notice, this list of conditions and the following disclaimer.
107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//     * Redistributions in binary form must reproduce the above
117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// copyright notice, this list of conditions and the following disclaimer
127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// in the documentation and/or other materials provided with the
137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// distribution.
147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//     * Neither the name of Google Inc. nor the names of its
157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// contributors may be used to endorse or promote products derived from
167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// this software without specific prior written permission.
177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman//
307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Author: wan@google.com (Zhanyong Wan)
317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
32b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include "gtest/internal/gtest-port.h"
337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include <limits.h>
357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include <stdlib.h>
367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#include <stdio.h>
37b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include <string.h>
387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
39190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#if GTEST_OS_WINDOWS_MOBILE
40b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <windows.h>  // For TerminateProcess()
41190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#elif GTEST_OS_WINDOWS
42b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <io.h>
43b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <sys/stat.h>
44e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#else
45b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <unistd.h>
46190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#endif  // GTEST_OS_WINDOWS_MOBILE
47e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
48190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#if GTEST_OS_MAC
49b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <mach/mach_init.h>
50b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <mach/task.h>
51b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# include <mach/vm_map.h>
52190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#endif  // GTEST_OS_MAC
537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
54b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include "gtest/gtest-spi.h"
55b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include "gtest/gtest-message.h"
56b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include "gtest/internal/gtest-internal.h"
57b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#include "gtest/internal/gtest-string.h"
587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
59e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Indicates that this translation unit is part of Google Test's
60e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// implementation.  It must come before gtest-internal-inl.h is
61e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// included, or there will be a compiler error.  This trick is to
62e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// prevent a user from accidentally including gtest-internal-inl.h in
63e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// his code.
64e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#define GTEST_IMPLEMENTATION_ 1
65e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#include "gtest/internal/gtest-internal-inl.h"
66e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#undef GTEST_IMPLEMENTATION_
677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace testing {
697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmannamespace internal {
707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
71190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#if defined(_MSC_VER) || defined(__BORLANDC__)
72190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
7357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerconst int kStdOutFileno = 1;
74e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerconst int kStdErrFileno = 2;
75e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#else
7657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerconst int kStdOutFileno = STDOUT_FILENO;
77e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerconst int kStdErrFileno = STDERR_FILENO;
78190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#endif  // _MSC_VER
79190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
80190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#if GTEST_OS_MAC
81190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
82190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// Returns the number of threads running in the process, or 0 to indicate that
83190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// we cannot detect it.
84190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramersize_t GetThreadCount() {
85190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const task_t task = mach_task_self();
86190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  mach_msg_type_number_t thread_count;
87190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  thread_act_array_t thread_list;
88190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
89190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  if (status == KERN_SUCCESS) {
90190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    // task_threads allocates resources in thread_list and we need to free them
91190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    // to avoid leaks.
92190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    vm_deallocate(task,
93190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer                  reinterpret_cast<vm_address_t>(thread_list),
94190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer                  sizeof(thread_t) * thread_count);
95190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    return static_cast<size_t>(thread_count);
96190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  } else {
97190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    return 0;
98190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  }
99190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer}
100190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
101190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#else
102190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
103190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramersize_t GetThreadCount() {
104190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  // There's no portable way to detect the number of threads, so we just
105190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  // return 0 to indicate that we cannot detect it.
106190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  return 0;
107190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer}
108190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
109190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#endif  // GTEST_OS_MAC
110e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
111e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#if GTEST_USES_POSIX_RE
1127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Implements RE.  Currently only needed for death tests.
1147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanRE::~RE() {
11657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  if (is_valid_) {
11757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    // regfree'ing an invalid regex might crash because the content
11857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    // of the regex is undefined. Since the regex's are essentially
11957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    // the same, one cannot be valid (or invalid) without the other
12057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    // being so too.
12157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    regfree(&partial_regex_);
12257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    regfree(&full_regex_);
12357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  }
1247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  free(const_cast<char*>(pattern_));
1257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
1267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Returns true iff regular expression re matches the entire str.
1287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanbool RE::FullMatch(const char* str, const RE& re) {
1297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (!re.is_valid_) return false;
1307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  regmatch_t match;
1327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
1337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
1347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Returns true iff regular expression re matches a substring of str
1367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// (including str itself).
1377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanbool RE::PartialMatch(const char* str, const RE& re) {
1387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (!re.is_valid_) return false;
1397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  regmatch_t match;
1417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
1427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
1437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Initializes an RE from its string representation.
1457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanvoid RE::Init(const char* regex) {
146190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  pattern_ = posix::StrDup(regex);
1477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // Reserves enough bytes to hold the regular expression used for a
1497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // full match.
1507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const size_t full_regex_len = strlen(regex) + 10;
1517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  char* const full_pattern = new char[full_regex_len];
1527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
1547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
1557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // We want to call regcomp(&partial_regex_, ...) even if the
1567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // previous expression returns false.  Otherwise partial_regex_ may
1577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // not be properly initialized can may cause trouble when it's
1587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // freed.
159e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  //
160e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // Some implementation of POSIX regex (e.g. on at least some
161e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // versions of Cygwin) doesn't accept the empty string as a valid
162e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // regex.  We change it to an equivalent form "()" to be safe.
16357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  if (is_valid_) {
16457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
16557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
16657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  }
1677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  EXPECT_TRUE(is_valid_)
1687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      << "Regular expression \"" << regex
1697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      << "\" is not a valid POSIX Extended regular expression.";
1707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  delete[] full_pattern;
1727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
1737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
174e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#elif GTEST_USES_SIMPLE_RE
175e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
176e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff ch appears anywhere in str (excluding the
177e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// terminating '\0' character).
178e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool IsInSet(char ch, const char* str) {
179e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return ch != '\0' && strchr(str, ch) != NULL;
180e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
181e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
182e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff ch belongs to the given classification.  Unlike
183e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// similar functions in <ctype.h>, these aren't affected by the
184e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// current locale.
185b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foadbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
186b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foadbool IsAsciiPunct(char ch) {
187e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
188e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
189e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
190b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foadbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
191b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foadbool IsAsciiWordChar(char ch) {
192e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
193e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      ('0' <= ch && ch <= '9') || ch == '_';
194e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
195e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
196e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff "\\c" is a supported escape sequence.
197e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool IsValidEscape(char c) {
198b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
199e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
200e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
201e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff the given atom (specified by escaped and pattern)
202e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// matches ch.  The result is undefined if the atom is invalid.
203e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
204e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (escaped) {  // "\\p" where p is pattern_char.
205e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    switch (pattern_char) {
206b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 'd': return IsAsciiDigit(ch);
207b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 'D': return !IsAsciiDigit(ch);
208e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      case 'f': return ch == '\f';
209e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      case 'n': return ch == '\n';
210e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      case 'r': return ch == '\r';
211b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 's': return IsAsciiWhiteSpace(ch);
212b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 'S': return !IsAsciiWhiteSpace(ch);
213e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      case 't': return ch == '\t';
214e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      case 'v': return ch == '\v';
215b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 'w': return IsAsciiWordChar(ch);
216b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad      case 'W': return !IsAsciiWordChar(ch);
217e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    }
218b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    return IsAsciiPunct(pattern_char) && pattern_char == ch;
219e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
220e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
221e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
222e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
223e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
224e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Helper function used by ValidateRegex() to format error messages.
225e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin KramerString FormatRegexSyntaxError(const char* regex, int index) {
226e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return (Message() << "Syntax error at index " << index
227e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer          << " in simple regular expression \"" << regex << "\": ").GetString();
228e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
229e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
230e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Generates non-fatal failures and returns false if regex is invalid;
231e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// otherwise returns true.
232e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool ValidateRegex(const char* regex) {
233e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (regex == NULL) {
234e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // TODO(wan@google.com): fix the source file location in the
235e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // assertion failures to match where the regex is used in user
236e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // code.
237e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
238e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return false;
239e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
240e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
241e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  bool is_valid = true;
242e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
243e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // True iff ?, *, or + can follow the previous atom.
244e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  bool prev_repeatable = false;
245e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  for (int i = 0; regex[i]; i++) {
246e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    if (regex[i] == '\\') {  // An escape sequence
247e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      i++;
248e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      if (regex[i] == '\0') {
249e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
250e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "'\\' cannot appear at the end.";
251e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        return false;
252e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      }
253e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
254e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      if (!IsValidEscape(regex[i])) {
255e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
256e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "invalid escape sequence \"\\" << regex[i] << "\".";
257e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        is_valid = false;
258e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      }
259e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      prev_repeatable = true;
260e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    } else {  // Not an escape sequence.
261e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      const char ch = regex[i];
262e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
263e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      if (ch == '^' && i > 0) {
264e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
265e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "'^' can only appear at the beginning.";
266e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        is_valid = false;
267e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      } else if (ch == '$' && regex[i + 1] != '\0') {
268e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
269e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "'$' can only appear at the end.";
270e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        is_valid = false;
271e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      } else if (IsInSet(ch, "()[]{}|")) {
272e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
273e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "'" << ch << "' is unsupported.";
274e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        is_valid = false;
275e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      } else if (IsRepeat(ch) && !prev_repeatable) {
276e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
277e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer                      << "'" << ch << "' can only follow a repeatable token.";
278e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        is_valid = false;
279e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      }
280e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
281e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      prev_repeatable = !IsInSet(ch, "^$?*+");
282e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    }
283e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
284e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
285e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return is_valid;
286e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
287e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
288e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Matches a repeated regex atom followed by a valid simple regular
289e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// expression.  The regex atom is defined as c if escaped is false,
290e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// or \c otherwise.  repeat is the repetition meta character (?, *,
291e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// or +).  The behavior is undefined if str contains too many
292e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// characters to be indexable by size_t, in which case the test will
293e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// probably time out anyway.  We are fine with this limitation as
294e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// std::string has it too.
295e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool MatchRepetitionAndRegexAtHead(
296e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    bool escaped, char c, char repeat, const char* regex,
297e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    const char* str) {
298e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const size_t min_count = (repeat == '+') ? 1 : 0;
299e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const size_t max_count = (repeat == '?') ? 1 :
300e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      static_cast<size_t>(-1) - 1;
301e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // We cannot call numeric_limits::max() as it conflicts with the
302e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // max() macro on Windows.
303e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
304e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  for (size_t i = 0; i <= max_count; ++i) {
305e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // We know that the atom matches each of the first i characters in str.
306e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
307e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      // We have enough matches at the head, and the tail matches too.
308e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      // Since we only care about *whether* the pattern matches str
309e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      // (as opposed to *how* it matches), there is no need to find a
310e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      // greedy match.
311e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      return true;
312e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    }
313e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
314e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      return false;
315e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
316e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return false;
317e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
318e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
319e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff regex matches a prefix of str.  regex must be a
320e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// valid simple regular expression and not start with "^", or the
321e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// result is undefined.
322e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool MatchRegexAtHead(const char* regex, const char* str) {
323e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (*regex == '\0')  // An empty regex matches a prefix of anything.
324e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return true;
325e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
326e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // "$" only matches the end of a string.  Note that regex being
327e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // valid guarantees that there's nothing after "$" in it.
328e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (*regex == '$')
329e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return *str == '\0';
330e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
331e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // Is the first thing in regex an escape sequence?
332e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const bool escaped = *regex == '\\';
333e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (escaped)
334e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    ++regex;
335e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (IsRepeat(regex[1])) {
336e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
337e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // here's an indirect recursion.  It terminates as the regex gets
338e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // shorter in each recursion.
339e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return MatchRepetitionAndRegexAtHead(
340e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        escaped, regex[0], regex[1], regex + 2, str);
341e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  } else {
342e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // regex isn't empty, isn't "$", and doesn't start with a
343e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // repetition.  We match the first atom of regex with the first
344e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // character of str and recurse.
345e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
346e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        MatchRegexAtHead(regex + 1, str + 1);
347e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
348e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
349e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
350e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff regex matches any substring of str.  regex must be
351e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// a valid simple regular expression, or the result is undefined.
352e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer//
353e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// The algorithm is recursive, but the recursion depth doesn't exceed
354e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// the regex length, so we won't need to worry about running out of
355e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// stack space normally.  In rare cases the time complexity can be
356e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// exponential with respect to the regex length + the string length,
357e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// but usually it's must faster (often close to linear).
358e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool MatchRegexAnywhere(const char* regex, const char* str) {
359e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (regex == NULL || str == NULL)
360e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return false;
361e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
362e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (*regex == '^')
363e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return MatchRegexAtHead(regex + 1, str);
364e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
365e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // A successful match can be anywhere in str.
366e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  do {
367e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    if (MatchRegexAtHead(regex, str))
368e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      return true;
369e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  } while (*str++ != '\0');
370e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return false;
371e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
372e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
373e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Implements the RE class.
374e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
375e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin KramerRE::~RE() {
376e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  free(const_cast<char*>(pattern_));
377e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  free(const_cast<char*>(full_pattern_));
378e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
379e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
380e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff regular expression re matches the entire str.
381e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool RE::FullMatch(const char* str, const RE& re) {
382e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
383e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
384e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
385e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Returns true iff regular expression re matches a substring of str
386e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// (including str itself).
387e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool RE::PartialMatch(const char* str, const RE& re) {
388e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
389e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
390e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
391e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Initializes an RE from its string representation.
392e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramervoid RE::Init(const char* regex) {
393e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  pattern_ = full_pattern_ = NULL;
394e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (regex != NULL) {
395190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    pattern_ = posix::StrDup(regex);
396e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
397e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
398e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  is_valid_ = ValidateRegex(regex);
399e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (!is_valid_) {
400e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    // No need to calculate the full pattern when the regex is invalid.
401e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    return;
402e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  }
403e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
404e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const size_t len = strlen(regex);
405e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // Reserves enough bytes to hold the regular expression used for a
406e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // full match: we need space to prepend a '^', append a '$', and
407e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // terminate the string with '\0'.
408e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  char* buffer = static_cast<char*>(malloc(len + 3));
409e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  full_pattern_ = buffer;
410e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
411e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (*regex != '^')
412e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
413e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
414e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // We don't use snprintf or strncpy, as they trigger a warning when
415e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  // compiled with VC++ 8.0.
416e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  memcpy(buffer, regex, len);
417e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  buffer += len;
418e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
419e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  if (len == 0 || regex[len - 1] != '$')
420e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
421e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
422e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  *buffer = '\0';
423e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
424e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
425e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#endif  // GTEST_USES_POSIX_RE
4267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
427b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foadconst char kUnknownFile[] = "unknown file";
428b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
429b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// Formats a source file path and a line number as they would appear
430b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// in an error message from the compiler used to compile this code.
431b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay FoadGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
432b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  const char* const file_name = file == NULL ? kUnknownFile : file;
433b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
434b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  if (line < 0) {
435b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    return String::Format("%s:", file_name).c_str();
436b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  }
437b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#ifdef _MSC_VER
438b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  return String::Format("%s(%d):", file_name, line).c_str();
439b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#else
440b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  return String::Format("%s:%d:", file_name, line).c_str();
441b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#endif  // _MSC_VER
442b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad}
443b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
444b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// Formats a file location for compiler-independent XML output.
445b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// Although this function is not platform dependent, we put it next to
446b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// FormatFileLocation in order to contrast the two functions.
447b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// Note that FormatCompilerIndependentFileLocation() does NOT append colon
448b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad// to the file location it produces, unlike FormatFileLocation().
449b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay FoadGTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
450b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    const char* file, int line) {
451b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  const char* const file_name = file == NULL ? kUnknownFile : file;
452b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
453b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  if (line < 0)
454b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    return file_name;
455b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad  else
456b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    return String::Format("%s:%d", file_name, line).c_str();
457b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad}
458b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
459190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer
460190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin KramerGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
461190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    : severity_(severity) {
4627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const char* const marker =
4637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      severity == GTEST_INFO ?    "[  INFO ]" :
4647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      severity == GTEST_WARNING ? "[WARNING]" :
4657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
466190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  GetStream() << ::std::endl << marker << " "
467190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer              << FormatFileLocation(file, line).c_str() << ": ";
4687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
4697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
470190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
471190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin KramerGTestLog::~GTestLog() {
472190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  GetStream() << ::std::endl;
473190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  if (severity_ == GTEST_FATAL) {
474190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    fflush(stderr);
475190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer    posix::Abort();
476190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  }
477190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer}
478e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Disable Microsoft deprecation warnings for POSIX functions called from
479e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// this class (creat, dup, dup2, and close)
480e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#ifdef _MSC_VER
481b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# pragma warning(push)
482b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# pragma warning(disable: 4996)
483e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#endif  // _MSC_VER
4847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
485b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#if GTEST_HAS_STREAM_REDIRECTION
4867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
48757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Object that captures an output stream (stdout/stderr).
48857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerclass CapturedStream {
4897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman public:
49057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  // The ctor redirects the stream to a temporary file.
49157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
492b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad
493b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# if GTEST_OS_WINDOWS
494e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
495e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
496e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
497e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
49857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    const UINT success = ::GetTempFileNameA(temp_dir_path,
49957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                                            "gtest_redir",
50057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                                            0,  // Generate unique file name.
50157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                                            temp_file_path);
50257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    GTEST_CHECK_(success != 0)
50357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer        << "Unable to create a temporary file in " << temp_dir_path;
504e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
50557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
50657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                                    << temp_file_path;
507e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    filename_ = temp_file_path;
508b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# else
5097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // There's no guarantee that a test has write access to the
5107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // current directory, so we create the temporary file in the /tmp
5117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // directory instead.
51257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    char name_template[] = "/tmp/captured_stream.XXXXXX";
5137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    const int captured_fd = mkstemp(name_template);
5147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    filename_ = name_template;
515b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# endif  // GTEST_OS_WINDOWS
5167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    fflush(NULL);
51757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    dup2(captured_fd, fd_);
5187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    close(captured_fd);
5197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
5207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
52157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  ~CapturedStream() {
5227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    remove(filename_.c_str());
5237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
5247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
52557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  String GetCapturedString() {
52657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    if (uncaptured_fd_ != -1) {
52757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer      // Restores the original stream.
52857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer      fflush(NULL);
52957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer      dup2(uncaptured_fd_, fd_);
53057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer      close(uncaptured_fd_);
53157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer      uncaptured_fd_ = -1;
53257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    }
5337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
53457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    FILE* const file = posix::FOpen(filename_.c_str(), "r");
53557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    const String content = ReadEntireFile(file);
53657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    posix::FClose(file);
53757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    return content;
53857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  }
5397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman private:
54157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  // Reads the entire content of a file as a String.
54257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  static String ReadEntireFile(FILE* file);
54357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
54457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  // Returns the size (in bytes) of a file.
54557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  static size_t GetFileSize(FILE* file);
54657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
54757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  const int fd_;  // A stream to capture.
5487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  int uncaptured_fd_;
54957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  // Name of the temporary file holding the stderr output.
5507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  ::std::string filename_;
5517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
55257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
55357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer};
5547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Returns the size (in bytes) of a file.
55657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramersize_t CapturedStream::GetFileSize(FILE* file) {
5577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  fseek(file, 0, SEEK_END);
5587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return static_cast<size_t>(ftell(file));
5597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
5607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Reads the entire content of a file as a string.
56257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerString CapturedStream::ReadEntireFile(FILE* file) {
5637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const size_t file_size = GetFileSize(file);
5647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  char* const buffer = new char[file_size];
5657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
5677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  size_t bytes_read = 0;       // # of bytes read so far
5687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  fseek(file, 0, SEEK_SET);
5707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // Keeps reading the file until we cannot read further or the
5727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // pre-determined file size is reached.
5737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  do {
5747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
5757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    bytes_read += bytes_last_read;
5767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  } while (bytes_last_read > 0 && bytes_read < file_size);
5777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
578190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const String content(buffer, bytes_read);
5797ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  delete[] buffer;
5807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
5817ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return content;
5827ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
5837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
584b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# ifdef _MSC_VER
585b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#  pragma warning(pop)
586b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad# endif  // _MSC_VER
58757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
58857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerstatic CapturedStream* g_captured_stderr = NULL;
58957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramerstatic CapturedStream* g_captured_stdout = NULL;
59057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
59157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Starts capturing an output stream (stdout/stderr).
59257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
59357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  if (*stream != NULL) {
59457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer    GTEST_LOG_(FATAL) << "Only one " << stream_name
59557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                      << " capturer can exist at a time.";
5967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
59757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  *stream = new CapturedStream(fd);
5987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
5997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
60057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Stops capturing the output stream and returns the captured string.
60157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerString GetCapturedStream(CapturedStream** captured_stream) {
60257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  const String content = (*captured_stream)->GetCapturedString();
603e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
60457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  delete *captured_stream;
60557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  *captured_stream = NULL;
6067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return content;
6087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
6097ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
61057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Starts capturing stdout.
61157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid CaptureStdout() {
61257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
61357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer}
61457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
61557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Starts capturing stderr.
61657240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramervoid CaptureStderr() {
61757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
61857240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer}
61957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
62057240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Stops capturing stdout and returns the captured string.
62157240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerString GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
62257240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
62357240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer// Stops capturing stderr and returns the captured string.
62457240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin KramerString GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
62557240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
626b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad#endif  // GTEST_HAS_STREAM_REDIRECTION
62757240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer
628e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer#if GTEST_HAS_DEATH_TEST
629e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
6307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// A copy of all command line arguments.  Set by InitGoogleTest().
6317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman::std::vector<String> g_argvs;
6327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Returns the command line as a vector of strings.
6347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanconst ::std::vector<String>& GetArgvs() { return g_argvs; }
6357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman#endif  // GTEST_HAS_DEATH_TEST
6377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
638190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#if GTEST_OS_WINDOWS_MOBILE
639190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramernamespace posix {
640190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramervoid Abort() {
6417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  DebugBreak();
6427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  TerminateProcess(GetCurrentProcess(), 1);
6437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
644190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer}  // namespace posix
645190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer#endif  // GTEST_OS_WINDOWS_MOBILE
6467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Returns the name of the environment variable corresponding to the
6487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// given flag.  For example, FlagToEnvVar("foo") will return
6497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// "GTEST_FOO" in the open-source version.
6507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanstatic String FlagToEnvVar(const char* flag) {
651e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const String full_flag =
652e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
6537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  Message env_var;
655190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  for (size_t i = 0; i != full_flag.length(); i++) {
656b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad    env_var << ToUpper(full_flag.c_str()[i]);
6577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
6587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6597ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return env_var.GetString();
6607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
6617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Parses 'str' for a 32-bit signed integer.  If successful, writes
6637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// the result to *value and returns true; otherwise leaves *value
6647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// unchanged and returns false.
6657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanbool ParseInt32(const Message& src_text, const char* str, Int32* value) {
6667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // Parses the environment variable as a decimal integer.
6677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  char* end = NULL;
6687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const long long_value = strtol(str, &end, 10);  // NOLINT
6697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // Has strtol() consumed all characters in the string?
6717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (*end != '\0') {
6727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // No - an invalid character was encountered.
6737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    Message msg;
6747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    msg << "WARNING: " << src_text
6757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        << " is expected to be a 32-bit integer, but actually"
6767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        << " has value \"" << str << "\".\n";
6777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    printf("%s", msg.GetString().c_str());
6787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    fflush(stdout);
6797ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return false;
6807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
6817ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6827ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  // Is the parsed value in the range of an Int32?
6837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const Int32 result = static_cast<Int32>(long_value);
6847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (long_value == LONG_MAX || long_value == LONG_MIN ||
6857ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      // The parsed value overflows as a long.  (strtol() returns
6867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      // LONG_MAX or LONG_MIN when the input overflows.)
6877ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      result != long_value
6887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      // The parsed value overflows as an Int32.
6897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman      ) {
6907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    Message msg;
6917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    msg << "WARNING: " << src_text
6927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        << " is expected to be a 32-bit integer, but actually"
6937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        << " has value " << str << ", which overflows.\n";
6947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    printf("%s", msg.GetString().c_str());
6957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    fflush(stdout);
6967ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return false;
6977ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
6987ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
6997ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  *value = result;
7007ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return true;
7017ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
7027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
703e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// Reads and returns the Boolean environment variable corresponding to
704e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// the given flag; if it's not set, returns default_value.
705e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer//
706e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer// The value is considered true iff it's not "0".
707e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerbool BoolFromGTestEnv(const char* flag, bool default_value) {
708e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  const String env_var = FlagToEnvVar(flag);
709190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const char* const string_value = posix::GetEnv(env_var.c_str());
710e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer  return string_value == NULL ?
711e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer      default_value : strcmp(string_value, "0") != 0;
712e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer}
713e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
7147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Reads and returns a 32-bit integer stored in the environment
7157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// variable corresponding to the given flag; if it isn't set or
7167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// doesn't represent a valid 32-bit integer, returns default_value.
7177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
7187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const String env_var = FlagToEnvVar(flag);
719190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const char* const string_value = posix::GetEnv(env_var.c_str());
7207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (string_value == NULL) {
7217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    // The environment variable is not set.
7227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return default_value;
7237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
7247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
7257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  Int32 result = default_value;
7267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  if (!ParseInt32(Message() << "Environment variable " << env_var,
7277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman                  string_value, &result)) {
7287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    printf("The default value %s is used.\n",
7297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman           (Message() << default_value).GetString().c_str());
7307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    fflush(stdout);
7317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return default_value;
7327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  }
7337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
7347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return result;
7357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
7367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
7377ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// Reads and returns the string environment variable corresponding to
7387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman// the given flag; if it's not set, returns default_value.
7397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanconst char* StringFromGTestEnv(const char* flag, const char* default_value) {
7407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  const String env_var = FlagToEnvVar(flag);
741190f8ee25a6977ac6eb71b816498df42f17ad9a7Benjamin Kramer  const char* const value = posix::GetEnv(env_var.c_str());
7427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  return value == NULL ? default_value : value;
7437ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}
7447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
7457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}  // namespace internal
7467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman}  // namespace testing
747