1fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Copyright 2008, Google Inc.
2fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// All rights reserved.
3fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
4fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Redistribution and use in source and binary forms, with or without
5fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// modification, are permitted provided that the following conditions are
6fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// met:
7fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
8fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//     * Redistributions of source code must retain the above copyright
9fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// notice, this list of conditions and the following disclaimer.
10fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//     * Redistributions in binary form must reproduce the above
11fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// copyright notice, this list of conditions and the following disclaimer
12fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// in the documentation and/or other materials provided with the
13fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// distribution.
14fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//     * Neither the name of Google Inc. nor the names of its
15fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// contributors may be used to endorse or promote products derived from
16fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// this software without specific prior written permission.
17fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
18fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
30fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Author: wan@google.com (Zhanyong Wan)
31fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
32fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "gtest/internal/gtest-port.h"
33fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
34fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include <limits.h>
35fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include <stdlib.h>
36fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include <stdio.h>
37fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include <string.h>
38fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
39fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_OS_WINDOWS_MOBILE
40fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <windows.h>  // For TerminateProcess()
41fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#elif GTEST_OS_WINDOWS
42fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <io.h>
43fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <sys/stat.h>
44fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#else
45fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <unistd.h>
46fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_OS_WINDOWS_MOBILE
47fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
48fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_OS_MAC
49fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <mach/mach_init.h>
50fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <mach/task.h>
51fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# include <mach/vm_map.h>
52fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_OS_MAC
53fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
54fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "gtest/gtest-spi.h"
55fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "gtest/gtest-message.h"
56fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "gtest/internal/gtest-internal.h"
57fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "gtest/internal/gtest-string.h"
58fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
59fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Indicates that this translation unit is part of Google Test's
60fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// implementation.  It must come before gtest-internal-inl.h is
61fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// included, or there will be a compiler error.  This trick is to
62fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// prevent a user from accidentally including gtest-internal-inl.h in
63fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// his code.
64fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#define GTEST_IMPLEMENTATION_ 1
65fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#include "src/gtest-internal-inl.h"
66fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#undef GTEST_IMPLEMENTATION_
67fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
68fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtnamespace testing {
69fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtnamespace internal {
70fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
71fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if defined(_MSC_VER) || defined(__BORLANDC__)
72fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
73fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst int kStdOutFileno = 1;
74fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst int kStdErrFileno = 2;
75fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#else
76fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst int kStdOutFileno = STDOUT_FILENO;
77fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst int kStdErrFileno = STDERR_FILENO;
78fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // _MSC_VER
79fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
80fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_OS_MAC
81fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
82fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns the number of threads running in the process, or 0 to indicate that
83fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// we cannot detect it.
84fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtsize_t GetThreadCount() {
85fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const task_t task = mach_task_self();
86fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  mach_msg_type_number_t thread_count;
87fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  thread_act_array_t thread_list;
88fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
89fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (status == KERN_SUCCESS) {
90fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // task_threads allocates resources in thread_list and we need to free them
91fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // to avoid leaks.
92fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    vm_deallocate(task,
93fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                  reinterpret_cast<vm_address_t>(thread_list),
94fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                  sizeof(thread_t) * thread_count);
95fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return static_cast<size_t>(thread_count);
96fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  } else {
97fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return 0;
98fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
99fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
100fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
101fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#else
102fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
103fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtsize_t GetThreadCount() {
104fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // There's no portable way to detect the number of threads, so we just
105fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // return 0 to indicate that we cannot detect it.
106fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return 0;
107fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
108fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
109fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_OS_MAC
110fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
111fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_USES_POSIX_RE
112fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
113fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Implements RE.  Currently only needed for death tests.
114fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
115fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtRE::~RE() {
116fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (is_valid_) {
117fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // regfree'ing an invalid regex might crash because the content
118fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // of the regex is undefined. Since the regex's are essentially
119fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // the same, one cannot be valid (or invalid) without the other
120fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // being so too.
121fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    regfree(&partial_regex_);
122fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    regfree(&full_regex_);
123fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
124fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  free(const_cast<char*>(pattern_));
125fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
126fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
127fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regular expression re matches the entire str.
128fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool RE::FullMatch(const char* str, const RE& re) {
129fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (!re.is_valid_) return false;
130fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
131fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  regmatch_t match;
132fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
133fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
134fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
135fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regular expression re matches a substring of str
136fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// (including str itself).
137fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool RE::PartialMatch(const char* str, const RE& re) {
138fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (!re.is_valid_) return false;
139fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
140fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  regmatch_t match;
141fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
142fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
143fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
144fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Initializes an RE from its string representation.
145fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid RE::Init(const char* regex) {
146fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  pattern_ = posix::StrDup(regex);
147fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
148fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Reserves enough bytes to hold the regular expression used for a
149fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // full match.
150fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const size_t full_regex_len = strlen(regex) + 10;
151fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  char* const full_pattern = new char[full_regex_len];
152fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
153fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
154fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
155fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // We want to call regcomp(&partial_regex_, ...) even if the
156fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // previous expression returns false.  Otherwise partial_regex_ may
157fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // not be properly initialized can may cause trouble when it's
158fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // freed.
159fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  //
160fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Some implementation of POSIX regex (e.g. on at least some
161fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // versions of Cygwin) doesn't accept the empty string as a valid
162fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // regex.  We change it to an equivalent form "()" to be safe.
163fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (is_valid_) {
164fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
165fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
166fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
167fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  EXPECT_TRUE(is_valid_)
168fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      << "Regular expression \"" << regex
169fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      << "\" is not a valid POSIX Extended regular expression.";
170fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
171fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  delete[] full_pattern;
172fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
173fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
174fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#elif GTEST_USES_SIMPLE_RE
175fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
176fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff ch appears anywhere in str (excluding the
177fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// terminating '\0' character).
178fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsInSet(char ch, const char* str) {
179fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return ch != '\0' && strchr(str, ch) != NULL;
180fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
181fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
182fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff ch belongs to the given classification.  Unlike
183fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// similar functions in <ctype.h>, these aren't affected by the
184fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// current locale.
185fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
186fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsAsciiPunct(char ch) {
187fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
188fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
189fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
190fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
191fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsAsciiWordChar(char ch) {
192fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
193fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      ('0' <= ch && ch <= '9') || ch == '_';
194fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
195fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
196fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff "\\c" is a supported escape sequence.
197fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool IsValidEscape(char c) {
198fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
199fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
200fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
201fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff the given atom (specified by escaped and pattern)
202fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// matches ch.  The result is undefined if the atom is invalid.
203fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
204fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (escaped) {  // "\\p" where p is pattern_char.
205fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    switch (pattern_char) {
206fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'd': return IsAsciiDigit(ch);
207fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'D': return !IsAsciiDigit(ch);
208fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'f': return ch == '\f';
209fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'n': return ch == '\n';
210fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'r': return ch == '\r';
211fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 's': return IsAsciiWhiteSpace(ch);
212fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'S': return !IsAsciiWhiteSpace(ch);
213fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 't': return ch == '\t';
214fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'v': return ch == '\v';
215fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'w': return IsAsciiWordChar(ch);
216fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      case 'W': return !IsAsciiWordChar(ch);
217fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    }
218fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return IsAsciiPunct(pattern_char) && pattern_char == ch;
219fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
220fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
221fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
222fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
223fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
224fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Helper function used by ValidateRegex() to format error messages.
225fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtString FormatRegexSyntaxError(const char* regex, int index) {
226fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return (Message() << "Syntax error at index " << index
227fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt          << " in simple regular expression \"" << regex << "\": ").GetString();
228fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
229fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
230fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Generates non-fatal failures and returns false if regex is invalid;
231fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// otherwise returns true.
232fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool ValidateRegex(const char* regex) {
233fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (regex == NULL) {
234fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // TODO(wan@google.com): fix the source file location in the
235fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // assertion failures to match where the regex is used in user
236fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // code.
237fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
238fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return false;
239fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
240fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
241fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  bool is_valid = true;
242fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
243fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // True iff ?, *, or + can follow the previous atom.
244fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  bool prev_repeatable = false;
245fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  for (int i = 0; regex[i]; i++) {
246fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    if (regex[i] == '\\') {  // An escape sequence
247fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      i++;
248fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      if (regex[i] == '\0') {
249fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
250fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "'\\' cannot appear at the end.";
251fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        return false;
252fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      }
253fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
254fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      if (!IsValidEscape(regex[i])) {
255fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
256fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "invalid escape sequence \"\\" << regex[i] << "\".";
257fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        is_valid = false;
258fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      }
259fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      prev_repeatable = true;
260fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    } else {  // Not an escape sequence.
261fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      const char ch = regex[i];
262fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
263fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      if (ch == '^' && i > 0) {
264fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
265fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "'^' can only appear at the beginning.";
266fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        is_valid = false;
267fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      } else if (ch == '$' && regex[i + 1] != '\0') {
268fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
269fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "'$' can only appear at the end.";
270fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        is_valid = false;
271fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      } else if (IsInSet(ch, "()[]{}|")) {
272fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
273fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "'" << ch << "' is unsupported.";
274fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        is_valid = false;
275fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      } else if (IsRepeat(ch) && !prev_repeatable) {
276fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
277fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << "'" << ch << "' can only follow a repeatable token.";
278fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        is_valid = false;
279fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      }
280fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
281fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      prev_repeatable = !IsInSet(ch, "^$?*+");
282fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    }
283fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
284fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
285fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return is_valid;
286fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
287fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
288fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Matches a repeated regex atom followed by a valid simple regular
289fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// expression.  The regex atom is defined as c if escaped is false,
290fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// or \c otherwise.  repeat is the repetition meta character (?, *,
291fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// or +).  The behavior is undefined if str contains too many
292fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// characters to be indexable by size_t, in which case the test will
293fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// probably time out anyway.  We are fine with this limitation as
294fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// std::string has it too.
295fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool MatchRepetitionAndRegexAtHead(
296fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    bool escaped, char c, char repeat, const char* regex,
297fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const char* str) {
298fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const size_t min_count = (repeat == '+') ? 1 : 0;
299fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const size_t max_count = (repeat == '?') ? 1 :
300fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      static_cast<size_t>(-1) - 1;
301fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // We cannot call numeric_limits::max() as it conflicts with the
302fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // max() macro on Windows.
303fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
304fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  for (size_t i = 0; i <= max_count; ++i) {
305fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // We know that the atom matches each of the first i characters in str.
306fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
307fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // We have enough matches at the head, and the tail matches too.
308fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // Since we only care about *whether* the pattern matches str
309fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // (as opposed to *how* it matches), there is no need to find a
310fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // greedy match.
311fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      return true;
312fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    }
313fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
314fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      return false;
315fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
316fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return false;
317fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
318fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
319fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regex matches a prefix of str.  regex must be a
320fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// valid simple regular expression and not start with "^", or the
321fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// result is undefined.
322fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool MatchRegexAtHead(const char* regex, const char* str) {
323fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*regex == '\0')  // An empty regex matches a prefix of anything.
324fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return true;
325fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
326fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // "$" only matches the end of a string.  Note that regex being
327fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // valid guarantees that there's nothing after "$" in it.
328fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*regex == '$')
329fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return *str == '\0';
330fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
331fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Is the first thing in regex an escape sequence?
332fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const bool escaped = *regex == '\\';
333fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (escaped)
334fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    ++regex;
335fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (IsRepeat(regex[1])) {
336fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
337fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // here's an indirect recursion.  It terminates as the regex gets
338fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // shorter in each recursion.
339fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return MatchRepetitionAndRegexAtHead(
340fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        escaped, regex[0], regex[1], regex + 2, str);
341fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  } else {
342fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // regex isn't empty, isn't "$", and doesn't start with a
343fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // repetition.  We match the first atom of regex with the first
344fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // character of str and recurse.
345fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
346fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        MatchRegexAtHead(regex + 1, str + 1);
347fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
348fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
349fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
350fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regex matches any substring of str.  regex must be
351fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// a valid simple regular expression, or the result is undefined.
352fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
353fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// The algorithm is recursive, but the recursion depth doesn't exceed
354fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// the regex length, so we won't need to worry about running out of
355fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// stack space normally.  In rare cases the time complexity can be
356fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// exponential with respect to the regex length + the string length,
357fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// but usually it's must faster (often close to linear).
358fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool MatchRegexAnywhere(const char* regex, const char* str) {
359fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (regex == NULL || str == NULL)
360fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return false;
361fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
362fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*regex == '^')
363fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return MatchRegexAtHead(regex + 1, str);
364fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
365fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // A successful match can be anywhere in str.
366fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  do {
367fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    if (MatchRegexAtHead(regex, str))
368fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      return true;
369fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  } while (*str++ != '\0');
370fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return false;
371fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
372fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
373fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Implements the RE class.
374fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
375fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtRE::~RE() {
376fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  free(const_cast<char*>(pattern_));
377fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  free(const_cast<char*>(full_pattern_));
378fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
379fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
380fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regular expression re matches the entire str.
381fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool RE::FullMatch(const char* str, const RE& re) {
382fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
383fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
384fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
385fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns true iff regular expression re matches a substring of str
386fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// (including str itself).
387fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool RE::PartialMatch(const char* str, const RE& re) {
388fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
389fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
390fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
391fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Initializes an RE from its string representation.
392fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid RE::Init(const char* regex) {
393fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  pattern_ = full_pattern_ = NULL;
394fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (regex != NULL) {
395fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    pattern_ = posix::StrDup(regex);
396fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
397fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
398fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  is_valid_ = ValidateRegex(regex);
399fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (!is_valid_) {
400fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // No need to calculate the full pattern when the regex is invalid.
401fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return;
402fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
403fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
404fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const size_t len = strlen(regex);
405fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Reserves enough bytes to hold the regular expression used for a
406fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // full match: we need space to prepend a '^', append a '$', and
407fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // terminate the string with '\0'.
408fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  char* buffer = static_cast<char*>(malloc(len + 3));
409fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  full_pattern_ = buffer;
410fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
411fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*regex != '^')
412fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
413fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
414fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // We don't use snprintf or strncpy, as they trigger a warning when
415fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // compiled with VC++ 8.0.
416fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  memcpy(buffer, regex, len);
417fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  buffer += len;
418fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
419fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (len == 0 || regex[len - 1] != '$')
420fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
421fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
422fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  *buffer = '\0';
423fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
424fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
425fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_USES_POSIX_RE
426fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
427fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst char kUnknownFile[] = "unknown file";
428fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
429fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Formats a source file path and a line number as they would appear
430fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// in an error message from the compiler used to compile this code.
431fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
432fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const file_name = file == NULL ? kUnknownFile : file;
433fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
434fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (line < 0) {
435fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return String::Format("%s:", file_name).c_str();
436fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
437fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#ifdef _MSC_VER
438fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return String::Format("%s(%d):", file_name, line).c_str();
439fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#else
440fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return String::Format("%s:%d:", file_name, line).c_str();
441fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // _MSC_VER
442fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
443fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
444fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Formats a file location for compiler-independent XML output.
445fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Although this function is not platform dependent, we put it next to
446fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// FormatFileLocation in order to contrast the two functions.
447fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Note that FormatCompilerIndependentFileLocation() does NOT append colon
448fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// to the file location it produces, unlike FormatFileLocation().
449fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtGTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
450fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const char* file, int line) {
451fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const file_name = file == NULL ? kUnknownFile : file;
452fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
453fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (line < 0)
454fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return file_name;
455fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  else
456fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return String::Format("%s:%d", file_name, line).c_str();
457fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
458fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
459fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
460fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
461fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    : severity_(severity) {
462fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const marker =
463fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      severity == GTEST_INFO ?    "[  INFO ]" :
464fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      severity == GTEST_WARNING ? "[WARNING]" :
465fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
466fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  GetStream() << ::std::endl << marker << " "
467fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt              << FormatFileLocation(file, line).c_str() << ": ";
468fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
469fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
470fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
471fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtGTestLog::~GTestLog() {
472fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  GetStream() << ::std::endl;
473fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (severity_ == GTEST_FATAL) {
474fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    fflush(stderr);
475fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    posix::Abort();
476fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
477fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
478fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Disable Microsoft deprecation warnings for POSIX functions called from
479fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// this class (creat, dup, dup2, and close)
480fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#ifdef _MSC_VER
481fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# pragma warning(push)
482fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# pragma warning(disable: 4996)
483fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // _MSC_VER
484fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
485fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_HAS_STREAM_REDIRECTION
486fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
487fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Object that captures an output stream (stdout/stderr).
488fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtclass CapturedStream {
489fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt public:
490fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // The ctor redirects the stream to a temporary file.
491fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
492fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
493fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# if GTEST_OS_WINDOWS
494fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
495fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
496fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
497fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
498fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const UINT success = ::GetTempFileNameA(temp_dir_path,
499fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                                            "gtest_redir",
500fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                                            0,  // Generate unique file name.
501fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                                            temp_file_path);
502fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    GTEST_CHECK_(success != 0)
503fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        << "Unable to create a temporary file in " << temp_dir_path;
504fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
505fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
506fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                                    << temp_file_path;
507fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    filename_ = temp_file_path;
508fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# else
509fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // There's no guarantee that a test has write access to the
510fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // current directory, so we create the temporary file in the /tmp
511fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // directory instead.
512fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    char name_template[] = "/tmp/captured_stream.XXXXXX";
513fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const int captured_fd = mkstemp(name_template);
514fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    filename_ = name_template;
515fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# endif  // GTEST_OS_WINDOWS
516fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    fflush(NULL);
517fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    dup2(captured_fd, fd_);
518fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    close(captured_fd);
519fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
520fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
521fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  ~CapturedStream() {
522fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    remove(filename_.c_str());
523fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
524fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
525fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  String GetCapturedString() {
526fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    if (uncaptured_fd_ != -1) {
527fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // Restores the original stream.
528fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      fflush(NULL);
529fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      dup2(uncaptured_fd_, fd_);
530fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      close(uncaptured_fd_);
531fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      uncaptured_fd_ = -1;
532fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    }
533fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
534fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    FILE* const file = posix::FOpen(filename_.c_str(), "r");
535fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    const String content = ReadEntireFile(file);
536fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    posix::FClose(file);
537fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return content;
538fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
539fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
540fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt private:
541fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Reads the entire content of a file as a String.
542fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  static String ReadEntireFile(FILE* file);
543fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
544fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Returns the size (in bytes) of a file.
545fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  static size_t GetFileSize(FILE* file);
546fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
547fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const int fd_;  // A stream to capture.
548fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  int uncaptured_fd_;
549fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Name of the temporary file holding the stderr output.
550fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  ::std::string filename_;
551fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
552fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
553fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt};
554fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
555fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns the size (in bytes) of a file.
556fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtsize_t CapturedStream::GetFileSize(FILE* file) {
557fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  fseek(file, 0, SEEK_END);
558fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return static_cast<size_t>(ftell(file));
559fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
560fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
561fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Reads the entire content of a file as a string.
562fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtString CapturedStream::ReadEntireFile(FILE* file) {
563fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const size_t file_size = GetFileSize(file);
564fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  char* const buffer = new char[file_size];
565fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
566fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
567fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  size_t bytes_read = 0;       // # of bytes read so far
568fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
569fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  fseek(file, 0, SEEK_SET);
570fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
571fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Keeps reading the file until we cannot read further or the
572fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // pre-determined file size is reached.
573fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  do {
574fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
575fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    bytes_read += bytes_last_read;
576fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  } while (bytes_last_read > 0 && bytes_read < file_size);
577fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
578fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String content(buffer, bytes_read);
579fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  delete[] buffer;
580fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
581fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return content;
582fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
583fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
584fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# ifdef _MSC_VER
585fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#  pragma warning(pop)
586fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt# endif  // _MSC_VER
587fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
588fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtstatic CapturedStream* g_captured_stderr = NULL;
589fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtstatic CapturedStream* g_captured_stdout = NULL;
590fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
591fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Starts capturing an output stream (stdout/stderr).
592fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
593fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*stream != NULL) {
594fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    GTEST_LOG_(FATAL) << "Only one " << stream_name
595fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                      << " capturer can exist at a time.";
596fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
597fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  *stream = new CapturedStream(fd);
598fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
599fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
600fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Stops capturing the output stream and returns the captured string.
601fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtString GetCapturedStream(CapturedStream** captured_stream) {
602fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String content = (*captured_stream)->GetCapturedString();
603fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
604fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  delete *captured_stream;
605fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  *captured_stream = NULL;
606fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
607fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return content;
608fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
609fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
610fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Starts capturing stdout.
611fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid CaptureStdout() {
612fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
613fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
614fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
615fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Starts capturing stderr.
616fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid CaptureStderr() {
617fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
618fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
619fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
620fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Stops capturing stdout and returns the captured string.
621fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtString GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
622fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
623fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Stops capturing stderr and returns the captured string.
624fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtString GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
625fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
626fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_HAS_STREAM_REDIRECTION
627fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
628fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_HAS_DEATH_TEST
629fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
630fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// A copy of all command line arguments.  Set by InitGoogleTest().
631fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt::std::vector<String> g_argvs;
632fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
633fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns the command line as a vector of strings.
634fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst ::std::vector<String>& GetArgvs() { return g_argvs; }
635fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
636fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_HAS_DEATH_TEST
637fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
638fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#if GTEST_OS_WINDOWS_MOBILE
639fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtnamespace posix {
640fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtvoid Abort() {
641fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  DebugBreak();
642fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  TerminateProcess(GetCurrentProcess(), 1);
643fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
644fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}  // namespace posix
645fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt#endif  // GTEST_OS_WINDOWS_MOBILE
646fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
647fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Returns the name of the environment variable corresponding to the
648fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// given flag.  For example, FlagToEnvVar("foo") will return
649fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// "GTEST_FOO" in the open-source version.
650fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtstatic String FlagToEnvVar(const char* flag) {
651fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String full_flag =
652fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
653fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
654fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  Message env_var;
655fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  for (size_t i = 0; i != full_flag.length(); i++) {
656fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    env_var << ToUpper(full_flag.c_str()[i]);
657fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
658fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
659fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return env_var.GetString();
660fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
661fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
662fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Parses 'str' for a 32-bit signed integer.  If successful, writes
663fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// the result to *value and returns true; otherwise leaves *value
664fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// unchanged and returns false.
665fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool ParseInt32(const Message& src_text, const char* str, Int32* value) {
666fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Parses the environment variable as a decimal integer.
667fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  char* end = NULL;
668fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const long long_value = strtol(str, &end, 10);  // NOLINT
669fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
670fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Has strtol() consumed all characters in the string?
671fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (*end != '\0') {
672fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // No - an invalid character was encountered.
673fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    Message msg;
674fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    msg << "WARNING: " << src_text
675fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        << " is expected to be a 32-bit integer, but actually"
676fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        << " has value \"" << str << "\".\n";
677fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    printf("%s", msg.GetString().c_str());
678fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    fflush(stdout);
679fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return false;
680fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
681fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
682fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  // Is the parsed value in the range of an Int32?
683fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const Int32 result = static_cast<Int32>(long_value);
684fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (long_value == LONG_MAX || long_value == LONG_MIN ||
685fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // The parsed value overflows as a long.  (strtol() returns
686fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // LONG_MAX or LONG_MIN when the input overflows.)
687fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      result != long_value
688fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      // The parsed value overflows as an Int32.
689fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      ) {
690fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    Message msg;
691fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    msg << "WARNING: " << src_text
692fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        << " is expected to be a 32-bit integer, but actually"
693fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt        << " has value " << str << ", which overflows.\n";
694fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    printf("%s", msg.GetString().c_str());
695fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    fflush(stdout);
696fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return false;
697fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
698fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
699fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  *value = result;
700fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return true;
701fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
702fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
703fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Reads and returns the Boolean environment variable corresponding to
704fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// the given flag; if it's not set, returns default_value.
705fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt//
706fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// The value is considered true iff it's not "0".
707fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtbool BoolFromGTestEnv(const char* flag, bool default_value) {
708fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String env_var = FlagToEnvVar(flag);
709fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const string_value = posix::GetEnv(env_var.c_str());
710fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return string_value == NULL ?
711fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt      default_value : strcmp(string_value, "0") != 0;
712fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
713fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
714fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Reads and returns a 32-bit integer stored in the environment
715fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// variable corresponding to the given flag; if it isn't set or
716fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// doesn't represent a valid 32-bit integer, returns default_value.
717fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric AnholtInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
718fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String env_var = FlagToEnvVar(flag);
719fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const string_value = posix::GetEnv(env_var.c_str());
720fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (string_value == NULL) {
721fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    // The environment variable is not set.
722fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return default_value;
723fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
724fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
725fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  Int32 result = default_value;
726fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  if (!ParseInt32(Message() << "Environment variable " << env_var,
727fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt                  string_value, &result)) {
728fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    printf("The default value %s is used.\n",
729fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt           (Message() << default_value).GetString().c_str());
730fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    fflush(stdout);
731fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt    return default_value;
732fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  }
733fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
734fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return result;
735fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
736fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
737fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// Reads and returns the string environment variable corresponding to
738fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt// the given flag; if it's not set, returns default_value.
739fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholtconst char* StringFromGTestEnv(const char* flag, const char* default_value) {
740fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const String env_var = FlagToEnvVar(flag);
741fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  const char* const value = posix::GetEnv(env_var.c_str());
742fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt  return value == NULL ? default_value : value;
743fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}
744fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt
745fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}  // namespace internal
746fe358c0ffa4acb7ecab10fda68ba9740497d2e7fEric Anholt}  // namespace testing
747