aboutsummaryrefslogtreecommitdiffstats
path: root/thirdparty/glog/glog-0.3.4/src
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/glog/glog-0.3.4/src')
-rw-r--r--thirdparty/glog/glog-0.3.4/src/base/commandlineflags.h134
-rw-r--r--thirdparty/glog/glog-0.3.4/src/base/googleinit.h51
-rw-r--r--thirdparty/glog/glog-0.3.4/src/base/mutex.h593
-rw-r--r--thirdparty/glog/glog-0.3.4/src/config_for_unittests.h66
-rw-r--r--thirdparty/glog/glog-0.3.4/src/demangle.cc1310
-rw-r--r--thirdparty/glog/glog-0.3.4/src/demangle.h84
-rw-r--r--thirdparty/glog/glog-0.3.4/src/demangle_unittest.cc142
-rw-r--r--thirdparty/glog/glog-0.3.4/src/demangle_unittest.sh95
-rw-r--r--thirdparty/glog/glog-0.3.4/src/demangle_unittest.txt137
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/log_severity.h92
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/logging.h.in1634
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/nstack_adapter.ph103
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/nstack_glog.ph424
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/nstack_glog_in.h215
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/raw_logging.h.in191
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/stl_logging.h.in220
-rw-r--r--thirdparty/glog/glog-0.3.4/src/glog/vlog_is_on.h.in129
-rw-r--r--thirdparty/glog/glog-0.3.4/src/googletest.h599
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging.cc2579
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_striplog_test.sh79
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_striptest10.cc35
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_striptest2.cc35
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_striptest_main.cc68
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_unittest.cc1219
-rw-r--r--thirdparty/glog/glog-0.3.4/src/logging_unittest.err305
-rw-r--r--thirdparty/glog/glog-0.3.4/src/mock-log.h158
-rw-r--r--thirdparty/glog/glog-0.3.4/src/mock-log_test.cc109
-rw-r--r--thirdparty/glog/glog-0.3.4/src/nstack_logging.cc1066
-rw-r--r--thirdparty/glog/glog-0.3.4/src/raw_logging.cc172
-rw-r--r--thirdparty/glog/glog-0.3.4/src/signalhandler.cc362
-rw-r--r--thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.cc97
-rw-r--r--thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.sh131
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace.h60
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_generic-inl.h59
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_libunwind-inl.h87
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_powerpc-inl.h133
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_unittest.cc208
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_x86-inl.h139
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stacktrace_x86_64-inl.h105
-rw-r--r--thirdparty/glog/glog-0.3.4/src/stl_logging_unittest.cc188
-rw-r--r--thirdparty/glog/glog-0.3.4/src/symbolize.cc851
-rw-r--r--thirdparty/glog/glog-0.3.4/src/symbolize.h155
-rw-r--r--thirdparty/glog/glog-0.3.4/src/symbolize_unittest.cc365
-rw-r--r--thirdparty/glog/glog-0.3.4/src/utilities.cc431
-rw-r--r--thirdparty/glog/glog-0.3.4/src/utilities.h230
-rw-r--r--thirdparty/glog/glog-0.3.4/src/utilities_unittest.cc54
-rw-r--r--thirdparty/glog/glog-0.3.4/src/vlog_is_on.cc252
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/config.h21
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/glog/log_severity.h96
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/glog/logging.h1607
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/glog/raw_logging.h189
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/glog/stl_logging.h224
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/glog/vlog_is_on.h133
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/port.cc64
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/port.h159
-rw-r--r--thirdparty/glog/glog-0.3.4/src/windows/preprocess.sh119
56 files changed, 18563 insertions, 0 deletions
diff --git a/thirdparty/glog/glog-0.3.4/src/base/commandlineflags.h b/thirdparty/glog/glog-0.3.4/src/base/commandlineflags.h
new file mode 100644
index 0000000..c0979d4
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/base/commandlineflags.h
@@ -0,0 +1,134 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// This file is a compatibility layer that defines Google's version of
+// command line flags that are used for configuration.
+//
+// We put flags into their own namespace. It is purposefully
+// named in an opaque way that people should have trouble typing
+// directly. The idea is that DEFINE puts the flag in the weird
+// namespace, and DECLARE imports the flag from there into the
+// current namespace. The net result is to force people to use
+// DECLARE to get access to a flag, rather than saying
+// extern bool FLAGS_logtostderr;
+// or some such instead. We want this so we can put extra
+// functionality (like sanity-checking) in DECLARE if we want,
+// and make sure it is picked up everywhere.
+//
+// We also put the type of the variable in the namespace, so that
+// people can't DECLARE_int32 something that they DEFINE_bool'd
+// elsewhere.
+#ifndef BASE_COMMANDLINEFLAGS_H__
+#define BASE_COMMANDLINEFLAGS_H__
+
+#include "config.h"
+#include <string>
+#include <string.h> // for memchr
+#include <stdlib.h> // for getenv
+
+#ifdef HAVE_LIB_GFLAGS
+
+#include <gflags/gflags.h>
+
+#else
+
+#include "glog/logging.h"
+
+#define DECLARE_VARIABLE(type, shorttype, name, tn) \
+ namespace fL_ns##shorttype { \
+ extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
+ } \
+ using fL_ns##shorttype::FLAGS_##name
+#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
+ namespace fL_ns##shorttype { \
+ GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value); \
+ char FLAGS_no##name; \
+ } \
+ using fL_ns##shorttype::FLAGS_##name
+
+// bool specialization
+#define DECLARE_bool(name) \
+ DECLARE_VARIABLE(bool, B, name, bool)
+#define DEFINE_bool(name, value, meaning) \
+ DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
+
+// int32 specialization
+#define DECLARE_int32(name) \
+ DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, int32)
+#define DEFINE_int32(name, value, meaning) \
+ DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, value, meaning, int32)
+
+// Special case for string, because we have to specify the namespace
+// std::string, which doesn't play nicely with our FLAG__namespace hackery.
+#define DECLARE_string(name) \
+ namespace fLS_ns { \
+ extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
+ } \
+ using fLS_ns::FLAGS_##name
+#define DEFINE_string(name, value, meaning) \
+ namespace fLS_ns{ \
+ std::string FLAGS_##name##_buf(value); \
+ GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name = FLAGS_##name##_buf; \
+ char FLAGS_no##name; \
+ } \
+ using fLS_ns::FLAGS_##name
+
+#endif // HAVE_LIB_GFLAGS
+
+// Define GLOG_DEFINE_* using DEFINE_* . By using these macros, we
+// have GLOG_* environ variables even if we have gflags installed.
+//
+// If both an environment variable and a flag are specified, the value
+// specified by a flag wins. E.g., if GLOG_v=0 and --v=1, the
+// verbosity will be 1, not 0.
+
+#define GLOG_DEFINE_bool(name, value, meaning) \
+ DEFINE_bool(name, EnvToBool("GLOG_" #name, value), meaning)
+
+#define GLOG_DEFINE_int32(name, value, meaning) \
+ DEFINE_int32(name, EnvToInt("GLOG_" #name, value), meaning)
+
+#define GLOG_DEFINE_string(name, value, meaning) \
+ DEFINE_string(name, EnvToString("GLOG_" #name, value), meaning)
+
+// These macros (could be functions, but I don't want to bother with a .cc
+// file), make it easier to initialize flags from the environment.
+
+
+#define EnvToString(envname, dflt) (dflt)
+
+#define EnvToBool(envname, dflt) (dflt)
+
+#define EnvToInt(envname, dflt) (dflt)
+
+#endif // BASE_COMMANDLINEFLAGS_H__
diff --git a/thirdparty/glog/glog-0.3.4/src/base/googleinit.h b/thirdparty/glog/glog-0.3.4/src/base/googleinit.h
new file mode 100644
index 0000000..5a8b515
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/base/googleinit.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Jacob Hoffman-Andrews
+
+#ifndef _GOOGLEINIT_H
+#define _GOOGLEINIT_H
+
+class GoogleInitializer {
+ public:
+ typedef void (*void_function)(void);
+ GoogleInitializer(const char*, void_function f) {
+ f();
+ }
+};
+
+#define REGISTER_MODULE_INITIALIZER(name, body) \
+ namespace { \
+ static void google_init_module_##name () { body; } \
+ GoogleInitializer google_initializer_module_##name(#name, \
+ google_init_module_##name); \
+ }
+
+#endif /* _GOOGLEINIT_H */
diff --git a/thirdparty/glog/glog-0.3.4/src/base/mutex.h b/thirdparty/glog/glog-0.3.4/src/base/mutex.h
new file mode 100644
index 0000000..7a45516
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/base/mutex.h
@@ -0,0 +1,593 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---
+// Author: Craig Silverstein.
+//
+// A simple mutex wrapper, supporting locks and read-write locks.
+// You should assume the locks are *not* re-entrant.
+//
+// To use: you should define the following macros in your configure.ac:
+// ACX_PTHREAD
+// AC_RWLOCK
+// The latter is defined in ../autoconf.
+//
+// This class is meant to be internal-only and should be wrapped by an
+// internal namespace. Before you use this module, please give the
+// name of your internal namespace for this module. Or, if you want
+// to expose it, you'll want to move it to the Google namespace. We
+// cannot put this class in global namespace because there can be some
+// problems when we have multiple versions of Mutex in each shared object.
+//
+// NOTE: by default, we have #ifdef'ed out the TryLock() method.
+// This is for two reasons:
+// 1) TryLock() under Windows is a bit annoying (it requires a
+// #define to be defined very early).
+// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
+// mode.
+// If you need TryLock(), and either these two caveats are not a
+// problem for you, or you're willing to work around them, then
+// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
+// in the code below.
+//
+// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
+// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
+// Because of that, we might as well use windows locks for
+// cygwin. They seem to be more reliable than the cygwin pthreads layer.
+//
+// TRICKY IMPLEMENTATION NOTE:
+// This class is designed to be safe to use during
+// dynamic-initialization -- that is, by global constructors that are
+// run before main() starts. The issue in this case is that
+// dynamic-initialization happens in an unpredictable order, and it
+// could be that someone else's dynamic initializer could call a
+// function that tries to acquire this mutex -- but that all happens
+// before this mutex's constructor has run. (This can happen even if
+// the mutex and the function that uses the mutex are in the same .cc
+// file.) Basically, because Mutex does non-trivial work in its
+// constructor, it's not, in the naive implementation, safe to use
+// before dynamic initialization has run on it.
+//
+// The solution used here is to pair the actual mutex primitive with a
+// bool that is set to true when the mutex is dynamically initialized.
+// (Before that it's false.) Then we modify all mutex routines to
+// look at the bool, and not try to lock/unlock until the bool makes
+// it to true (which happens after the Mutex constructor has run.)
+//
+// This works because before main() starts -- particularly, during
+// dynamic initialization -- there are no threads, so a) it's ok that
+// the mutex operations are a no-op, since we don't need locking then
+// anyway; and b) we can be quite confident our bool won't change
+// state between a call to Lock() and a call to Unlock() (that would
+// require a global constructor in one translation unit to call Lock()
+// and another global constructor in another translation unit to call
+// Unlock() later, which is pretty perverse).
+//
+// That said, it's tricky, and can conceivably fail; it's safest to
+// avoid trying to acquire a mutex in a global constructor, if you
+// can. One way it can fail is that a really smart compiler might
+// initialize the bool to true at static-initialization time (too
+// early) rather than at dynamic-initialization time. To discourage
+// that, we set is_safe_ to true in code (not the constructor
+// colon-initializer) and set it to true via a function that always
+// evaluates to true, but that the compiler can't know always
+// evaluates to true. This should be good enough.
+
+#ifndef GOOGLE_MUTEX_H_
+#define GOOGLE_MUTEX_H_
+
+#include "config.h" // to figure out pthreads support
+#include <stdint.h>
+
+/* open the trylock */
+#define GMUTEX_TRYLOCK 1
+
+
+
+#define USE_USR_GM_TIME 1
+#define MPLOCKED "lock ; "
+
+extern int glogCtrlOpt;
+typedef int int32_t;
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+
+/**
+ * The rtp_rwlock_t type.
+ *
+ * cnt is -1 when write lock is held, and > 0 when read locks are held.
+ */
+typedef struct {
+ volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */
+} nstack_rwlock_t;
+
+/**
+ * The atomic counter structure.
+ */
+typedef struct {
+ volatile int32_t cnt; /**< An internal counter value. */
+} nstack_atomic32_t;
+
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+/**
+ * PAUSE instruction for tight loops (avoid busy waiting)
+ */
+static inline void
+nstack_pause (void)
+{
+ _mm_pause();
+}
+#else
+static inline void
+nstack_pause(void) {}
+#endif
+
+/*------------------------- 32 bit atomic operations -------------------------*/
+
+static inline int
+nstack_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
+{
+ uint8_t res;
+
+ asm volatile(
+ MPLOCKED
+ "cmpxchgl %[src], %[dst];"
+ "sete %[res];"
+ : [res] "=a" (res), /* output */
+ [dst] "=m" (*dst)
+ : [src] "r" (src), /* input */
+ "a" (exp),
+ "m" (*dst)
+ : "memory"); /* no-clobber list */
+ return res;
+}
+
+static inline void
+nstack_atomic32_inc(nstack_atomic32_t *v)
+{
+ asm volatile(
+ MPLOCKED
+ "incl %[cnt]"
+ : [cnt] "=m" (v->cnt) /* output */
+ : "m" (v->cnt) /* input */
+ );
+}
+
+static inline void
+nstack_atomic32_dec(nstack_atomic32_t *v)
+{
+ asm volatile(
+ MPLOCKED
+ "decl %[cnt]"
+ : [cnt] "=m" (v->cnt) /* output */
+ : "m" (v->cnt) /* input */
+ );
+}
+
+/*
+ init the rwlock
+*/
+static inline void
+nstack_rwlock_lock_init(nstack_rwlock_t *rwl)
+{
+ rwl->cnt = 0;
+}
+
+/*
+ init the rwlock
+*/
+static inline void
+nstack_rwlock_lock_destroy(nstack_rwlock_t *rwl)
+{
+ rwl->cnt = 0;
+}
+
+/**
+ * Take a read lock. Loop until the lock is held.
+ *
+ * @param rwl
+ * A pointer to a rwlock structure.
+ */
+static inline void
+nstack_rwlock_read_lock(nstack_rwlock_t *rwl)
+{
+ int32_t x;
+ int success = 0;
+
+ while (success == 0) {
+ x = rwl->cnt;
+ /* write lock is held */
+ if (x < 0) {
+ nstack_pause();
+ continue;
+ }
+ success = nstack_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
+ x, x + 1);
+ }
+}
+
+/**
+ * Release a read lock.
+ *
+ * @param rwl
+ * A pointer to the rwlock structure.
+ */
+static inline void
+nstack_rwlock_read_unlock(nstack_rwlock_t *rwl)
+{
+ nstack_atomic32_dec((nstack_atomic32_t *)(intptr_t)&rwl->cnt);
+}
+
+/**
+ * Take a write lock. Loop until the lock is held.
+ *
+ * @param rwl
+ * A pointer to a rwlock structure.
+ */
+static inline void
+nstack_rwlock_write_lock(nstack_rwlock_t *rwl)
+{
+ int32_t x;
+ int success = 0;
+
+ while (success == 0) {
+ x = rwl->cnt;
+ /* a lock is held */
+ if (x != 0) {
+ nstack_pause();
+ continue;
+ }
+ success = nstack_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
+ 0, -1);
+ }
+}
+
+/**
+ * Release a write lock.
+ *
+ * @param rwl
+ * A pointer to a rwlock structure.
+ */
+static inline void
+nstack_rwlock_write_unlock(nstack_rwlock_t *rwl)
+{
+ nstack_atomic32_inc((nstack_atomic32_t *)(intptr_t)&rwl->cnt);
+}
+
+
+#if defined(NO_THREADS)
+ typedef int MutexType; // to keep a lock-count
+#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN // We only need minimal includes
+# endif
+# ifdef GMUTEX_TRYLOCK
+ // We need Windows NT or later for TryEnterCriticalSection(). If you
+ // don't need that functionality, you can remove these _WIN32_WINNT
+ // lines, and change TryLock() to assert(0) or something.
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0400
+# endif
+# endif
+// To avoid macro definition of ERROR.
+# ifndef NOGDI
+# define NOGDI
+# endif
+// To avoid macro definition of min/max.
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# include <windows.h>
+ typedef CRITICAL_SECTION MutexType;
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+ // Needed for pthread_rwlock_*. If it causes problems, you could take it
+ // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
+ // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
+ // for locking there.)
+# ifdef __linux__
+# ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
+# endif
+# endif
+# include <pthread.h>
+ typedef pthread_rwlock_t MutexType;
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+ typedef pthread_mutex_t MutexType;
+#else
+# error Need to implement mutex.h for your architecture, or #define NO_THREADS
+#endif
+
+// We need to include these header files after defining _XOPEN_SOURCE
+// as they may define the _XOPEN_SOURCE macro.
+#include <assert.h>
+#include <stdlib.h> // for abort()
+
+
+
+#define MUTEX_NAMESPACE glog_ns_internal_namespace_
+
+namespace MUTEX_NAMESPACE {
+
+class Mutex {
+ public:
+ // Create a Mutex that is not held by anybody. This constructor is
+ // typically used for Mutexes allocated on the heap or the stack.
+ // See below for a recommendation for constructing global Mutex
+ // objects.
+ inline Mutex();
+
+ // Destructor
+ inline ~Mutex();
+
+ inline void Lock(); // Block if needed until free then acquire exclusively
+ inline void Unlock(); // Release a lock acquired via Lock()
+
+ inline void ForceUnlock(); // Release a lock acquired via Lock()
+
+#ifdef GMUTEX_TRYLOCK
+ inline bool TryLock(); // If free, Lock() and return true, else return false
+#endif
+ // Note that on systems that don't support read-write locks, these may
+ // be implemented as synonyms to Lock() and Unlock(). So you can use
+ // these for efficiency, but don't use them anyplace where being able
+ // to do shared reads is necessary to avoid deadlock.
+ inline void ReaderLock(); // Block until free or shared then acquire a share
+ inline void ReaderUnlock(); // Release a read share of this Mutex
+ inline void WriterLock() { Lock(); } // Acquire an exclusive lock
+ inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
+
+ // TODO(hamaji): Do nothing, implement correctly.
+ inline void AssertHeld() {}
+
+ private:
+ MutexType mutex_;
+ // We want to make sure that the compiler sets is_safe_ to true only
+ // when we tell it to, and never makes assumptions is_safe_ is
+ // always true. volatile is the most reliable way to do that.
+ volatile bool is_safe_;
+
+ nstack_rwlock_t rwlock_;
+
+
+ inline void SetIsSafe() { is_safe_ = true; }
+
+ // Catch the error of writing Mutex when intending MutexLock.
+ Mutex(Mutex* /*ignored*/) {}
+ // Disallow "evil" constructors
+ Mutex(const Mutex&);
+ void operator=(const Mutex&);
+};
+
+// Now the implementation of Mutex for various systems
+#if defined(NO_THREADS)
+
+// When we don't have threads, we can be either reading or writing,
+// but not both. We can have lots of readers at once (in no-threads
+// mode, that's most likely to happen in recursive function calls),
+// but only one writer. We represent this by having mutex_ be -1 when
+// writing and a number > 0 when reading (and 0 when no lock is held).
+//
+// In debug mode, we assert these invariants, while in non-debug mode
+// we do nothing, for efficiency. That's why everything is in an
+// assert.
+
+Mutex::Mutex() : mutex_(0) { }
+Mutex::~Mutex() { assert(mutex_ == 0); }
+void Mutex::Lock() { assert(--mutex_ == -1); }
+void Mutex::Unlock() { assert(mutex_++ == -1); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
+#endif
+void Mutex::ReaderLock() { assert(++mutex_ > 0); }
+void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
+
+#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+
+Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
+Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
+void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
+void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock() { return is_safe_ ?
+ TryEnterCriticalSection(&mutex_) != 0 : true; }
+#endif
+void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
+void Mutex::ReaderUnlock() { Unlock(); }
+
+#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+
+#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
+ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
+} while (0)
+
+
+Mutex::Mutex() {
+ SetIsSafe();
+ if (is_safe_){
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_lock_init(&rwlock_);
+ }
+ else
+ {
+ if(pthread_rwlock_init(&mutex_, NULL) != 0)
+ abort();
+ }
+
+ }
+}
+Mutex::~Mutex(){
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_lock_destroy(&rwlock_);
+ }
+ else {
+ SAFE_PTHREAD(pthread_rwlock_destroy);
+ }
+}
+void Mutex::Lock() {
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_write_lock(&rwlock_);
+ }
+ else {
+ SAFE_PTHREAD(pthread_rwlock_wrlock);
+ }
+}
+
+void Mutex::Unlock(){
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_write_unlock(&rwlock_);
+ }
+ else {
+ SAFE_PTHREAD(pthread_rwlock_unlock);
+ }
+}
+
+void Mutex::ForceUnlock(){
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_lock_destroy(&rwlock_);
+ }
+ else
+ {
+
+ Mutex::TryLock();
+ Mutex::Unlock();
+ }
+}
+
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock(){
+ if(is_safe_){
+ if (glogCtrlOpt == USE_USR_GM_TIME)
+ return true;
+ else
+ return pthread_rwlock_trywrlock(&mutex_) == 0;
+
+ }
+ else
+ return true;
+}
+
+#endif
+void Mutex::ReaderLock(){
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_read_lock(&rwlock_);
+ }
+ else {
+ SAFE_PTHREAD(pthread_rwlock_rdlock);
+ }
+}
+
+void Mutex::ReaderUnlock() {
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ nstack_rwlock_read_unlock(&rwlock_);
+ }
+ else {
+ SAFE_PTHREAD(pthread_rwlock_unlock);
+ }
+}
+#undef SAFE_PTHREAD
+
+#elif defined(HAVE_PTHREAD)
+
+#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
+ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
+} while (0)
+
+Mutex::Mutex() {
+ SetIsSafe();
+ if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
+void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
+void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
+#ifdef GMUTEX_TRYLOCK
+bool Mutex::TryLock() { return is_safe_ ?
+ pthread_mutex_trylock(&mutex_) == 0 : true; }
+#endif
+void Mutex::ReaderLock() { Lock(); }
+void Mutex::ReaderUnlock() { Unlock(); }
+#undef SAFE_PTHREAD
+
+#endif
+
+// --------------------------------------------------------------------------
+// Some helper classes
+
+// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
+class MutexLock {
+ public:
+ explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
+ ~MutexLock() { mu_->Unlock(); }
+ private:
+ Mutex * const mu_;
+ // Disallow "evil" constructors
+ MutexLock(const MutexLock&);
+ void operator=(const MutexLock&);
+};
+
+// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
+class ReaderMutexLock {
+ public:
+ explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
+ ~ReaderMutexLock() { mu_->ReaderUnlock(); }
+ private:
+ Mutex * const mu_;
+ // Disallow "evil" constructors
+ ReaderMutexLock(const ReaderMutexLock&);
+ void operator=(const ReaderMutexLock&);
+};
+
+class WriterMutexLock {
+ public:
+ explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
+ ~WriterMutexLock() { mu_->WriterUnlock(); }
+ private:
+ Mutex * const mu_;
+ // Disallow "evil" constructors
+ WriterMutexLock(const WriterMutexLock&);
+ void operator=(const WriterMutexLock&);
+};
+
+// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
+#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
+#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
+#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
+
+} // namespace MUTEX_NAMESPACE
+
+using namespace MUTEX_NAMESPACE;
+
+#undef MUTEX_NAMESPACE
+
+#endif /* #define GOOGLE_MUTEX_H__ */
diff --git a/thirdparty/glog/glog-0.3.4/src/config_for_unittests.h b/thirdparty/glog/glog-0.3.4/src/config_for_unittests.h
new file mode 100644
index 0000000..13ea8ea
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/config_for_unittests.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// All Rights Reserved.
+//
+// Author: Craig Silverstein
+// Copied from google-perftools and modified by Shinichiro Hamaji
+//
+// This file is needed for windows -- unittests are not part of the
+// glog dll, but still want to include config.h just like the
+// dll does, so they can use internal tools and APIs for testing.
+//
+// The problem is that config.h declares GOOGLE_GLOG_DLL_DECL to be
+// for exporting symbols, but the unittest needs to *import* symbols
+// (since it's not the dll).
+//
+// The solution is to have this file, which is just like config.h but
+// sets GOOGLE_GLOG_DLL_DECL to do a dllimport instead of a dllexport.
+//
+// The reason we need this extra GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
+// variable is in case people want to set GOOGLE_GLOG_DLL_DECL explicitly
+// to something other than __declspec(dllexport). In that case, they
+// may want to use something other than __declspec(dllimport) for the
+// unittest case. For that, we allow folks to define both
+// GOOGLE_GLOG_DLL_DECL and GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS explicitly.
+//
+// NOTE: This file is equivalent to config.h on non-windows systems,
+// which never defined GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS and always
+// define GOOGLE_GLOG_DLL_DECL to the empty string.
+
+#include "config.h"
+
+#undef GOOGLE_GLOG_DLL_DECL
+#ifdef GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
+# define GOOGLE_GLOG_DLL_DECL GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
+#else
+// if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
+# define GOOGLE_GLOG_DLL_DECL
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/demangle.cc b/thirdparty/glog/glog-0.3.4/src/demangle.cc
new file mode 100644
index 0000000..a90916c
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/demangle.cc
@@ -0,0 +1,1310 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// For reference check out:
+// http://www.codesourcery.com/public/cxx-abi/abi.html#mangling
+//
+// Note that we only have partial C++0x support yet.
+
+#include <stdio.h> // for NULL
+#include "demangle.h"
+
+_START_GOOGLE_NAMESPACE_
+
+typedef struct {
+ const char *abbrev;
+ const char *real_name;
+} AbbrevPair;
+
+// List of operators from Itanium C++ ABI.
+static const AbbrevPair kOperatorList[] = {
+ { "nw", "new" },
+ { "na", "new[]" },
+ { "dl", "delete" },
+ { "da", "delete[]" },
+ { "ps", "+" },
+ { "ng", "-" },
+ { "ad", "&" },
+ { "de", "*" },
+ { "co", "~" },
+ { "pl", "+" },
+ { "mi", "-" },
+ { "ml", "*" },
+ { "dv", "/" },
+ { "rm", "%" },
+ { "an", "&" },
+ { "or", "|" },
+ { "eo", "^" },
+ { "aS", "=" },
+ { "pL", "+=" },
+ { "mI", "-=" },
+ { "mL", "*=" },
+ { "dV", "/=" },
+ { "rM", "%=" },
+ { "aN", "&=" },
+ { "oR", "|=" },
+ { "eO", "^=" },
+ { "ls", "<<" },
+ { "rs", ">>" },
+ { "lS", "<<=" },
+ { "rS", ">>=" },
+ { "eq", "==" },
+ { "ne", "!=" },
+ { "lt", "<" },
+ { "gt", ">" },
+ { "le", "<=" },
+ { "ge", ">=" },
+ { "nt", "!" },
+ { "aa", "&&" },
+ { "oo", "||" },
+ { "pp", "++" },
+ { "mm", "--" },
+ { "cm", "," },
+ { "pm", "->*" },
+ { "pt", "->" },
+ { "cl", "()" },
+ { "ix", "[]" },
+ { "qu", "?" },
+ { "st", "sizeof" },
+ { "sz", "sizeof" },
+ { NULL, NULL },
+};
+
+// List of builtin types from Itanium C++ ABI.
+static const AbbrevPair kBuiltinTypeList[] = {
+ { "v", "void" },
+ { "w", "wchar_t" },
+ { "b", "bool" },
+ { "c", "char" },
+ { "a", "signed char" },
+ { "h", "unsigned char" },
+ { "s", "short" },
+ { "t", "unsigned short" },
+ { "i", "int" },
+ { "j", "unsigned int" },
+ { "l", "long" },
+ { "m", "unsigned long" },
+ { "x", "long long" },
+ { "y", "unsigned long long" },
+ { "n", "__int128" },
+ { "o", "unsigned __int128" },
+ { "f", "float" },
+ { "d", "double" },
+ { "e", "long double" },
+ { "g", "__float128" },
+ { "z", "ellipsis" },
+ { NULL, NULL }
+};
+
+// List of substitutions Itanium C++ ABI.
+static const AbbrevPair kSubstitutionList[] = {
+ { "St", "" },
+ { "Sa", "allocator" },
+ { "Sb", "basic_string" },
+ // std::basic_string<char, std::char_traits<char>,std::allocator<char> >
+ { "Ss", "string"},
+ // std::basic_istream<char, std::char_traits<char> >
+ { "Si", "istream" },
+ // std::basic_ostream<char, std::char_traits<char> >
+ { "So", "ostream" },
+ // std::basic_iostream<char, std::char_traits<char> >
+ { "Sd", "iostream" },
+ { NULL, NULL }
+};
+
+// State needed for demangling.
+typedef struct {
+ const char *mangled_cur; // Cursor of mangled name.
+ char *out_cur; // Cursor of output string.
+ const char *out_begin; // Beginning of output string.
+ const char *out_end; // End of output string.
+ const char *prev_name; // For constructors/destructors.
+ int prev_name_length; // For constructors/destructors.
+ short nest_level; // For nested names.
+ bool append; // Append flag.
+ bool overflowed; // True if output gets overflowed.
+} State;
+
+// We don't use strlen() in libc since it's not guaranteed to be async
+// signal safe.
+static size_t StrLen(const char *str) {
+ size_t len = 0;
+ while (*str != '\0') {
+ ++str;
+ ++len;
+ }
+ return len;
+}
+
+// Returns true if "str" has at least "n" characters remaining.
+static bool AtLeastNumCharsRemaining(const char *str, int n) {
+ for (int i = 0; i < n; ++i) {
+ if (str[i] == '\0') {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Returns true if "str" has "prefix" as a prefix.
+static bool StrPrefix(const char *str, const char *prefix) {
+ size_t i = 0;
+ while (str[i] != '\0' && prefix[i] != '\0' &&
+ str[i] == prefix[i]) {
+ ++i;
+ }
+ return prefix[i] == '\0'; // Consumed everything in "prefix".
+}
+
+static void InitState(State *state, const char *mangled,
+ char *out, int out_size) {
+ state->mangled_cur = mangled;
+ state->out_cur = out;
+ state->out_begin = out;
+ state->out_end = out + out_size;
+ state->prev_name = NULL;
+ state->prev_name_length = -1;
+ state->nest_level = -1;
+ state->append = true;
+ state->overflowed = false;
+}
+
+// Returns true and advances "mangled_cur" if we find "one_char_token"
+// at "mangled_cur" position. It is assumed that "one_char_token" does
+// not contain '\0'.
+static bool ParseOneCharToken(State *state, const char one_char_token) {
+ if (state->mangled_cur[0] == one_char_token) {
+ ++state->mangled_cur;
+ return true;
+ }
+ return false;
+}
+
+// Returns true and advances "mangled_cur" if we find "two_char_token"
+// at "mangled_cur" position. It is assumed that "two_char_token" does
+// not contain '\0'.
+static bool ParseTwoCharToken(State *state, const char *two_char_token) {
+ if (state->mangled_cur[0] == two_char_token[0] &&
+ state->mangled_cur[1] == two_char_token[1]) {
+ state->mangled_cur += 2;
+ return true;
+ }
+ return false;
+}
+
+// Returns true and advances "mangled_cur" if we find any character in
+// "char_class" at "mangled_cur" position.
+static bool ParseCharClass(State *state, const char *char_class) {
+ if (state->mangled_cur[0] == '\0') {
+ return false;
+ }
+ const char *p = char_class;
+ for (; *p != '\0'; ++p) {
+ if (state->mangled_cur[0] == *p) {
+ ++state->mangled_cur;
+ return true;
+ }
+ }
+ return false;
+}
+
+// This function is used for handling an optional non-terminal.
+static bool Optional(bool) {
+ return true;
+}
+
+// This function is used for handling <non-terminal>+ syntax.
+typedef bool (*ParseFunc)(State *);
+static bool OneOrMore(ParseFunc parse_func, State *state) {
+ if (parse_func(state)) {
+ while (parse_func(state)) {
+ }
+ return true;
+ }
+ return false;
+}
+
+// This function is used for handling <non-terminal>* syntax. The function
+// always returns true and must be followed by a termination token or a
+// terminating sequence not handled by parse_func (e.g.
+// ParseOneCharToken(state, 'E')).
+static bool ZeroOrMore(ParseFunc parse_func, State *state) {
+ while (parse_func(state)) {
+ }
+ return true;
+}
+
+// Append "str" at "out_cur". If there is an overflow, "overflowed"
+// is set to true for later use. The output string is ensured to
+// always terminate with '\0' as long as there is no overflow.
+static void Append(State *state, const char * const str, const int length) {
+ int i;
+ for (i = 0; i < length; ++i) {
+ if (state->out_cur + 1 < state->out_end) { // +1 for '\0'
+ *state->out_cur = str[i];
+ ++state->out_cur;
+ } else {
+ state->overflowed = true;
+ break;
+ }
+ }
+ if (!state->overflowed) {
+ *state->out_cur = '\0'; // Terminate it with '\0'
+ }
+}
+
+// We don't use equivalents in libc to avoid locale issues.
+static bool IsLower(char c) {
+ return c >= 'a' && c <= 'z';
+}
+
+static bool IsAlpha(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+static bool IsDigit(char c) {
+ return c >= '0' && c <= '9';
+}
+
+// Returns true if "str" is a function clone suffix. These suffixes are used
+// by GCC 4.5.x and later versions to indicate functions which have been
+// cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as
+// a function clone suffix.
+static bool IsFunctionCloneSuffix(const char *str) {
+ size_t i = 0;
+ while (str[i] != '\0') {
+ // Consume a single .<alpha>+.<digit>+ sequence.
+ if (str[i] != '.' || !IsAlpha(str[i + 1])) {
+ return false;
+ }
+ i += 2;
+ while (IsAlpha(str[i])) {
+ ++i;
+ }
+ if (str[i] != '.' || !IsDigit(str[i + 1])) {
+ return false;
+ }
+ i += 2;
+ while (IsDigit(str[i])) {
+ ++i;
+ }
+ }
+ return true; // Consumed everything in "str".
+}
+
+// Append "str" with some tweaks, iff "append" state is true.
+// Returns true so that it can be placed in "if" conditions.
+static void MaybeAppendWithLength(State *state, const char * const str,
+ const int length) {
+ if (state->append && length > 0) {
+ // Append a space if the output buffer ends with '<' and "str"
+ // starts with '<' to avoid <<<.
+ if (str[0] == '<' && state->out_begin < state->out_cur &&
+ state->out_cur[-1] == '<') {
+ Append(state, " ", 1);
+ }
+ // Remember the last identifier name for ctors/dtors.
+ if (IsAlpha(str[0]) || str[0] == '_') {
+ state->prev_name = state->out_cur;
+ state->prev_name_length = length;
+ }
+ Append(state, str, length);
+ }
+}
+
+// A convenient wrapper arount MaybeAppendWithLength().
+static bool MaybeAppend(State *state, const char * const str) {
+ if (state->append) {
+ int length = StrLen(str);
+ MaybeAppendWithLength(state, str, length);
+ }
+ return true;
+}
+
+// This function is used for handling nested names.
+static bool EnterNestedName(State *state) {
+ state->nest_level = 0;
+ return true;
+}
+
+// This function is used for handling nested names.
+static bool LeaveNestedName(State *state, short prev_value) {
+ state->nest_level = prev_value;
+ return true;
+}
+
+// Disable the append mode not to print function parameters, etc.
+static bool DisableAppend(State *state) {
+ state->append = false;
+ return true;
+}
+
+// Restore the append mode to the previous state.
+static bool RestoreAppend(State *state, bool prev_value) {
+ state->append = prev_value;
+ return true;
+}
+
+// Increase the nest level for nested names.
+static void MaybeIncreaseNestLevel(State *state) {
+ if (state->nest_level > -1) {
+ ++state->nest_level;
+ }
+}
+
+// Appends :: for nested names if necessary.
+static void MaybeAppendSeparator(State *state) {
+ if (state->nest_level >= 1) {
+ MaybeAppend(state, "::");
+ }
+}
+
+// Cancel the last separator if necessary.
+static void MaybeCancelLastSeparator(State *state) {
+ if (state->nest_level >= 1 && state->append &&
+ state->out_begin <= state->out_cur - 2) {
+ state->out_cur -= 2;
+ *state->out_cur = '\0';
+ }
+}
+
+// Returns true if the identifier of the given length pointed to by
+// "mangled_cur" is anonymous namespace.
+static bool IdentifierIsAnonymousNamespace(State *state, int length) {
+ static const char anon_prefix[] = "_GLOBAL__N_";
+ return (length > (int)sizeof(anon_prefix) - 1 && // Should be longer.
+ StrPrefix(state->mangled_cur, anon_prefix));
+}
+
+// Forward declarations of our parsing functions.
+static bool ParseMangledName(State *state);
+static bool ParseEncoding(State *state);
+static bool ParseName(State *state);
+static bool ParseUnscopedName(State *state);
+static bool ParseUnscopedTemplateName(State *state);
+static bool ParseNestedName(State *state);
+static bool ParsePrefix(State *state);
+static bool ParseUnqualifiedName(State *state);
+static bool ParseSourceName(State *state);
+static bool ParseLocalSourceName(State *state);
+static bool ParseNumber(State *state, int *number_out);
+static bool ParseFloatNumber(State *state);
+static bool ParseSeqId(State *state);
+static bool ParseIdentifier(State *state, int length);
+static bool ParseOperatorName(State *state);
+static bool ParseSpecialName(State *state);
+static bool ParseCallOffset(State *state);
+static bool ParseNVOffset(State *state);
+static bool ParseVOffset(State *state);
+static bool ParseCtorDtorName(State *state);
+static bool ParseType(State *state);
+static bool ParseCVQualifiers(State *state);
+static bool ParseBuiltinType(State *state);
+static bool ParseFunctionType(State *state);
+static bool ParseBareFunctionType(State *state);
+static bool ParseClassEnumType(State *state);
+static bool ParseArrayType(State *state);
+static bool ParsePointerToMemberType(State *state);
+static bool ParseTemplateParam(State *state);
+static bool ParseTemplateTemplateParam(State *state);
+static bool ParseTemplateArgs(State *state);
+static bool ParseTemplateArg(State *state);
+static bool ParseExpression(State *state);
+static bool ParseExprPrimary(State *state);
+static bool ParseLocalName(State *state);
+static bool ParseDiscriminator(State *state);
+static bool ParseSubstitution(State *state);
+
+// Implementation note: the following code is a straightforward
+// translation of the Itanium C++ ABI defined in BNF with a couple of
+// exceptions.
+//
+// - Support GNU extensions not defined in the Itanium C++ ABI
+// - <prefix> and <template-prefix> are combined to avoid infinite loop
+// - Reorder patterns to shorten the code
+// - Reorder patterns to give greedier functions precedence
+// We'll mark "Less greedy than" for these cases in the code
+//
+// Each parsing function changes the state and returns true on
+// success. Otherwise, don't change the state and returns false. To
+// ensure that the state isn't changed in the latter case, we save the
+// original state before we call more than one parsing functions
+// consecutively with &&, and restore the state if unsuccessful. See
+// ParseEncoding() as an example of this convention. We follow the
+// convention throughout the code.
+//
+// Originally we tried to do demangling without following the full ABI
+// syntax but it turned out we needed to follow the full syntax to
+// parse complicated cases like nested template arguments. Note that
+// implementing a full-fledged demangler isn't trivial (libiberty's
+// cp-demangle.c has +4300 lines).
+//
+// Note that (foo) in <(foo) ...> is a modifier to be ignored.
+//
+// Reference:
+// - Itanium C++ ABI
+// <http://www.codesourcery.com/cxx-abi/abi.html#mangling>
+
+// <mangled-name> ::= _Z <encoding>
+static bool ParseMangledName(State *state) {
+ return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
+}
+
+// <encoding> ::= <(function) name> <bare-function-type>
+// ::= <(data) name>
+// ::= <special-name>
+static bool ParseEncoding(State *state) {
+ State copy = *state;
+ if (ParseName(state) && ParseBareFunctionType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseName(state) || ParseSpecialName(state)) {
+ return true;
+ }
+ return false;
+}
+
+// <name> ::= <nested-name>
+// ::= <unscoped-template-name> <template-args>
+// ::= <unscoped-name>
+// ::= <local-name>
+static bool ParseName(State *state) {
+ if (ParseNestedName(state) || ParseLocalName(state)) {
+ return true;
+ }
+
+ State copy = *state;
+ if (ParseUnscopedTemplateName(state) &&
+ ParseTemplateArgs(state)) {
+ return true;
+ }
+ *state = copy;
+
+ // Less greedy than <unscoped-template-name> <template-args>.
+ if (ParseUnscopedName(state)) {
+ return true;
+ }
+ return false;
+}
+
+// <unscoped-name> ::= <unqualified-name>
+// ::= St <unqualified-name>
+static bool ParseUnscopedName(State *state) {
+ if (ParseUnqualifiedName(state)) {
+ return true;
+ }
+
+ State copy = *state;
+ if (ParseTwoCharToken(state, "St") &&
+ MaybeAppend(state, "std::") &&
+ ParseUnqualifiedName(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <unscoped-template-name> ::= <unscoped-name>
+// ::= <substitution>
+static bool ParseUnscopedTemplateName(State *state) {
+ return ParseUnscopedName(state) || ParseSubstitution(state);
+}
+
+// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+static bool ParseNestedName(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'N') &&
+ EnterNestedName(state) &&
+ Optional(ParseCVQualifiers(state)) &&
+ ParsePrefix(state) &&
+ LeaveNestedName(state, copy.nest_level) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// This part is tricky. If we literally translate them to code, we'll
+// end up infinite loop. Hence we merge them to avoid the case.
+//
+// <prefix> ::= <prefix> <unqualified-name>
+// ::= <template-prefix> <template-args>
+// ::= <template-param>
+// ::= <substitution>
+// ::= # empty
+// <template-prefix> ::= <prefix> <(template) unqualified-name>
+// ::= <template-param>
+// ::= <substitution>
+static bool ParsePrefix(State *state) {
+ bool has_something = false;
+ while (true) {
+ MaybeAppendSeparator(state);
+ if (ParseTemplateParam(state) ||
+ ParseSubstitution(state) ||
+ ParseUnscopedName(state)) {
+ has_something = true;
+ MaybeIncreaseNestLevel(state);
+ continue;
+ }
+ MaybeCancelLastSeparator(state);
+ if (has_something && ParseTemplateArgs(state)) {
+ return ParsePrefix(state);
+ } else {
+ break;
+ }
+ }
+ return true;
+}
+
+// <unqualified-name> ::= <operator-name>
+// ::= <ctor-dtor-name>
+// ::= <source-name>
+// ::= <local-source-name>
+static bool ParseUnqualifiedName(State *state) {
+ return (ParseOperatorName(state) ||
+ ParseCtorDtorName(state) ||
+ ParseSourceName(state) ||
+ ParseLocalSourceName(state));
+}
+
+// <source-name> ::= <positive length number> <identifier>
+static bool ParseSourceName(State *state) {
+ State copy = *state;
+ int length = -1;
+ if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <local-source-name> ::= L <source-name> [<discriminator>]
+//
+// References:
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
+// http://gcc.gnu.org/viewcvs?view=rev&revision=124467
+static bool ParseLocalSourceName(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&
+ Optional(ParseDiscriminator(state))) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <number> ::= [n] <non-negative decimal integer>
+// If "number_out" is non-null, then *number_out is set to the value of the
+// parsed number on success.
+static bool ParseNumber(State *state, int *number_out) {
+ int sign = 1;
+ if (ParseOneCharToken(state, 'n')) {
+ sign = -1;
+ }
+ const char *p = state->mangled_cur;
+ int number = 0;
+ for (;*p != '\0'; ++p) {
+ if (IsDigit(*p)) {
+ number = number * 10 + (*p - '0');
+ } else {
+ break;
+ }
+ }
+ if (p != state->mangled_cur) { // Conversion succeeded.
+ state->mangled_cur = p;
+ if (number_out != NULL) {
+ *number_out = number * sign;
+ }
+ return true;
+ }
+ return false;
+}
+
+// Floating-point literals are encoded using a fixed-length lowercase
+// hexadecimal string.
+static bool ParseFloatNumber(State *state) {
+ const char *p = state->mangled_cur;
+ for (;*p != '\0'; ++p) {
+ if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {
+ break;
+ }
+ }
+ if (p != state->mangled_cur) { // Conversion succeeded.
+ state->mangled_cur = p;
+ return true;
+ }
+ return false;
+}
+
+// The <seq-id> is a sequence number in base 36,
+// using digits and upper case letters
+static bool ParseSeqId(State *state) {
+ const char *p = state->mangled_cur;
+ for (;*p != '\0'; ++p) {
+ if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {
+ break;
+ }
+ }
+ if (p != state->mangled_cur) { // Conversion succeeded.
+ state->mangled_cur = p;
+ return true;
+ }
+ return false;
+}
+
+// <identifier> ::= <unqualified source code identifier> (of given length)
+static bool ParseIdentifier(State *state, int length) {
+ if (length == -1 ||
+ !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
+ return false;
+ }
+ if (IdentifierIsAnonymousNamespace(state, length)) {
+ MaybeAppend(state, "(anonymous namespace)");
+ } else {
+ MaybeAppendWithLength(state, state->mangled_cur, length);
+ }
+ state->mangled_cur += length;
+ return true;
+}
+
+// <operator-name> ::= nw, and other two letters cases
+// ::= cv <type> # (cast)
+// ::= v <digit> <source-name> # vendor extended operator
+static bool ParseOperatorName(State *state) {
+ if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) {
+ return false;
+ }
+ // First check with "cv" (cast) case.
+ State copy = *state;
+ if (ParseTwoCharToken(state, "cv") &&
+ MaybeAppend(state, "operator ") &&
+ EnterNestedName(state) &&
+ ParseType(state) &&
+ LeaveNestedName(state, copy.nest_level)) {
+ return true;
+ }
+ *state = copy;
+
+ // Then vendor extended operators.
+ if (ParseOneCharToken(state, 'v') && ParseCharClass(state, "0123456789") &&
+ ParseSourceName(state)) {
+ return true;
+ }
+ *state = copy;
+
+ // Other operator names should start with a lower alphabet followed
+ // by a lower/upper alphabet.
+ if (!(IsLower(state->mangled_cur[0]) &&
+ IsAlpha(state->mangled_cur[1]))) {
+ return false;
+ }
+ // We may want to perform a binary search if we really need speed.
+ const AbbrevPair *p;
+ for (p = kOperatorList; p->abbrev != NULL; ++p) {
+ if (state->mangled_cur[0] == p->abbrev[0] &&
+ state->mangled_cur[1] == p->abbrev[1]) {
+ MaybeAppend(state, "operator");
+ if (IsLower(*p->real_name)) { // new, delete, etc.
+ MaybeAppend(state, " ");
+ }
+ MaybeAppend(state, p->real_name);
+ state->mangled_cur += 2;
+ return true;
+ }
+ }
+ return false;
+}
+
+// <special-name> ::= TV <type>
+// ::= TT <type>
+// ::= TI <type>
+// ::= TS <type>
+// ::= Tc <call-offset> <call-offset> <(base) encoding>
+// ::= GV <(object) name>
+// ::= T <call-offset> <(base) encoding>
+// G++ extensions:
+// ::= TC <type> <(offset) number> _ <(base) type>
+// ::= TF <type>
+// ::= TJ <type>
+// ::= GR <name>
+// ::= GA <encoding>
+// ::= Th <call-offset> <(base) encoding>
+// ::= Tv <call-offset> <(base) encoding>
+//
+// Note: we don't care much about them since they don't appear in
+// stack traces. The are special data.
+static bool ParseSpecialName(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'T') &&
+ ParseCharClass(state, "VTIS") &&
+ ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) &&
+ ParseCallOffset(state) && ParseEncoding(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "GV") &&
+ ParseName(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) &&
+ ParseEncoding(state)) {
+ return true;
+ }
+ *state = copy;
+
+ // G++ extensions
+ if (ParseTwoCharToken(state, "TC") && ParseType(state) &&
+ ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
+ DisableAppend(state) &&
+ ParseType(state)) {
+ RestoreAppend(state, copy.append);
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") &&
+ ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "GR") && ParseName(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") &&
+ ParseCallOffset(state) && ParseEncoding(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <call-offset> ::= h <nv-offset> _
+// ::= v <v-offset> _
+static bool ParseCallOffset(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'h') &&
+ ParseNVOffset(state) && ParseOneCharToken(state, '_')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'v') &&
+ ParseVOffset(state) && ParseOneCharToken(state, '_')) {
+ return true;
+ }
+ *state = copy;
+
+ return false;
+}
+
+// <nv-offset> ::= <(offset) number>
+static bool ParseNVOffset(State *state) {
+ return ParseNumber(state, NULL);
+}
+
+// <v-offset> ::= <(offset) number> _ <(virtual offset) number>
+static bool ParseVOffset(State *state) {
+ State copy = *state;
+ if (ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
+ ParseNumber(state, NULL)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <ctor-dtor-name> ::= C1 | C2 | C3
+// ::= D0 | D1 | D2
+static bool ParseCtorDtorName(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'C') &&
+ ParseCharClass(state, "123")) {
+ const char * const prev_name = state->prev_name;
+ const int prev_name_length = state->prev_name_length;
+ MaybeAppendWithLength(state, prev_name, prev_name_length);
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'D') &&
+ ParseCharClass(state, "012")) {
+ const char * const prev_name = state->prev_name;
+ const int prev_name_length = state->prev_name_length;
+ MaybeAppend(state, "~");
+ MaybeAppendWithLength(state, prev_name, prev_name_length);
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <type> ::= <CV-qualifiers> <type>
+// ::= P <type> # pointer-to
+// ::= R <type> # reference-to
+// ::= O <type> # rvalue reference-to (C++0x)
+// ::= C <type> # complex pair (C 2000)
+// ::= G <type> # imaginary (C 2000)
+// ::= U <source-name> <type> # vendor extended type qualifier
+// ::= <builtin-type>
+// ::= <function-type>
+// ::= <class-enum-type>
+// ::= <array-type>
+// ::= <pointer-to-member-type>
+// ::= <template-template-param> <template-args>
+// ::= <template-param>
+// ::= <substitution>
+// ::= Dp <type> # pack expansion of (C++0x)
+// ::= Dt <expression> E # decltype of an id-expression or class
+// # member access (C++0x)
+// ::= DT <expression> E # decltype of an expression (C++0x)
+//
+static bool ParseType(State *state) {
+ // We should check CV-qualifers, and PRGC things first.
+ State copy = *state;
+ if (ParseCVQualifiers(state) && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseCharClass(state, "OPRCG") && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "Dp") && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") &&
+ ParseExpression(state) && ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
+ ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseBuiltinType(state) ||
+ ParseFunctionType(state) ||
+ ParseClassEnumType(state) ||
+ ParseArrayType(state) ||
+ ParsePointerToMemberType(state) ||
+ ParseSubstitution(state)) {
+ return true;
+ }
+
+ if (ParseTemplateTemplateParam(state) &&
+ ParseTemplateArgs(state)) {
+ return true;
+ }
+ *state = copy;
+
+ // Less greedy than <template-template-param> <template-args>.
+ if (ParseTemplateParam(state)) {
+ return true;
+ }
+
+ return false;
+}
+
+// <CV-qualifiers> ::= [r] [V] [K]
+// We don't allow empty <CV-qualifiers> to avoid infinite loop in
+// ParseType().
+static bool ParseCVQualifiers(State *state) {
+ int num_cv_qualifiers = 0;
+ num_cv_qualifiers += ParseOneCharToken(state, 'r');
+ num_cv_qualifiers += ParseOneCharToken(state, 'V');
+ num_cv_qualifiers += ParseOneCharToken(state, 'K');
+ return num_cv_qualifiers > 0;
+}
+
+// <builtin-type> ::= v, etc.
+// ::= u <source-name>
+static bool ParseBuiltinType(State *state) {
+ const AbbrevPair *p;
+ for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) {
+ if (state->mangled_cur[0] == p->abbrev[0]) {
+ MaybeAppend(state, p->real_name);
+ ++state->mangled_cur;
+ return true;
+ }
+ }
+
+ State copy = *state;
+ if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <function-type> ::= F [Y] <bare-function-type> E
+static bool ParseFunctionType(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'F') &&
+ Optional(ParseOneCharToken(state, 'Y')) &&
+ ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <bare-function-type> ::= <(signature) type>+
+static bool ParseBareFunctionType(State *state) {
+ State copy = *state;
+ DisableAppend(state);
+ if (OneOrMore(ParseType, state)) {
+ RestoreAppend(state, copy.append);
+ MaybeAppend(state, "()");
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <class-enum-type> ::= <name>
+static bool ParseClassEnumType(State *state) {
+ return ParseName(state);
+}
+
+// <array-type> ::= A <(positive dimension) number> _ <(element) type>
+// ::= A [<(dimension) expression>] _ <(element) type>
+static bool ParseArrayType(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'A') && ParseNumber(state, NULL) &&
+ ParseOneCharToken(state, '_') && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) &&
+ ParseOneCharToken(state, '_') && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <pointer-to-member-type> ::= M <(class) type> <(member) type>
+static bool ParsePointerToMemberType(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'M') && ParseType(state) &&
+ ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <template-param> ::= T_
+// ::= T <parameter-2 non-negative number> _
+static bool ParseTemplateParam(State *state) {
+ if (ParseTwoCharToken(state, "T_")) {
+ MaybeAppend(state, "?"); // We don't support template substitutions.
+ return true;
+ }
+
+ State copy = *state;
+ if (ParseOneCharToken(state, 'T') && ParseNumber(state, NULL) &&
+ ParseOneCharToken(state, '_')) {
+ MaybeAppend(state, "?"); // We don't support template substitutions.
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+
+// <template-template-param> ::= <template-param>
+// ::= <substitution>
+static bool ParseTemplateTemplateParam(State *state) {
+ return (ParseTemplateParam(state) ||
+ ParseSubstitution(state));
+}
+
+// <template-args> ::= I <template-arg>+ E
+static bool ParseTemplateArgs(State *state) {
+ State copy = *state;
+ DisableAppend(state);
+ if (ParseOneCharToken(state, 'I') &&
+ OneOrMore(ParseTemplateArg, state) &&
+ ParseOneCharToken(state, 'E')) {
+ RestoreAppend(state, copy.append);
+ MaybeAppend(state, "<>");
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <template-arg> ::= <type>
+// ::= <expr-primary>
+// ::= I <template-arg>* E # argument pack
+// ::= X <expression> E
+static bool ParseTemplateArg(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'I') &&
+ ZeroOrMore(ParseTemplateArg, state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseType(state) ||
+ ParseExprPrimary(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <expression> ::= <template-param>
+// ::= <expr-primary>
+// ::= <unary operator-name> <expression>
+// ::= <binary operator-name> <expression> <expression>
+// ::= <trinary operator-name> <expression> <expression>
+// <expression>
+// ::= st <type>
+// ::= sr <type> <unqualified-name> <template-args>
+// ::= sr <type> <unqualified-name>
+static bool ParseExpression(State *state) {
+ if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
+ return true;
+ }
+
+ State copy = *state;
+ if (ParseOperatorName(state) &&
+ ParseExpression(state) &&
+ ParseExpression(state) &&
+ ParseExpression(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOperatorName(state) &&
+ ParseExpression(state) &&
+ ParseExpression(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOperatorName(state) &&
+ ParseExpression(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "st") && ParseType(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
+ ParseUnqualifiedName(state) &&
+ ParseTemplateArgs(state)) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
+ ParseUnqualifiedName(state)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <expr-primary> ::= L <type> <(value) number> E
+// ::= L <type> <(value) float> E
+// ::= L <mangled-name> E
+// // A bug in g++'s C++ ABI version 2 (-fabi-version=2).
+// ::= LZ <encoding> E
+static bool ParseExprPrimary(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'L') && ParseType(state) &&
+ ParseNumber(state, NULL) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'L') && ParseType(state) &&
+ ParseFloatNumber(state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'L') && ParseMangledName(state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseTwoCharToken(state, "LZ") && ParseEncoding(state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ *state = copy;
+
+ return false;
+}
+
+// <local-name> := Z <(function) encoding> E <(entity) name>
+// [<discriminator>]
+// := Z <(function) encoding> E s [<discriminator>]
+static bool ParseLocalName(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
+ ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") &&
+ ParseName(state) && Optional(ParseDiscriminator(state))) {
+ return true;
+ }
+ *state = copy;
+
+ if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
+ ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <discriminator> := _ <(non-negative) number>
+static bool ParseDiscriminator(State *state) {
+ State copy = *state;
+ if (ParseOneCharToken(state, '_') && ParseNumber(state, NULL)) {
+ return true;
+ }
+ *state = copy;
+ return false;
+}
+
+// <substitution> ::= S_
+// ::= S <seq-id> _
+// ::= St, etc.
+static bool ParseSubstitution(State *state) {
+ if (ParseTwoCharToken(state, "S_")) {
+ MaybeAppend(state, "?"); // We don't support substitutions.
+ return true;
+ }
+
+ State copy = *state;
+ if (ParseOneCharToken(state, 'S') && ParseSeqId(state) &&
+ ParseOneCharToken(state, '_')) {
+ MaybeAppend(state, "?"); // We don't support substitutions.
+ return true;
+ }
+ *state = copy;
+
+ // Expand abbreviations like "St" => "std".
+ if (ParseOneCharToken(state, 'S')) {
+ const AbbrevPair *p;
+ for (p = kSubstitutionList; p->abbrev != NULL; ++p) {
+ if (state->mangled_cur[0] == p->abbrev[1]) {
+ MaybeAppend(state, "std");
+ if (p->real_name[0] != '\0') {
+ MaybeAppend(state, "::");
+ MaybeAppend(state, p->real_name);
+ }
+ ++state->mangled_cur;
+ return true;
+ }
+ }
+ }
+ *state = copy;
+ return false;
+}
+
+// Parse <mangled-name>, optionally followed by either a function-clone suffix
+// or version suffix. Returns true only if all of "mangled_cur" was consumed.
+static bool ParseTopLevelMangledName(State *state) {
+ if (ParseMangledName(state)) {
+ if (state->mangled_cur[0] != '\0') {
+ // Drop trailing function clone suffix, if any.
+ if (IsFunctionCloneSuffix(state->mangled_cur)) {
+ return true;
+ }
+ // Append trailing version suffix if any.
+ // ex. _Z3foo@@GLIBCXX_3.4
+ if (state->mangled_cur[0] == '@') {
+ MaybeAppend(state, state->mangled_cur);
+ return true;
+ }
+ return false; // Unconsumed suffix.
+ }
+ return true;
+ }
+ return false;
+}
+
+// The demangler entry point.
+bool Demangle(const char *mangled, char *out, int out_size) {
+ State state;
+ InitState(&state, mangled, out, out_size);
+ return ParseTopLevelMangledName(&state) && !state.overflowed;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/demangle.h b/thirdparty/glog/glog-0.3.4/src/demangle.h
new file mode 100644
index 0000000..9c75915
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/demangle.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// An async-signal-safe and thread-safe demangler for Itanium C++ ABI
+// (aka G++ V3 ABI).
+
+// The demangler is implemented to be used in async signal handlers to
+// symbolize stack traces. We cannot use libstdc++'s
+// abi::__cxa_demangle() in such signal handlers since it's not async
+// signal safe (it uses malloc() internally).
+//
+// Note that this demangler doesn't support full demangling. More
+// specifically, it doesn't print types of function parameters and
+// types of template arguments. It just skips them. However, it's
+// still very useful to extract basic information such as class,
+// function, constructor, destructor, and operator names.
+//
+// See the implementation note in demangle.cc if you are interested.
+//
+// Example:
+//
+// | Mangled Name | The Demangler | abi::__cxa_demangle()
+// |---------------|---------------|-----------------------
+// | _Z1fv | f() | f()
+// | _Z1fi | f() | f(int)
+// | _Z3foo3bar | foo() | foo(bar)
+// | _Z1fIiEvi | f<>() | void f<int>(int)
+// | _ZN1N1fE | N::f | N::f
+// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
+// | _Zrm1XS_" | operator%() | operator%(X, X)
+// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
+// | _Z1fSs | f() | f(std::basic_string<char,
+// | | | std::char_traits<char>,
+// | | | std::allocator<char> >)
+//
+// See the unit test for more examples.
+//
+// Note: we might want to write demanglers for ABIs other than Itanium
+// C++ ABI in the future.
+//
+
+#ifndef BASE_DEMANGLE_H_
+#define BASE_DEMANGLE_H_
+
+#include "config.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// Demangle "mangled". On success, return true and write the
+// demangled symbol name to "out". Otherwise, return false.
+// "out" is modified even if demangling is unsuccessful.
+bool Demangle(const char *mangled, char *out, int out_size);
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // BASE_DEMANGLE_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/demangle_unittest.cc b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.cc
new file mode 100644
index 0000000..9d219e6
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// Unit tests for functions in demangle.c.
+
+#include "utilities.h"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include "glog/logging.h"
+#include "demangle.h"
+#include "googletest.h"
+#include "config.h"
+
+GLOG_DEFINE_bool(demangle_filter, false,
+ "Run demangle_unittest in filter mode");
+
+using namespace std;
+using namespace GOOGLE_NAMESPACE;
+
+// A wrapper function for Demangle() to make the unit test simple.
+static const char *DemangleIt(const char * const mangled) {
+ static char demangled[4096];
+ if (Demangle(mangled, demangled, sizeof(demangled))) {
+ return demangled;
+ } else {
+ return mangled;
+ }
+}
+
+// Test corner cases of bounary conditions.
+TEST(Demangle, CornerCases) {
+ char tmp[10];
+ EXPECT_TRUE(Demangle("_Z6foobarv", tmp, sizeof(tmp)));
+ // sizeof("foobar()") == 9
+ EXPECT_STREQ("foobar()", tmp);
+ EXPECT_TRUE(Demangle("_Z6foobarv", tmp, 9));
+ EXPECT_STREQ("foobar()", tmp);
+ EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 8)); // Not enough.
+ EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 1));
+ EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 0));
+ EXPECT_FALSE(Demangle("_Z6foobarv", NULL, 0)); // Should not cause SEGV.
+}
+
+// Test handling of functions suffixed with .clone.N, which is used by GCC
+// 4.5.x, and .constprop.N and .isra.N, which are used by GCC 4.6.x. These
+// suffixes are used to indicate functions which have been cloned during
+// optimization. We ignore these suffixes.
+TEST(Demangle, Clones) {
+ char tmp[20];
+ EXPECT_TRUE(Demangle("_ZL3Foov", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.clone.3", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.constprop.80", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.isra.18", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Invalid (truncated), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
+ // Invalid (.clone. not followed by number), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
+ // Invalid (.clone. followed by non-number), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
+ // Invalid (.constprop. not followed by number), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
+}
+
+TEST(Demangle, FromFile) {
+ string test_file = FLAGS_test_srcdir + "/src/demangle_unittest.txt";
+ ifstream f(test_file.c_str()); // The file should exist.
+ EXPECT_FALSE(f.fail());
+
+ string line;
+ while (getline(f, line)) {
+ // Lines start with '#' are considered as comments.
+ if (line.empty() || line[0] == '#') {
+ continue;
+ }
+ // Each line should contain a mangled name and a demangled name
+ // separated by '\t'. Example: "_Z3foo\tfoo"
+ string::size_type tab_pos = line.find('\t');
+ EXPECT_NE(string::npos, tab_pos);
+ string mangled = line.substr(0, tab_pos);
+ string demangled = line.substr(tab_pos + 1);
+ EXPECT_EQ(demangled, DemangleIt(mangled.c_str()));
+ }
+}
+
+int main(int argc, char **argv) {
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ InitGoogleTest(&argc, argv);
+
+ FLAGS_logtostderr = true;
+ InitGoogleLogging(argv[0]);
+ if (FLAGS_demangle_filter) {
+ // Read from cin and write to cout.
+ string line;
+ while (getline(cin, line, '\n')) {
+ cout << DemangleIt(line.c_str()) << endl;
+ }
+ return 0;
+ } else if (argc > 1) {
+ cout << DemangleIt(argv[1]) << endl;
+ return 0;
+ } else {
+ return RUN_ALL_TESTS();
+ }
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/demangle_unittest.sh b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.sh
new file mode 100644
index 0000000..91deee2
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.sh
@@ -0,0 +1,95 @@
+#! /bin/sh
+#
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: Satoru Takabayashi
+#
+# Unit tests for demangle.c with a real binary.
+
+set -e
+
+die () {
+ echo $1
+ exit 1
+}
+
+BINDIR=".libs"
+LIBGLOG="$BINDIR/libglog.so"
+
+DEMANGLER="$BINDIR/demangle_unittest"
+
+if test -e "$DEMANGLER"; then
+ # We need shared object.
+ export LD_LIBRARY_PATH=$BINDIR
+ export DYLD_LIBRARY_PATH=$BINDIR
+else
+ # For windows
+ DEMANGLER="./demangle_unittest.exe"
+ if ! test -e "$DEMANGLER"; then
+ echo "We coundn't find demangle_unittest binary."
+ exit 1
+ fi
+fi
+
+# Extract C++ mangled symbols from libbase.so.
+NM_OUTPUT="demangle.nm"
+nm "$LIBGLOG" | perl -nle 'print $1 if /\s(_Z\S+$)/' > "$NM_OUTPUT"
+
+# Check if mangled symbols exist. If there are none, we quit.
+# The binary is more likely compiled with GCC 2.95 or something old.
+if ! grep --quiet '^_Z' "$NM_OUTPUT"; then
+ echo "PASS"
+ exit 0
+fi
+
+# Demangle the symbols using our demangler.
+DM_OUTPUT="demangle.dm"
+GLOG_demangle_filter=1 "$DEMANGLER" --demangle_filter < "$NM_OUTPUT" > "$DM_OUTPUT"
+
+# Calculate the numbers of lines.
+NM_LINES=`wc -l "$NM_OUTPUT" | awk '{ print $1 }'`
+DM_LINES=`wc -l "$DM_OUTPUT" | awk '{ print $1 }'`
+
+# Compare the numbers of lines. They must be the same.
+if test "$NM_LINES" != "$DM_LINES"; then
+ die "$NM_OUTPUT and $DM_OUTPUT don't have the same numbers of lines"
+fi
+
+# Check if mangled symbols exist. They must not exist.
+if grep --quiet '^_Z' "$DM_OUTPUT"; then
+ MANGLED=`grep '^_Z' "$DM_OUTPUT" | wc -l | awk '{ print \$1 }'`
+ echo "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT:"
+ grep '^_Z' "$DM_OUTPUT"
+ die "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT"
+fi
+
+# All C++ symbols are demangled successfully.
+echo "PASS"
+exit 0
diff --git a/thirdparty/glog/glog-0.3.4/src/demangle_unittest.txt b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.txt
new file mode 100644
index 0000000..4e23c65
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/demangle_unittest.txt
@@ -0,0 +1,137 @@
+# Test caces for demangle_unittest. Each line consists of a
+# tab-separated pair of mangled and demangled symbol names.
+
+# Constructors and destructors.
+_ZN3FooC1Ev Foo::Foo()
+_ZN3FooD1Ev Foo::~Foo()
+_ZNSoD0Ev std::ostream::~ostream()
+
+# G++ extensions.
+_ZTCN10LogMessage9LogStreamE0_So LogMessage::LogStream
+_ZTv0_n12_N10LogMessage9LogStreamD0Ev LogMessage::LogStream::~LogStream()
+_ZThn4_N7icu_3_410UnicodeSetD0Ev icu_3_4::UnicodeSet::~UnicodeSet()
+
+# A bug in g++'s C++ ABI version 2 (-fabi-version=2).
+_ZN7NSSInfoI5groupjjXadL_Z10getgrgid_rEELZ19nss_getgrgid_r_nameEEC1Ei NSSInfo<>::NSSInfo()
+
+# C linkage symbol names. Should keep them untouched.
+main main
+Demangle Demangle
+_ZERO _ZERO
+
+# Cast operator.
+_Zcviv operator int()
+_ZN3foocviEv foo::operator int()
+
+# Versioned symbols.
+_Z3Foo@GLIBCXX_3.4 Foo@GLIBCXX_3.4
+_Z3Foo@@GLIBCXX_3.4 Foo@@GLIBCXX_3.4
+
+# Abbreviations.
+_ZNSaE std::allocator
+_ZNSbE std::basic_string
+_ZNSdE std::iostream
+_ZNSiE std::istream
+_ZNSoE std::ostream
+_ZNSsE std::string
+
+# Substitutions. We just replace them with ?.
+_ZN3fooS_E foo::?
+_ZN3foo3barS0_E foo::bar::?
+_ZNcvT_IiEEv operator ?<>()
+
+# "<< <" case.
+_ZlsI3fooE operator<< <>
+
+# Random things we found interesting.
+_ZN3FooISt6vectorISsSaISsEEEclEv Foo<>::operator()()
+_ZTI9Callback1IiE Callback1<>
+_ZN7icu_3_47UMemorynwEj icu_3_4::UMemory::operator new()
+_ZNSt6vectorIbE9push_backE std::vector<>::push_back
+_ZNSt6vectorIbSaIbEE9push_backEb std::vector<>::push_back()
+_ZlsRSoRK15PRIVATE_Counter operator<<()
+_ZSt6fill_nIPPN9__gnu_cxx15_Hashtable_nodeISt4pairIKPKcjEEEjS8_ET_SA_T0_RKT1_ std::fill_n<>()
+_ZZ3FoovE3Bar Foo()::Bar
+_ZGVZ7UpTimervE8up_timer UpTimer()::up_timer
+
+# Test cases from gcc-4.1.0/libstdc++-v3/testsuite/demangle.
+# Collected by:
+# % grep verify_demangle **/*.cc | perl -nle 'print $1 if /"(_Z.*?)"/' |
+# sort | uniq
+#
+# Note that the following symbols are invalid.
+# That's why they are not demangled.
+# - _ZNZN1N1fEiE1X1gE
+# - _ZNZN1N1fEiE1X1gEv
+# - _Z1xINiEE
+_Z1fA37_iPS_ f()
+_Z1fAszL_ZZNK1N1A1fEvE3foo_0E_i f()
+_Z1fI1APS0_PKS0_EvT_T0_T1_PA4_S3_M1CS8_ f<>()
+_Z1fI1XENT_1tES2_ f<>()
+_Z1fI1XEvPVN1AIT_E1TE f<>()
+_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE f<>()
+_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE f<>()
+_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE f<>()
+_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE f<>()
+_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE f<>()
+_Z1fIiEvi f<>()
+_Z1fKPFiiE f()
+_Z1fM1AFivEPS0_ f()
+_Z1fM1AKFivE f()
+_Z1fM1AKFvvE f()
+_Z1fPFPA1_ivE f()
+_Z1fPFYPFiiEiE f()
+_Z1fPFvvEM1SFvvE f()
+_Z1fPKM1AFivE f()
+_Z1fi f()
+_Z1fv f()
+_Z1jM1AFivEPS1_ j()
+_Z1rM1GFivEMS_KFivES_M1HFivES1_4whatIKS_E5what2IS8_ES3_ r()
+_Z1sPA37_iPS0_ s()
+_Z1xINiEE _Z1xINiEE
+_Z3absILi11EEvv abs<>()
+_Z3foo3bar foo()
+_Z3foo5Hello5WorldS0_S_ foo()
+_Z3fooA30_A_i foo()
+_Z3fooIA6_KiEvA9_KT_rVPrS4_ foo<>()
+_Z3fooILi2EEvRAplT_Li1E_i foo<>()
+_Z3fooIiFvdEiEvv foo<>()
+_Z3fooPM2ABi foo()
+_Z3fooc foo()
+_Z3fooiPiPS_PS0_PS1_PS2_PS3_PS4_PS5_PS6_PS7_PS8_PS9_PSA_PSB_PSC_ foo()
+_Z3kooPA28_A30_i koo()
+_Z4makeI7FactoryiET_IT0_Ev make<>()
+_Z5firstI3DuoEvS0_ first<>()
+_Z5firstI3DuoEvT_ first<>()
+_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE hairyfunc()
+_ZGVN5libcw24_GLOBAL__N_cbll.cc0ZhUKa23compiler_bug_workaroundISt6vectorINS_13omanip_id_tctINS_5debug32memblk_types_manipulator_data_ctEEESaIS6_EEE3idsE libcw::(anonymous namespace)::compiler_bug_workaround<>::ids
+_ZN12libcw_app_ct10add_optionIS_EEvMT_FvPKcES3_cS3_S3_ libcw_app_ct::add_option<>()
+_ZN1AIfEcvT_IiEEv A<>::operator ?<>()
+_ZN1N1TIiiE2mfES0_IddE N::T<>::mf()
+_ZN1N1fE N::f
+_ZN1f1fE f::f
+_ZN3FooIA4_iE3barE Foo<>::bar
+_ZN5Arena5levelE Arena::level
+_ZN5StackIiiE5levelE Stack<>::level
+_ZN5libcw5debug13cwprint_usingINS_9_private_12GlobalObjectEEENS0_17cwprint_using_tctIT_EERKS5_MS5_KFvRSt7ostreamE libcw::debug::cwprint_using<>()
+_ZN6System5Sound4beepEv System::Sound::beep()
+_ZNKSt14priority_queueIP27timer_event_request_base_ctSt5dequeIS1_SaIS1_EE13timer_greaterE3topEv std::priority_queue<>::top()
+_ZNKSt15_Deque_iteratorIP15memory_block_stRKS1_PS2_EeqERKS5_ std::_Deque_iterator<>::operator==()
+_ZNKSt17__normal_iteratorIPK6optionSt6vectorIS0_SaIS0_EEEmiERKS6_ std::__normal_iterator<>::operator-()
+_ZNSbIcSt11char_traitsIcEN5libcw5debug27no_alloc_checking_allocatorEE12_S_constructIPcEES6_T_S7_RKS3_ std::basic_string<>::_S_construct<>()
+_ZNSt13_Alloc_traitsISbIcSt18string_char_traitsIcEN5libcw5debug9_private_17allocator_adaptorIcSt24__default_alloc_templateILb0ELi327664EELb1EEEENS5_IS9_S7_Lb1EEEE15_S_instancelessE std::_Alloc_traits<>::_S_instanceless
+_ZNSt3_In4wardE std::_In::ward
+_ZNZN1N1fEiE1X1gE _ZNZN1N1fEiE1X1gE
+_ZNZN1N1fEiE1X1gEv _ZNZN1N1fEiE1X1gEv
+_ZSt1BISt1DIP1ARKS2_PS3_ES0_IS2_RS2_PS2_ES2_ET0_T_SB_SA_PT1_ std::B<>()
+_ZSt5state std::state
+_ZTI7a_class a_class
+_ZZN1N1fEiE1p N::f()::p
+_ZZN1N1fEiEs N::f()
+_ZlsRK1XS1_ operator<<()
+_ZlsRKU3fooU4bart1XS0_ operator<<()
+_ZlsRKU3fooU4bart1XS2_ operator<<()
+_ZlsRSoRKSs operator<<()
+_ZngILi42EEvN1AIXplT_Li2EEE1TE operator-<>()
+_ZplR1XS0_ operator+()
+_Zrm1XS_ operator%()
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/log_severity.h b/thirdparty/glog/glog-0.3.4/src/glog/log_severity.h
new file mode 100644
index 0000000..99945a4
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/log_severity.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef BASE_LOG_SEVERITY_H__
+#define BASE_LOG_SEVERITY_H__
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+// Variables of type LogSeverity are widely taken to lie in the range
+// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
+// you ever need to change their values or add a new severity.
+typedef int LogSeverity;
+
+const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
+ NUM_SEVERITIES = 4;
+#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
+# ifdef ERROR
+# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
+# endif
+const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
+ ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
+#endif
+
+// DFATAL is FATAL in debug mode, ERROR in normal mode
+#ifdef NDEBUG
+#define DFATAL_LEVEL ERROR
+#else
+#define DFATAL_LEVEL FATAL
+#endif
+
+extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
+
+// NDEBUG usage helpers related to (RAW_)DCHECK:
+//
+// DEBUG_MODE is for small !NDEBUG uses like
+// if (DEBUG_MODE) foo.CheckThatFoo();
+// instead of substantially more verbose
+// #ifndef NDEBUG
+// foo.CheckThatFoo();
+// #endif
+//
+// IF_DEBUG_MODE is for small !NDEBUG uses like
+// IF_DEBUG_MODE( string error; )
+// DCHECK(Foo(&error)) << error;
+// instead of substantially more verbose
+// #ifndef NDEBUG
+// string error;
+// DCHECK(Foo(&error)) << error;
+// #endif
+//
+#ifdef NDEBUG
+enum { DEBUG_MODE = 0 };
+#define IF_DEBUG_MODE(x)
+#else
+enum { DEBUG_MODE = 1 };
+#define IF_DEBUG_MODE(x) x
+#endif
+
+#endif // BASE_LOG_SEVERITY_H__
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/logging.h.in b/thirdparty/glog/glog-0.3.4/src/glog/logging.h.in
new file mode 100644
index 0000000..9d13916
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/logging.h.in
@@ -0,0 +1,1634 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney
+//
+// This file contains #include information about logging-related stuff.
+// Pretty much everybody needs to #include this file so that they can
+// log various happenings.
+//
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <iosfwd>
+#include <ostream>
+#include <sstream>
+#include <string>
+#if @ac_cv_have_unistd_h@
+# include <unistd.h>
+#endif
+#include <vector>
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+#if defined(_MSC_VER)
+#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
+ __pragma(warning(disable:n))
+#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
+#else
+#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
+#define GLOG_MSVC_POP_WARNING()
+#endif
+
+// We care a lot about number of bits things take up. Unfortunately,
+// systems define their bit-specific ints in a lot of different ways.
+// We use our own way, and have a typedef to get there.
+// Note: these commands below may look like "#if 1" or "#if 0", but
+// that's because they were constructed that way at ./configure time.
+// Look at logging.h.in to see how they're calculated (based on your config).
+#if @ac_cv_have_stdint_h@
+#include <stdint.h> // the normal place uint16_t is defined
+#endif
+#if @ac_cv_have_systypes_h@
+#include <sys/types.h> // the normal place u_int16_t is defined
+#endif
+#if @ac_cv_have_inttypes_h@
+#include <inttypes.h> // a third place for uint16_t or u_int16_t
+#endif
+
+#if @ac_cv_have_libgflags@
+#include <gflags/gflags.h>
+#endif
+
+
+
+namespace google_ns {
+
+#if @ac_cv_have_uint16_t@ // the C99 format
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#elif @ac_cv_have_u_int16_t@ // the BSD format
+typedef int32_t int32;
+typedef u_int32_t uint32;
+typedef int64_t int64;
+typedef u_int64_t uint64;
+#elif @ac_cv_have___uint16@ // the windows (vc7) format
+typedef __int32 int32;
+typedef unsigned __int32 uint32;
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+#else
+#error Do not know how to define a 32-bit integer quantity on your system
+#endif
+
+}
+
+// The global value of GOOGLE_STRIP_LOG. All the messages logged to
+// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
+// If it can be determined at compile time that the message will not be
+// printed, the statement will be compiled out.
+//
+// Example: to strip out all INFO and WARNING messages, use the value
+// of 2 below. To make an exception for WARNING messages from a single
+// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
+// base/logging.h
+#ifndef GOOGLE_STRIP_LOG
+#define GOOGLE_STRIP_LOG 0
+#endif
+
+// GCC can be told that a certain branch is not likely to be taken (for
+// instance, a CHECK failure), and use that information in static analysis.
+// Giving it this information can help it optimize for the common case in
+// the absence of better information (ie. -fprofile-arcs).
+//
+#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
+#if @ac_cv_have___builtin_expect@
+#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
+#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
+#define GOOGLE_PREDICT_FALSE(x) x
+#define GOOGLE_PREDICT_TRUE(x) x
+#endif
+#endif
+
+// Make a bunch of macros for logging. The way to log things is to stream
+// things to LOG(<a particular severity level>). E.g.,
+//
+// LOG(INFO) << "Found " << num_cookies << " cookies";
+//
+// You can capture log messages in a string, rather than reporting them
+// immediately:
+//
+// vector<string> errors;
+// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
+//
+// This pushes back the new error onto 'errors'; if given a NULL pointer,
+// it reports the error via LOG(ERROR).
+//
+// You can also do conditional logging:
+//
+// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// You can also do occasional logging (log every n'th occurrence of an
+// event):
+//
+// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
+//
+// The above will cause log messages to be output on the 1st, 11th, 21st, ...
+// times it is executed. Note that the special google::COUNTER value is used
+// to identify which repetition is happening.
+//
+// You can also do occasional conditional logging (log every n'th
+// occurrence of an event, when condition is satisfied):
+//
+// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
+// << "th big cookie";
+//
+// You can log messages the first N times your code executes a line. E.g.
+//
+// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
+//
+// Outputs log messages for the first 20 times it is executed.
+//
+// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
+// These log to syslog as well as to the normal logs. If you use these at
+// all, you need to be aware that syslog can drastically reduce performance,
+// especially if it is configured for remote logging! Don't use these
+// unless you fully understand this and have a concrete need to use them.
+// Even then, try to minimize your use of them.
+//
+// There are also "debug mode" logging macros like the ones above:
+//
+// DLOG(INFO) << "Found cookies";
+//
+// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
+//
+// All "debug mode" logging is compiled away to nothing for non-debug mode
+// compiles.
+//
+// We also have
+//
+// LOG_ASSERT(assertion);
+// DLOG_ASSERT(assertion);
+//
+// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
+//
+// There are "verbose level" logging macros. They look like
+//
+// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
+// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
+//
+// These always log at the INFO log level (when they log at all).
+// The verbose logging can also be turned on module-by-module. For instance,
+// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
+// will cause:
+// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
+// b. VLOG(1) and lower messages to be printed from file.{h,cc}
+// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
+// d. VLOG(0) and lower messages to be printed from elsewhere
+//
+// The wildcarding functionality shown by (c) supports both '*' (match
+// 0 or more characters) and '?' (match any single character) wildcards.
+//
+// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
+//
+// if (VLOG_IS_ON(2)) {
+// // do some logging preparation and logging
+// // that can't be accomplished with just VLOG(2) << ...;
+// }
+//
+// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
+// condition macros for sample cases, when some extra computation and
+// preparation for logs is not needed.
+// VLOG_IF(1, (size > 1024))
+// << "I'm printed when size is more than 1024 and when you run the "
+// "program with --v=1 or more";
+// VLOG_EVERY_N(1, 10)
+// << "I'm printed every 10th occurrence, and when you run the program "
+// "with --v=1 or more. Present occurence is " << google::COUNTER;
+// VLOG_IF_EVERY_N(1, (size > 1024), 10)
+// << "I'm printed on every 10th occurence of case when size is more "
+// " than 1024, when you run the program with --v=1 or more. ";
+// "Present occurence is " << google::COUNTER;
+//
+// The supported severity levels for macros that allow you to specify one
+// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
+// Note that messages of a given severity are logged not only in the
+// logfile for that severity, but also in all logfiles of lower severity.
+// E.g., a message of severity FATAL will be logged to the logfiles of
+// severity FATAL, ERROR, WARNING, and INFO.
+//
+// There is also the special severity of DFATAL, which logs FATAL in
+// debug mode, ERROR in normal mode.
+//
+// Very important: logging a message at the FATAL severity level causes
+// the program to terminate (after the message is logged).
+//
+// Unless otherwise specified, logs will be written to the filename
+// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
+// by the date, time, and pid (you can't prevent the date, time, and pid
+// from being in the filename).
+//
+// The logging code takes two flags:
+// --v=# set the verbose level
+// --logtostderr log all the messages to stderr instead of to logfiles
+
+// LOG LINE PREFIX FORMAT
+//
+// Log lines have this form:
+//
+// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
+//
+// where the fields are defined as follows:
+//
+// L A single character, representing the log level
+// (eg 'I' for INFO)
+// mm The month (zero padded; ie May is '05')
+// dd The day (zero padded)
+// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
+// threadid The space-padded thread ID as returned by GetTID()
+// (this matches the PID on Linux)
+// file The file name
+// line The line number
+// msg The user-supplied message
+//
+// Example:
+//
+// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
+// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
+//
+// NOTE: although the microseconds are useful for comparing events on
+// a single machine, clocks on different machines may not be well
+// synchronized. Hence, use caution when comparing the low bits of
+// timestamps from different machines.
+
+#ifndef DECLARE_VARIABLE
+#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#define DECLARE_VARIABLE(type, shorttype, name, tn) \
+ namespace fL_ns##shorttype { \
+ extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
+ } \
+ using fL_ns##shorttype::FLAGS_##name
+
+// bool specialization
+#define DECLARE_bool(name) \
+ DECLARE_VARIABLE(bool, B, name, bool)
+
+// int32 specialization
+#define DECLARE_int32(name) \
+ DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name, int32)
+
+// Special case for string, because we have to specify the namespace
+// std::string, which doesn't play nicely with our FLAG__namespace hackery.
+#define DECLARE_string(name) \
+ namespace fLS_ns { \
+ extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
+ } \
+ using fLS_ns::FLAGS_##name
+#endif
+
+// Set whether log messages go to stderr instead of logfiles
+DECLARE_bool(logtostderr);
+
+// Set whether log messages go to stderr in addition to logfiles.
+DECLARE_bool(alsologtostderr);
+
+// Set color messages logged to stderr (if supported by terminal).
+DECLARE_bool(colorlogtostderr);
+
+// Log messages at a level >= this flag are automatically sent to
+// stderr in addition to log files.
+DECLARE_int32(stderrthreshold);
+
+// Set whether the log prefix should be prepended to each line of output.
+DECLARE_bool(log_prefix);
+
+// Log messages at a level <= this flag are buffered.
+// Log messages at a higher level are flushed immediately.
+DECLARE_int32(logbuflevel);
+
+// Sets the maximum number of seconds which logs may be buffered for.
+DECLARE_int32(logbufsecs);
+
+// Log suppression level: messages logged at a lower level than this
+// are suppressed.
+DECLARE_int32(minloglevel);
+
+// If specified, logfiles are written into this directory instead of the
+// default logging directory.
+DECLARE_string(log_dir);
+
+// Sets the path of the directory into which to put additional links
+// to the log files.
+DECLARE_string(log_link);
+
+DECLARE_int32(v); // in vlog_is_on.cc
+
+// Sets the maximum log file size (in MB).
+DECLARE_int32(max_log_size);
+
+// Sets whether to avoid logging to the disk if the disk is full.
+DECLARE_bool(stop_logging_if_full_disk);
+
+#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#undef DECLARE_VARIABLE
+#undef DECLARE_bool
+#undef DECLARE_int32
+#undef DECLARE_string
+#endif
+
+// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
+// security reasons. See LOG(severtiy) below.
+
+// A few definitions of macros that don't generate much code. Since
+// LOG(INFO) and its ilk are used all over our code, it's
+// better to have compact code for these operations.
+
+#if GOOGLE_STRIP_LOG == 0
+#define COMPACT_GOOGLE_LOG_INFO @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__)
+#define LOG_TO_STRING_INFO(message) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_INFO, message)
+#else
+#define COMPACT_GOOGLE_LOG_INFO @ac_google_namespace@::NullStream()
+#define LOG_TO_STRING_INFO(message) @ac_google_namespace@::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 1
+#define COMPACT_GOOGLE_LOG_WARNING @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_WARNING)
+#define LOG_TO_STRING_WARNING(message) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_WARNING, message)
+#else
+#define COMPACT_GOOGLE_LOG_WARNING @ac_google_namespace@::NullStream()
+#define LOG_TO_STRING_WARNING(message) @ac_google_namespace@::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 2
+#define COMPACT_GOOGLE_LOG_ERROR @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR)
+#define LOG_TO_STRING_ERROR(message) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR, message)
+#else
+#define COMPACT_GOOGLE_LOG_ERROR @ac_google_namespace@::NullStream()
+#define LOG_TO_STRING_ERROR(message) @ac_google_namespace@::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 3
+#define COMPACT_GOOGLE_LOG_FATAL @ac_google_namespace@::LogMessageFatal( \
+ __FILE__, __LINE__)
+#define LOG_TO_STRING_FATAL(message) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_FATAL, message)
+#else
+#define COMPACT_GOOGLE_LOG_FATAL @ac_google_namespace@::NullStreamFatal()
+#define LOG_TO_STRING_FATAL(message) @ac_google_namespace@::NullStreamFatal()
+#endif
+
+// For DFATAL, we want to use LogMessage (as opposed to
+// LogMessageFatal), to be consistent with the original behavior.
+#ifdef NDEBUG
+#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
+#elif GOOGLE_STRIP_LOG <= 3
+#define COMPACT_GOOGLE_LOG_DFATAL @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_FATAL)
+#else
+#define COMPACT_GOOGLE_LOG_DFATAL @ac_google_namespace@::NullStreamFatal()
+#endif
+
+#define GOOGLE_LOG_INFO(counter) @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_INFO, counter, &@ac_google_namespace@::LogMessage::SendToLog)
+#define SYSLOG_INFO(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_INFO, counter, \
+ &@ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_WARNING(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_WARNING, counter, \
+ &@ac_google_namespace@::LogMessage::SendToLog)
+#define SYSLOG_WARNING(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_WARNING, counter, \
+ &@ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_ERROR(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR, counter, \
+ &@ac_google_namespace@::LogMessage::SendToLog)
+#define SYSLOG_ERROR(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR, counter, \
+ &@ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_FATAL(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_FATAL, counter, \
+ &@ac_google_namespace@::LogMessage::SendToLog)
+#define SYSLOG_FATAL(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_FATAL, counter, \
+ &@ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_DFATAL(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::DFATAL_LEVEL, counter, \
+ &@ac_google_namespace@::LogMessage::SendToLog)
+#define SYSLOG_DFATAL(counter) \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::DFATAL_LEVEL, counter, \
+ &@ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+// A very useful logging macro to log windows errors:
+#define LOG_SYSRESULT(result) \
+ if (FAILED(HRESULT_FROM_WIN32(result))) { \
+ LPSTR message = NULL; \
+ LPSTR msg = reinterpret_cast<LPSTR>(&message); \
+ DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
+ FORMAT_MESSAGE_FROM_SYSTEM, \
+ 0, result, 0, msg, 100, NULL); \
+ if (message_length > 0) { \
+ @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR, 0, \
+ &@ac_google_namespace@::LogMessage::SendToLog).stream() \
+ << reinterpret_cast<const char*>(message); \
+ LocalFree(message); \
+ } \
+ }
+#endif
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+//#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
+#define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
+
+// user define log
+#include "glog/nstack_adapter.ph"
+#define COMPACT_NSTACK_LOG_INFO nstack_space::LogMessageAdapter(__FILE__, __LINE__, __func__, @ac_google_namespace@::GLOG_INFO)
+#define COMPACT_NSTACK_LOG_WARNING nstack_space::LogMessageAdapter(__FILE__, __LINE__, __func__, @ac_google_namespace@::GLOG_WARNING)
+#define COMPACT_NSTACK_LOG_ERROR nstack_space::LogMessageAdapter(__FILE__, __LINE__, __func__, @ac_google_namespace@::GLOG_ERROR)
+#define COMPACT_NSTACK_LOG_FATAL nstack_space::LogMessageAdapter(__FILE__, __LINE__, __func__, @ac_google_namespace@::GLOG_FATAL)
+
+#define NSTACK_LOG(severity) COMPACT_NSTACK_LOG_ ## severity.stream()
+#define LOG(severity) NSTACK_LOG(severity)
+
+namespace google_ns {
+
+// They need the definitions of integer types.
+#include "glog/log_severity.h"
+#include "glog/vlog_is_on.h"
+
+GOOGLE_GLOG_DLL_DECL void glog_release_rw_lock();
+
+// Initialize google's logging library. You will see the program name
+// specified by argv0 in log outputs.
+GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
+
+// Shutdown google's logging library.
+GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
+
+// Install a function which will be called after LOG(FATAL).
+GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)());
+
+class LogSink; // defined below
+
+// If a non-NULL sink pointer is given, we push this message to that sink.
+// For LOG_TO_SINK we then do normal LOG(severity) logging as well.
+// This is useful for capturing messages and passing/storing them
+// somewhere more specific than the global log of the process.
+// Argument types:
+// LogSink* sink;
+// LogSeverity severity;
+// The cast is to disambiguate NULL arguments.
+#define LOG_TO_SINK(sink, severity) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, \
+ @ac_google_namespace@::GLOG_ ## severity, \
+ static_cast<@ac_google_namespace@::LogSink*>(sink), true).stream()
+#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, \
+ @ac_google_namespace@::GLOG_ ## severity, \
+ static_cast<@ac_google_namespace@::LogSink*>(sink), false).stream()
+
+// If a non-NULL string pointer is given, we write this message to that string.
+// We then do normal LOG(severity) logging as well.
+// This is useful for capturing messages and storing them somewhere more
+// specific than the global log of the process.
+// Argument types:
+// string* message;
+// LogSeverity severity;
+// The cast is to disambiguate NULL arguments.
+// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
+// severity.
+#define LOG_TO_STRING(severity, message) \
+ LOG_TO_STRING_##severity(static_cast<string*>(message)).stream()
+
+// If a non-NULL pointer is given, we push the message onto the end
+// of a vector of strings; otherwise, we report it with LOG(severity).
+// This is handy for capturing messages and perhaps passing them back
+// to the caller, rather than reporting them immediately.
+// Argument types:
+// LogSeverity severity;
+// vector<string> *outvec;
+// The cast is to disambiguate NULL arguments.
+#define LOG_STRING(severity, outvec) \
+ LOG_TO_STRING_##severity(static_cast<vector<string>*>(outvec)).stream()
+
+#define LOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+#define SYSLOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & SYSLOG(severity)
+
+#define LOG_ASSERT(condition) \
+ LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
+#define SYSLOG_ASSERT(condition) \
+ SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
+
+// CHECK dies with a fatal error if condition is not true. It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode. Therefore, it is safe to do things like:
+// CHECK(fp->Write(x) == 4)
+#define CHECK(condition) \
+ LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
+ << "Check failed: " #condition " "
+
+// A container for a string pointer which can be evaluated to a bool -
+// true iff the pointer is NULL.
+struct CheckOpString {
+ CheckOpString(std::string* str) : str_(str) { }
+ // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
+ // so there's no point in cleaning up str_.
+ operator bool() const {
+ return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL);
+ }
+ std::string* str_;
+};
+
+// Function is overloaded for integral types to allow static const
+// integrals declared in classes and not defined to be used as arguments to
+// CHECK* macros. It's not encouraged though.
+template <class T>
+inline const T& GetReferenceableValue(const T& t) { return t; }
+inline char GetReferenceableValue(char t) { return t; }
+inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
+inline signed char GetReferenceableValue(signed char t) { return t; }
+inline short GetReferenceableValue(short t) { return t; }
+inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
+inline int GetReferenceableValue(int t) { return t; }
+inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
+inline long GetReferenceableValue(long t) { return t; }
+inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
+inline long long GetReferenceableValue(long long t) { return t; }
+inline unsigned long long GetReferenceableValue(unsigned long long t) {
+ return t;
+}
+
+// This is a dummy class to define the following operator.
+struct DummyClassToDefineOperator {};
+
+}
+
+// Define global operator<< to declare using ::operator<<.
+// This declaration will allow use to use CHECK macros for user
+// defined classes which have operator<< (e.g., stl_logging.h).
+inline std::ostream& operator<<(
+ std::ostream& out, const google_ns::DummyClassToDefineOperator&) {
+ return out;
+}
+
+@ac_google_start_namespace@
+
+// This formats a value for a failing CHECK_XX statement. Ordinarily,
+// it uses the definition for operator<<, with a few special cases below.
+template <typename T>
+inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
+ (*os) << v;
+}
+
+// Overrides for char types provide readable values for unprintable
+// characters.
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const char& v);
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const signed char& v);
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
+
+// Build the error message string. Specify no inlining for code size.
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
+ @ac_cv___attribute___noinline@;
+
+namespace base_ns {
+namespace internal_ns {
+
+// If "s" is less than base_ns_logging::INFO, returns base_ns_logging::INFO.
+// If "s" is greater than base_ns_logging::FATAL, returns
+// base_ns_logging::ERROR. Otherwise, returns "s".
+LogSeverity NormalizeSeverity(LogSeverity s);
+
+} // namespace internal_ns
+
+// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
+// statement. See MakeCheckOpString for sample usage. Other
+// approaches were considered: use of a template method (e.g.,
+// base_ns::BuildCheckOpString(exprtext, base_ns::Print<T1>, &v1,
+// base_ns::Print<T2>, &v2), however this approach has complications
+// related to volatile arguments and function-pointer arguments).
+class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
+ public:
+ // Inserts "exprtext" and " (" to the stream.
+ explicit CheckOpMessageBuilder(const char *exprtext);
+ // Deletes "stream_".
+ ~CheckOpMessageBuilder();
+ // For inserting the first variable.
+ std::ostream* ForVar1() { return stream_; }
+ // For inserting the second variable (adds an intermediate " vs. ").
+ std::ostream* ForVar2();
+ // Get the result (inserts the closing ")").
+ std::string* NewString();
+
+ private:
+ std::ostringstream *stream_;
+};
+
+} // namespace base_ns
+
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
+ base_ns::CheckOpMessageBuilder comb(exprtext);
+ MakeCheckOpValueString(comb.ForVar1(), v1);
+ MakeCheckOpValueString(comb.ForVar2(), v2);
+ return comb.NewString();
+}
+
+// Helper functions for CHECK_OP macro.
+// The (int, int) specialization works around the issue that the compiler
+// will not instantiate the template version of the function on values of
+// unnamed enum type - see comment below.
+#define DEFINE_CHECK_OP_IMPL(name, op) \
+ template <typename T1, typename T2> \
+ inline std::string* name##Impl(const T1& v1, const T2& v2, \
+ const char* exprtext) { \
+ if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
+ else return MakeCheckOpString(v1, v2, exprtext); \
+ } \
+ inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
+ return name##Impl<int, int>(v1, v2, exprtext); \
+ }
+
+// We use the full name Check_EQ, Check_NE, etc. in case the file including
+// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
+// This happens if, for example, those are used as token names in a
+// yacc grammar.
+DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
+DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
+DEFINE_CHECK_OP_IMPL(Check_LE, <=)
+DEFINE_CHECK_OP_IMPL(Check_LT, < )
+DEFINE_CHECK_OP_IMPL(Check_GE, >=)
+DEFINE_CHECK_OP_IMPL(Check_GT, > )
+#undef DEFINE_CHECK_OP_IMPL
+
+// Helper macro for binary operators.
+// Don't use this macro directly in your code, use CHECK_EQ et al below.
+
+#if defined(STATIC_ANALYSIS)
+// Only for static analysis tool to know that it is equivalent to assert
+#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
+#elif !defined(NDEBUG)
+// In debug mode, avoid constructing CheckOpStrings if possible,
+// to reduce the overhead of CHECK statments by 2x.
+// Real DCHECK-heavy tests have seen 1.5x speedups.
+
+// The meaning of "string" might be different between now and
+// when this macro gets invoked (e.g., if someone is experimenting
+// with other string implementations that get defined after this
+// file is included). Save the current meaning now and use it
+// in the macro.
+typedef std::string _Check_string;
+#define CHECK_OP_LOG(name, op, val1, val2, log) \
+ while (@ac_google_namespace@::_Check_string* _result = \
+ @ac_google_namespace@::Check##name##Impl( \
+ @ac_google_namespace@::GetReferenceableValue(val1), \
+ @ac_google_namespace@::GetReferenceableValue(val2), \
+ #val1 " " #op " " #val2)) \
+ log(__FILE__, __LINE__, \
+ @ac_google_namespace@::CheckOpString(_result)).stream()
+#else
+// In optimized mode, use CheckOpString to hint to compiler that
+// the while condition is unlikely.
+#define CHECK_OP_LOG(name, op, val1, val2, log) \
+ while (@ac_google_namespace@::CheckOpString _result = \
+ @ac_google_namespace@::Check##name##Impl( \
+ @ac_google_namespace@::GetReferenceableValue(val1), \
+ @ac_google_namespace@::GetReferenceableValue(val2), \
+ #val1 " " #op " " #val2)) \
+ log(__FILE__, __LINE__, _result).stream()
+#endif // STATIC_ANALYSIS, !NDEBUG
+
+#if GOOGLE_STRIP_LOG <= 3
+#define CHECK_OP(name, op, val1, val2) \
+ CHECK_OP_LOG(name, op, val1, val2, @ac_google_namespace@::LogMessageFatal)
+#else
+#define CHECK_OP(name, op, val1, val2) \
+ CHECK_OP_LOG(name, op, val1, val2, @ac_google_namespace@::NullStreamFatal)
+#endif // STRIP_LOG <= 3
+
+// Equality/Inequality checks - compare two values, and log a FATAL message
+// including the two values when the result is not as expected. The values
+// must have operator<<(ostream, ...) defined.
+//
+// You may append to the error message like so:
+// CHECK_NE(1, 2) << ": The world must be ending!";
+//
+// We are very careful to ensure that each argument is evaluated exactly
+// once, and that anything which is legal to pass as a function argument is
+// legal here. In particular, the arguments may be temporary expressions
+// which will end up being destroyed at the end of the apparent statement,
+// for example:
+// CHECK_EQ(string("abc")[1], 'b');
+//
+// WARNING: These don't compile correctly if one of the arguments is a pointer
+// and the other is NULL. To work around this, simply static_cast NULL to the
+// type of the desired pointer.
+
+#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
+#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
+#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
+#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
+#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
+#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
+
+// Check that the input is non NULL. This very useful in constructor
+// initializer lists.
+
+#define CHECK_NOTNULL(val) \
+ @ac_google_namespace@::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
+
+// Helper functions for string comparisons.
+// To avoid bloat, the definitions are in logging.cc.
+#define DECLARE_CHECK_STROP_IMPL(func, expected) \
+ GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \
+ const char* s1, const char* s2, const char* names);
+DECLARE_CHECK_STROP_IMPL(strcmp, true)
+DECLARE_CHECK_STROP_IMPL(strcmp, false)
+DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
+DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
+#undef DECLARE_CHECK_STROP_IMPL
+
+// Helper macro for string comparisons.
+// Don't use this macro directly in your code, use CHECK_STREQ et al below.
+#define CHECK_STROP(func, op, expected, s1, s2) \
+ while (@ac_google_namespace@::CheckOpString _result = \
+ @ac_google_namespace@::Check##func##expected##Impl((s1), (s2), \
+ #s1 " " #op " " #s2)) \
+ LOG(FATAL) << *_result.str_
+
+
+// String (char*) equality/inequality checks.
+// CASE versions are case-insensitive.
+//
+// Note that "s1" and "s2" may be temporary strings which are destroyed
+// by the compiler at the end of the current "full expression"
+// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())).
+
+#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2)
+#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2)
+#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2)
+#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2)
+
+#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0])))
+#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0])))
+
+#define CHECK_DOUBLE_EQ(val1, val2) \
+ do { \
+ CHECK_LE((val1), (val2)+0.000000000000001L); \
+ CHECK_GE((val1), (val2)-0.000000000000001L); \
+ } while (0)
+
+#define CHECK_NEAR(val1, val2, margin) \
+ do { \
+ CHECK_LE((val1), (val2)+(margin)); \
+ CHECK_GE((val1), (val2)-(margin)); \
+ } while (0)
+
+// perror()..googly style!
+//
+// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and
+// CHECK equivalents with the addition that they postpend a description
+// of the current state of errno to their output lines.
+
+#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()
+
+#define GOOGLE_PLOG(severity, counter) \
+ @ac_google_namespace@::ErrnoLogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, counter, \
+ &@ac_google_namespace@::LogMessage::SendToLog)
+
+#define PLOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & PLOG(severity)
+
+// A CHECK() macro that postpends errno if the condition is false. E.g.
+//
+// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... }
+#define PCHECK(condition) \
+ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
+ << "Check failed: " #condition " "
+
+// A CHECK() macro that lets you assert the success of a function that
+// returns -1 and sets errno in case of an error. E.g.
+//
+// CHECK_ERR(mkdir(path, 0700));
+//
+// or
+//
+// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename;
+#define CHECK_ERR(invocation) \
+PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
+ << #invocation
+
+// Use macro expansion to create, for each use of LOG_EVERY_N(), static
+// variables with the __LINE__ expansion as part of the variable name.
+#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line)
+#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line
+
+#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
+#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
+
+#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (condition && \
+ ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::ErrnoLogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0; \
+ if (LOG_OCCURRENCES <= n) \
+ ++LOG_OCCURRENCES; \
+ if (LOG_OCCURRENCES <= n) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+namespace glog_ns_internal_namespace_ {
+template <bool>
+struct CompileAssert {
+};
+struct CrashReason;
+} // namespace glog_ns_internal_namespace_
+
+#define GOOGLE_GLOG_COMPILE_ASSERT(expr, msg) \
+ typedef @ac_google_namespace@::glog_ns_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+
+#define LOG_EVERY_N(severity, n) \
+ __attribute__((unused)) GOOGLE_GLOG_COMPILE_ASSERT(@ac_google_namespace@::GLOG_ ## severity < \
+ @ac_google_namespace@::NUM_SEVERITIES, \
+ INVALID_REQUESTED_LOG_SEVERITY); \
+ SOME_KIND_OF_LOG_EVERY_N(severity, (n), @ac_google_namespace@::LogMessage::SendToLog)
+
+#define SYSLOG_EVERY_N(severity, n) \
+ SOME_KIND_OF_LOG_EVERY_N(severity, (n), @ac_google_namespace@::LogMessage::SendToSyslogAndLog)
+
+#define PLOG_EVERY_N(severity, n) \
+ SOME_KIND_OF_PLOG_EVERY_N(severity, (n), @ac_google_namespace@::LogMessage::SendToLog)
+
+#define LOG_FIRST_N(severity, n) \
+ SOME_KIND_OF_LOG_FIRST_N(severity, (n), @ac_google_namespace@::LogMessage::SendToLog)
+
+#define LOG_IF_EVERY_N(severity, condition, n) \
+ SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), @ac_google_namespace@::LogMessage::SendToLog)
+
+// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
+enum PRIVATE_Counter {COUNTER};
+
+#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
+// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
+// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
+// to keep using this syntax, we define this macro to do the same thing
+// as COMPACT_GOOGLE_LOG_ERROR.
+#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
+#define SYSLOG_0 SYSLOG_ERROR
+#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
+// Needed for LOG_IS_ON(ERROR).
+const LogSeverity GLOG_0 = GLOG_ERROR;
+#else
+// Users may include windows.h after logging.h without
+// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
+// For this case, we cannot detect if ERROR is defined before users
+// actually use ERROR. Let's make an undefined symbol to warn users.
+# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
+# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
+# define SYSLOG_0 GLOG_ERROR_MSG
+# define LOG_TO_STRING_0 GLOG_ERROR_MSG
+# define GLOG_0 GLOG_ERROR_MSG
+#endif
+
+// Plus some debug-logging macros that get compiled to nothing for production
+
+#ifndef NDEBUG
+
+#define DLOG(severity) LOG(severity)
+#define DVLOG(verboselevel) VLOG(verboselevel)
+#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
+#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
+#define DLOG_IF_EVERY_N(severity, condition, n) \
+ LOG_IF_EVERY_N(severity, condition, n)
+#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
+
+// debug-only checking. not executed in NDEBUG mode.
+#define DCHECK(condition) CHECK(condition)
+#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
+#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
+#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
+#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
+#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
+#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
+#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
+#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
+#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
+#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
+#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
+
+#else // NDEBUG
+
+#define DLOG(severity) \
+ true ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+
+#define DVLOG(verboselevel) \
+ (true || !VLOG_IS_ON(verboselevel)) ?\
+ (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(INFO)
+
+#define DLOG_IF(severity, condition) \
+ (true || !(condition)) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_EVERY_N(severity, n) \
+ true ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_IF_EVERY_N(severity, condition, n) \
+ (true || !(condition))? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_ASSERT(condition) \
+ true ? (void) 0 : LOG_ASSERT(condition)
+
+// MSVC warning C4127: conditional expression is constant
+#define DCHECK(condition) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK(condition)
+
+#define DCHECK_EQ(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
+
+#define DCHECK_NE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
+
+#define DCHECK_LE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
+
+#define DCHECK_LT(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
+
+#define DCHECK_GE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
+
+#define DCHECK_GT(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
+
+// You may see warnings in release mode if you don't use the return
+// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
+#define DCHECK_NOTNULL(val) (val)
+
+#define DCHECK_STREQ(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
+
+#define DCHECK_STRCASEEQ(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
+
+#define DCHECK_STRNE(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
+
+#define DCHECK_STRCASENE(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
+
+#endif // NDEBUG
+
+// Log only in verbose mode.
+
+#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
+
+#define VLOG_IF(verboselevel, condition) \
+ LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
+
+#define VLOG_EVERY_N(verboselevel, n) \
+ LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n)
+
+#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
+ LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
+
+namespace base_ns_logging {
+
+// LogMessage::LogStream is a std::ostream backed by this streambuf.
+// This class ignores overflow and leaves two bytes at the end of the
+// buffer to allow for a '\n' and '\0'.
+class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
+ public:
+ // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
+ LogStreamBuf(char *buf, int len) {
+ setp(buf, buf + len - 2);
+ }
+ // This effectively ignores overflow.
+ virtual int_type overflow(int_type ch) {
+ return ch;
+ }
+
+ // Legacy public ostrstream method.
+ size_t pcount() const { return pptr() - pbase(); }
+ char* pbase() const { return std::streambuf::pbase(); }
+};
+
+} // namespace base_ns_logging
+
+//
+// This class more or less represents a particular log message. You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though. You should use the LOG() macro (and variants thereof)
+// above.
+class GOOGLE_GLOG_DLL_DECL LogMessage {
+public:
+ enum {
+ // Passing kNoLogPrefix for the line number disables the
+ // log-message prefix. Useful for using the LogMessage
+ // infrastructure as a printing utility. See also the --log_prefix
+ // flag for controlling the log-message prefix on an
+ // application-wide basis.
+ kNoLogPrefix = -1
+ };
+
+ // LogStream inherit from non-DLL-exported class (std::ostrstream)
+ // and VC++ produces a warning for this situation.
+ // However, MSDN says "C4275 can be ignored in Microsoft Visual C++
+ // 2005 if you are deriving from a type in the Standard C++ Library"
+ // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
+ // Let's just ignore the warning.
+#ifdef _MSC_VER
+# pragma warning(disable: 4275)
+#endif
+ class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
+#ifdef _MSC_VER
+# pragma warning(default: 4275)
+#endif
+ public:
+ LogStream(char *buf, int len, int log_ctr)
+ : std::ostream(NULL),
+ streambuf_(buf, len),
+ ctr_(log_ctr),
+ self_(this) {
+ rdbuf(&streambuf_);
+ }
+
+ int ctr() const { return ctr_; }
+ void set_ctr(int s_ctr) { ctr_ = s_ctr; }
+ LogStream* self() const { return self_; }
+
+ // Legacy std::streambuf methods.
+ size_t pcount() const { return streambuf_.pcount(); }
+ char* pbase() const { return streambuf_.pbase(); }
+ char* str() const { return pbase(); }
+
+ private:
+ base_ns_logging::LogStreamBuf streambuf_;
+ int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
+ LogStream *self_; // Consistency check hack
+ };
+
+public:
+ // icc 8 requires this typedef to avoid an internal compiler error.
+ typedef void (LogMessage::*SendMethod)();
+
+ LogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ SendMethod send_method);
+
+ // Two special constructors that generate reduced amounts of code at
+ // LOG call sites for common cases.
+
+ // Used for LOG(INFO): Implied are:
+ // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog.
+ //
+ // Using this constructor instead of the more complex constructor above
+ // saves 19 bytes per call site.
+ LogMessage(const char* file, int line);
+
+ // Used for LOG(severity) where severity != INFO. Implied
+ // are: ctr = 0, send_method = &LogMessage::SendToLog
+ //
+ // Using this constructor instead of the more complex constructor above
+ // saves 17 bytes per call site.
+ LogMessage(const char* file, int line, LogSeverity severity);
+
+ //overload function,
+ //ctr = 0, send_method = &LogMessage::SendToLog
+ //to replace LogMessage(const char* file, int line, LogSeverity severity);
+ LogMessage(const char* file, int line, LogSeverity severity, int level);
+
+ // Constructor to log this message to a specified sink (if not NULL).
+ // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if
+ // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise.
+ LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink,
+ bool also_send_to_log);
+
+ // Constructor where we also give a vector<string> pointer
+ // for storing the messages (if the pointer is not NULL).
+ // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog.
+ LogMessage(const char* file, int line, LogSeverity severity,
+ std::vector<std::string>* outvec);
+
+ // Constructor where we also give a string pointer for storing the
+ // message (if the pointer is not NULL). Implied are: ctr = 0,
+ // send_method = &LogMessage::WriteToStringAndLog.
+ LogMessage(const char* file, int line, LogSeverity severity,
+ std::string* message);
+
+ // A special constructor used for check failures
+ LogMessage(const char* file, int line, const CheckOpString& result);
+
+ ~LogMessage();
+
+ // Flush a buffered message to the sink set in the constructor. Always
+ // called by the destructor, it may also be called from elsewhere if
+ // needed. Only the first call is actioned; any later ones are ignored.
+ void Flush();
+
+ // An arbitrary limit on the length of a single log message. This
+ // is so that streaming can be done more efficiently.
+ static const size_t kMaxLogMessageLen;
+
+ // Theses should not be called directly outside of logging.*,
+ // only passed as SendMethod arguments to other LogMessage methods:
+ void SendToLog(); // Actually dispatch to the logs
+ void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs
+
+ // Call abort() or similar to perform LOG(FATAL) crash.
+ static void Fail() @ac_cv___attribute___noreturn@;
+
+ std::ostream& stream();
+
+ int preserved_errno() const;
+
+ // Must be called without the log_mutex held. (L < log_mutex)
+ static int64 num_messages(int severity);
+
+ struct LogMessageData;
+
+private:
+ // Fully internal SendMethod cases:
+ void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
+ void SendToSink(); // Send to sink if provided, do nothing otherwise.
+
+ // Write to string if provided and dispatch to the logs.
+ void WriteToStringAndLog();
+
+ void SaveOrSendToLog(); // Save to stringvec if provided, else to logs
+
+ void Init(const char* file, int line, LogSeverity severity,
+ void (LogMessage::*send_method)());
+
+ void Init(const char* file, int line, LogSeverity severity,int level,
+ void (LogMessage::*send_method)());
+
+ // Used to fill in crash information during LOG(FATAL) failures.
+ void RecordCrashReason(glog_ns_internal_namespace_::CrashReason* reason);
+
+ // Counts of messages sent at each priority:
+ static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex
+
+ // We keep the data in a separate struct so that each instance of
+ // LogMessage uses less stack space.
+ LogMessageData* allocated_;
+ LogMessageData* data_;
+
+ friend class LogDestination;
+
+ LogMessage(const LogMessage&);
+ void operator=(const LogMessage&);
+};
+
+// This class happens to be thread-hostile because all instances share
+// a single data buffer, but since it can only be created just before
+// the process dies, we don't worry so much.
+class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage {
+ public:
+ LogMessageFatal(const char* file, int line);
+ LogMessageFatal(const char* file, int line, const CheckOpString& result);
+ ~LogMessageFatal() @ac_cv___attribute___noreturn@;
+};
+
+// A non-macro interface to the log facility; (useful
+// when the logging level is not a compile-time constant).
+inline void LogAtLevel(int const severity, std::string const &msg) {
+ LogMessage(__FILE__, __LINE__, severity).stream() << msg;
+}
+
+// A macro alternative of LogAtLevel. New code may want to use this
+// version since there are two advantages: 1. this version outputs the
+// file name and the line number where this macro is put like other
+// LOG macros, 2. this macro can be used as C++ stream.
+#define LOG_AT_LEVEL(severity) @ac_google_namespace@::LogMessage(__FILE__, __LINE__, severity).stream()
+
+// A small helper for CHECK_NOTNULL().
+template <typename T>
+T* CheckNotNull(const char *file, int line, const char *names, T* t) {
+ if (t == NULL) {
+ LogMessageFatal(file, line, new std::string(names));
+ }
+ return t;
+}
+
+// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
+// only works if ostream is a LogStream. If the ostream is not a
+// LogStream you'll get an assert saying as much at runtime.
+GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os,
+ const PRIVATE_Counter&);
+
+
+// Derived class for PLOG*() above.
+class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage {
+ public:
+
+ ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ void (LogMessage::*send_method)());
+
+ // Postpends ": strerror(errno) [errno]".
+ ~ErrnoLogMessage();
+
+ private:
+ ErrnoLogMessage(const ErrnoLogMessage&);
+ void operator=(const ErrnoLogMessage&);
+};
+
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros. This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+
+class GOOGLE_GLOG_DLL_DECL LogMessageVoidify {
+ public:
+ LogMessageVoidify() { }
+ // This has to be an operator with a precedence lower than << but
+ // higher than ?:
+ void operator&(std::ostream&) { }
+};
+
+
+// Flushes all log files that contains messages that are at least of
+// the specified severity level. Thread-safe.
+GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity);
+
+// Flushes all log files that contains messages that are at least of
+// the specified severity level. Thread-hostile because it ignores
+// locking -- used for catastrophic failures.
+GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity);
+
+GOOGLE_GLOG_DLL_DECL void RleaseLogSinkLock(LogSeverity min_severity);
+
+//
+// Set the destination to which a particular severity level of log
+// messages is sent. If base_filename is "", it means "don't log this
+// severity". Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity,
+ const char* base_filename);
+
+//
+// Set the basename of the symlink to the latest log file at a given
+// severity. If symlink_basename is empty, do not make a symlink. If
+// you don't call this function, the symlink basename is the
+// invocation name of the program. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity,
+ const char* symlink_basename);
+
+//
+// Used to send logs to some other kind of destination
+// Users should subclass LogSink and override send to do whatever they want.
+// Implementations must be thread-safe because a shared instance will
+// be called from whichever thread ran the LOG(XXX) line.
+class GOOGLE_GLOG_DLL_DECL LogSink {
+ public:
+ virtual ~LogSink();
+
+ // Sink's logging logic (message_len is such as to exclude '\n' at the end).
+ // This method can't use LOG() or CHECK() as logging system mutex(s) are held
+ // during this call.
+ virtual void send(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line,
+ const struct ::tm* tm_time,
+ const char* message, size_t message_len) = 0;
+
+ // Redefine this to implement waiting for
+ // the sink's logging logic to complete.
+ // It will be called after each send() returns,
+ // but before that LogMessage exits or crashes.
+ // By default this function does nothing.
+ // Using this function one can implement complex logic for send()
+ // that itself involves logging; and do all this w/o causing deadlocks and
+ // inconsistent rearrangement of log messages.
+ // E.g. if a LogSink has thread-specific actions, the send() method
+ // can simply add the message to a queue and wake up another thread that
+ // handles real logging while itself making some LOG() calls;
+ // WaitTillSent() can be implemented to wait for that logic to complete.
+ // See our unittest for an example.
+ virtual void WaitTillSent();
+
+ // Returns the normal text output of the log message.
+ // Can be useful to implement send().
+ static std::string ToString(LogSeverity severity, const char* file, int line,
+ const struct ::tm* tm_time,
+ const char* message, size_t message_len);
+};
+
+// Add or remove a LogSink as a consumer of logging data. Thread-safe.
+GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
+GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination);
+
+//
+// Specify an "extension" added to the filename specified via
+// SetLogDestination. This applies to all severity levels. It's
+// often used to append the port we're listening on to the logfile
+// name. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
+ const char* filename_extension);
+
+//
+// Make it so that all log messages of at least a particular severity
+// are logged to stderr (in addition to logging to the usual log
+// file(s)). Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity);
+
+//
+// Make it so that all log messages go only to stderr. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void LogToStderr();
+
+
+//
+// Make it so that all log messages of at least a particular severity are
+// logged via email to a list of addresses (in addition to logging to the
+// usual log file(s)). The list of addresses is just a string containing
+// the email addresses to send to (separated by spaces, say). Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
+ const char* addresses);
+
+
+// A simple function that sends email. dest is a commma-separated
+// list of addressess. Thread-safe.
+GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
+ const char *subject, const char *body);
+
+GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories();
+void UpdateLoggingDirectories();
+
+// For tests only: Clear the internal [cached] list of logging directories to
+// force a refresh the next time GetLoggingDirectories is called.
+// Thread-hostile.
+void TestOnly_ClearLoggingDirectoriesList();
+
+// Returns a set of existing temporary directories, which will be a
+// subset of the directories returned by GetLogginDirectories().
+// Thread-safe.
+GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
+ std::vector<std::string>* list);
+
+// Print any fatal message again -- useful to call from signal handler
+// so that the last thing in the output is the fatal message.
+// Thread-hostile, but a race is unlikely.
+GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage();
+
+// Truncate a log file that may be the append-only output of multiple
+// processes and hence can't simply be renamed/reopened (typically a
+// stdout/stderr). If the file "path" is > "limit" bytes, copy the
+// last "keep" bytes to offset 0 and truncate the rest. Since we could
+// be racing with other writers, this approach has the potential to
+// lose very small amounts of data. For security, only follow symlinks
+// if the path is /proc/self/fd/*
+GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
+ int64 limit, int64 keep);
+
+// Truncate stdout and stderr if they are over the value specified by
+// --max_log_size; keep the final 1MB. This function has the same
+// race condition as TruncateLogFile.
+GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr();
+
+// Return the string representation of the provided LogSeverity level.
+// Thread-safe.
+GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
+
+// ---------------------------------------------------------------------
+// Implementation details that are not useful to most clients
+// ---------------------------------------------------------------------
+
+// A Logger is the interface used by logging modules to emit entries
+// to a log. A typical implementation will dump formatted data to a
+// sequence of files. We also provide interfaces that will forward
+// the data to another thread so that the invoker never blocks.
+// Implementations should be thread-safe since the logging system
+// will write to them from multiple threads.
+
+namespace base_ns {
+
+class GOOGLE_GLOG_DLL_DECL Logger {
+ public:
+ virtual ~Logger();
+
+ // Writes "message[0,message_len-1]" corresponding to an event that
+ // occurred at "timestamp". If "force_flush" is true, the log file
+ // is flushed immediately.
+ //
+ // The input message has already been formatted as deemed
+ // appropriate by the higher level logging facility. For example,
+ // textual log messages already contain timestamps, and the
+ // file:linenumber header.
+ virtual void Write(bool force_flush,
+ time_t timestamp,
+ const char* message,
+ int message_len) = 0;
+
+ // Flush any buffered messages
+ virtual void Flush() = 0;
+
+ // Get the current LOG file size.
+ // The returned value is approximate since some
+ // logged data may not have been flushed to disk yet.
+ virtual uint32 LogSize() = 0;
+};
+
+// Get the logger for the specified severity level. The logger
+// remains the property of the logging module and should not be
+// deleted by the caller. Thread-safe.
+extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level);
+
+// Set the logger for the specified severity level. The logger
+// becomes the property of the logging module and should not
+// be deleted by the caller. Thread-safe.
+extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
+
+}
+
+// glibc has traditionally implemented two incompatible versions of
+// strerror_r(). There is a poorly defined convention for picking the
+// version that we want, but it is not clear whether it even works with
+// all versions of glibc.
+// So, instead, we provide this wrapper that automatically detects the
+// version that is in use, and then implements POSIX semantics.
+// N.B. In addition to what POSIX says, we also guarantee that "buf" will
+// be set to an empty string, if this function failed. This means, in most
+// cases, you do not need to check the error code and you can directly
+// use the value of "buf". It will never have an undefined value.
+// DEPRECATED: Use StrError(int) instead.
+GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
+
+// A thread-safe replacement for strerror(). Returns a string describing the
+// given POSIX error code.
+GOOGLE_GLOG_DLL_DECL std::string StrError(int err);
+
+// A class for which we define operator<<, which does nothing.
+class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
+ public:
+ // Initialize the LogStream so the messages can be written somewhere
+ // (they'll never be actually displayed). This will be needed if a
+ // NullStream& is implicitly converted to LogStream&, in which case
+ // the overloaded NullStream::operator<< will not be invoked.
+ NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
+ NullStream(const char* /*file*/, int /*line*/,
+ const CheckOpString& /*result*/) :
+ LogMessage::LogStream(message_buffer_, 1, 0) { }
+ NullStream &stream() { return *this; }
+ private:
+ // A very short buffer for messages (which we discard anyway). This
+ // will be needed if NullStream& converted to LogStream& (e.g. as a
+ // result of a conditional expression).
+ char message_buffer_[2];
+};
+
+// Do nothing. This operator is inline, allowing the message to be
+// compiled away. The message will not be compiled away if we do
+// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when
+// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly
+// converted to LogStream and the message will be computed and then
+// quietly discarded.
+template<class T>
+inline NullStream& operator<<(NullStream &str, const T &) { return str; }
+
+// Similar to NullStream, but aborts the program (without stack
+// trace), like LogMessageFatal.
+class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream {
+ public:
+ NullStreamFatal() { }
+ NullStreamFatal(const char* file, int line, const CheckOpString& result) :
+ NullStream(file, line, result) { }
+ @ac_cv___attribute___noreturn@ ~NullStreamFatal() { _exit(1); }
+};
+
+// Install a signal handler that will dump signal information and a stack
+// trace when the program crashes on certain signals. We'll install the
+// signal handler for the following signals.
+//
+// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
+//
+// By default, the signal handler will write the failure dump to the
+// standard error. You can customize the destination by installing your
+// own writer function by InstallFailureWriter() below.
+//
+// Note on threading:
+//
+// The function should be called before threads are created, if you want
+// to use the failure signal handler for all threads. The stack trace
+// will be shown only for the thread that receives the signal. In other
+// words, stack traces of other threads won't be shown.
+GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler();
+
+// Installs a function that is used for writing the failure dump. "data"
+// is the pointer to the beginning of a message to be written, and "size"
+// is the size of the message. You should not expect the data is
+// terminated with '\0'.
+GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
+ void (*writer)(const char* data, int size));
+
+@ac_google_end_namespace@
+
+#endif // _LOGGING_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/nstack_adapter.ph b/thirdparty/glog/glog-0.3.4/src/glog/nstack_adapter.ph
new file mode 100644
index 0000000..28aede0
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/nstack_adapter.ph
@@ -0,0 +1,103 @@
+#ifndef __NSTACK_ADAPTER_H__
+#define __NSTACK_ADAPTER_H__
+
+#include <ostream>
+#include <sstream>
+#include <string>
+#include "glog/nstack_glog.ph"
+
+namespace nstack_space {
+
+// LogMessageAdapter::LogStream is a std::ostream backed by this streambuf.
+// This class ignores overflow and leaves two bytes at the end of the
+// buffer to allow for a '\n' and '\0'.
+class LogStreamBuf : public std::streambuf {
+public:
+ // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
+ LogStreamBuf(char *buf, int len) {
+ setp(buf, buf + len - 2);
+ }
+
+ // This effectively ignores overflow.
+ virtual int_type overflow(int_type ch) {
+ return ch;
+ }
+
+ // Legacy public ostrstream method.
+ size_t pcount() const { return pptr() - pbase(); }
+ char* pbase() const { return std::streambuf::pbase(); }
+};
+
+class LogMessageAdapter {
+public:
+ class LogRamMgnt {
+ public:
+ LogRamMgnt() {};
+ ~LogRamMgnt() {};
+
+ void *operator new(std::size_t size);
+ void operator delete(void *ptr);
+ };
+
+ class LogStream : public std::ostream, public LogRamMgnt {
+ public:
+ LogStream(char *buf, int len, int log_ctr)
+ : std::ostream(NULL),
+ streambuf_(buf, len),
+ ctr_(log_ctr),
+ self_(this) {
+ rdbuf(&streambuf_);
+ }
+
+ int ctr() const { return ctr_; }
+ void set_ctr(int s_ctr) { ctr_ = s_ctr; }
+ LogStream* self() const { return self_; }
+
+ // Legacy std::streambuf methods.
+ size_t pcount() const { return streambuf_.pcount(); }
+ char* pbase() const { return streambuf_.pbase(); }
+ char* str() const { return pbase(); }
+
+
+ private:
+ LogStreamBuf streambuf_;
+ int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
+ LogStream *self_; // Consistency check hack
+ };
+
+
+ LogMessageAdapter(const char *file,
+ int line,
+ const char *funcName,
+ int logLevel);
+
+
+ ~LogMessageAdapter();
+
+ std::ostream& stream();
+
+ class LogMsgAdpData : public LogRamMgnt {
+ public:
+ LogMsgAdpData(){};
+
+ char *pMsgBuff;
+ int level;
+ char fileName[MAX_ROSA_LOG_LEN];
+ int line;
+ char func[MAX_ROSA_LOG_LEN];
+
+ LogStream* stream_alloc_;
+ LogStream* stream_;
+
+ ~LogMsgAdpData();
+ };
+
+private:
+ LogMsgAdpData* allocated;
+ LogMsgAdpData* data;
+
+};
+
+}
+
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog.ph b/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog.ph
new file mode 100644
index 0000000..a78585c
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog.ph
@@ -0,0 +1,424 @@
+/**
+* @file nstack_glog.ph
+*
+* Copyright(C), Huawei Tech. Co., Ltd. ALL RIGHTS RESERVED. \n
+*
+* @brief glog on the nsatck header file, glog on nsatck all external interface.
+* @verbatim
+ Functional Description: the APIs provide to print
+ Target users: nStack
+ Use the constraints: internal function call, do not do function check, please ensure that the user's legitimacy
+ Upgrade effect: no
+@endverbatim
+*/
+#ifndef __H_NSTACK_GLOG_H__
+#define __H_NSTACK_GLOG_H__
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+/**
+* @ingroup GLOG
+* @brief log type.
+*
+<br/>Function description: Alternate log type for printing.
+<br/>use constraint: NA.
+<br/>upgrade effect: no.
+*/
+typedef enum glogEnumPrintType
+{
+ HLOG_PRINT_TYPE_HOOK = 0, /**< Hook log*/
+ HLOG_PRINT_TYPE_GLOG, /**< nStack log */
+
+ HLOG_PRINT_TYPE_BUTT,
+}glog_printType_e;
+
+
+/**
+* Product maximum length of a single log 63, set a character stored '\ 0'
+*/
+#define MAX_ROSA_LOG_LEN 64
+
+/**
+* nStack single log transition length
+*/
+#define MAX_NSTACK_LOG_TRANSITIONAL_LEN 256
+
+/**
+* nStack The average length of a single log
+*/
+#define MAX_LOG_TRANSITIONAL_LEN 2048
+
+/**
+* nStack maximum length of a single log: 30K
+*/
+#define MAX_NSTACK_LOG_LENGTH 30720
+
+/**
+* nStack Sets the log level environment variable
+*/
+#define ENV_LOG_LEVEL_ENABLE_FLAG "NSTACK_LOG_LEVEL_ENABLE"
+
+/**
+* nStack sets the HOOK log level environment variable
+*/
+#define NSTACK_LOG_HOOK_LEVEL "NSTACK_LOG_HOOK_LEVEL"
+
+/**
+* nStack Sets the environment variable for each log print length
+*/
+#define ENV_LOG_PRINT_LEN_FLAG "NSTACK_LOG_PRINT_LEN"
+
+/**
+* Single log prefix maximum length: 8 log records + 1 separator: +3 log serial number + 1 separator]
+*/
+#define NSTACK_LOG_PRE_LEN 13
+
+/**
+* Send product log count calculation
+*/
+#define NSTACK_LOG_TRANSFER_TO_PRODUCE_ITEMS(_len) (((_len) -1) / (MAX_ROSA_LOG_LEN - NSTACK_LOG_PRE_LEN) +1)
+
+/**
+* @ingroup glog_atomic
+* @brief brief atomic variable structure.
+<br/> Functional Description: Definition of atomic variable structure.
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+typedef struct {
+ volatile int counter;
+} glog_atomic_t;
+
+/*****************************************************************************
+Function name: glogAtomicRead
+Function Description: Get the atomic variable value.
+Input parameters: v: atomic variable.
+Output parameters: NA
+Return Value: The atomic variable value.
+*****************************************************************************/
+static inline int glogAtomicRead(const glog_atomic_t *v)
+{
+ return v->counter;
+}
+
+/*****************************************************************************
+Function name: glogAtomicInc
+Functional Description: Atomic self-increment.
+Input parameters: v: atomic variable.
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+static inline void glogAtomicInc(glog_atomic_t *v)
+{
+ (void)__sync_fetch_and_add(&v->counter, 1);
+}
+
+/**
+* @ingroup GLOG
+* @brief glog provides C interface print log.
+*
+* @verbatim
+ Function Description: Print the log.
+ Target users: LITESERVICE
+ Use the constraint: the user guarantees the correctness of the entry
+ Upgrade effect: no
+@endverbatim
+* @param type [input] print type
+* @param prestr [input] pre string
+* @param level [input] real level
+* @param count [input] repeat count
+* @param fileName [input] file name
+* @param fileLine [input] file line number
+* @param funcName [input] function name
+* @param format [input] accepts arguments
+*
+* @return NA
+* @par dependency:
+* <li>nstack_glog.ph£ºThis interface declares the header file.</li></ul>
+ * @see NA¡£
+* @since V100R002C00
+*/
+
+void glog_print(unsigned int type,
+ const char *prestr,
+ unsigned int level,
+ int count,
+ char *fileName,
+ const unsigned int fileLine,
+ const char *funcName,
+ const char *format,
+ ...);
+
+/*****************************************************************************
+Function name: glogInit
+Function description: Hlog initialization.
+Input parameters: param incoming parameters that can make module ID and so on
+Output parameters: NA
+Return value: NA
+*****************************************************************************/
+void glogInit(char *param);
+
+/*****************************************************************************
+Function name: glogExit
+Function description: Hlog exits
+Input parameters: NA
+Output parameters: NA
+Return value: NA
+*****************************************************************************/
+void glogExit(void);
+
+/*****************************************************************************
+Function name: glogDestinationSet
+Function Description: Set different files based on different levels of log basename.
+Input parameters: logLevel log level
+ base_filename file
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogDestinationSet(unsigned int logLevel, const char* base_filename);
+
+/*****************************************************************************
+Function name: n_glogLevelSet
+Function Description: Set the log level to be printed.
+Enter the parameters: severity log level, see nstack_log_level
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void n_glogLevelSet(unsigned int logLevel);
+
+/*****************************************************************************
+Function name: glogToStderrSet
+Function Description: Set whether the log print standard output, the default need to print the file
+Input parameters: logToStderr is valid, 1: print standard output, do not print the file
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogToStderrSet(int logToStderr);
+
+/*****************************************************************************
+Function name: glogFlushLogSecsSet
+Function Description: Sets the maximum number of seconds which logs may be buffered for.
+Enter the parameters: secs seconds
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogFlushLogSecsSet(int secs);
+
+/*****************************************************************************
+Function name: glogMaxLogSizeSet
+Function Description: Sets the maximum log file size (in MB).
+Input parameters: maxSize the maximum log file size (in MB)
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogMaxLogSizeSet(int maxSize);
+
+/*****************************************************************************
+Function name: glogLevelGet
+Function Description: Get the log print level
+Input parameters: NA
+Output parameters: NA
+Return Value: Success: Log level
+ Failed: GLOG_LEVEL_BUTT
+*****************************************************************************/
+int glogLevelGet(void);
+
+/*****************************************************************************
+Function name: glogDir
+Function Description: If specified, logfiles are written into this directory instead of
+ the default logging directory
+Enter the parameters: logDir: directory
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogDir(char *logDir);
+
+/*****************************************************************************
+Function name: glogBufLevelSet
+Function Description: When the log level is greater than this level will immediately output,
+ without caching. Buffer log messages logged at this level or lower ,
+ -1 means don't buffer; 0 means buffer only.
+Enter the parameters: log level, see nstack_log_level,and cannot bigger than GLOG_LEVEL_ERROR.
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogBufLevelSet(unsigned int logLevel);
+
+/*****************************************************************************
+ Function name: nstack_modify_log_dir
+ Function Description: If specified, modify the glog prit path dynamic.
+ Enter the parameters: logDir: directory
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void nstack_modify_log_dir(char *log_dir);
+
+/*****************************************************************************
+ Function name: release the lock of glog when fork
+ Function Description: release the lock of glog when fork.
+ Enter the parameters: NA
+ Output parameters: NA
+ Return Value: NA
+ issue: DTS2017110709083
+*****************************************************************************/
+void nstack_log_lock_release(void);
+
+/*****************************************************************************
+Function name: glogInstallFailureSignalHandler
+Function Description: Install a signal handler that will dump signal information and a stack
+ trace when the program crashes on certain signals. We'll install the
+ signal handler for the following signals.
+
+ SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
+
+ By default, the signal handler will write the failure dump to the
+ standard error. You can customize the destination by installing your
+ own writer function by InstallFailureWriter() below.
+
+ Note on threading:
+
+ The function should be called before threads are created, if you want
+ to use the failure signal handler for all threads. The stack trace
+ will be shown only for the thread that receives the signal. In other
+ words, stack traces of other threads won't be shown.
+Enter the parameters: NA
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogInstallFailureSignalHandler(void);
+
+typedef void (*glogFailfuncHook)(void);
+/*****************************************************************************
+Function name: glogInstallFailureFunction
+Function Description: Install a function which will be called after LOG(FATAL).
+Enter the parameters: hook: function you want to call after LOG(FATAL).
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogInstallFailureFunction(glogFailfuncHook hook);
+
+typedef void (*glogInstallFailureWriterHook)(const char* data, int size);
+/*****************************************************************************
+Function name: glogInstallFailureWriter
+Function Description: By default, the signal handler writes the failure dump to the standard error.
+ You can customize the destination by glogInstallFailureWriter().
+Enter the parameters: hook: the signal handler writes the failure dump to the destination you want.
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogInstallFailureWriter(glogInstallFailureWriterHook hook);
+
+/*****************************************************************************
+Function name: glogRavage
+Functional Description: Segment the NSTACK log to suit the product log mode for easy integration
+Enter the file name: fileName
+ fileLine file line number
+ funcName function name
+ fmtString NSTACK prints content
+Output Parameters: pLogString: Returns the formatted log
+Return Value: NA
+*****************************************************************************/
+void glogRavage(char *fileName,
+ const unsigned int fileLine,
+ const char *funcName,
+ const char *fmtString,
+ char *pLogString);
+
+/*****************************************************************************
+Function name: glogPrintLengthSet
+Function Description: Set the number of characters to print for each log, up to 256
+Input parameters: len: character length
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogPrintLengthSet(unsigned int len);
+
+/*****************************************************************************
+Function name: glogSetLogSymlink
+Function Description: Set the basename of the symlink to the latest log file at a given
+ severity. If symlink_basename is empty, do not make a symlink
+ you do not call this function, the symlink basename is the
+ invocation name of the program. Thread-safe.
+Input parameters: level: log level, such as nstack_log_level
+ symlink_basename: link basename, NULL is no link
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogSetLogSymlink(unsigned int level, const char* symlink_basename);
+
+/*****************************************************************************
+Function name: glogFlushLogFiles
+Function Description: Flushes all log files that contains messages that are at least of
+ the specified severity level. Thread-safe.
+Input parameters: min_level: log level, such as nstack_log_level
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogFlushLogFiles(unsigned int min_level);
+
+/*****************************************************************************
+Function name: glogSetLogFilenameExtension
+Function Description: Specify an "extension" added to the filename specified via
+ SetLogDestination. This applies to all severity levels. It's
+ often used to append the port we're listening on to the logfile
+ name. Thread-safe.
+Input parameters: filename_extension: extension filename of log file
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogSetLogFilenameExtension(const char* filename_extension);
+
+/**
+* Memory request release registration callback
+*/
+typedef struct tagGlogAllocator {
+ /** Function to allocate memory. */
+ void* (*allocCb)(size_t size);
+ /** Function to free memory. */
+ void (*freeCb)(void *pointer);
+} glog_allocator_s;
+
+/*****************************************************************************
+Function name: glogMemAllocatorReg
+Function Description: Register the memory application function.
+Input parameters: allocator: memory request and release interface callback registration
+Output parameters: NA
+Return value: function returned successfully 0; unsuccessful return -1
+*****************************************************************************/
+int glogMemAllocatorReg(glog_allocator_s *allocator);
+
+/*****************************************************************************
+Function name: glogMalloc
+Function Description: Memory application function.
+Enter the size of the memory request
+Output parameters: NA
+Return Value: The function executed successfully to return to the requested memory address;
+ returned NULL without success
+*****************************************************************************/
+void *glogMalloc(unsigned int size);
+
+/*****************************************************************************
+Function name: glogFree
+Function Description: Memory release function.
+Input parameter: pointer: memory release pointer
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogFree(void *pointer);
+
+/* [DTS2017122008920][2012-12-21] */
+void SetGlogCtrlOpt(int opt);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog_in.h b/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog_in.h
new file mode 100644
index 0000000..52eb747
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/nstack_glog_in.h
@@ -0,0 +1,215 @@
+/**
+* @file nstack_glog_in.h
+*
+* Copyright(C), Huawei Tech. Co., Ltd. ALL RIGHTS RESERVED. \n
+*
+* @brief glog header file outside
+* @verbatim
+ function Description: user define glog print
+ user: Custom print log
+ Use constraints: NA
+ Upgrade effects: no
+@endverbatim
+*/
+#ifndef __NSTACK_GLOG_IN_H__
+#define __NSTACK_GLOG_IN_H__
+
+#include <stdio.h>
+
+/**@defgroup GLOG */
+
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+/**
+* @ingroup GLOG
+* @brief print point
+*
+<br/> function description: dot log.
+<br/> use constraints: NA.
+<br/> upgrade effects: no.
+*/
+#define LOG_CODE 1U
+
+/**
+* @ingroup GLOG
+* @brief log level
+*
+<br/> function description: log level.
+<br/> use constraints: NA.
+<br/> upgrade effects: no.
+
+*/
+typedef enum tagLogLevel
+{
+ GLOG_LEVEL_DEBUG = 0, /**< Debug*/
+ GLOG_LEVEL_INFO = 1, /**< INFO,google_ns::INFO */
+ GLOG_LEVEL_WARNING = 2, /**< WARNING,google_ns::WARNING */
+ GLOG_LEVEL_ERROR = 3, /**< ERROR,google_ns::ERROR */
+ GLOG_LEVEL_FATAL = 4, /**< FATAL,google_ns::FATAL */
+
+ GLOG_LEVEL_BUTT
+} nstack_log_level;
+
+
+/**
+* @ingroup GLOG
+* @brief ROSA LOG HOOk
+*
+* @verbatim
+ Function Description: Register the hook for LiteService log printing.
+ Target users: users who use the custom print logs
+ Use the constraints: the need for users to achieve log printing, dotted by the ROSA unified allocation, the iteration only passed the fixed value LOG_CODE.
+ Upgrade effect: no
+
+@endverbatim
+* @param logCode [input] log RBI ID, such as ROSA LOGCode, reserved
+* @param logLevel [input] log level
+* @param format [input] log format
+* @param data [input] parameter
+*
+* @return NA
+* @par dependency: product registration
+* <li>nstack_glog_in.h£ºThe interface declares the header file</li></ul>
+ * @see NA¡£
+* @since V100R002C00
+*/
+typedef void (*nstack_log_hook)(unsigned int logCode,
+ unsigned int logLevel,
+ void *format,
+ void *data);
+
+/**
+* @ingroup GLOG
+* @brief from the process of subscribing to hook functions.
+*
+<br/> Function description: The hook function issued from the process status information, the user implements and registers the SF function.
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+typedef struct log_hook_tag {
+ nstack_log_hook log_hook; /**< Custom log callback interface*/
+ unsigned int register_cnt; /**< Number of registrations to prevent multiple registrations */
+ unsigned int level;
+}log_hook_tag_t;
+
+extern log_hook_tag_t g_log_hook_tag;
+
+
+/**
+* @ingroup NSTACK_LOG
+* @brief product to NSTACK registration log hook.
+*
+* @verbatim
+ Function Description: Set the log to print the hook.
+ Target users: users who use NSTACK to print logs
+ Use the constraint: log_hook parameter can not be empty, repeat the registration to the last time.
+ Upgrade effect: no
+
+@endverbatim
+* @param log_hook [input] ROSA registered to NSTACK callback function, can not be empty
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: empty, or re-registered
+* @par dependency: Requires product call
+* <li>nstack_glog_in.h The interface declares the header file. </li></ul>
+* @see NA¡£
+* @since V100R002C00
+*/
+int nstack_log_hook_set(nstack_log_hook log_hook);
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log level to be printed, and logs greater than or equal to this level will be printed.
+*
+* @verbatim
+ Function Description: Set the log level to be printed.Support for reading environment variables:
+ NSTACK_LOG_HOOK_LEVEL = DBG / INF / WAR / ERR / FTL,If the value of NSTACK_LOG_HOOK_LEVEL is set
+ incorrectly, the log level is unchanged Dynamically set the level
+ Target users: users who use NSTACK to print logs
+ Use constraint: log level See nstack_log_level.
+ First set the priority level with NSTACK_LOG_HOOK_LEVEL,
+ If the NSTACK_LOG_HOOK_LEVEL environment variable is not set,
+ And then to nstack_log_hook_level_set incoming log_level prevail,
+ The default is INFO level.
+ Note the use of environment variable NSTACK_LOG_HOOK_LEVEL settings and clear.
+ Upgrade effect: no
+@endverbatim
+* @param log_level [input] log level, see enum nstack_log_level
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: level is not in the range, before the log level unchanged
+* @par dependency:NA
+* @see NA¡£
+* @since V100R002C00
+*/
+int nstack_log_hook_level_set(unsigned int log_level);
+
+
+/**
+* @ingroup NSTACK_LOG£¬init the hook
+
+* @see NA¡£
+* @since V100R002C00
+*/
+
+void nstack_log_hook_init();
+
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log file number.
+*
+* @verbatim
+ Function Description: Set the log file number.
+ Target users: users who use NSTACK to print logs
+ Use constraint: The default is 10
+ Upgrade effect: no
+@endverbatim
+* @param count [input] log file number,
+*
+* @return NA
+* @par dependency:NA
+* @see NA¡£
+* @since V100R002C00
+*/
+void nstack_log_count_set(unsigned int count);
+
+
+/**
+* @ingroup GLOG
+* @brief Set the log level to be printed, and logs greater than or equal to this level will be printed.
+*
+* @verbatim
+ Function Description: Set the log level to be printed.
+ Support for reading environment variables NSTACK_LOG_LEVEL_ENABLE = DEBUG / INFO / WARNING / ERROR / FATAL,
+ Dynamically set the level
+ Target users: users who use the NSTACK software to print logs
+ Use constraint: log level See nstack_log_level, which must be called when NSTACK_LOG_LEVEL_ENABLE is used.
+ First to NSTACK_LOG_LEVEL_ENABLE set the level prevail, again with the incoming logLevel prevail,
+ The default is INFO level. Please note that the environment variable NSTACK_LOG_LEVEL_ENABLE settings and clear.
+ Upgrade effect: no
+@endverbatim
+* @param logLevel [input] log level, see nstack_log_level
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: the rank is not in range
+* @par dependency:
+* <li>nstack_glog_in.h£ºThe interface declares the header file.</li></ul>
+ * @see NA¡£
+* @since V100R002C00
+*/
+int glogLevelSet(unsigned int logLevel);
+
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/raw_logging.h.in b/thirdparty/glog/glog-0.3.4/src/glog/raw_logging.h.in
new file mode 100644
index 0000000..65076df
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/raw_logging.h.in
@@ -0,0 +1,191 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Maxim Lifantsev
+//
+// Thread-safe logging routines that do not allocate any memory or
+// acquire any locks, and can therefore be used by low-level memory
+// allocation and synchronization code.
+
+#ifndef BASE_RAW_LOGGING_H_
+#define BASE_RAW_LOGGING_H_
+
+#include <time.h>
+
+@ac_google_start_namespace@
+
+#include "glog/log_severity.h"
+#include "glog/vlog_is_on.h"
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+// This is similar to LOG(severity) << format... and VLOG(level) << format..,
+// but
+// * it is to be used ONLY by low-level modules that can't use normal LOG()
+// * it is desiged to be a low-level logger that does not allocate any
+// memory and does not need any locks, hence:
+// * it logs straight and ONLY to STDERR w/o buffering
+// * it uses an explicit format and arguments list
+// * it will silently chop off really long message strings
+// Usage example:
+// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
+// RAW_VLOG(3, "status is %i", status);
+// These will print an almost standard log lines like this to stderr only:
+// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+// I0821 211317 file.cc:142] RAW: status is 20
+#define RAW_LOG(severity, ...) \
+ do { \
+ switch (@ac_google_namespace@::GLOG_ ## severity) { \
+ case 0: \
+ RAW_LOG_INFO(__VA_ARGS__); \
+ break; \
+ case 1: \
+ RAW_LOG_WARNING(__VA_ARGS__); \
+ break; \
+ case 2: \
+ RAW_LOG_ERROR(__VA_ARGS__); \
+ break; \
+ case 3: \
+ RAW_LOG_FATAL(__VA_ARGS__); \
+ break; \
+ default: \
+ break; \
+ } \
+ } while (0)
+
+// The following STRIP_LOG testing is performed in the header file so that it's
+// possible to completely compile out the logging code and the log messages.
+#if STRIP_LOG == 0 //lint !e553 config.h.in Configuration
+#define RAW_VLOG(verboselevel, ...) \
+ do { \
+ if (VLOG_IS_ON(verboselevel)) { \
+ RAW_LOG_INFO(__VA_ARGS__); \
+ } \
+ } while (0)
+#else
+#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG == 0
+
+/*[DTS2017102309930][2017-10-23][l00349752][VPP OR] modify namespace google to google_ns,
+ avoid conflict with other PDT using glog. */
+
+#if STRIP_LOG == 0 //lint !e553 config.h.in Configuration
+#define RAW_LOG_INFO(...) google_ns::RawLog__(google_ns::GLOG_INFO, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG == 0
+
+#if STRIP_LOG <= 1 //lint !e553 config.h.in Configuration
+#define RAW_LOG_WARNING(...) google_ns::RawLog__(google_ns::GLOG_WARNING, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG <= 1
+
+#if STRIP_LOG <= 2 //lint !e553 config.h.in Configuration
+#define RAW_LOG_ERROR(...) google_ns::RawLog__(google_ns::GLOG_ERROR, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG <= 2
+
+#if STRIP_LOG <= 3 //lint !e553 config.h.in Configuration
+#define RAW_LOG_FATAL(...) google_ns::RawLog__(google_ns::GLOG_FATAL, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_FATAL(...) \
+ do { \
+ @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__); \
+ exit(1); \
+ } while (0)
+#endif // STRIP_LOG <= 3
+
+// Similar to CHECK(condition) << message,
+// but for low-level modules: we use only RAW_LOG that does not allocate memory.
+// We do not want to provide args list here to encourage this usage:
+// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
+// so that the args are not computed when not needed.
+#define RAW_CHECK(condition, message) \
+ do { \
+ if (!(condition)) { \
+ RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
+ } \
+ } while (0)
+
+// Debug versions of RAW_LOG and RAW_CHECK
+#ifndef NDEBUG
+
+#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
+#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
+
+#else // NDEBUG
+
+#define RAW_DLOG(severity, ...) \
+ while (false) \
+ RAW_LOG(severity, __VA_ARGS__)
+#define RAW_DCHECK(condition, message) \
+ while (false) \
+ RAW_CHECK(condition, message)
+
+#endif // NDEBUG
+
+// Stub log function used to work around for unused variable warnings when
+// building with STRIP_LOG > 0.
+static inline void RawLogStub__(int /* ignored */, ...) {
+}
+
+// Helper function to implement RAW_LOG and RAW_VLOG
+// Logs format... at "severity" level, reporting it
+// as called from file:line.
+// This does not allocate memory or acquire locks.
+GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
+ const char* file,
+ int line,
+ const char* format, ...)
+ @ac_cv___attribute___printf_4_5@;
+
+// Hack to propagate time information into this module so that
+// this module does not have to directly call localtime_r(),
+// which could allocate memory.
+GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
+
+@ac_google_end_namespace@
+
+#endif // BASE_RAW_LOGGING_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/stl_logging.h.in b/thirdparty/glog/glog-0.3.4/src/glog/stl_logging.h.in
new file mode 100644
index 0000000..600945d
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/stl_logging.h.in
@@ -0,0 +1,220 @@
+// Copyright (c) 2003, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Stream output operators for STL containers; to be used for logging *only*.
+// Inclusion of this file lets you do:
+//
+// list<string> x;
+// LOG(INFO) << "data: " << x;
+// vector<int> v1, v2;
+// CHECK_EQ(v1, v2);
+//
+// If you want to use this header file with hash maps or slist, you
+// need to define macros before including this file:
+//
+// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
+// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
+// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
+// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
+//
+
+#ifndef UTIL_GTL_STL_LOGGING_INL_H_
+#define UTIL_GTL_STL_LOGGING_INL_H_
+
+#if !@ac_cv_cxx_using_operator@
+# error We do not support stl_logging for this compiler
+#endif
+
+#include <deque>
+#include <list>
+#include <map>
+#include <ostream>
+#include <set>
+#include <utility>
+#include <vector>
+
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+# include <unordered_map>
+# include <unordered_set>
+#endif
+
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+# include <tr1/unordered_map>
+# include <tr1/unordered_set>
+#endif
+
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+# include <ext/hash_set>
+# include <ext/hash_map>
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
+# include <ext/slist>
+#endif
+
+// Forward declare these two, and define them after all the container streams
+// operators so that we can recurse from pair -> container -> container -> pair
+// properly.
+template<class First, class Second>
+std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
+
+@ac_google_start_namespace@
+
+template<class Iter>
+void PrintSequence(std::ostream& out, Iter begin, Iter end);
+
+@ac_google_end_namespace@
+
+#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
+template<class T1, class T2> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2>& seq) { \
+ @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_TWO_ARG_CONTAINER(std::vector)
+OUTPUT_TWO_ARG_CONTAINER(std::deque)
+OUTPUT_TWO_ARG_CONTAINER(std::list)
+#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
+OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
+#endif
+
+#undef OUTPUT_TWO_ARG_CONTAINER
+
+#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3>& seq) { \
+ @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_THREE_ARG_CONTAINER(std::set)
+OUTPUT_THREE_ARG_CONTAINER(std::multiset)
+
+#undef OUTPUT_THREE_ARG_CONTAINER
+
+#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3, class T4> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3, T4>& seq) { \
+ @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_FOUR_ARG_CONTAINER(std::map)
+OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
+OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
+OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
+OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
+#endif
+
+#undef OUTPUT_FOUR_ARG_CONTAINER
+
+#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3, class T4, class T5> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3, T4, T5>& seq) { \
+ @ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
+OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
+OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
+OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
+#endif
+
+#undef OUTPUT_FIVE_ARG_CONTAINER
+
+template<class First, class Second>
+inline std::ostream& operator<<(std::ostream& out,
+ const std::pair<First, Second>& p) {
+ out << '(' << p.first << ", " << p.second << ')';
+ return out;
+}
+
+@ac_google_start_namespace@
+
+template<class Iter>
+inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
+ // Output at most 100 elements -- appropriate if used for logging.
+ for (int i = 0; begin != end && i < 100; ++i, ++begin) {
+ if (i > 0) out << ' ';
+ out << *begin;
+ }
+ if (begin != end) {
+ out << " ...";
+ }
+}
+
+@ac_google_end_namespace@
+
+// Note that this is technically undefined behavior! We are adding things into
+// the std namespace for a reason though -- we are providing new operations on
+// types which are themselves defined with this namespace. Without this, these
+// operator overloads cannot be found via ADL. If these definitions are not
+// found via ADL, they must be #included before they're used, which requires
+// this header to be included before apparently independent other headers.
+//
+// For example, base/logging.h defines various template functions to implement
+// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
+// It does so via the function template MakeCheckOpValueString:
+// template<class T>
+// void MakeCheckOpValueString(strstream* ss, const T& v) {
+// (*ss) << v;
+// }
+// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
+// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
+// find these operator definitions via ADL.
+//
+// Even this solution has problems -- it may pull unintended operators into the
+// namespace as well, allowing them to also be found via ADL, and creating code
+// that only works with a particular order of includes. Long term, we need to
+// move all of the *definitions* into namespace std, bet we need to ensure no
+// one references them first. This lets us take that step. We cannot define them
+// in both because that would create ambiguous overloads when both are found.
+namespace std { using ::operator<<; }
+
+#endif // UTIL_GTL_STL_LOGGING_INL_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/glog/vlog_is_on.h.in b/thirdparty/glog/glog-0.3.4/src/glog/vlog_is_on.h.in
new file mode 100644
index 0000000..3f4c4a3
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/glog/vlog_is_on.h.in
@@ -0,0 +1,129 @@
+// Copyright (c) 1999, 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney and many others
+//
+// Defines the VLOG_IS_ON macro that controls the variable-verbosity
+// conditional logging.
+//
+// It's used by VLOG and VLOG_IF in logging.h
+// and by RAW_VLOG in raw_logging.h to trigger the logging.
+//
+// It can also be used directly e.g. like this:
+// if (VLOG_IS_ON(2)) {
+// // do some logging preparation and logging
+// // that can't be accomplished e.g. via just VLOG(2) << ...;
+// }
+//
+// The truth value that VLOG_IS_ON(level) returns is determined by
+// the three verbosity level flags:
+// --v=<n> Gives the default maximal active V-logging level;
+// 0 is the default.
+// Normally positive values are used for V-logging levels.
+// --vmodule=<str> Gives the per-module maximal V-logging levels to override
+// the value given by --v.
+// E.g. "my_module=2,foo*=3" would change the logging level
+// for all code in source files "my_module.*" and "foo*.*"
+// ("-inl" suffixes are also disregarded for this matching).
+//
+// SetVLOGLevel helper function is provided to do limited dynamic control over
+// V-logging by overriding the per-module settings given via --vmodule flag.
+//
+// CAVEAT: --vmodule functionality is not available in non gcc compilers.
+//
+
+#ifndef BASE_VLOG_IS_ON_H_
+#define BASE_VLOG_IS_ON_H_
+
+#include "glog/log_severity.h"
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+#if defined(__GNUC__)
+// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
+// (Normally) the first time every VLOG_IS_ON(n) site is hit,
+// we determine what variable will dynamically control logging at this site:
+// it's either FLAGS_v or an appropriate internal variable
+// matching the current source file that represents results of
+// parsing of --vmodule flag and/or SetVLOGLevel calls.
+#define VLOG_IS_ON(verboselevel) \
+ __extension__ \
+ ({ static @ac_google_namespace@::int32* vlocal__ = &@ac_google_namespace@::kLogSiteUninitialized; \
+ @ac_google_namespace@::int32 verbose_level__ = (verboselevel); \
+ (*vlocal__ >= verbose_level__) && \
+ ((vlocal__ != &@ac_google_namespace@::kLogSiteUninitialized) || \
+ (@ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
+ __FILE__, verbose_level__))); })
+#else
+// GNU extensions not available, so we do not support --vmodule.
+// Dynamic value of FLAGS_v always controls the logging level.
+#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
+#endif
+
+// Set VLOG(_IS_ON) level for module_pattern to log_level.
+// This lets us dynamically control what is normally set by the --vmodule flag.
+// Returns the level that previously applied to module_pattern.
+// NOTE: To change the log level for VLOG(_IS_ON) sites
+// that have already executed after/during InitGoogleLogging,
+// one needs to supply the exact --vmodule pattern that applied to them.
+// (If no --vmodule pattern applied to them
+// the value of FLAGS_v will continue to control them.)
+extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
+ int log_level);
+
+// Various declarations needed for VLOG_IS_ON above: =========================
+
+// Special value used to indicate that a VLOG_IS_ON site has not been
+// initialized. We make this a large value, so the common-case check
+// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
+// passes in such cases and InitVLOG3__ is then triggered.
+extern @ac_google_namespace@::int32 kLogSiteUninitialized;
+
+// Helper routine which determines the logging info for a particalur VLOG site.
+// site_flag is the address of the site-local pointer to the controlling
+// verbosity level
+// site_default is the default to use for *site_flag
+// fname is the current source file name
+// verbose_level is the argument to VLOG_IS_ON
+// We will return the return value for VLOG_IS_ON
+// and if possible set *site_flag appropriately.
+extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
+ @ac_google_namespace@::int32** site_flag,
+ @ac_google_namespace@::int32* site_default,
+ const char* fname,
+ @ac_google_namespace@::int32 verbose_level);
+
+#endif // BASE_VLOG_IS_ON_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/googletest.h b/thirdparty/glog/glog-0.3.4/src/googletest.h
new file mode 100644
index 0000000..ca99c8d
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/googletest.h
@@ -0,0 +1,599 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+// (based on googletest: http://code.google.com/p/googletest/)
+
+#ifdef GOOGLETEST_H__
+#error You must not include this file twice.
+#endif
+#define GOOGLETEST_H__
+
+#include "utilities.h"
+
+#include <ctype.h>
+#include <setjmp.h>
+#include <time.h>
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "base/commandlineflags.h"
+
+using std::map;
+using std::string;
+using std::vector;
+
+_START_GOOGLE_NAMESPACE_
+
+extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
+
+_END_GOOGLE_NAMESPACE_
+
+#undef GOOGLE_GLOG_DLL_DECL
+#define GOOGLE_GLOG_DLL_DECL
+
+static inline string GetTempDir() {
+#ifndef OS_WINDOWS
+ return "/tmp";
+#else
+ char tmp[MAX_PATH];
+ GetTempPathA(MAX_PATH, tmp);
+ return tmp;
+#endif
+}
+
+#if defined(OS_WINDOWS) && defined(_MSC_VER)
+// The test will run in glog/vsproject/<project name>
+// (e.g., glog/vsproject/logging_unittest).
+static const char TEST_SRC_DIR[] = "../..";
+#elif !defined(TEST_SRC_DIR)
+# warning TEST_SRC_DIR should be defined in config.h
+static const char TEST_SRC_DIR[] = ".";
+#endif
+
+DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
+DEFINE_string(test_srcdir, TEST_SRC_DIR,
+ "Source-dir root, needed to find glog_unittest_flagfile");
+DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
+#ifdef NDEBUG
+DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
+#else
+DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
+#endif
+
+#ifdef HAVE_LIB_GTEST
+# include <gtest/gtest.h>
+// Use our ASSERT_DEATH implementation.
+# undef ASSERT_DEATH
+# undef ASSERT_DEBUG_DEATH
+using testing::InitGoogleTest;
+#else
+
+_START_GOOGLE_NAMESPACE_
+
+void InitGoogleTest(int*, char**) {}
+
+// The following is some bare-bones testing infrastructure
+
+#define EXPECT_TRUE(cond) \
+ do { \
+ if (!(cond)) { \
+ fprintf(stderr, "Check failed: %s\n", #cond); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
+
+#define EXPECT_OP(op, val1, val2) \
+ do { \
+ if (!((val1) op (val2))) { \
+ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
+#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
+#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
+#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
+
+#define EXPECT_NAN(arg) \
+ do { \
+ if (!isnan(arg)) { \
+ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_INF(arg) \
+ do { \
+ if (!isinf(arg)) { \
+ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_DOUBLE_EQ(val1, val2) \
+ do { \
+ if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
+ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+#define EXPECT_STREQ(val1, val2) \
+ do { \
+ if (strcmp((val1), (val2)) != 0) { \
+ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
+ exit(1); \
+ } \
+ } while (0)
+
+vector<void (*)()> g_testlist; // the tests to run
+
+#define TEST(a, b) \
+ struct Test_##a##_##b { \
+ Test_##a##_##b() { g_testlist.push_back(&Run); } \
+ static void Run() { FlagSaver fs; RunTest(); } \
+ static void RunTest(); \
+ }; \
+ static Test_##a##_##b g_test_##a##_##b; \
+ void Test_##a##_##b::RunTest()
+
+
+static inline int RUN_ALL_TESTS() {
+ vector<void (*)()>::const_iterator it;
+ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
+ (*it)();
+ }
+ fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
+ return 0;
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // ! HAVE_LIB_GTEST
+
+_START_GOOGLE_NAMESPACE_
+
+static bool g_called_abort;
+static jmp_buf g_jmp_buf;
+static inline void CalledAbort() {
+ g_called_abort = true;
+ longjmp(g_jmp_buf, 1);
+}
+
+#ifdef OS_WINDOWS
+// TODO(hamaji): Death test somehow doesn't work in Windows.
+#define ASSERT_DEATH(fn, msg)
+#else
+#define ASSERT_DEATH(fn, msg) \
+ do { \
+ g_called_abort = false; \
+ /* in logging.cc */ \
+ void (*original_logging_fail_func)() = g_logging_fail_func; \
+ g_logging_fail_func = &CalledAbort; \
+ if (!setjmp(g_jmp_buf)) fn; \
+ /* set back to their default */ \
+ g_logging_fail_func = original_logging_fail_func; \
+ if (!g_called_abort) { \
+ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
+ exit(1); \
+ } \
+ } while (0)
+#endif
+
+#ifdef NDEBUG
+#define ASSERT_DEBUG_DEATH(fn, msg)
+#else
+#define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
+#endif // NDEBUG
+
+// Benchmark tools.
+
+#define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n);
+
+map<string, void (*)(int)> g_benchlist; // the benchmarks to run
+
+class BenchmarkRegisterer {
+ public:
+ BenchmarkRegisterer(const char* name, void (*function)(int iters)) {
+ EXPECT_TRUE(g_benchlist.insert(std::make_pair(name, function)).second);
+ }
+};
+
+static inline void RunSpecifiedBenchmarks() {
+ if (!FLAGS_run_benchmark) {
+ return;
+ }
+
+ int iter_cnt = FLAGS_benchmark_iters;
+ puts("Benchmark\tTime(ns)\tIterations");
+ for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
+ iter != g_benchlist.end();
+ ++iter) {
+ clock_t start = clock();
+ iter->second(iter_cnt);
+ double elapsed_ns =
+ ((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
+ printf("%s\t%8.2lf\t%10d\n",
+ iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
+ }
+ puts("");
+}
+
+// ----------------------------------------------------------------------
+// Golden file functions
+// ----------------------------------------------------------------------
+
+class CapturedStream {
+ public:
+ CapturedStream(int fd, const string & cap_filename) :
+ fd_(fd),
+ uncaptured_fd_(-1),
+ filename_(cap_filename) {
+ Capture();
+ }
+
+ ~CapturedStream() {
+ if (uncaptured_fd_ != -1) {
+ CHECK(close(uncaptured_fd_) != -1);
+ }
+ }
+
+ // Start redirecting output to a file
+ void Capture() {
+ // Keep original stream for later
+ CHECK(uncaptured_fd_ == -1) << ", Stream " << fd_ << " already captured!";
+ uncaptured_fd_ = dup(fd_);
+ CHECK(uncaptured_fd_ != -1);
+
+ // Open file to save stream to
+ int cap_fd = open(filename_.c_str(),
+ O_CREAT | O_TRUNC | O_WRONLY,
+ S_IRUSR | S_IWUSR);
+ CHECK(cap_fd != -1);
+
+ // Send stdout/stderr to this file
+ fflush(NULL);
+ CHECK(dup2(cap_fd, fd_) != -1);
+ CHECK(close(cap_fd) != -1);
+ }
+
+ // Remove output redirection
+ void StopCapture() {
+ // Restore original stream
+ if (uncaptured_fd_ != -1) {
+ fflush(NULL);
+ CHECK(dup2(uncaptured_fd_, fd_) != -1);
+ }
+ }
+
+ const string & filename() const { return filename_; }
+
+ private:
+ int fd_; // file descriptor being captured
+ int uncaptured_fd_; // where the stream was originally being sent to
+ string filename_; // file where stream is being saved
+};
+static CapturedStream * s_captured_streams[STDERR_FILENO+1];
+// Redirect a file descriptor to a file.
+// fd - Should be STDOUT_FILENO or STDERR_FILENO
+// filename - File where output should be stored
+static inline void CaptureTestOutput(int fd, const string & filename) {
+ CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
+ CHECK(s_captured_streams[fd] == NULL);
+ s_captured_streams[fd] = new CapturedStream(fd, filename);
+}
+static inline void CaptureTestStderr() {
+ CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
+}
+// Return the size (in bytes) of a file
+static inline size_t GetFileSize(FILE * file) {
+ fseek(file, 0, SEEK_END);
+ return static_cast<size_t>(ftell(file));
+}
+// Read the entire content of a file as a string
+static inline string ReadEntireFile(FILE * file) {
+ const size_t file_size = GetFileSize(file);
+ char * const buffer = new char[file_size];
+
+ size_t bytes_last_read = 0; // # of bytes read in the last fread()
+ size_t bytes_read = 0; // # of bytes read so far
+
+ fseek(file, 0, SEEK_SET);
+
+ // Keep reading the file until we cannot read further or the
+ // pre-determined file size is reached.
+ do {
+ bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+ bytes_read += bytes_last_read;
+ } while (bytes_last_read > 0 && bytes_read < file_size);
+
+ const string content = string(buffer, buffer+bytes_read);
+ delete[] buffer;
+
+ return content;
+}
+// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
+// fd is STDERR_FILENO) as a string
+static inline string GetCapturedTestOutput(int fd) {
+ CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
+ CapturedStream * const cap = s_captured_streams[fd];
+ CHECK(cap)
+ << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
+
+ // Make sure everything is flushed.
+ cap->StopCapture();
+
+ // Read the captured file.
+ FILE * const file = fopen(cap->filename().c_str(), "r");
+ const string content = ReadEntireFile(file);
+ fclose(file);
+
+ delete cap;
+ s_captured_streams[fd] = NULL;
+
+ return content;
+}
+// Get the captured stderr of a test as a string.
+static inline string GetCapturedTestStderr() {
+ return GetCapturedTestOutput(STDERR_FILENO);
+}
+
+// Check if the string is [IWEF](\d{4}|DATE)
+static inline bool IsLoggingPrefix(const string& s) {
+ if (s.size() != 5) return false;
+ if (!strchr("IWEF", s[0])) return false;
+ for (int i = 1; i <= 4; ++i) {
+ if (!isdigit(s[i]) && s[i] != "DATE"[i-1]) return false;
+ }
+ return true;
+}
+
+// Convert log output into normalized form.
+//
+// Example:
+// I0102 030405 logging_unittest.cc:345] RAW: vlog -1
+// => IDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
+static inline string MungeLine(const string& line) {
+ std::istringstream iss(line);
+ string before, logcode_date, time, thread_lineinfo;
+ iss >> logcode_date;
+ while (!IsLoggingPrefix(logcode_date)) {
+ before += " " + logcode_date;
+ if (!(iss >> logcode_date)) {
+ // We cannot find the header of log output.
+ return before;
+ }
+ }
+ if (!before.empty()) before += " ";
+ iss >> time;
+ iss >> thread_lineinfo;
+ CHECK(!thread_lineinfo.empty());
+ if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
+ // We found thread ID.
+ string tmp;
+ iss >> tmp;
+ CHECK(!tmp.empty());
+ CHECK_EQ(']', tmp[tmp.size() - 1]);
+ thread_lineinfo = "THREADID " + tmp;
+ }
+ size_t index = thread_lineinfo.find(':');
+ CHECK_NE(string::npos, index);
+ thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
+ string rest;
+ std::getline(iss, rest);
+ return (before + logcode_date[0] + "DATE TIME__ " + thread_lineinfo +
+ MungeLine(rest));
+}
+
+static inline void StringReplace(string* str,
+ const string& oldsub,
+ const string& newsub) {
+ size_t pos = str->find(oldsub);
+ if (pos != string::npos) {
+ str->replace(pos, oldsub.size(), newsub.c_str());
+ }
+}
+
+static inline string Munge(const string& filename) {
+ FILE* fp = fopen(filename.c_str(), "rb");
+ CHECK(fp != NULL) << filename << ": couldn't open";
+ char buf[4096];
+ string result;
+ while (fgets(buf, 4095, fp)) {
+ string line = MungeLine(buf);
+ char null_str[256];
+ sprintf(null_str, "%p", static_cast<void*>(NULL));
+ StringReplace(&line, "__NULLP__", null_str);
+ // Remove 0x prefix produced by %p. VC++ doesn't put the prefix.
+ StringReplace(&line, " 0x", " ");
+
+ StringReplace(&line, "__SUCCESS__", StrError(0));
+ StringReplace(&line, "__ENOENT__", StrError(ENOENT));
+ StringReplace(&line, "__EINTR__", StrError(EINTR));
+ StringReplace(&line, "__ENXIO__", StrError(ENXIO));
+ StringReplace(&line, "__ENOEXEC__", StrError(ENOEXEC));
+ result += line + "\n";
+ }
+ fclose(fp);
+ return result;
+}
+
+static inline void WriteToFile(const string& body, const string& file) {
+ FILE* fp = fopen(file.c_str(), "wb");
+ fwrite(body.data(), 1, body.size(), fp);
+ fclose(fp);
+}
+
+static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
+ CapturedStream* cap = s_captured_streams[STDERR_FILENO];
+ CHECK(cap) << ": did you forget CaptureTestStderr()?";
+
+ cap->StopCapture();
+
+ // Run munge
+ const string captured = Munge(cap->filename());
+ const string golden = Munge(golden_filename);
+ if (captured != golden) {
+ fprintf(stderr,
+ "Test with golden file failed. We'll try to show the diff:\n");
+ string munged_golden = golden_filename + ".munged";
+ WriteToFile(golden, munged_golden);
+ string munged_captured = cap->filename() + ".munged";
+ WriteToFile(captured, munged_captured);
+ string diffcmd("diff -u " + munged_golden + " " + munged_captured);
+ if (system(diffcmd.c_str()) != 0) {
+ fprintf(stderr, "diff command was failed.\n");
+ }
+ unlink(munged_golden.c_str());
+ unlink(munged_captured.c_str());
+ return false;
+ }
+ LOG(INFO) << "Diff was successful";
+ return true;
+}
+
+// Save flags used from logging_unittest.cc.
+#ifndef HAVE_LIB_GFLAGS
+struct FlagSaver {
+ FlagSaver()
+ : v_(FLAGS_v),
+ stderrthreshold_(FLAGS_stderrthreshold),
+ logtostderr_(FLAGS_logtostderr),
+ alsologtostderr_(FLAGS_alsologtostderr) {}
+ ~FlagSaver() {
+ FLAGS_v = v_;
+ FLAGS_stderrthreshold = stderrthreshold_;
+ FLAGS_logtostderr = logtostderr_;
+ FLAGS_alsologtostderr = alsologtostderr_;
+ }
+ int v_;
+ int stderrthreshold_;
+ bool logtostderr_;
+ bool alsologtostderr_;
+};
+#endif
+
+class Thread {
+ public:
+ virtual ~Thread() {}
+
+ void SetJoinable(bool) {}
+#if defined(OS_WINDOWS) || defined(OS_CYGWIN)
+ void Start() {
+ handle_ = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
+ (LPVOID)this,
+ 0,
+ &th_);
+ CHECK(handle_) << "CreateThread";
+ }
+ void Join() {
+ WaitForSingleObject(handle_, INFINITE);
+ }
+#elif defined(HAVE_PTHREAD)
+ void Start() {
+ pthread_create(&th_, NULL, &Thread::InvokeThread, this);
+ }
+ void Join() {
+ pthread_join(th_, NULL);
+ }
+#else
+# error No thread implementation.
+#endif
+
+ protected:
+ virtual void Run() = 0;
+
+ private:
+ static void* InvokeThread(void* self) {
+ ((Thread*)self)->Run();
+ return NULL;
+ }
+
+#if defined(OS_WINDOWS) || defined(OS_CYGWIN)
+ HANDLE handle_;
+ DWORD th_;
+#else
+ pthread_t th_;
+#endif
+};
+
+static inline void SleepForMilliseconds(int t) {
+#ifndef OS_WINDOWS
+ usleep(t * 1000);
+#else
+ Sleep(t);
+#endif
+}
+
+// Add hook for operator new to ensure there are no memory allocation.
+
+void (*g_new_hook)() = NULL;
+
+_END_GOOGLE_NAMESPACE_
+
+void* operator new(size_t size) throw(std::bad_alloc) {
+ if (GOOGLE_NAMESPACE::g_new_hook) {
+ GOOGLE_NAMESPACE::g_new_hook();
+ }
+ return malloc(size);
+}
+
+void* operator new[](size_t size) throw(std::bad_alloc) {
+ return ::operator new(size);
+}
+
+void operator delete(void* p) throw() {
+ free(p);
+}
+
+void operator delete[](void* p) throw() {
+ ::operator delete(p);
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/logging.cc b/thirdparty/glog/glog-0.3.4/src/logging.cc
new file mode 100644
index 0000000..6245ebf
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging.cc
@@ -0,0 +1,2579 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#define _GNU_SOURCE 1 // needed for O_NOFOLLOW and pread()/pwrite()
+
+#include "utilities.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iomanip>
+#include <string>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> // For _exit.
+#endif
+#include <climits>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h> // For uname.
+#endif
+#include <fcntl.h>
+#include <cstdio>
+#include <iostream>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <dirent.h>
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+# include <syslog.h>
+#endif
+#include <vector>
+#include <errno.h> // for errno
+#include <sstream>
+#include "base/commandlineflags.h" // to get the program name
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
+#include "base/googleinit.h"
+
+#ifdef HAVE_STACKTRACE
+# include "stacktrace.h"
+#endif
+
+using std::string;
+using std::vector;
+using std::setw;
+using std::setfill;
+using std::hex;
+using std::dec;
+using std::min;
+using std::ostream;
+using std::ostringstream;
+
+using std::FILE;
+using std::fwrite;
+using std::fclose;
+using std::fflush;
+using std::fprintf;
+using std::perror;
+
+#ifdef __QNX__
+using std::fdopen;
+#endif
+
+// There is no thread annotation support.
+#define EXCLUSIVE_LOCKS_REQUIRED(mu)
+
+#define DIR_NAME_LEN 256
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log file number..
+<br/> Functional Description: Set the log file number.
+<br/> use constraint: The default is 10.
+<br/> upgrade effect: no.
+*/
+unsigned int log_file_count = 10;
+/**
+* @ingroup NSTACK_LOG
+* @brief use for log path modify dynamic.
+<br/> Functional Description: nstack_modify_log_dir.
+<br/> use constraint: The default is 0.
+<br/> upgrade effect: no.
+*/
+unsigned int modify_path_count = 0;
+
+
+int glogCtrlOpt = 0;
+
+
+/*****************************************************************************
+* Prototype : get_date_time
+* Description : get log file date time
+* Input : char * old_file
+* const char * log_name
+* Output : NA
+* Return Value : char *
+* Calls :
+* Called By :
+*
+*
+*****************************************************************************/
+char * get_date_time(char *old_file, const char *log_name)
+{
+ unsigned int len = 0;
+
+ if (NULL == old_file || NULL == log_name)
+ {
+ return NULL;
+ }
+
+ len = strlen(log_name);
+ if (strlen(old_file) <= len)
+ {
+ return NULL;
+ }
+
+ if (0 != strncmp(old_file, log_name, len))
+ {
+ return NULL;
+ }
+
+ return old_file + len + 1;
+}
+
+/*****************************************************************************
+* Prototype : remove_old_file
+* Description : remove the old log exceed the log_file_count
+* Input : const * log_path
+* const char * log_name
+* Output : NA
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int remove_old_file(const char *log_path, const char *log_name)
+{
+
+ char backup_dir[DIR_NAME_LEN];
+ struct dirent *log_entry = NULL;
+ int file_count = 0;
+ int dir_fd = -1;
+
+ int ret = 0;
+ char *oldest_file_time = NULL;
+ char oldest_string[DIR_NAME_LEN] = {0};
+ char *oldest_file = NULL;
+ char *cur_file_time = NULL;
+ struct stat file_info;
+ ret = snprintf(oldest_string, DIR_NAME_LEN, "%s", "99999999999999");
+ if(ret < 0)
+ {
+ return -1;
+ }
+ oldest_file_time = oldest_string;
+
+ const char *file_name = strrchr(log_name,'/') + 1;
+ if(NULL == file_name)
+ {
+ return -1;
+ }
+
+ // save current dir
+ if (NULL == getcwd(backup_dir, sizeof(backup_dir)))
+ {
+ return -1;
+ }
+
+ DIR *log_dir = opendir(log_path);
+ if (NULL == log_dir)
+ {
+ return -1;
+ }
+
+ dir_fd = dirfd(log_dir);
+ if (-1 == dir_fd)
+ {
+ (void)closedir(log_dir);
+ ret = chdir(backup_dir);
+ return ret;
+ }
+
+ if (-1 == fchdir(dir_fd))
+ {
+ (void)closedir(log_dir);
+ ret = chdir(backup_dir);
+ return ret;
+ }
+
+ while (NULL != (log_entry = readdir(log_dir)))
+ {
+ ret = stat(log_entry->d_name, &file_info);
+ if (0 != ret)
+ {
+ continue;
+ }
+
+ if (log_entry->d_type == DT_DIR)
+ {
+ continue;
+ }
+
+ cur_file_time = get_date_time(log_entry->d_name, file_name);
+ if (NULL != cur_file_time)
+ {
+ file_count++;
+ if (strcmp(cur_file_time, oldest_file_time) < 0)
+ {
+ oldest_file = log_entry->d_name;
+ oldest_file_time = cur_file_time;
+ }
+ }
+ }
+
+ if ((file_count > log_file_count) && (NULL != oldest_file))
+ {
+ (void)remove(oldest_file);
+ }
+
+ (void)closedir(log_dir);
+ ret = chdir(backup_dir);
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : get_file_size
+* Description : get the file size of file fd
+* Input : int fd
+* Output : NA
+* Return Value : unsigned int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline unsigned int get_file_size(int fd)
+{
+ struct stat buf;
+ if (fd < 0)
+ {
+ return 0;
+ }
+ memset(&buf, 0, sizeof(buf));
+
+ if (fstat(fd, &buf) != 0)
+ {
+ return 0;
+ }
+
+ return (uint32_t)buf.st_size;
+}
+
+
+static bool BoolFromEnv(const char *varname, bool defval) {
+ const char* const valstr = getenv(varname);
+ if (!valstr) {
+ return defval;
+ }
+ return memchr("tTyY1\0", valstr[0], 6) != NULL;
+}
+
+GLOG_DEFINE_bool(logtostderr, BoolFromEnv("GOOGLE_LOGTOSTDERR", false),
+ "log messages go to stderr instead of logfiles");
+GLOG_DEFINE_bool(alsologtostderr, BoolFromEnv("GOOGLE_ALSOLOGTOSTDERR", false),
+ "log messages go to stderr in addition to logfiles");
+GLOG_DEFINE_bool(colorlogtostderr, false,
+ "color messages logged to stderr (if supported by terminal)");
+#ifdef OS_LINUX
+GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "
+ "Logs can grow very quickly and they are rarely read before they "
+ "need to be evicted from memory. Instead, drop them from memory "
+ "as soon as they are flushed to disk.");
+_START_GOOGLE_NAMESPACE_
+namespace logging {
+static const int64 kPageSize = getpagesize();
+}
+_END_GOOGLE_NAMESPACE_
+#endif
+
+// By default, errors (including fatal errors) get logged to stderr as
+// well as the file.
+//
+// The default is ERROR instead of FATAL so that users can see problems
+// when they run a program without having to look in another file.
+DEFINE_int32(stderrthreshold,
+ GOOGLE_NAMESPACE::GLOG_ERROR,
+ "log messages at or above this level are copied to stderr in "
+ "addition to logfiles. This flag obsoletes --alsologtostderr.");
+
+GLOG_DEFINE_string(alsologtoemail, "",
+ "log messages go to these email addresses "
+ "in addition to logfiles");
+GLOG_DEFINE_bool(log_prefix, true,
+ "Prepend the log prefix to the start of each log line");
+GLOG_DEFINE_int32(minloglevel, 0, "Messages logged at a lower level than this don't "
+ "actually get logged anywhere");
+GLOG_DEFINE_int32(logbuflevel, 0,
+ "Buffer log messages logged at this level or lower"
+ " (-1 means don't buffer; 0 means buffer INFO only;"
+ " ...)");
+GLOG_DEFINE_int32(logbufsecs, 30,
+ "Buffer log messages for at most this many seconds");
+GLOG_DEFINE_int32(logemaillevel, 999,
+ "Email log messages logged at this level or higher"
+ " (0 means email all; 3 means email FATAL only;"
+ " ...)");
+GLOG_DEFINE_string(logmailer, "/bin/mail",
+ "Mailer used to send logging email");
+
+// Compute the default value for --log_dir
+static const char* DefaultLogDir() {
+ const char* env;
+ env = getenv("GOOGLE_LOG_DIR");
+ if (env != NULL && env[0] != '\0') {
+ return env;
+ }
+ env = getenv("TEST_TMPDIR");
+ if (env != NULL && env[0] != '\0') {
+ return env;
+ }
+ return "";
+}
+
+
+GLOG_DEFINE_string(log_dir, DefaultLogDir(),
+ "If specified, logfiles are written into this directory instead "
+ "of the default logging directory.");
+GLOG_DEFINE_string(log_link, "", "Put additional links to the log "
+ "files in this directory");
+
+GLOG_DEFINE_int32(max_log_size, 1800,
+ "approx. maximum log file size (in MB). A value of 0 will "
+ "be silently overridden to 1.");
+
+GLOG_DEFINE_bool(stop_logging_if_full_disk, false,
+ "Stop attempting to log to disk if the disk is full.");
+
+GLOG_DEFINE_string(log_backtrace_at, "",
+ "Emit a backtrace when logging at file:linenum.");
+
+// TODO(hamaji): consider windows
+#define PATH_SEPARATOR '/'
+
+
+#ifndef HAVE_PREAD
+#if defined(OS_WINDOWS)
+#include <BaseTsd.h>
+#define ssize_t SSIZE_T
+#endif
+static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
+ off_t orig_offset = lseek(fd, 0, SEEK_CUR);
+ if (orig_offset == (off_t)-1)
+ return -1;
+ if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
+ return -1;
+ ssize_t len = read(fd, buf, count);
+ if (len < 0)
+ return len;
+ if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
+ return -1;
+ return len;
+}
+#endif // !HAVE_PREAD
+
+#ifndef HAVE_PWRITE
+static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) {
+ off_t orig_offset = lseek(fd, 0, SEEK_CUR);
+ if (orig_offset == (off_t)-1)
+ return -1;
+ if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
+ return -1;
+ ssize_t len = write(fd, buf, count);
+ if (len < 0)
+ return len;
+ if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
+ return -1;
+ return len;
+}
+#endif // !HAVE_PWRITE
+static void GetHostName(string* hostname) {
+#if defined(HAVE_SYS_UTSNAME_H)
+ struct utsname buf;
+ if (0 != uname(&buf)) {
+ // ensure null termination on failure
+ *buf.nodename = '\0';
+ }
+ *hostname = buf.nodename;
+#elif defined(OS_WINDOWS)
+ char buf[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
+ if (GetComputerNameA(buf, &len)) {
+ *hostname = buf;
+ } else {
+ hostname->clear();
+ }
+#else
+# warning There is no way to retrieve the host name.
+ *hostname = "(unknown)";
+#endif
+}
+
+
+// Returns true iff terminal supports using colors in output.
+static bool TerminalSupportsColor() {
+ bool term_supports_color = false;
+#ifdef OS_WINDOWS
+ // on Windows TERM variable is usually not set, but the console does
+ // support colors.
+ term_supports_color = true;
+#else
+ // On non-Windows platforms, we rely on the TERM variable.
+ const char* const term = getenv("TERM");
+ if (term != NULL && term[0] != '\0') {
+ term_supports_color =
+ !strcmp(term, "xterm") ||
+ !strcmp(term, "xterm-color") ||
+ !strcmp(term, "xterm-256color") ||
+ !strcmp(term, "screen") ||
+ !strcmp(term, "linux") ||
+ !strcmp(term, "cygwin");
+ }
+#endif
+ return term_supports_color;
+}
+
+_START_GOOGLE_NAMESPACE_
+
+enum GLogColor {
+ COLOR_DEFAULT,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW
+};
+
+static GLogColor SeverityToColor(LogSeverity severity) {
+ assert(severity >= 0 && severity < NUM_SEVERITIES);
+ GLogColor color = COLOR_DEFAULT;
+ switch (severity) {
+ case GLOG_INFO:
+ color = COLOR_DEFAULT;
+ break;
+ case GLOG_WARNING:
+ color = COLOR_YELLOW;
+ break;
+ case GLOG_ERROR:
+ case GLOG_FATAL:
+ color = COLOR_RED;
+ break;
+ default:
+ // should never get here.
+ assert(false);
+ }
+ return color;
+}
+
+#ifdef OS_WINDOWS
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GLogColor color) {
+ switch (color) {
+ case COLOR_RED: return FOREGROUND_RED;
+ case COLOR_GREEN: return FOREGROUND_GREEN;
+ case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+ default: return 0;
+ }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.
+const char* GetAnsiColorCode(GLogColor color) {
+ switch (color) {
+ case COLOR_RED: return "1";
+ case COLOR_GREEN: return "2";
+ case COLOR_YELLOW: return "3";
+ case COLOR_DEFAULT: return "";
+ };
+ return NULL; // stop warning about return type.
+}
+
+#endif // OS_WINDOWS
+
+
+// Safely get max_log_size, overriding to 1 if it somehow gets defined as 0
+static int32 MaxLogSize() {
+ return (FLAGS_max_log_size > 0 ? FLAGS_max_log_size : 1);
+}
+
+// An arbitrary limit on the length of a single log message. This
+// is so that streaming can be done more efficiently.
+const size_t LogMessage::kMaxLogMessageLen = 30000;
+
+struct LogMessage::LogMessageData {
+ LogMessageData();
+
+ int preserved_errno_; // preserved errno
+ // Buffer space; contains complete message text.
+ char message_text_[LogMessage::kMaxLogMessageLen+1];
+ LogStream stream_;
+ char severity_; // What level is this LogMessage logged at?
+ int level_;
+ int line_; // line number where logging call is.
+ void (LogMessage::*send_method_)(); // Call this in destructor to send
+ union { // At most one of these is used: union to keep the size low.
+ LogSink* sink_; // NULL or sink to send message to
+ std::vector<std::string>* outvec_; // NULL or vector to push message onto
+ std::string* message_; // NULL or string to write message into
+ };
+ time_t timestamp_; // Time of creation of LogMessage
+ struct ::tm tm_time_; // Time of creation of LogMessage
+ size_t num_prefix_chars_; // # of chars of prefix in this message
+ size_t num_chars_to_log_; // # of chars of msg to send to log
+ size_t num_chars_to_syslog_; // # of chars of msg to send to syslog
+ const char* basename_; // basename of file that called LOG
+ const char* fullname_; // fullname of file that called LOG
+ bool has_been_flushed_; // false => data has not been flushed
+ bool first_fatal_; // true => this was first fatal msg
+
+ private:
+ LogMessageData(const LogMessageData&);
+ void operator=(const LogMessageData&);
+};
+
+// A mutex that allows only one thread to log at a time, to keep things from
+// getting jumbled. Some other very uncommon logging operations (like
+// changing the destination file for log messages of a given severity) also
+// lock this mutex. Please be sure that anybody who might possibly need to
+// lock it does so.
+static Mutex log_mutex;
+static Mutex fatal_msg_lock;
+
+/*****************************************************************************
+* Prototype : glog_release_rw_lock
+* Description : release log lock
+* Input : NA
+* Output : NA
+* Return Value : NA
+* Calls :
+* Called By :
+*****************************************************************************/
+void glog_release_rw_lock()
+{
+#if defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+ if (glog_ns_internal_namespace_::IsGoogleLoggingInitialized()) {
+ log_mutex.ForceUnlock();
+ fatal_msg_lock.ForceUnlock();
+ }
+#endif
+ return;
+}
+
+
+// Number of messages sent at each severity. Under log_mutex.
+int64 LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
+
+// Globally disable log writing (if disk is full)
+static bool stop_writing = false;
+
+const char*const LogSeverityNames[NUM_SEVERITIES] = {
+ "INFO", "WARNING", "ERROR", "FATAL"
+};
+
+
+
+const char*const nstack_level_names[NUM_SEVERITIES+1] = {
+ "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"
+};
+
+// Has the user called SetExitOnDFatal(true)?
+static bool exit_on_dfatal = true;
+
+const char* GetLogSeverityName(LogSeverity severity) {
+ return LogSeverityNames[severity];
+}
+
+static bool SendEmailInternal(const char*dest, const char *subject,
+ const char*body, bool use_logging);
+
+base_ns::Logger::~Logger() {
+}
+
+namespace {
+
+// Encapsulates all file-system related state
+class LogFileObject : public base_ns::Logger {
+ public:
+ LogFileObject(LogSeverity severity, const char* base_filename);
+ ~LogFileObject();
+
+ virtual void Write(bool force_flush, // Should we force a flush here?
+ time_t timestamp, // Timestamp for this entry
+ const char* message,
+ int message_len);
+
+ // Configuration options
+ void SetBasename(const char* basename);
+ void SetExtension(const char* ext);
+ void SetSymlinkBasename(const char* symlink_basename);
+
+ // Normal flushing routine
+ virtual void Flush();
+
+ // It is the actual file length for the system loggers,
+ // i.e., INFO, ERROR, etc.
+ virtual uint32 LogSize() {
+ MutexLock l(&lock_);
+ return file_length_;
+ }
+
+ // Internal flush routine. Exposed so that FlushLogFilesUnsafe()
+ // can avoid grabbing a lock. Usually Flush() calls it after
+ // acquiring lock_.
+ void FlushUnlocked();
+
+ void ReleaseObjectlock();
+
+
+ private:
+ static const uint32 kRolloverAttemptFrequency = 0x20;
+
+ Mutex lock_;
+ bool base_filename_selected_;
+ string base_filename_;
+ string symlink_basename_;
+ string filename_extension_; // option users can specify (eg to add port#)
+ string whole_filename_;
+ FILE* file_;
+ LogSeverity severity_;
+ uint32 bytes_since_flush_;
+ uint32 file_length_;
+ unsigned int rollover_attempt_;
+ int64 next_flush_time_; // cycle count at which to flush log
+
+ // Actually create a logfile using the value of base_filename_ and the
+ // supplied argument time_pid_string
+ // REQUIRES: lock_ is held
+ bool CreateLogfile();
+};
+
+} // namespace
+
+class LogDestination {
+ public:
+ friend class LogMessage;
+ friend void ReprintFatalMessage();
+ friend base_ns::Logger* base_ns::GetLogger(LogSeverity);
+ friend void base_ns::SetLogger(LogSeverity, base_ns::Logger*);
+
+ // These methods are just forwarded to by their global versions.
+ static void SetLogDestination(LogSeverity severity,
+ const char* base_filename);
+ static void SetLogSymlink(LogSeverity severity,
+ const char* symlink_basename);
+ static void AddLogSink(LogSink *destination);
+ static void RemoveLogSink(LogSink *destination);
+ static void SetLogFilenameExtension(const char* filename_extension);
+ static void SetStderrLogging(LogSeverity min_severity);
+ static void SetEmailLogging(LogSeverity min_severity, const char* addresses);
+ static void LogToStderr();
+ // Flush all log files that are at least at the given severity level
+ static void FlushLogFiles(int min_severity);
+ static void FlushLogFilesUnsafe(int min_severity);
+
+
+ static void RleaseLogSinkLock(int min_severity);
+
+
+ // we set the maximum size of our packet to be 1400, the logic being
+ // to prevent fragmentation.
+ // Really this number is arbitrary.
+ static const int kNetworkBytes = 1400;
+
+ static const string& hostname();
+ static const bool& terminal_supports_color() {
+ return terminal_supports_color_;
+ }
+
+ static void DeleteLogDestinations();
+
+ private:
+ LogDestination(LogSeverity severity, const char* base_filename);
+ ~LogDestination() { }
+
+ // Take a log message of a particular severity and log it to stderr
+ // iff it's of a high enough severity to deserve it.
+ static void MaybeLogToStderr(LogSeverity severity, const char* message,
+ size_t len);
+
+ // Take a log message of a particular severity and log it to email
+ // iff it's of a high enough severity to deserve it.
+ static void MaybeLogToEmail(LogSeverity severity, const char* message,
+ size_t len);
+ // Take a log message of a particular severity and log it to a file
+ // iff the base filename is not "" (which means "don't log to me")
+ static void MaybeLogToLogfile(LogSeverity severity,
+ time_t timestamp,
+ const char* message, size_t len);
+ // Take a log message of a particular severity and log it to the file
+ // for that severity and also for all files with severity less than
+ // this severity.
+ static void LogToAllLogfiles(LogSeverity severity,
+ time_t timestamp,
+ const char* message, size_t len);
+
+ // Send logging info to all registered sinks.
+ static void LogToSinks(LogSeverity severity,
+ const char *full_filename,
+ const char *base_filename,
+ int line,
+ const struct ::tm* tm_time,
+ const char* message,
+ size_t message_len);
+
+ // Wait for all registered sinks via WaitTillSent
+ // including the optional one in "data".
+ static void WaitForSinks(LogMessage::LogMessageData* data);
+
+ static LogDestination* log_destination(LogSeverity severity);
+
+ LogFileObject fileobject_;
+ base_ns::Logger* logger_; // Either &fileobject_, or wrapper around it
+
+ static LogDestination* log_destinations_[NUM_SEVERITIES];
+ static LogSeverity email_logging_severity_;
+ static string addresses_;
+ static string hostname_;
+ static bool terminal_supports_color_;
+
+ // arbitrary global logging destinations.
+ static vector<LogSink*>* sinks_;
+
+ // Protects the vector sinks_,
+ // but not the LogSink objects its elements reference.
+ static Mutex sink_mutex_;
+
+ // Disallow
+ LogDestination(const LogDestination&);
+ LogDestination& operator=(const LogDestination&);
+};
+
+// Errors do not get logged to email by default.
+LogSeverity LogDestination::email_logging_severity_ = 99999;
+
+string LogDestination::addresses_;
+string LogDestination::hostname_;
+
+vector<LogSink*>* LogDestination::sinks_ = NULL;
+Mutex LogDestination::sink_mutex_;
+bool LogDestination::terminal_supports_color_ = TerminalSupportsColor();
+
+/* static */
+const string& LogDestination::hostname() {
+ if (hostname_.empty()) {
+ GetHostName(&hostname_);
+ if (hostname_.empty()) {
+ hostname_ = "(unknown)";
+ }
+ }
+ return hostname_;
+}
+
+LogDestination::LogDestination(LogSeverity severity,
+ const char* base_filename)
+ : fileobject_(severity, base_filename),
+ logger_(&fileobject_) {
+}
+
+inline void LogDestination::FlushLogFilesUnsafe(int min_severity) {
+ // assume we have the log_mutex or we simply don't care
+ // about it
+ for (int i = min_severity; i < NUM_SEVERITIES; i++) {
+ LogDestination* log = log_destination(i);
+ if (log != NULL) {
+ // Flush the base fileobject_ logger directly instead of going
+ // through any wrappers to reduce chance of deadlock.
+ log->fileobject_.FlushUnlocked();
+ }
+ }
+}
+
+inline void LogDestination::FlushLogFiles(int min_severity) {
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&log_mutex);
+ for (int i = min_severity; i < NUM_SEVERITIES; i++) {
+ LogDestination* log = log_destination(i);
+ if (log != NULL) {
+ log->logger_->Flush();
+ }
+ }
+}
+
+inline void LogDestination::RleaseLogSinkLock(int min_severity) {
+ // release the class static lock sink_lock_
+#if defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+ sink_mutex_.ForceUnlock();
+ for (int i = min_severity; i < NUM_SEVERITIES; i++) {
+ LogDestination* log = log_destination(i);
+ if (log != NULL) {
+ // Flush the base fileobject_ logger directly instead of going
+ // through any wrappers to reduce chance of deadlock.
+ log->fileobject_.ReleaseObjectlock();
+ }
+ }
+#endif
+ return;
+}
+
+
+inline void LogDestination::SetLogDestination(LogSeverity severity,
+ const char* base_filename) {
+ assert(severity >= 0 && severity < NUM_SEVERITIES);
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&log_mutex);
+ log_destination(severity)->fileobject_.SetBasename(base_filename);
+}
+
+inline void LogDestination::SetLogSymlink(LogSeverity severity,
+ const char* symlink_basename) {
+ CHECK_GE(severity, 0);
+ CHECK_LT(severity, NUM_SEVERITIES);
+ MutexLock l(&log_mutex);
+ log_destination(severity)->fileobject_.SetSymlinkBasename(symlink_basename);
+}
+
+inline void LogDestination::AddLogSink(LogSink *destination) {
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&sink_mutex_);
+ if (!sinks_) sinks_ = new vector<LogSink*>;
+ sinks_->push_back(destination);
+}
+
+inline void LogDestination::RemoveLogSink(LogSink *destination) {
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&sink_mutex_);
+ // This doesn't keep the sinks in order, but who cares?
+ if (sinks_) {
+ for (int i = sinks_->size() - 1; i >= 0; i--) {
+ if ((*sinks_)[i] == destination) {
+ (*sinks_)[i] = (*sinks_)[sinks_->size() - 1];
+ sinks_->pop_back();
+ break;
+ }
+ }
+ }
+}
+
+inline void LogDestination::SetLogFilenameExtension(const char* ext) {
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&log_mutex);
+ for ( int severity = 0; severity < NUM_SEVERITIES; ++severity ) {
+ log_destination(severity)->fileobject_.SetExtension(ext);
+ }
+}
+
+inline void LogDestination::SetStderrLogging(LogSeverity min_severity) {
+ assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&log_mutex);
+ FLAGS_stderrthreshold = min_severity;
+}
+
+inline void LogDestination::LogToStderr() {
+ // *Don't* put this stuff in a mutex lock, since SetStderrLogging &
+ // SetLogDestination already do the locking!
+ SetStderrLogging(0); // thus everything is "also" logged to stderr
+ for ( int i = 0; i < NUM_SEVERITIES; ++i ) {
+ SetLogDestination(i, ""); // "" turns off logging to a logfile
+ }
+}
+
+inline void LogDestination::SetEmailLogging(LogSeverity min_severity,
+ const char* addresses) {
+ assert(min_severity >= 0 && min_severity < NUM_SEVERITIES);
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // all this stuff.
+ MutexLock l(&log_mutex);
+ LogDestination::email_logging_severity_ = min_severity;
+ LogDestination::addresses_ = addresses;
+}
+
+
+
+static void ColoredWriteToStderr(LogSeverity severity,
+ const char* message, size_t len) {
+ const GLogColor color =
+ (LogDestination::terminal_supports_color() && FLAGS_colorlogtostderr) ?
+ SeverityToColor(severity) : COLOR_DEFAULT;
+
+ // Avoid using cerr from this module since we may get called during
+ // exit code, and cerr may be partially or fully destroyed by then.
+ if (COLOR_DEFAULT == color) {
+ fwrite(message, len, 1, stdout);
+ return;
+ }
+#ifdef OS_WINDOWS
+ const HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+
+ // Gets the current text color.
+ CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+ GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);
+ const WORD old_color_attrs = buffer_info.wAttributes;
+
+ // We need to flush the stream buffers into the console before each
+ // SetConsoleTextAttribute call lest it affect the text that is already
+ // printed but has not yet reached the console.
+ //fflush(stdout);
+ SetConsoleTextAttribute(stderr_handle,
+ GetColorAttribute(color) | FOREGROUND_INTENSITY);
+ fwrite(message, len, 1, stdout);
+ //fflush(stdout);
+ // Restores the text color.
+ SetConsoleTextAttribute(stderr_handle, old_color_attrs);
+#else
+ fprintf(stdout, "\033[0;3%sm", GetAnsiColorCode(color));
+ fwrite(message, len, 1, stdout);
+ fprintf(stdout, "\033[m"); // Resets the terminal to default.
+#endif // OS_WINDOWS
+}
+
+static void WriteToStderr(const char* message, size_t len) {
+ // Avoid using cerr from this module since we may get called during
+ // exit code, and cerr may be partially or fully destroyed by then.
+ fwrite(message, len, 1, stdout);
+}
+
+
+
+inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
+ const char* message, size_t len) {
+ if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
+ ColoredWriteToStderr(severity, message, len);
+#ifdef OS_WINDOWS
+ // On Windows, also output to the debugger
+ ::OutputDebugStringA(string(message,len).c_str());
+#endif
+ }
+}
+
+
+inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
+ const char* message, size_t len) {
+ if (severity >= email_logging_severity_ ||
+ severity >= FLAGS_logemaillevel) {
+ string to(FLAGS_alsologtoemail);
+ if (!addresses_.empty()) {
+ if (!to.empty()) {
+ to += ",";
+ }
+ to += addresses_;
+ }
+ const string subject(string("[LOG] ") + LogSeverityNames[severity] + ": " +
+ glog_ns_internal_namespace_::ProgramInvocationShortName());
+ string body(hostname());
+ body += "\n\n";
+ body.append(message, len);
+
+ // should NOT use SendEmail(). The caller of this function holds the
+ // log_mutex and SendEmail() calls LOG/VLOG which will block trying to
+ // acquire the log_mutex object. Use SendEmailInternal() and set
+ // use_logging to false.
+ SendEmailInternal(to.c_str(), subject.c_str(), body.c_str(), false);
+ }
+}
+
+
+inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
+ time_t timestamp,
+ const char* message,
+ size_t len) {
+ const bool should_flush = severity > FLAGS_logbuflevel;
+ LogDestination* destination = log_destination(severity);
+ destination->logger_->Write(should_flush, timestamp, message, len);
+}
+
+
+
+inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
+ time_t timestamp,
+ const char* message,
+ size_t len) {
+
+ if ( FLAGS_logtostderr ) { // global flag: never log to file
+ ColoredWriteToStderr(severity, message, len);
+ } else {
+ // for (int i = severity; i >= 0; --i)
+ LogDestination::MaybeLogToLogfile(severity, timestamp, message, len);
+ }
+}
+
+inline void LogDestination::LogToSinks(LogSeverity severity,
+ const char *full_filename,
+ const char *base_filename,
+ int line,
+ const struct ::tm* tm_time,
+ const char* message,
+ size_t message_len) {
+ ReaderMutexLock l(&sink_mutex_);
+ if (sinks_) {
+ for (int i = sinks_->size() - 1; i >= 0; i--) {
+ (*sinks_)[i]->send(severity, full_filename, base_filename,
+ line, tm_time, message, message_len);
+ }
+ }
+}
+
+inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) {
+ ReaderMutexLock l(&sink_mutex_);
+ if (sinks_) {
+ for (int i = sinks_->size() - 1; i >= 0; i--) {
+ (*sinks_)[i]->WaitTillSent();
+ }
+ }
+ const bool send_to_sink =
+ (data->send_method_ == &LogMessage::SendToSink) ||
+ (data->send_method_ == &LogMessage::SendToSinkAndLog);
+ if (send_to_sink && data->sink_ != NULL) {
+ data->sink_->WaitTillSent();
+ }
+}
+/*lint +e695 */
+LogDestination* LogDestination::log_destinations_[NUM_SEVERITIES];
+
+inline LogDestination* LogDestination::log_destination(LogSeverity severity) {
+ assert(severity >=0 && severity < NUM_SEVERITIES);
+ if (!log_destinations_[severity]) {
+ log_destinations_[severity] = new LogDestination(severity, NULL);
+ }
+ return log_destinations_[severity];
+}
+
+void LogDestination::DeleteLogDestinations() {
+ for (int severity = 0; severity < NUM_SEVERITIES; ++severity) {
+ delete log_destinations_[severity];
+ log_destinations_[severity] = NULL;
+ }
+}
+
+namespace {
+
+LogFileObject::LogFileObject(LogSeverity severity,
+ const char* base_filename)
+ : base_filename_selected_(base_filename != NULL),
+ base_filename_((base_filename != NULL) ? base_filename : ""),
+ symlink_basename_(glog_ns_internal_namespace_::ProgramInvocationShortName()),
+ filename_extension_(),
+ whole_filename_(),
+ file_(NULL),
+ severity_(severity),
+ bytes_since_flush_(0),
+ file_length_(0),
+ rollover_attempt_(kRolloverAttemptFrequency-1),
+ next_flush_time_(0) {
+ assert(severity >= 0);
+ assert(severity < NUM_SEVERITIES);
+}
+
+LogFileObject::~LogFileObject() {
+ MutexLock l(&lock_);
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+}
+
+void LogFileObject::SetBasename(const char* basename) {
+ MutexLock l(&lock_);
+ base_filename_selected_ = true;
+ if (base_filename_ != basename) {
+ // Get rid of old log file since we are changing names
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ rollover_attempt_ = kRolloverAttemptFrequency-1;
+ }
+ base_filename_ = basename;
+ }
+}
+
+void LogFileObject::SetExtension(const char* ext) {
+ MutexLock l(&lock_);
+ if (filename_extension_ != ext) {
+ // Get rid of old log file since we are changing names
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ rollover_attempt_ = kRolloverAttemptFrequency-1;
+ }
+ filename_extension_ = ext;
+ }
+}
+
+void LogFileObject::SetSymlinkBasename(const char* symlink_basename) {
+ MutexLock l(&lock_);
+ symlink_basename_ = symlink_basename;
+}
+
+void LogFileObject::Flush() {
+ MutexLock l(&lock_);
+ FlushUnlocked();
+}
+
+void LogFileObject::FlushUnlocked(){
+ if (file_ != NULL) {
+ fflush(file_);
+ bytes_since_flush_ = 0;
+ }
+ // Figure out when we are due for another flush.
+ const int64 next = (FLAGS_logbufsecs
+ * static_cast<int64>(1000000)); // in usec
+ next_flush_time_ = CycleClock_Now() + UsecToCycles(next);
+}
+
+
+void LogFileObject::ReleaseObjectlock(){
+// release the file object lock lock_
+#if defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
+ lock_.ForceUnlock();
+#endif
+ return;
+}
+
+
+/*
+ 1. the writing log file don't has timestamp,no need input time string,
+ 2. the string_filename diff with running and operation file which
+ in one process;
+ 3. add a new member whole_filename_ which will use in Write;
+ 4. add the permission check for filename;
+ 5. fcntl will enter nstack api ,and no need check here, delete.*/
+
+bool LogFileObject::CreateLogfile( ) {
+/* string string_filename = base_filename_+filename_extension_+
+ time_pid_string; */
+ string string_filename = "";
+ uint32 last_file_len = 0;
+ /* segregate the dump info, Begin */
+ if(severity_ == GLOG_WARNING)
+ {
+ string_filename = base_filename_+"operation.log";
+ }
+ else if(severity_ == GLOG_ERROR)
+ {
+ string_filename = base_filename_+"nstack_error.log";
+ }
+ else
+ {
+ string_filename = base_filename_+filename_extension_;
+ }
+ /* End */
+ whole_filename_ = string_filename;
+ const char* filename = string_filename.c_str();
+
+ int fd = open(filename, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC , 0664);
+ if (fd == -1) return false;
+
+ //when restart the stack,it can add on same file unreach the Max log size.
+ if(0 == access(filename, W_OK))
+ {
+ last_file_len = get_file_size(fd);
+ file_length_ += last_file_len;
+ bytes_since_flush_ += last_file_len;
+ }
+
+#ifdef HAVE_FCNTL
+ // Mark the file close-on-exec. We don't really care if this fails
+ // fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+ file_ = fdopen(fd, "a"); // Make a FILE*.
+ if (file_ == NULL) { // Man, we're screwed!
+ close(fd);
+ unlink(filename); // Erase the half-baked evidence: an unusable log file
+ return false;
+ }
+
+ // We try to create a symlink called <program_name>.<severity>,
+ // which is easier to use. (Every time we create a new logfile,
+ // we destroy the old symlink and create a new one, so it always
+ // points to the latest logfile.) If it fails, we're sad but it's
+ // no error.
+ if (!symlink_basename_.empty()) {
+ // take directory from filename
+ const char* slash = strrchr(filename, PATH_SEPARATOR);
+ const string linkname =
+ symlink_basename_ + '.' + LogSeverityNames[severity_];
+ string linkpath;
+ if ( slash ) linkpath = string(filename, slash-filename+1); // get dirname
+ linkpath += linkname;
+ unlink(linkpath.c_str()); // delete old one if it exists
+
+#if defined(OS_WINDOWS)
+ // TODO(hamaji): Create lnk file on Windows?
+#elif defined(HAVE_UNISTD_H)
+ // We must have unistd.h.
+ // Make the symlink be relative (in the same dir) so that if the
+ // entire log directory gets relocated the link is still valid.
+ const char *linkdest = slash ? (slash + 1) : filename;
+ if (symlink(linkdest, linkpath.c_str()) != 0) {
+ // silently ignore failures
+ }
+
+ // Make an additional link to the log file in a place specified by
+ // FLAGS_log_link, if indicated
+ if (!FLAGS_log_link.empty()) {
+ linkpath = FLAGS_log_link + "/" + linkname;
+ unlink(linkpath.c_str()); // delete old one if it exists
+ if (symlink(filename, linkpath.c_str()) != 0) {
+ // silently ignore failures
+ }
+ }
+#endif
+ }
+
+ return true; // Everything worked
+}
+
+/*
+ 1. no need new pid use a new file writing log,
+ 2. add the modify_path_count,if log num exceed modify_path_count, remove old new;
+ 3. if log file exceed max_size or log file num , flues , bytes_since_flush_ = 1000000;
+ 4. remove the no useful fields in log file name;
+ 5. fcntl will enter nstack api ,and no need check here, delete.*/
+
+void LogFileObject::Write(bool force_flush,
+ time_t timestamp,
+ const char* message,
+ int message_len) {
+ MutexLock l(&lock_);
+
+ // We don't log if the base_name_ is "" (which means "don't write")
+ if (base_filename_selected_ && base_filename_.empty()) {
+ return;
+ }
+
+ if (static_cast<int>(file_length_ >> 20) >= MaxLogSize() ||
+ modify_path_count > 0){
+
+ int retVal = -1;
+ unsigned int same_file_count = 1;
+ char fileno[2];
+ struct ::tm postfix_time;
+
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ my_gmtime_r(&timestamp, &postfix_time);
+ }
+ else {
+ localtime_r(&timestamp, &postfix_time);
+ }
+
+
+ // The logfile's filename will have the date/time & pid in it
+ ostringstream time_stream;
+ time_stream.fill('0');
+ time_stream << 1900+postfix_time.tm_year
+ << setw(2) << 1+postfix_time.tm_mon
+ << setw(2) << postfix_time.tm_mday
+ << setw(2) << postfix_time.tm_hour
+ << setw(2) << postfix_time.tm_min
+ << setw(2) << postfix_time.tm_sec;
+ const string& time_string = time_stream.str();
+ string new_filename = whole_filename_+'.'+time_string;
+ string temp_filename = new_filename;
+
+ // rename file, incase same log file generate in one second
+ while ((same_file_count < log_file_count)
+ && (0 == access(new_filename.c_str(), W_OK)))
+ {
+ retVal = snprintf(fileno, sizeof(fileno), "%d",same_file_count);
+ if (-1 == retVal)
+ {
+ return;
+ }
+ new_filename = temp_filename+'.'+fileno;
+ same_file_count++;
+ }
+
+ (void)rename(whole_filename_.c_str(), new_filename.c_str());
+ (void)remove(whole_filename_.c_str());
+
+ // We're going to (potentially) try to put logs in several different dirs
+ const vector<string> & log_dirs = GetLoggingDirectories();
+
+ // Go through the list of dirs, and try to create the log file in each
+ // until we succeed or run out of options
+ for (vector<string>::const_iterator dir = log_dirs.begin();
+ dir != log_dirs.end();
+ ++dir) {
+ string log_path = *dir + "/";
+
+ (void)remove_old_file(log_path.c_str(), whole_filename_.c_str());
+ }
+
+ if (file_ != NULL) fclose(file_);
+ file_ = NULL;
+ file_length_ = 0;
+ //when backup or modify path, log recently.
+ bytes_since_flush_ = 1000000;
+ rollover_attempt_ = kRolloverAttemptFrequency-1;
+
+ if(modify_path_count > 0){
+
+ UpdateLoggingDirectories();
+ base_filename_.clear();
+ whole_filename_.clear();
+ modify_path_count = 0;
+ }
+
+ }
+
+ // If there's no destination file, make one before outputting
+ if (file_ == NULL) {
+ // Try to rollover the log file every 32 log messages. The only time
+ // this could matter would be when we have trouble creating the log
+ // file. If that happens, we'll lose lots of log messages, of course!
+ if (++rollover_attempt_ != kRolloverAttemptFrequency) return;
+ rollover_attempt_ = 0;
+
+ if (base_filename_selected_) {
+ if (!CreateLogfile()) {
+ perror("Could not create log file");
+ fprintf(stderr, "COULD NOT CREATE LOGFILE !\n");
+ return;
+ }
+ } else {
+ // If no base filename for logs of this severity has been set, use a
+ // default base filename of
+ // "<program name>.<hostname>.<user name>.log.<severity level>.". So
+ // logfiles will have names like
+ // webserver.examplehost.root.log.INFO.19990817-150000.4354, where
+ // 19990817 is a date (1999 August 17), 150000 is a time (15:00:00),
+ // and 4354 is the pid of the logging process. The date & time reflect
+ // when the file was created for output.
+ //
+ // Where does the file get put? Successively try the directories
+ // "/tmp", and "."
+ // We're going to (potentially) try to put logs in several different dirs
+ const vector<string> & log_dirs = GetLoggingDirectories();
+
+ // Go through the list of dirs, and try to create the log file in each
+ // until we succeed or run out of options
+ bool success = false;
+ for (vector<string>::const_iterator dir = log_dirs.begin();
+ dir != log_dirs.end();
+ ++dir) {
+
+ base_filename_ = *dir + "/";
+ if ( CreateLogfile() ) {
+ success = true;
+ break;
+ }
+ }
+ // If we never succeeded, we have to give up
+ if ( success == false ) {
+ perror("Could not create logging file");
+ fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE !");
+ return;
+ }
+ }
+
+ struct ::tm tm_time;
+
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ my_gmtime_r(&timestamp, &tm_time);
+ }
+ else {
+ localtime_r(&timestamp, &tm_time);
+ }
+
+
+ // Write a header message into the log file
+ ostringstream file_header_stream;
+ file_header_stream.fill('0');
+ file_header_stream << "Log file created at: "
+ << 1900+tm_time.tm_year << '/'
+ << setw(2) << 1+tm_time.tm_mon << '/'
+ << setw(2) << tm_time.tm_mday
+ << ' '
+ << setw(2) << tm_time.tm_hour << ':'
+ << setw(2) << tm_time.tm_min << ':'
+ << setw(2) << tm_time.tm_sec << '\n'
+ << "Running on machine: "
+ << LogDestination::hostname() << '\n'
+ << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
+ << "threadid file:line] msg" << '\n';
+ const string& file_header_string = file_header_stream.str();
+
+ const int header_len = file_header_string.size();
+ fwrite(file_header_string.data(), 1, header_len, file_);
+ file_length_ += header_len;
+ bytes_since_flush_ += header_len;
+ }
+
+ // Write to LOG file
+ if ( !stop_writing ) {
+ // fwrite() doesn't return an error when the disk is full, for
+ // messages that are less than 4096 bytes. When the disk is full,
+ // it returns the message length for messages that are less than
+ // 4096 bytes. fwrite() returns 4096 for message lengths that are
+ // greater than 4096, thereby indicating an error.
+ errno = 0;
+ fwrite(message, 1, message_len, file_);
+ if ( FLAGS_stop_logging_if_full_disk &&
+ errno == ENOSPC ) { // disk full, stop writing to disk
+ stop_writing = true; // until the disk is
+ return;
+ } else {
+ file_length_ += message_len;
+ bytes_since_flush_ += message_len;
+ }
+ } else {
+ if ( CycleClock_Now() >= next_flush_time_ )
+ stop_writing = false; // check to see if disk has free space.
+ return; // no need to flush
+ }
+
+ // See important msgs *now*. Also, flush logs at least every 10^6 chars,
+ // or every "FLAGS_logbufsecs" seconds.
+
+
+ if(force_flush) {
+ FlushUnlocked();
+
+#ifdef OS_LINUX
+ if (FLAGS_drop_log_memory) {
+ if (file_length_ >= logging::kPageSize) {
+ // don't evict the most recent page
+ uint32 len = file_length_ & ~(logging::kPageSize - 1);
+ posix_fadvise(fileno(file_), 0, len, POSIX_FADV_DONTNEED);
+ }
+ }
+#endif
+ }
+}
+
+} // namespace
+
+
+
+// Static log data space to avoid alloc failures in a LOG(FATAL)
+//
+// Since multiple threads may call LOG(FATAL), and we want to preserve
+// the data from the first call, we allocate two sets of space. One
+// for exclusive use by the first thread, and one for shared use by
+// all other threads.
+static CrashReason crash_reason;
+static bool fatal_msg_exclusive = true;
+static LogMessage::LogMessageData fatal_msg_data_exclusive;
+static LogMessage::LogMessageData fatal_msg_data_shared;
+
+LogMessage::LogMessageData::LogMessageData()
+ : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
+}
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
+ int ctr, void (LogMessage::*send_method)())
+ : allocated_(NULL) {
+ Init(file, line, severity, send_method);
+ data_->stream_.set_ctr(ctr);
+}
+
+LogMessage::LogMessage(const char* file, int line,
+ const CheckOpString& result)
+ : allocated_(NULL) {
+ Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
+ stream() << "Check failed: " << (*result.str_) << " ";
+}
+
+LogMessage::LogMessage(const char* file, int line)
+ : allocated_(NULL) {
+ Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
+}
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
+ : allocated_(NULL) {
+ Init(file, line, severity, &LogMessage::SendToLog);
+}
+
+
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity, int level)
+ : allocated_(NULL) {
+ Init(file, line, severity,level, &LogMessage::SendToLog);
+}
+
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
+ LogSink* sink, bool also_send_to_log)
+ : allocated_(NULL) {
+ Init(file, line, severity, also_send_to_log ? &LogMessage::SendToSinkAndLog :
+ &LogMessage::SendToSink);
+ data_->sink_ = sink; // override Init()'s setting to NULL
+}
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
+ vector<string> *outvec)
+ : allocated_(NULL) {
+ Init(file, line, severity, &LogMessage::SaveOrSendToLog);
+ data_->outvec_ = outvec; // override Init()'s setting to NULL
+}
+
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
+ string *message)
+ : allocated_(NULL) {
+ Init(file, line, severity, &LogMessage::WriteToStringAndLog);
+ data_->message_ = message; // override Init()'s setting to NULL
+}
+
+void LogMessage::Init(const char* file,
+ int line,
+ LogSeverity severity,
+ void (LogMessage::*send_method)()) {
+ allocated_ = NULL;
+ if (severity != GLOG_FATAL || !exit_on_dfatal) {
+ allocated_ = new LogMessageData();
+ data_ = allocated_;
+ data_->first_fatal_ = false;
+ } else {
+ MutexLock l(&fatal_msg_lock);
+ if (fatal_msg_exclusive) {
+ fatal_msg_exclusive = false;
+ data_ = &fatal_msg_data_exclusive;
+ data_->first_fatal_ = true;
+ } else {
+ data_ = &fatal_msg_data_shared;
+ data_->first_fatal_ = false;
+ }
+ }
+
+ stream().fill('0');
+ data_->preserved_errno_ = errno;
+ data_->severity_ = severity;
+ data_->line_ = line;
+ data_->send_method_ = send_method;
+ data_->sink_ = NULL;
+ data_->outvec_ = NULL;
+ WallTime now = WallTime_Now();
+ data_->timestamp_ = static_cast<time_t>(now);
+
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ my_gmtime_r(&data_->timestamp_, &data_->tm_time_);
+ }
+ else {
+ localtime_r(&data_->timestamp_, &data_->tm_time_);
+ }
+
+ int usecs = static_cast<int>((now - data_->timestamp_) * 1000000);
+ RawLog__SetLastTime(data_->tm_time_, usecs);
+
+ data_->num_chars_to_log_ = 0;
+ data_->num_chars_to_syslog_ = 0;
+ data_->basename_ = const_basename(file);
+ data_->fullname_ = file;
+ data_->has_been_flushed_ = false;
+
+ // If specified, prepend a prefix to each line. For example:
+ // I1018 160715 f5d4fbb0 logging.cc:1153]
+ // (log level, GMT month, date, time, thread_id, file basename, line)
+ // We exclude the thread_id for the default thread.
+ if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
+ stream() << LogSeverityNames[severity][0]
+ << setw(2) << 1+data_->tm_time_.tm_mon
+ << setw(2) << data_->tm_time_.tm_mday
+ << ' '
+ << setw(2) << data_->tm_time_.tm_hour << ':'
+ << setw(2) << data_->tm_time_.tm_min << ':'
+ << setw(2) << data_->tm_time_.tm_sec << "."
+ << setw(6) << usecs
+ << ' '
+ << setfill(' ') << setw(5)
+ << static_cast<unsigned int>(GetTID()) << setfill('0')
+ << ' '
+ << data_->basename_ << ':' << data_->line_ << "] ";
+ }
+ data_->num_prefix_chars_ = data_->stream_.pcount();
+
+ if (!FLAGS_log_backtrace_at.empty()) {
+ char fileline[128];
+ snprintf(fileline, sizeof(fileline), "%s:%d", data_->basename_, line);
+#ifdef HAVE_STACKTRACE
+ if (!strcmp(FLAGS_log_backtrace_at.c_str(), fileline)) {
+ string stacktrace;
+ DumpStackTraceToString(&stacktrace);
+ stream() << " (stacktrace:\n" << stacktrace << ") ";
+ }
+#endif
+ }
+}
+
+
+
+void LogMessage::Init(const char* file,
+ int line,
+ LogSeverity severity,
+ int level,
+ void (LogMessage::*send_method)()) {
+ allocated_ = NULL;
+ if (severity != GLOG_FATAL || !exit_on_dfatal) {
+ allocated_ = new LogMessageData();
+ data_ = allocated_;
+ data_->first_fatal_ = false;
+ } else {
+ MutexLock l(&fatal_msg_lock);
+ if (fatal_msg_exclusive) {
+ fatal_msg_exclusive = false;
+ data_ = &fatal_msg_data_exclusive;
+ data_->first_fatal_ = true;
+ } else {
+ data_ = &fatal_msg_data_shared;
+ data_->first_fatal_ = false;
+ }
+ }
+
+ stream().fill('0');
+ data_->preserved_errno_ = errno;
+ data_->severity_ = severity;
+ data_->level_ = level;
+ data_->line_ = line;
+ data_->send_method_ = send_method;
+ data_->sink_ = NULL;
+ data_->outvec_ = NULL;
+ WallTime now = WallTime_Now();
+ data_->timestamp_ = static_cast<time_t>(now);
+
+ if (glogCtrlOpt == USE_USR_GM_TIME) {
+ my_gmtime_r(&data_->timestamp_, &data_->tm_time_);
+ }
+ else {
+ localtime_r(&data_->timestamp_, &data_->tm_time_);
+ }
+
+ int usecs = static_cast<int>((now - data_->timestamp_) * 1000000);
+ RawLog__SetLastTime(data_->tm_time_, usecs);
+
+ data_->num_chars_to_log_ = 0;
+ data_->num_chars_to_syslog_ = 0;
+ data_->basename_ = const_basename(file);
+ data_->fullname_ = file;
+ data_->has_been_flushed_ = false;
+
+
+ if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
+ stream() << nstack_level_names[level][0]
+ << setw(2) << 1+data_->tm_time_.tm_mon
+ << setw(2) << data_->tm_time_.tm_mday
+ << ' '
+ << setw(2) << data_->tm_time_.tm_hour << ':'
+ << setw(2) << data_->tm_time_.tm_min << ':'
+ << setw(2) << data_->tm_time_.tm_sec << "."
+ << setw(6) << usecs
+ << ' '
+ << setfill(' ') << setw(5)
+ << static_cast<unsigned int>(GetTID()) << setfill('0')
+ << ' '
+ << data_->basename_ << ':' << data_->line_ << "] ";
+ }
+ data_->num_prefix_chars_ = data_->stream_.pcount();
+
+ if (!FLAGS_log_backtrace_at.empty()) {
+ char fileline[128];
+ snprintf(fileline, sizeof(fileline), "%s:%d", data_->basename_, line);
+#ifdef HAVE_STACKTRACE
+ if (!strcmp(FLAGS_log_backtrace_at.c_str(), fileline)) {
+ string stacktrace;
+ DumpStackTraceToString(&stacktrace);
+ stream() << " (stacktrace:\n" << stacktrace << ") ";
+ }
+#endif
+ }
+}
+
+
+LogMessage::~LogMessage() {
+ Flush();
+ delete allocated_;
+}
+
+int LogMessage::preserved_errno() const {
+ return data_->preserved_errno_;
+}
+
+ostream& LogMessage::stream() {
+
+ return data_->stream_;
+
+}
+
+// Flush buffered message, called by the destructor, or any other function
+// that needs to synchronize the log.
+void LogMessage::Flush() {
+ if (data_->has_been_flushed_ || data_->severity_ < FLAGS_minloglevel)
+ return;
+
+ data_->num_chars_to_log_ = data_->stream_.pcount();
+ data_->num_chars_to_syslog_ =
+ data_->num_chars_to_log_ - data_->num_prefix_chars_;
+
+ // Do we need to add a \n to the end of this message?
+ bool append_newline =
+ (data_->message_text_[data_->num_chars_to_log_-1] != '\n');
+ char original_final_char = '\0';
+
+ // If we do need to add a \n, we'll do it by violating the memory of the
+ // ostrstream buffer. This is quick, and we'll make sure to undo our
+ // modification before anything else is done with the ostrstream. It
+ // would be preferable not to do things this way, but it seems to be
+ // the best way to deal with this.
+ if (append_newline) {
+ original_final_char = data_->message_text_[data_->num_chars_to_log_];
+ data_->message_text_[data_->num_chars_to_log_++] = '\n';
+ }
+
+ // Prevent any subtle race conditions by wrapping a mutex lock around
+ // the actual logging action per se.
+ {
+ MutexLock l(&log_mutex);
+ (this->*(data_->send_method_))();
+
+ ++num_messages_[static_cast<int>(data_->severity_)];
+
+ }
+ LogDestination::WaitForSinks(data_);
+
+ if (append_newline) {
+ // Fix the ostrstream back how it was before we screwed with it.
+ // It's 99.44% certain that we don't need to worry about doing this.
+ data_->message_text_[data_->num_chars_to_log_-1] = original_final_char;
+ }
+
+ // If errno was already set before we enter the logging call, we'll
+ // set it back to that value when we return from the logging call.
+ // It happens often that we log an error message after a syscall
+ // failure, which can potentially set the errno to some other
+ // values. We would like to preserve the original errno.
+ if (data_->preserved_errno_ != 0) {
+ errno = data_->preserved_errno_;
+ }
+
+ // Note that this message is now safely logged. If we're asked to flush
+ // again, as a result of destruction, say, we'll do nothing on future calls.
+ data_->has_been_flushed_ = true;
+}
+
+// Copy of first FATAL log message so that we can print it out again
+// after all the stack traces. To preserve legacy behavior, we don't
+// use fatal_msg_data_exclusive.
+static time_t fatal_time;
+static char fatal_message[256];
+
+void ReprintFatalMessage() {
+ if (fatal_message[0]) {
+ const int n = strlen(fatal_message);
+ if (!FLAGS_logtostderr) {
+ // Also write to stderr (don't color to avoid terminal checks)
+ WriteToStderr(fatal_message, n);
+ }
+ LogDestination::LogToAllLogfiles(GLOG_ERROR, fatal_time, fatal_message, n);
+ }
+}
+
+// L >= log_mutex (callers must hold the log_mutex).
+void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
+ static bool already_warned_before_initgoogle = false;
+
+ log_mutex.AssertHeld();
+
+ RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
+ data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
+
+ // Messages of a given severity get logged to lower severity logs, too
+
+ if (!already_warned_before_initgoogle && !IsGoogleLoggingInitialized()) {
+ const char w[] = "WARNING: Logging before InitGoogleLogging() is "
+ "written to STDERR\n";
+ WriteToStderr(w, strlen(w));
+ already_warned_before_initgoogle = true;
+ }
+
+ // global flag: never log to file if set. Also -- don't log to a
+ // file if we haven't parsed the command line flags to get the
+ // program name.
+ if (FLAGS_logtostderr || !IsGoogleLoggingInitialized()) {
+ ColoredWriteToStderr(data_->severity_,
+ data_->message_text_, data_->num_chars_to_log_);
+
+ // this could be protected by a flag if necessary.
+ LogDestination::LogToSinks(data_->severity_,
+ data_->fullname_, data_->basename_,
+ data_->line_, &data_->tm_time_,
+ data_->message_text_ + data_->num_prefix_chars_,
+ (data_->num_chars_to_log_ -
+ data_->num_prefix_chars_ - 1));
+ } else {
+
+ // log this message to all log files of severity <= severity_
+ LogDestination::LogToAllLogfiles(data_->severity_, data_->timestamp_,
+ data_->message_text_,
+ data_->num_chars_to_log_);
+
+ LogDestination::MaybeLogToStderr(data_->severity_, data_->message_text_,
+ data_->num_chars_to_log_);
+ LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_,
+ data_->num_chars_to_log_);
+ LogDestination::LogToSinks(data_->severity_,
+ data_->fullname_, data_->basename_,
+ data_->line_, &data_->tm_time_,
+ data_->message_text_ + data_->num_prefix_chars_,
+ (data_->num_chars_to_log_
+ - data_->num_prefix_chars_ - 1));
+ // NOTE: -1 removes trailing \n
+ }
+
+ // If we log a FATAL message, flush all the log destinations, then toss
+ // a signal for others to catch. We leave the logs in a state that
+ // someone else can use them (as long as they flush afterwards)
+ if (data_->severity_ == GLOG_FATAL && exit_on_dfatal) {
+ if (data_->first_fatal_) {
+ // Store crash information so that it is accessible from within signal
+ // handlers that may be invoked later.
+ RecordCrashReason(&crash_reason);
+ SetCrashReason(&crash_reason);
+
+ // Store shortened fatal message for other logs and GWQ status
+ const int copy = min<int>(data_->num_chars_to_log_,
+ sizeof(fatal_message)-1);
+ memcpy(fatal_message, data_->message_text_, copy);
+ fatal_message[copy] = '\0';
+ fatal_time = data_->timestamp_;
+ }
+
+ if (!FLAGS_logtostderr) {
+ for (int i = 0; i < NUM_SEVERITIES; ++i) {
+ if ( LogDestination::log_destinations_[i] )
+ LogDestination::log_destinations_[i]->logger_->Write(true, 0, "", 0);
+ }
+ }
+
+ // release the lock that our caller (directly or indirectly)
+ // LogMessage::~LogMessage() grabbed so that signal handlers
+ // can use the logging facility. Alternately, we could add
+ // an entire unsafe logging interface to bypass locking
+ // for signal handlers but this seems simpler.
+ log_mutex.Unlock();
+ LogDestination::WaitForSinks(data_);
+
+ // no need to print this message. by CAD/LSK request
+#if 0
+ const char* message = "*** Check failure stack trace: ***\n";
+ if (write(STDERR_FILENO, message, strlen(message)) < 0) {
+ // Ignore errors.
+ }
+#endif
+
+ Fail();
+ }
+}
+
+void LogMessage::RecordCrashReason(
+ glog_ns_internal_namespace_::CrashReason* reason) {
+ reason->filename = fatal_msg_data_exclusive.fullname_;
+ reason->line_number = fatal_msg_data_exclusive.line_;
+ reason->message = fatal_msg_data_exclusive.message_text_ +
+ fatal_msg_data_exclusive.num_prefix_chars_;
+#ifdef HAVE_STACKTRACE
+ // Retrieve the stack trace, omitting the logging frames that got us here.
+ reason->depth = GetStackTrace(reason->stack, ARRAYSIZE(reason->stack), 4);
+#else
+ reason->depth = 0;
+#endif
+}
+
+#ifdef HAVE___ATTRIBUTE__
+# define ATTRIBUTE_NORETURN __attribute__((noreturn))
+#else
+# define ATTRIBUTE_NORETURN
+#endif
+
+static void logging_fail() ATTRIBUTE_NORETURN;
+
+static void logging_fail() {
+#if defined(_DEBUG) && defined(_MSC_VER)
+ // When debugging on windows, avoid the obnoxious dialog and make
+ // it possible to continue past a LOG(FATAL) in the debugger
+ _asm int 3
+#else
+ abort();
+#endif
+}
+
+typedef void (*logging_fail_func_t)() ATTRIBUTE_NORETURN;
+
+GOOGLE_GLOG_DLL_DECL
+logging_fail_func_t g_logging_fail_func = &logging_fail;
+
+void InstallFailureFunction(void (*fail_func)()) {
+ g_logging_fail_func = (logging_fail_func_t)fail_func;
+}
+
+void LogMessage::Fail() {
+ g_logging_fail_func();
+}
+
+// L >= log_mutex (callers must hold the log_mutex).
+void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
+ if (data_->sink_ != NULL) {
+ RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
+ data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
+ data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_,
+ data_->line_, &data_->tm_time_,
+ data_->message_text_ + data_->num_prefix_chars_,
+ (data_->num_chars_to_log_ -
+ data_->num_prefix_chars_ - 1));
+ }
+}
+
+// L >= log_mutex (callers must hold the log_mutex).
+void LogMessage::SendToSinkAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
+ SendToSink();
+ SendToLog();
+}
+
+// L >= log_mutex (callers must hold the log_mutex).
+void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
+ if (data_->outvec_ != NULL) {
+ RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
+ data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
+ // Omit prefix of message and trailing newline when recording in outvec_.
+ const char *start = data_->message_text_ + data_->num_prefix_chars_;
+ int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
+ data_->outvec_->push_back(string(start, len));
+ } else {
+ SendToLog();
+ }
+}
+
+void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
+ if (data_->message_ != NULL) {
+ RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
+ data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
+ // Omit prefix of message and trailing newline when writing to message_.
+ const char *start = data_->message_text_ + data_->num_prefix_chars_;
+ int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
+ data_->message_->assign(start, len);
+ }
+ SendToLog();
+}
+
+// L >= log_mutex (callers must hold the log_mutex).
+void LogMessage::SendToSyslogAndLog() {
+#ifdef HAVE_SYSLOG_H
+ // Before any calls to syslog(), make a single call to openlog()
+ static bool openlog_already_called = false;
+ if (!openlog_already_called) {
+ openlog(glog_ns_internal_namespace_::ProgramInvocationShortName(),
+ LOG_CONS | LOG_NDELAY | LOG_PID,
+ LOG_USER);
+ openlog_already_called = true;
+ }
+
+ // This array maps Google severity levels to syslog levels
+ const int SEVERITY_TO_LEVEL[] = { LOG_INFO, LOG_WARNING, LOG_ERR, LOG_EMERG };
+ syslog(LOG_USER | SEVERITY_TO_LEVEL[static_cast<int>(data_->severity_)], "%.*s",
+ int(data_->num_chars_to_syslog_),
+ data_->message_text_ + data_->num_prefix_chars_);
+ SendToLog();
+#else
+ LOG(ERROR) << "No syslog support: message=" << data_->message_text_;
+#endif
+}
+
+base_ns::Logger* base_ns::GetLogger(LogSeverity severity) {
+ MutexLock l(&log_mutex);
+ return LogDestination::log_destination(severity)->logger_;
+}
+
+void base_ns::SetLogger(LogSeverity severity, base_ns::Logger* logger) {
+ MutexLock l(&log_mutex);
+ LogDestination::log_destination(severity)->logger_ = logger;
+}
+
+// L < log_mutex. Acquires and releases mutex_.
+int64 LogMessage::num_messages(int severity) {
+ MutexLock l(&log_mutex);
+ return num_messages_[severity];
+}
+
+// Output the COUNTER value. This is only valid if ostream is a
+// LogStream.
+ostream& operator<<(ostream &os, const PRIVATE_Counter&) {
+#ifdef DISABLE_RTTI
+ LogMessage::LogStream *log = static_cast<LogMessage::LogStream*>(&os);
+#else
+ LogMessage::LogStream *log = dynamic_cast<LogMessage::LogStream*>(&os);
+#endif
+ CHECK(log && log == log->self())
+ << "You must not use COUNTER with non-glog ostream";
+ os << log->ctr();
+ return os;
+}
+
+ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
+ LogSeverity severity, int ctr,
+ void (LogMessage::*send_method)())
+ : LogMessage(file, line, severity, ctr, send_method) {
+}
+
+ErrnoLogMessage::~ErrnoLogMessage() {
+ // Don't access errno directly because it may have been altered
+ // while streaming the message.
+ stream() << ": " << StrError(preserved_errno()) << " ["
+ << preserved_errno() << "]";
+}
+
+
+void FlushLogFiles(LogSeverity min_severity) {
+ LogDestination::FlushLogFiles(min_severity);
+}
+
+void FlushLogFilesUnsafe(LogSeverity min_severity) {
+ LogDestination::FlushLogFilesUnsafe(min_severity);
+}
+
+
+void RleaseLogSinkLock(LogSeverity min_severity) {
+ LogDestination::RleaseLogSinkLock(min_severity);
+}
+
+void SetLogDestination(LogSeverity severity, const char* base_filename) {
+ LogDestination::SetLogDestination(severity, base_filename);
+}
+
+void SetLogSymlink(LogSeverity severity, const char* symlink_basename) {
+ LogDestination::SetLogSymlink(severity, symlink_basename);
+}
+
+LogSink::~LogSink() {
+}
+
+void LogSink::WaitTillSent() {
+ // noop default
+}
+
+string LogSink::ToString(LogSeverity severity, const char* file, int line,
+ const struct ::tm* tm_time,
+ const char* message, size_t message_len) {
+ ostringstream stream(string(message, message_len));
+ stream.fill('0');
+
+ // FIXME(jrvb): Updating this to use the correct value for usecs
+ // requires changing the signature for both this method and
+ // LogSink::send(). This change needs to be done in a separate CL
+ // so subclasses of LogSink can be updated at the same time.
+ int usecs = 0;
+
+ stream << LogSeverityNames[severity][0]
+ << setw(2) << 1+tm_time->tm_mon
+ << setw(2) << tm_time->tm_mday
+ << ' '
+ << setw(2) << tm_time->tm_hour << ':'
+ << setw(2) << tm_time->tm_min << ':'
+ << setw(2) << tm_time->tm_sec << '.'
+ << setw(6) << usecs
+ << ' '
+ << setfill(' ') << setw(5) << GetTID() << setfill('0')
+ << ' '
+ << file << ':' << line << "] ";
+
+ stream << string(message, message_len);
+ return stream.str();
+}
+
+void AddLogSink(LogSink *destination) {
+ LogDestination::AddLogSink(destination);
+}
+
+void RemoveLogSink(LogSink *destination) {
+ LogDestination::RemoveLogSink(destination);
+}
+
+void SetLogFilenameExtension(const char* ext) {
+ LogDestination::SetLogFilenameExtension(ext);
+}
+
+void SetStderrLogging(LogSeverity min_severity) {
+ LogDestination::SetStderrLogging(min_severity);
+}
+
+void SetEmailLogging(LogSeverity min_severity, const char* addresses) {
+ LogDestination::SetEmailLogging(min_severity, addresses);
+}
+
+void LogToStderr() {
+ LogDestination::LogToStderr();
+}
+
+namespace base_ns {
+namespace internal_ns {
+
+bool GetExitOnDFatal() {
+ MutexLock l(&log_mutex);
+ return exit_on_dfatal;
+}
+
+// Determines whether we exit the program for a LOG(DFATAL) message in
+// debug mode. It does this by skipping the call to Fail/FailQuietly.
+// This is intended for testing only.
+//
+// This can have some effects on LOG(FATAL) as well. Failure messages
+// are always allocated (rather than sharing a buffer), the crash
+// reason is not recorded, the "gwq" status message is not updated,
+// and the stack trace is not recorded. The LOG(FATAL) *will* still
+// exit the program. Since this function is used only in testing,
+// these differences are acceptable.
+void SetExitOnDFatal(bool value) {
+ MutexLock l(&log_mutex);
+ exit_on_dfatal = value;
+}
+
+} // namespace internal_ns
+} // namespace base_ns
+
+// use_logging controls whether the logging functions LOG/VLOG are used
+// to log errors. It should be set to false when the caller holds the
+// log_mutex.
+static bool SendEmailInternal(const char*dest, const char *subject,
+ const char*body, bool use_logging) {
+ if (dest && *dest) {
+ if ( use_logging ) {
+ VLOG(1) << "Trying to send TITLE:" << subject
+ << " BODY:" << body << " to " << dest;
+ } else {
+ fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n",
+ subject, body, dest);
+ }
+
+ string cmd =
+ FLAGS_logmailer + " -s\"" + subject + "\" " + dest;
+ FILE* pipe = popen(cmd.c_str(), "w");
+ if (pipe != NULL) {
+ // Add the body if we have one
+ if (body)
+ fwrite(body, sizeof(char), strlen(body), pipe);
+ bool ok = pclose(pipe) != -1;
+ if ( !ok ) {
+ if ( use_logging ) {
+ LOG(ERROR) << "Problems sending mail to " << dest << ": "
+ << StrError(errno);
+ } else {
+ fprintf(stderr, "Problems sending mail to %s: %s\n",
+ dest, StrError(errno).c_str());
+ }
+ }
+ return ok;
+ } else {
+ if ( use_logging ) {
+ LOG(ERROR) << "Unable to send mail to " << dest;
+ } else {
+ fprintf(stderr, "Unable to send mail to %s\n", dest);
+ }
+ }
+ }
+ return false;
+}
+
+bool SendEmail(const char*dest, const char *subject, const char*body){
+ return SendEmailInternal(dest, subject, body, true);
+}
+
+static void GetTempDirectories(vector<string>* list) {
+ list->clear();
+#ifdef OS_WINDOWS
+ // On windows we'll try to find a directory in this order:
+ // C:/Documents & Settings/whomever/TEMP (or whatever GetTempPath() is)
+ // C:/TMP/
+ // C:/TEMP/
+ // C:/WINDOWS/ or C:/WINNT/
+ // .
+ char tmp[MAX_PATH];
+ if (GetTempPathA(MAX_PATH, tmp))
+ list->push_back(tmp);
+ list->push_back("C:\\tmp\\");
+ list->push_back("C:\\temp\\");
+#else
+ // Directories, in order of preference. If we find a dir that
+ // exists, we stop adding other less-preferred dirs
+ const char * candidates[] = {
+ // Non-null only during unittest/regtest
+ getenv("TEST_TMPDIR"),
+
+ // Explicitly-supplied temp dirs
+ getenv("TMPDIR"), getenv("TMP"),
+
+ // If all else fails
+ "/tmp",
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE(candidates); i++) {
+ const char *d = candidates[i];
+ if (!d) continue; // Empty env var
+
+ // Make sure we don't surprise anyone who's expecting a '/'
+ string dstr = d;
+ if (dstr[dstr.size() - 1] != '/') {
+ dstr += "/";
+ }
+ list->push_back(dstr);
+
+ struct stat statbuf;
+ if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode)) {
+ // We found a dir that exists - we're done.
+ return;
+ }
+ }
+
+#endif
+}
+
+
+static vector<string>* logging_directories_list;
+
+
+const vector<string>& GetLoggingDirectories() {
+ // Not strictly thread-safe but we're called early in InitGoogle().
+ if (logging_directories_list == NULL) {
+ logging_directories_list = new vector<string>;
+
+ if ( !FLAGS_log_dir.empty() ) {
+ // A dir was specified, we should use it
+ logging_directories_list->push_back(FLAGS_log_dir.c_str());
+ } else {
+ GetTempDirectories(logging_directories_list);
+#ifdef OS_WINDOWS
+ char tmp[MAX_PATH];
+ if (GetWindowsDirectoryA(tmp, MAX_PATH))
+ logging_directories_list->push_back(tmp);
+ logging_directories_list->push_back(".\\");
+#else
+ logging_directories_list->push_back("./");
+#endif
+ }
+ }
+ return *logging_directories_list;
+}
+
+/*****************************************************************************
+* Prototype : UpdateLoggingDirectories
+* Description : modify the log directories,
+* Input : NA
+* Output : NA
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void UpdateLoggingDirectories() {
+ if (NULL != logging_directories_list && !FLAGS_log_dir.empty()) {
+ vector<string>::iterator dir = logging_directories_list->begin();
+ while(dir != logging_directories_list->end()){
+ dir = logging_directories_list->erase(dir);
+ }
+
+ logging_directories_list->push_back(FLAGS_log_dir.c_str());
+ }
+ return;
+}
+
+
+void TestOnly_ClearLoggingDirectoriesList() {
+ fprintf(stderr, "TestOnly_ClearLoggingDirectoriesList should only be "
+ "called from test code.\n");
+ delete logging_directories_list;
+ logging_directories_list = NULL;
+}
+
+void GetExistingTempDirectories(vector<string>* list) {
+ GetTempDirectories(list);
+ vector<string>::iterator i_dir = list->begin();
+ while( i_dir != list->end() ) {
+ // zero arg to access means test for existence; no constant
+ // defined on windows
+ if ( access(i_dir->c_str(), 0) ) {
+ i_dir = list->erase(i_dir);
+ } else {
+ ++i_dir;
+ }
+ }
+}
+
+void TruncateLogFile(const char *path, int64 limit, int64 keep) {
+#ifdef HAVE_UNISTD_H
+ struct stat statbuf;
+ const int kCopyBlockSize = 8 << 10;
+ char copybuf[kCopyBlockSize];
+ int64 read_offset, write_offset;
+ // Don't follow symlinks unless they're our own fd symlinks in /proc
+ int flags = O_RDWR;
+ // TODO(hamaji): Support other environments.
+#ifdef OS_LINUX
+ const char *procfd_prefix = "/proc/self/fd/";
+ if (strncmp(procfd_prefix, path, strlen(procfd_prefix))) flags |= O_NOFOLLOW;
+#endif
+
+ int fd = open(path, flags);
+ if (fd == -1) {
+ if (errno == EFBIG) {
+ // The log file in question has got too big for us to open. The
+ // real fix for this would be to compile logging.cc (or probably
+ // all of base/...) with -D_FILE_OFFSET_BITS=64 but that's
+ // rather scary.
+ // Instead just truncate the file to something we can manage
+ if (truncate(path, 0) == -1) {
+ PLOG(ERROR) << "Unable to truncate " << path;
+ } else {
+ LOG(ERROR) << "Truncated " << path << " due to EFBIG error";
+ }
+ } else {
+ PLOG(ERROR) << "Unable to open " << path;
+ }
+ return;
+ }
+
+ if (fstat(fd, &statbuf) == -1) {
+ PLOG(ERROR) << "Unable to fstat()";
+ goto out_close_fd;
+ }
+
+ // See if the path refers to a regular file bigger than the
+ // specified limit
+ if (!S_ISREG(statbuf.st_mode)) goto out_close_fd;
+ if (statbuf.st_size <= limit) goto out_close_fd;
+ if (statbuf.st_size <= keep) goto out_close_fd;
+
+ // This log file is too large - we need to truncate it
+ LOG(INFO) << "Truncating " << path << " to " << keep << " bytes";
+
+ // Copy the last "keep" bytes of the file to the beginning of the file
+ read_offset = statbuf.st_size - keep;
+ write_offset = 0;
+ int bytesin, bytesout;
+ while ((bytesin = pread(fd, copybuf, sizeof(copybuf), read_offset)) > 0) {
+ bytesout = pwrite(fd, copybuf, bytesin, write_offset);
+ if (bytesout == -1) {
+ PLOG(ERROR) << "Unable to write to " << path;
+ break;
+ } else if (bytesout != bytesin) {
+ LOG(ERROR) << "Expected to write " << bytesin << ", wrote " << bytesout;
+ }
+ read_offset += bytesin;
+ write_offset += bytesout;
+ }
+ if (bytesin == -1) PLOG(ERROR) << "Unable to read from " << path;
+
+ // Truncate the remainder of the file. If someone else writes to the
+ // end of the file after our last read() above, we lose their latest
+ // data. Too bad ...
+ if (ftruncate(fd, write_offset) == -1) {
+ PLOG(ERROR) << "Unable to truncate " << path;
+ }
+
+ out_close_fd:
+ close(fd);
+#else
+ LOG(ERROR) << "No log truncation support.";
+#endif
+}
+
+void TruncateStdoutStderr() {
+#ifdef HAVE_UNISTD_H
+ int64 limit = MaxLogSize() << 20;
+ int64 keep = 1 << 20;
+ TruncateLogFile("/proc/self/fd/1", limit, keep);
+ TruncateLogFile("/proc/self/fd/2", limit, keep);
+#else
+ LOG(ERROR) << "No log truncation support.";
+#endif
+}
+
+
+// Helper functions for string comparisons.
+#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
+ string* Check##func##expected##Impl(const char* s1, const char* s2, \
+ const char* names) { \
+ bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
+ if (equal == expected) return NULL; \
+ else { \
+ ostringstream ss; \
+ if (!s1) s1 = ""; \
+ if (!s2) s2 = ""; \
+ ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
+ return new string(ss.str()); \
+ } \
+ }
+DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
+#undef DEFINE_CHECK_STROP_IMPL
+
+int posix_strerror_r(int err, char *buf, size_t len) {
+ // Sanity check input parameters
+ if (buf == NULL || len <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Reset buf and errno, and try calling whatever version of strerror_r()
+ // is implemented by glibc
+ buf[0] = '\000';
+ int old_errno = errno;
+ errno = 0;
+ char *rc = reinterpret_cast<char *>(strerror_r(err, buf, len));
+
+ // Both versions set errno on failure
+ if (errno) {
+ // Should already be there, but better safe than sorry
+ buf[0] = '\000';
+ return -1;
+ }
+ errno = old_errno;
+
+ // POSIX is vague about whether the string will be terminated, although
+ // is indirectly implies that typically ERANGE will be returned, instead
+ // of truncating the string. This is different from the GNU implementation.
+ // We play it safe by always terminating the string explicitly.
+ buf[len-1] = '\000';
+
+ // If the function succeeded, we can use its exit code to determine the
+ // semantics implemented by glibc
+ if (!rc) {
+ return 0;
+ } else {
+ // GNU semantics detected
+ if (rc == buf) {
+ return 0;
+ } else {
+ buf[0] = '\000';
+#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+ if (reinterpret_cast<intptr_t>(rc) < sys_nerr) {
+ // This means an error on MacOSX or FreeBSD.
+ return -1;
+ }
+#endif
+ strncat(buf, rc, len-1);
+ return 0;
+ }
+ }
+}
+
+string StrError(int err) {
+ char buf[100];
+ int rc = posix_strerror_r(err, buf, sizeof(buf));
+ if ((rc < 0) || (buf[0] == '\000')) {
+ snprintf(buf, sizeof(buf), "Error number %d", err);
+ }
+ return buf;
+}
+
+LogMessageFatal::LogMessageFatal(const char* file, int line) :
+ LogMessage(file, line, GLOG_FATAL) {}
+
+LogMessageFatal::LogMessageFatal(const char* file, int line,
+ const CheckOpString& result) :
+ LogMessage(file, line, result) {}
+
+LogMessageFatal::~LogMessageFatal() {
+ Flush();
+ LogMessage::Fail();
+}
+
+namespace base_ns {
+
+CheckOpMessageBuilder::CheckOpMessageBuilder(const char *exprtext)
+ : stream_(new ostringstream) {
+ *stream_ << exprtext << " (";
+}
+
+CheckOpMessageBuilder::~CheckOpMessageBuilder() {
+ delete stream_;
+}
+
+ostream* CheckOpMessageBuilder::ForVar2() {
+ *stream_ << " vs. ";
+ return stream_;
+}
+
+string* CheckOpMessageBuilder::NewString() {
+ *stream_ << ")";
+ return new string(stream_->str());
+}
+
+} // namespace base_ns
+
+template <>
+void MakeCheckOpValueString(std::ostream* os, const char& v) {
+ if (v >= 32 && v <= 126) {
+ (*os) << "'" << v << "'";
+ } else {
+ (*os) << "char value " << (short)v;
+ }
+}
+
+template <>
+void MakeCheckOpValueString(std::ostream* os, const signed char& v) {
+ if (v >= 32 && v <= 126) {
+ (*os) << "'" << v << "'";
+ } else {
+ (*os) << "signed char value " << (short)v;
+ }
+}
+
+template <>
+void MakeCheckOpValueString(std::ostream* os, const unsigned char& v) {
+ if (v >= 32 && v <= 126) {
+ (*os) << "'" << v << "'";
+ } else {
+ (*os) << "unsigned char value " << (unsigned short)v;
+ }
+}
+
+
+
+void InitGoogleLogging(const char* argv0) {
+ // Add: Protect to repeat init glog
+ if (glog_ns_internal_namespace_::IsGoogleLoggingInitialized()) {
+ LOG(ERROR) << "You init GLOG twice!";
+ return;
+ }
+ // End: Protect to repeat init glog
+ glog_ns_internal_namespace_::InitGoogleLoggingUtilities(argv0);
+}
+
+void ShutdownGoogleLogging() {
+ // Add: Protect to shutdown twice
+ if (!glog_ns_internal_namespace_::IsGoogleLoggingInitialized()) {
+ LOG(ERROR) << "Without initing GLOG, please init first!";
+ return;
+ }
+ // End: Protect to shutdown twice
+ glog_ns_internal_namespace_::ShutdownGoogleLoggingUtilities();
+ LogDestination::DeleteLogDestinations();
+ delete logging_directories_list;
+ logging_directories_list = NULL;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_striplog_test.sh b/thirdparty/glog/glog-0.3.4/src/logging_striplog_test.sh
new file mode 100644
index 0000000..73492bd
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_striplog_test.sh
@@ -0,0 +1,79 @@
+#! /bin/sh
+#
+# Copyright (c) 2007, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: Sergey Ioffe
+
+get_strings () {
+ if test -e ".libs/$1"; then
+ binary=".libs/$1"
+ elif test -e "$1.exe"; then
+ binary="$1.exe"
+ else
+ echo "We coundn't find $1 binary."
+ exit 1
+ fi
+
+ strings -n 10 $binary | sort | awk '/TESTMESSAGE/ {printf "%s ", $2}'
+}
+
+# Die if "$1" != "$2", print $3 as death reason
+check_eq () {
+ if [ "$1" != "$2" ]; then
+ echo "Check failed: '$1' == '$2' ${3:+ ($3)}"
+ exit 1
+ fi
+}
+
+die () {
+ echo $1
+ exit 1
+}
+
+# Check that the string literals are appropriately stripped. This will
+# not be the case in debug mode.
+
+mode=`GLOG_check_mode=1 ./logging_striptest0 2> /dev/null`
+if [ "$mode" = "opt" ];
+then
+ echo "In OPT mode"
+ check_eq "`get_strings logging_striptest0`" "COND ERROR FATAL INFO USAGE WARNING "
+ check_eq "`get_strings logging_striptest2`" "COND ERROR FATAL USAGE "
+ check_eq "`get_strings logging_striptest10`" ""
+else
+ echo "In DBG mode; not checking strings"
+fi
+
+# Check that LOG(FATAL) aborts even for large STRIP_LOG
+
+./logging_striptest2 2>/dev/null && die "Did not abort for STRIP_LOG=2"
+./logging_striptest10 2>/dev/null && die "Did not abort for STRIP_LOG=10"
+
+echo "PASS"
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_striptest10.cc b/thirdparty/glog/glog-0.3.4/src/logging_striptest10.cc
new file mode 100644
index 0000000..f6e1078
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_striptest10.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Sergey Ioffe
+
+#define GOOGLE_STRIP_LOG 10
+
+// Include the actual test.
+#include "logging_striptest_main.cc"
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_striptest2.cc b/thirdparty/glog/glog-0.3.4/src/logging_striptest2.cc
new file mode 100644
index 0000000..a64685c
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_striptest2.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Sergey Ioffe
+
+#define GOOGLE_STRIP_LOG 2
+
+// Include the actual test.
+#include "logging_striptest_main.cc"
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_striptest_main.cc b/thirdparty/glog/glog-0.3.4/src/logging_striptest_main.cc
new file mode 100644
index 0000000..006584f
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_striptest_main.cc
@@ -0,0 +1,68 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Sergey Ioffe
+
+// The common part of the striplog tests.
+
+#include <stdio.h>
+#include <string>
+#include <iosfwd>
+#include "glog/logging.h"
+#include "base/commandlineflags.h"
+#include "config.h"
+
+DECLARE_bool(logtostderr);
+GLOG_DEFINE_bool(check_mode, false, "Prints 'opt' or 'dbg'");
+
+using std::string;
+using namespace GOOGLE_NAMESPACE;
+
+
+struct A { };
+std::ostream &operator<<(std::ostream &str, const A&) {return str;}
+
+int main(int, char* argv[]) {
+ FLAGS_logtostderr = true;
+ InitGoogleLogging(argv[0]);
+ if (FLAGS_check_mode) {
+ printf("%s\n", DEBUG_MODE ? "dbg" : "opt");
+ return 0;
+ }
+ LOG(INFO) << "TESTMESSAGE INFO";
+ LOG(WARNING) << 2 << "something" << "TESTMESSAGE WARNING"
+ << 1 << 'c' << A() << std::endl;
+ LOG(ERROR) << "TESTMESSAGE ERROR";
+ bool flag = true;
+ (flag ? LOG(INFO) : LOG(ERROR)) << "TESTMESSAGE COND";
+ LOG(FATAL) << "TESTMESSAGE FATAL";
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_unittest.cc b/thirdparty/glog/glog-0.3.4/src/logging_unittest.cc
new file mode 100644
index 0000000..3c1283e
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_unittest.cc
@@ -0,0 +1,1219 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2002, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney
+
+#include "config_for_unittests.h"
+#include "utilities.h"
+
+#include <fcntl.h>
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "base/commandlineflags.h"
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
+#include "googletest.h"
+
+DECLARE_string(log_backtrace_at); // logging.cc
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using testing::_;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::AllOf;
+using testing::StrNe;
+using testing::StrictMock;
+using testing::InitGoogleMock;
+using GOOGLE_NAMESPACE::glog_ns_testing::ScopedMockLog;
+#endif
+
+using namespace std;
+using namespace GOOGLE_NAMESPACE;
+
+// Some non-advertised functions that we want to test or use.
+_START_GOOGLE_NAMESPACE_
+namespace base_ns {
+namespace internal_ns {
+bool GetExitOnDFatal();
+void SetExitOnDFatal(bool value);
+} // namespace internal
+} // namespace base
+_END_GOOGLE_NAMESPACE_
+
+static void TestLogging(bool check_counts);
+static void TestRawLogging();
+static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
+static void TestLoggingLevels();
+static void TestLogString();
+static void TestLogSink();
+static void TestLogToString();
+static void TestLogSinkWaitTillSent();
+static void TestCHECK();
+static void TestDCHECK();
+static void TestSTREQ();
+static void TestBasename();
+static void TestSymlink();
+static void TestExtension();
+static void TestWrapper();
+static void TestErrno();
+static void TestTruncate();
+
+static int x = -1;
+static void BM_Check1(int n) {
+ while (n-- > 0) {
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ }
+}
+BENCHMARK(BM_Check1);
+
+static void CheckFailure(int a, int b, const char* file, int line, const char* msg);
+static void BM_Check3(int n) {
+ while (n-- > 0) {
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ }
+}
+BENCHMARK(BM_Check3);
+
+static void BM_Check2(int n) {
+ if (n == 17) {
+ x = 5;
+ }
+ while (n-- > 0) {
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ }
+}
+BENCHMARK(BM_Check2);
+
+static void CheckFailure(int, int, const char* /* file */, int /* line */,
+ const char* /* msg */) {
+}
+
+static void BM_logspeed(int n) {
+ while (n-- > 0) {
+ LOG(INFO) << "test message";
+ }
+}
+BENCHMARK(BM_logspeed);
+
+static void BM_vlog(int n) {
+ while (n-- > 0) {
+ VLOG(1) << "test message";
+ }
+}
+BENCHMARK(BM_vlog);
+
+int main(int argc, char **argv) {
+ FLAGS_colorlogtostderr = false;
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ // Make sure stderr is not buffered as stderr seems to be buffered
+ // on recent windows.
+ setbuf(stderr, NULL);
+
+ // Test some basics before InitGoogleLogging:
+ CaptureTestStderr();
+ LogWithLevels(FLAGS_v, FLAGS_stderrthreshold,
+ FLAGS_logtostderr, FLAGS_alsologtostderr);
+ LogWithLevels(0, 0, 0, 0); // simulate "before global c-tors"
+ const string early_stderr = GetCapturedTestStderr();
+
+ InitGoogleLogging(argv[0]);
+
+ RunSpecifiedBenchmarks();
+
+ FLAGS_logtostderr = true;
+
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+ InitGoogleMock(&argc, argv);
+#endif
+
+ // so that death tests run before we use threads
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+
+ CaptureTestStderr();
+
+ // re-emit early_stderr
+ LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr;
+
+ TestLogging(true);
+ TestRawLogging();
+ TestLoggingLevels();
+ TestLogString();
+ TestLogSink();
+ TestLogToString();
+ TestLogSinkWaitTillSent();
+ TestCHECK();
+ TestDCHECK();
+ TestSTREQ();
+
+ // TODO: The golden test portion of this test is very flakey.
+ EXPECT_TRUE(
+ MungeAndDiffTestStderr(FLAGS_test_srcdir + "/src/logging_unittest.err"));
+
+ FLAGS_logtostderr = false;
+
+ TestBasename();
+ TestSymlink();
+ TestExtension();
+ TestWrapper();
+ TestErrno();
+ TestTruncate();
+
+ ShutdownGoogleLogging();
+
+ fprintf(stdout, "PASS\n");
+ return 0;
+}
+
+void TestLogging(bool check_counts) {
+ int64 base_num_infos = LogMessage::num_messages(GLOG_INFO);
+ int64 base_num_warning = LogMessage::num_messages(GLOG_WARNING);
+ int64 base_num_errors = LogMessage::num_messages(GLOG_ERROR);
+
+ LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4;
+ for ( int i = 0; i < 10; ++i ) {
+ int old_errno = errno;
+ errno = i;
+ PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER;
+ errno = old_errno;
+
+ LOG_EVERY_N(ERROR, 3) << "Log every 3, iteration " << COUNTER << endl;
+ LOG_EVERY_N(ERROR, 4) << "Log every 4, iteration " << COUNTER << endl;
+
+ LOG_IF_EVERY_N(WARNING, true, 5) << "Log if every 5, iteration " << COUNTER;
+ LOG_IF_EVERY_N(WARNING, false, 3)
+ << "Log if every 3, iteration " << COUNTER;
+ LOG_IF_EVERY_N(INFO, true, 1) << "Log if every 1, iteration " << COUNTER;
+ LOG_IF_EVERY_N(ERROR, (i < 3), 2)
+ << "Log if less than 3 every 2, iteration " << COUNTER;
+ }
+ LOG_IF(WARNING, true) << "log_if this";
+ LOG_IF(WARNING, false) << "don't log_if this";
+
+ char s[] = "array";
+ LOG(INFO) << s;
+ const char const_s[] = "const array";
+ LOG(INFO) << const_s;
+ int j = 1000;
+ LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
+ << setw(1) << hex << j;
+
+ LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
+
+ if (check_counts) {
+ CHECK_EQ(base_num_infos + 14, LogMessage::num_messages(GLOG_INFO));
+ CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING));
+ CHECK_EQ(base_num_errors + 15, LogMessage::num_messages(GLOG_ERROR));
+ }
+}
+
+static void NoAllocNewHook() {
+ CHECK(false) << "unexpected new";
+}
+
+struct NewHook {
+ NewHook() {
+ g_new_hook = &NoAllocNewHook;
+ }
+ ~NewHook() {
+ g_new_hook = NULL;
+ }
+};
+
+TEST(DeathNoAllocNewHook, logging) {
+ // tests that NewHook used below works
+ NewHook new_hook;
+ ASSERT_DEATH({
+ new int;
+ }, "unexpected new");
+}
+
+void TestRawLogging() {
+ string* foo = new string("foo ");
+ string huge_str(50000, 'a');
+
+ FlagSaver saver;
+
+ // Check that RAW loggging does not use mallocs.
+ NewHook new_hook;
+
+ RAW_LOG(INFO, "%s%s%d%c%f", foo->c_str(), "bar ", 10, ' ', 3.4);
+ char s[] = "array";
+ RAW_LOG(WARNING, "%s", s);
+ const char const_s[] = "const array";
+ RAW_LOG(INFO, "%s", const_s);
+ void* p = reinterpret_cast<void*>(0x12345678);
+ RAW_LOG(INFO, "ptr %p", p);
+ p = NULL;
+ RAW_LOG(INFO, "ptr %p", p);
+ int j = 1000;
+ RAW_LOG(ERROR, "%s%d%c%010d%s%1x", foo->c_str(), j, ' ', j, " ", j);
+ RAW_VLOG(0, "foo %d", j);
+
+#ifdef NDEBUG
+ RAW_LOG(INFO, "foo %d", j); // so that have same stderr to compare
+#else
+ RAW_DLOG(INFO, "foo %d", j); // test RAW_DLOG in debug mode
+#endif
+
+ // test how long messages are chopped:
+ RAW_LOG(WARNING, "Huge string: %s", huge_str.c_str());
+ RAW_VLOG(0, "Huge string: %s", huge_str.c_str());
+
+ FLAGS_v = 0;
+ RAW_LOG(INFO, "log");
+ RAW_VLOG(0, "vlog 0 on");
+ RAW_VLOG(1, "vlog 1 off");
+ RAW_VLOG(2, "vlog 2 off");
+ RAW_VLOG(3, "vlog 3 off");
+ FLAGS_v = 2;
+ RAW_LOG(INFO, "log");
+ RAW_VLOG(1, "vlog 1 on");
+ RAW_VLOG(2, "vlog 2 on");
+ RAW_VLOG(3, "vlog 3 off");
+
+#ifdef NDEBUG
+ RAW_DCHECK(1 == 2, " RAW_DCHECK's shouldn't be compiled in normal mode");
+#endif
+
+ RAW_CHECK(1 == 1, "should be ok");
+ RAW_DCHECK(true, "should be ok");
+
+ delete foo;
+}
+
+void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
+ RAW_LOG(INFO,
+ "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d",
+ v, severity, err, alsoerr);
+
+ FlagSaver saver;
+
+ FLAGS_v = v;
+ FLAGS_stderrthreshold = severity;
+ FLAGS_logtostderr = err;
+ FLAGS_alsologtostderr = alsoerr;
+
+ RAW_VLOG(-1, "vlog -1");
+ RAW_VLOG(0, "vlog 0");
+ RAW_VLOG(1, "vlog 1");
+ RAW_LOG(INFO, "log info");
+ RAW_LOG(WARNING, "log warning");
+ RAW_LOG(ERROR, "log error");
+
+ VLOG(-1) << "vlog -1";
+ VLOG(0) << "vlog 0";
+ VLOG(1) << "vlog 1";
+ LOG(INFO) << "log info";
+ LOG(WARNING) << "log warning";
+ LOG(ERROR) << "log error";
+
+ VLOG_IF(-1, true) << "vlog_if -1";
+ VLOG_IF(-1, false) << "don't vlog_if -1";
+ VLOG_IF(0, true) << "vlog_if 0";
+ VLOG_IF(0, false) << "don't vlog_if 0";
+ VLOG_IF(1, true) << "vlog_if 1";
+ VLOG_IF(1, false) << "don't vlog_if 1";
+ LOG_IF(INFO, true) << "log_if info";
+ LOG_IF(INFO, false) << "don't log_if info";
+ LOG_IF(WARNING, true) << "log_if warning";
+ LOG_IF(WARNING, false) << "don't log_if warning";
+ LOG_IF(ERROR, true) << "log_if error";
+ LOG_IF(ERROR, false) << "don't log_if error";
+
+ int c;
+ c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1);
+ c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1);
+ c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1);
+ c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1);
+ c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0);
+ c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0);
+
+ c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
+ EXPECT_EQ(c, -1);
+ c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
+ EXPECT_EQ(c, -1);
+ c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
+ EXPECT_EQ(c, 0);
+ c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
+ EXPECT_EQ(c, 0);
+ c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
+ EXPECT_EQ(c, 1);
+ c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
+ EXPECT_EQ(c, 1);
+ c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
+ EXPECT_EQ(c, 0);
+ c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
+ EXPECT_EQ(c, 0);
+}
+
+void TestLoggingLevels() {
+ LogWithLevels(0, GLOG_INFO, false, false);
+ LogWithLevels(1, GLOG_INFO, false, false);
+ LogWithLevels(-1, GLOG_INFO, false, false);
+ LogWithLevels(0, GLOG_WARNING, false, false);
+ LogWithLevels(0, GLOG_ERROR, false, false);
+ LogWithLevels(0, GLOG_FATAL, false, false);
+ LogWithLevels(0, GLOG_FATAL, true, false);
+ LogWithLevels(0, GLOG_FATAL, false, true);
+ LogWithLevels(1, GLOG_WARNING, false, false);
+ LogWithLevels(1, GLOG_FATAL, false, true);
+}
+
+TEST(DeathRawCHECK, logging) {
+ ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
+ "RAW: Check false failed: failure 1");
+ ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"),
+ "RAW: Check 1 == 2 failed: failure 2");
+}
+
+void TestLogString() {
+ vector<string> errors;
+ vector<string> *no_errors = NULL;
+
+ LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info";
+ LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning";
+ LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error";
+
+ LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info";
+ LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning";
+ LOG_STRING(ERROR, NULL) << "LOG_STRING: " << "reported error";
+
+ for (size_t i = 0; i < errors.size(); ++i) {
+ LOG(INFO) << "Captured by LOG_STRING: " << errors[i];
+ }
+}
+
+void TestLogToString() {
+ string error;
+ string* no_error = NULL;
+
+ LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+ LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+ LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+
+ LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info";
+ LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning";
+ LOG_TO_STRING(ERROR, NULL) << "LOG_TO_STRING: " << "reported error";
+}
+
+class TestLogSinkImpl : public LogSink {
+ public:
+ vector<string> errors;
+ virtual void send(LogSeverity severity, const char* /* full_filename */,
+ const char* base_filename, int line,
+ const struct tm* tm_time,
+ const char* message, size_t message_len) {
+ errors.push_back(
+ ToString(severity, base_filename, line, tm_time, message, message_len));
+ }
+};
+
+void TestLogSink() {
+ TestLogSinkImpl sink;
+ LogSink *no_sink = NULL;
+
+ LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info";
+ LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning";
+ LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error";
+
+ LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info";
+ LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning";
+ LOG_TO_SINK(NULL, ERROR) << "LOG_TO_SINK: " << "reported error";
+
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error";
+
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(NULL, ERROR)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed error";
+
+ LOG(INFO) << "Captured by LOG_TO_SINK:";
+ for (size_t i = 0; i < sink.errors.size(); ++i) {
+ LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
+ << sink.errors[i];
+ }
+}
+
+// For testing using CHECK*() on anonymous enums.
+enum {
+ CASE_A,
+ CASE_B
+};
+
+void TestCHECK() {
+ // Tests using CHECK*() on int values.
+ CHECK(1 == 1);
+ CHECK_EQ(1, 1);
+ CHECK_NE(1, 2);
+ CHECK_GE(1, 1);
+ CHECK_GE(2, 1);
+ CHECK_LE(1, 1);
+ CHECK_LE(1, 2);
+ CHECK_GT(2, 1);
+ CHECK_LT(1, 2);
+
+ // Tests using CHECK*() on anonymous enums.
+ // Apple's GCC doesn't like this.
+#if !defined(OS_MACOSX)
+ CHECK_EQ(CASE_A, CASE_A);
+ CHECK_NE(CASE_A, CASE_B);
+ CHECK_GE(CASE_A, CASE_A);
+ CHECK_GE(CASE_B, CASE_A);
+ CHECK_LE(CASE_A, CASE_A);
+ CHECK_LE(CASE_A, CASE_B);
+ CHECK_GT(CASE_B, CASE_A);
+ CHECK_LT(CASE_A, CASE_B);
+#endif
+}
+
+void TestDCHECK() {
+#ifdef NDEBUG
+ DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode";
+#endif
+ DCHECK( 1 == 1 );
+ DCHECK_EQ(1, 1);
+ DCHECK_NE(1, 2);
+ DCHECK_GE(1, 1);
+ DCHECK_GE(2, 1);
+ DCHECK_LE(1, 1);
+ DCHECK_LE(1, 2);
+ DCHECK_GT(2, 1);
+ DCHECK_LT(1, 2);
+
+ auto_ptr<int64> sptr(new int64);
+ int64* ptr = DCHECK_NOTNULL(sptr.get());
+ CHECK_EQ(ptr, sptr.get());
+}
+
+void TestSTREQ() {
+ CHECK_STREQ("this", "this");
+ CHECK_STREQ(NULL, NULL);
+ CHECK_STRCASEEQ("this", "tHiS");
+ CHECK_STRCASEEQ(NULL, NULL);
+ CHECK_STRNE("this", "tHiS");
+ CHECK_STRNE("this", NULL);
+ CHECK_STRCASENE("this", "that");
+ CHECK_STRCASENE(NULL, "that");
+ CHECK_STREQ((string("a")+"b").c_str(), "ab");
+ CHECK_STREQ(string("test").c_str(),
+ (string("te") + string("st")).c_str());
+}
+
+TEST(DeathSTREQ, logging) {
+ ASSERT_DEATH(CHECK_STREQ(NULL, "this"), "");
+ ASSERT_DEATH(CHECK_STREQ("this", "siht"), "");
+ ASSERT_DEATH(CHECK_STRCASEEQ(NULL, "siht"), "");
+ ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), "");
+ ASSERT_DEATH(CHECK_STRNE(NULL, NULL), "");
+ ASSERT_DEATH(CHECK_STRNE("this", "this"), "");
+ ASSERT_DEATH(CHECK_STREQ((string("a")+"b").c_str(), "abc"), "");
+}
+
+TEST(CheckNOTNULL, Simple) {
+ int64 t;
+ void *ptr = static_cast<void *>(&t);
+ void *ref = CHECK_NOTNULL(ptr);
+ EXPECT_EQ(ptr, ref);
+ CHECK_NOTNULL(reinterpret_cast<char *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<unsigned char *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<int *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<int64 *>(ptr));
+}
+
+TEST(DeathCheckNN, Simple) {
+ ASSERT_DEATH(CHECK_NOTNULL(static_cast<void *>(NULL)), "");
+}
+
+// Get list of file names that match pattern
+static void GetFiles(const string& pattern, vector<string>* files) {
+ files->clear();
+#if defined(HAVE_GLOB_H)
+ glob_t g;
+ const int r = glob(pattern.c_str(), 0, NULL, &g);
+ CHECK((r == 0) || (r == GLOB_NOMATCH)) << ": error matching " << pattern;
+ for (size_t i = 0; i < g.gl_pathc; i++) {
+ files->push_back(string(g.gl_pathv[i]));
+ }
+ globfree(&g);
+#elif defined(OS_WINDOWS)
+ WIN32_FIND_DATAA data;
+ HANDLE handle = FindFirstFileA(pattern.c_str(), &data);
+ size_t index = pattern.rfind('\\');
+ if (index == string::npos) {
+ LOG(FATAL) << "No directory separator.";
+ }
+ const string dirname = pattern.substr(0, index + 1);
+ if (FAILED(handle)) {
+ // Finding no files is OK.
+ return;
+ }
+ do {
+ files->push_back(dirname + data.cFileName);
+ } while (FindNextFileA(handle, &data));
+ LOG_SYSRESULT(FindClose(handle));
+#else
+# error There is no way to do glob.
+#endif
+}
+
+// Delete files patching pattern
+static void DeleteFiles(const string& pattern) {
+ vector<string> files;
+ GetFiles(pattern, &files);
+ for (size_t i = 0; i < files.size(); i++) {
+ CHECK(unlink(files[i].c_str()) == 0) << ": " << strerror(errno);
+ }
+}
+
+static void CheckFile(const string& name, const string& expected_string) {
+ vector<string> files;
+ GetFiles(name + "*", &files);
+ CHECK_EQ(files.size(), 1UL);
+
+ FILE* file = fopen(files[0].c_str(), "r");
+ CHECK(file != NULL) << ": could not open " << files[0];
+ char buf[1000];
+ while (fgets(buf, sizeof(buf), file) != NULL) {
+ if (strstr(buf, expected_string.c_str()) != NULL) {
+ fclose(file);
+ return;
+ }
+ }
+ fclose(file);
+ LOG(FATAL) << "Did not find " << expected_string << " in " << files[0];
+}
+
+static void TestBasename() {
+ fprintf(stderr, "==== Test setting log file basename\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename";
+ DeleteFiles(dest + "*");
+
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base";
+ FlushLogFiles(GLOG_INFO);
+
+ CheckFile(dest, "message to new base");
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+static void TestSymlink() {
+#ifndef OS_WINDOWS
+ fprintf(stderr, "==== Test setting log file symlink\n");
+ string dest = FLAGS_test_tmpdir + "/logging_test_symlink";
+ string sym = FLAGS_test_tmpdir + "/symlinkbase";
+ DeleteFiles(dest + "*");
+ DeleteFiles(sym + "*");
+
+ SetLogSymlink(GLOG_INFO, "symlinkbase");
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new symlink";
+ FlushLogFiles(GLOG_INFO);
+ CheckFile(sym, "message to new symlink");
+
+ DeleteFiles(dest + "*");
+ DeleteFiles(sym + "*");
+#endif
+}
+
+static void TestExtension() {
+ fprintf(stderr, "==== Test setting log file extension\n");
+ string dest = FLAGS_test_tmpdir + "/logging_test_extension";
+ DeleteFiles(dest + "*");
+
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ SetLogFilenameExtension("specialextension");
+ LOG(INFO) << "message to new extension";
+ FlushLogFiles(GLOG_INFO);
+ CheckFile(dest, "message to new extension");
+
+ // Check that file name ends with extension
+ vector<string> filenames;
+ GetFiles(dest + "*", &filenames);
+ CHECK_EQ(filenames.size(), 1UL);
+ CHECK(strstr(filenames[0].c_str(), "specialextension") != NULL);
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+struct MyLogger : public base_ns::Logger {
+ string data;
+
+ virtual void Write(bool /* should_flush */,
+ time_t /* timestamp */,
+ const char* message,
+ int length) {
+ data.append(message, length);
+ }
+
+ virtual void Flush() { }
+
+ virtual uint32 LogSize() { return data.length(); }
+};
+
+static void TestWrapper() {
+ fprintf(stderr, "==== Test log wrapper\n");
+
+ MyLogger my_logger;
+ base_ns::Logger* old_logger = base_ns::GetLogger(GLOG_INFO);
+ base_ns::SetLogger(GLOG_INFO, &my_logger);
+ LOG(INFO) << "Send to wrapped logger";
+ FlushLogFiles(GLOG_INFO);
+ base_ns::SetLogger(GLOG_INFO, old_logger);
+
+ CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL);
+}
+
+static void TestErrno() {
+ fprintf(stderr, "==== Test errno preservation\n");
+
+ errno = ENOENT;
+ TestLogging(false);
+ CHECK_EQ(errno, ENOENT);
+}
+
+static void TestOneTruncate(const char *path, int64 limit, int64 keep,
+ int64 dsize, int64 ksize, int64 expect) {
+ int fd;
+ CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
+
+ const char *discardstr = "DISCARDME!", *keepstr = "KEEPME!";
+
+ // Fill the file with the requested data; first discard data, then kept data
+ int64 written = 0;
+ while (written < dsize) {
+ int bytes = min<int64>(dsize - written, strlen(discardstr));
+ CHECK_ERR(write(fd, discardstr, bytes));
+ written += bytes;
+ }
+ written = 0;
+ while (written < ksize) {
+ int bytes = min<int64>(ksize - written, strlen(keepstr));
+ CHECK_ERR(write(fd, keepstr, bytes));
+ written += bytes;
+ }
+
+ TruncateLogFile(path, limit, keep);
+
+ // File should now be shorter
+ struct stat statbuf;
+ CHECK_ERR(fstat(fd, &statbuf));
+ CHECK_EQ(statbuf.st_size, expect);
+ CHECK_ERR(lseek(fd, 0, SEEK_SET));
+
+ // File should contain the suffix of the original file
+ const size_t buf_size = statbuf.st_size + 1;
+ char* buf = new char[buf_size];
+ memset(buf, 0, buf_size);
+ CHECK_ERR(read(fd, buf, buf_size));
+
+ const char *p = buf;
+ int64 checked = 0;
+ while (checked < expect) {
+ int bytes = min<int64>(expect - checked, strlen(keepstr));
+ CHECK(!memcmp(p, keepstr, bytes));
+ checked += bytes;
+ }
+ close(fd);
+ delete[] buf;
+}
+
+static void TestTruncate() {
+#ifdef HAVE_UNISTD_H
+ fprintf(stderr, "==== Test log truncation\n");
+ string path = FLAGS_test_tmpdir + "/truncatefile";
+
+ // Test on a small file
+ TestOneTruncate(path.c_str(), 10, 10, 10, 10, 10);
+
+ // And a big file (multiple blocks to copy)
+ TestOneTruncate(path.c_str(), 2<<20, 4<<10, 3<<20, 4<<10, 4<<10);
+
+ // Check edge-case limits
+ TestOneTruncate(path.c_str(), 10, 20, 0, 20, 20);
+ TestOneTruncate(path.c_str(), 10, 0, 0, 0, 0);
+ TestOneTruncate(path.c_str(), 10, 50, 0, 10, 10);
+ TestOneTruncate(path.c_str(), 50, 100, 0, 30, 30);
+
+ // MacOSX 10.4 doesn't fail in this case.
+ // Windows doesn't have symlink.
+ // Let's just ignore this test for these cases.
+#if !defined(OS_MACOSX) && !defined(OS_WINDOWS)
+ // Through a symlink should fail to truncate
+ string linkname = path + ".link";
+ unlink(linkname.c_str());
+ CHECK_ERR(symlink(path.c_str(), linkname.c_str()));
+ TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30);
+#endif
+
+ // The /proc/self path makes sense only for linux.
+#if defined(OS_LINUX)
+ // Through an open fd symlink should work
+ int fd;
+ CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
+ char fdpath[64];
+ snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
+ TestOneTruncate(fdpath, 10, 10, 10, 10, 10);
+#endif
+
+#endif
+}
+
+_START_GOOGLE_NAMESPACE_
+namespace glog_ns_internal_namespace_ {
+extern // in logging.cc
+bool SafeFNMatch_(const char* pattern, size_t patt_len,
+ const char* str, size_t str_len);
+} // namespace glog_internal_namespace_
+using glog_ns_internal_namespace_::SafeFNMatch_;
+_END_GOOGLE_NAMESPACE_
+
+static bool WrapSafeFNMatch(string pattern, string str) {
+ pattern += "abc";
+ str += "defgh";
+ return SafeFNMatch_(pattern.data(), pattern.size() - 3,
+ str.data(), str.size() - 5);
+}
+
+TEST(SafeFNMatch, logging) {
+ CHECK(WrapSafeFNMatch("foo", "foo"));
+ CHECK(!WrapSafeFNMatch("foo", "bar"));
+ CHECK(!WrapSafeFNMatch("foo", "fo"));
+ CHECK(!WrapSafeFNMatch("foo", "foo2"));
+ CHECK(WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext"));
+ CHECK(WrapSafeFNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/baz.ext"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext.zip"));
+ CHECK(WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext"));
+ CHECK(WrapSafeFNMatch("ba?/*.ext", "baZ/FOO.ext"));
+ CHECK(!WrapSafeFNMatch("ba?/*.ext", "barr/foo.ext"));
+ CHECK(!WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext2"));
+ CHECK(WrapSafeFNMatch("ba?/*", "bar/foo.ext2"));
+ CHECK(WrapSafeFNMatch("ba?/*", "bar/"));
+ CHECK(!WrapSafeFNMatch("ba?/?", "bar/"));
+ CHECK(!WrapSafeFNMatch("ba?/*", "bar"));
+}
+
+// TestWaitingLogSink will save messages here
+// No lock: Accessed only by TestLogSinkWriter thread
+// and after its demise by its creator.
+static vector<string> global_messages;
+
+// helper for TestWaitingLogSink below.
+// Thread that does the logic of TestWaitingLogSink
+// It's free to use LOG() itself.
+class TestLogSinkWriter : public Thread {
+ public:
+
+ TestLogSinkWriter() : should_exit_(false) {
+ SetJoinable(true);
+ Start();
+ }
+
+ // Just buffer it (can't use LOG() here).
+ void Buffer(const string& message) {
+ mutex_.Lock();
+ RAW_LOG(INFO, "Buffering");
+ messages_.push(message);
+ mutex_.Unlock();
+ RAW_LOG(INFO, "Buffered");
+ }
+
+ // Wait for the buffer to clear (can't use LOG() here).
+ void Wait() {
+ RAW_LOG(INFO, "Waiting");
+ mutex_.Lock();
+ while (!NoWork()) {
+ mutex_.Unlock();
+ SleepForMilliseconds(1);
+ mutex_.Lock();
+ }
+ RAW_LOG(INFO, "Waited");
+ mutex_.Unlock();
+ }
+
+ // Trigger thread exit.
+ void Stop() {
+ MutexLock l(&mutex_);
+ should_exit_ = true;
+ }
+
+ private:
+
+ // helpers ---------------
+
+ // For creating a "Condition".
+ bool NoWork() { return messages_.empty(); }
+ bool HaveWork() { return !messages_.empty() || should_exit_; }
+
+ // Thread body; CAN use LOG() here!
+ virtual void Run() {
+ while (1) {
+ mutex_.Lock();
+ while (!HaveWork()) {
+ mutex_.Unlock();
+ SleepForMilliseconds(1);
+ mutex_.Lock();
+ }
+ if (should_exit_ && messages_.empty()) {
+ mutex_.Unlock();
+ break;
+ }
+ // Give the main thread time to log its message,
+ // so that we get a reliable log capture to compare to golden file.
+ // Same for the other sleep below.
+ SleepForMilliseconds(20);
+ RAW_LOG(INFO, "Sink got a messages"); // only RAW_LOG under mutex_ here
+ string message = messages_.front();
+ messages_.pop();
+ // Normally this would be some more real/involved logging logic
+ // where LOG() usage can't be eliminated,
+ // e.g. pushing the message over with an RPC:
+ int messages_left = messages_.size();
+ mutex_.Unlock();
+ SleepForMilliseconds(20);
+ // May not use LOG while holding mutex_, because Buffer()
+ // acquires mutex_, and Buffer is called from LOG(),
+ // which has its own internal mutex:
+ // LOG()->LogToSinks()->TestWaitingLogSink::send()->Buffer()
+ LOG(INFO) << "Sink is sending out a message: " << message;
+ LOG(INFO) << "Have " << messages_left << " left";
+ global_messages.push_back(message);
+ }
+ }
+
+ // data ---------------
+
+ Mutex mutex_;
+ bool should_exit_;
+ queue<string> messages_; // messages to be logged
+};
+
+// A log sink that exercises WaitTillSent:
+// it pushes data to a buffer and wakes up another thread to do the logging
+// (that other thread can than use LOG() itself),
+class TestWaitingLogSink : public LogSink {
+ public:
+
+ TestWaitingLogSink() {
+ tid_ = pthread_self(); // for thread-specific behavior
+ AddLogSink(this);
+ }
+ ~TestWaitingLogSink() {
+ RemoveLogSink(this);
+ writer_.Stop();
+ writer_.Join();
+ }
+
+ // (re)define LogSink interface
+
+ virtual void send(LogSeverity severity, const char* /* full_filename */,
+ const char* base_filename, int line,
+ const struct tm* tm_time,
+ const char* message, size_t message_len) {
+ // Push it to Writer thread if we are the original logging thread.
+ // Note: Something like ThreadLocalLogSink is a better choice
+ // to do thread-specific LogSink logic for real.
+ if (pthread_equal(tid_, pthread_self())) {
+ writer_.Buffer(ToString(severity, base_filename, line,
+ tm_time, message, message_len));
+ }
+ }
+ virtual void WaitTillSent() {
+ // Wait for Writer thread if we are the original logging thread.
+ if (pthread_equal(tid_, pthread_self())) writer_.Wait();
+ }
+
+ private:
+
+ pthread_t tid_;
+ TestLogSinkWriter writer_;
+};
+
+// Check that LogSink::WaitTillSent can be used in the advertised way.
+// We also do golden-stderr comparison.
+static void TestLogSinkWaitTillSent() {
+ { TestWaitingLogSink sink;
+ // Sleeps give the sink threads time to do all their work,
+ // so that we get a reliable log capture to compare to the golden file.
+ LOG(INFO) << "Message 1";
+ SleepForMilliseconds(60);
+ LOG(ERROR) << "Message 2";
+ SleepForMilliseconds(60);
+ LOG(WARNING) << "Message 3";
+ SleepForMilliseconds(60);
+ }
+ for (size_t i = 0; i < global_messages.size(); ++i) {
+ LOG(INFO) << "Sink capture: " << global_messages[i];
+ }
+ CHECK_EQ(global_messages.size(), 3UL);
+}
+
+TEST(Strerror, logging) {
+ int errcode = EINTR;
+ char *msg = strdup(strerror(errcode));
+ const size_t buf_size = strlen(msg) + 1;
+ char *buf = new char[buf_size];
+ CHECK_EQ(posix_strerror_r(errcode, NULL, 0), -1);
+ buf[0] = 'A';
+ CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
+ CHECK_EQ(buf[0], 'A');
+ CHECK_EQ(posix_strerror_r(errcode, NULL, buf_size), -1);
+#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+ // MacOSX or FreeBSD considers this case is an error since there is
+ // no enough space.
+ CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
+#else
+ CHECK_EQ(posix_strerror_r(errcode, buf, 1), 0);
+#endif
+ CHECK_STREQ(buf, "");
+ CHECK_EQ(posix_strerror_r(errcode, buf, buf_size), 0);
+ CHECK_STREQ(buf, msg);
+ delete[] buf;
+ CHECK_EQ(msg, StrError(errcode));
+ free(msg);
+}
+
+// Simple routines to look at the sizes of generated code for LOG(FATAL) and
+// CHECK(..) via objdump
+void MyFatal() {
+ LOG(FATAL) << "Failed";
+}
+void MyCheck(bool a, bool b) {
+ CHECK_EQ(a, b);
+}
+
+#ifdef HAVE_LIB_GMOCK
+
+TEST(DVLog, Basic) {
+ ScopedMockLog log;
+
+#if NDEBUG
+ // We are expecting that nothing is logged.
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+#else
+ EXPECT_CALL(log, Log(INFO, __FILE__, "debug log"));
+#endif
+
+ FLAGS_v = 1;
+ DVLOG(1) << "debug log";
+}
+
+TEST(DVLog, V0) {
+ ScopedMockLog log;
+
+ // We are expecting that nothing is logged.
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+
+ FLAGS_v = 0;
+ DVLOG(1) << "debug log";
+}
+
+TEST(LogAtLevel, Basic) {
+ ScopedMockLog log;
+
+ // The function version outputs "logging.h" as a file name.
+ EXPECT_CALL(log, Log(WARNING, StrNe(__FILE__), "function version"));
+ EXPECT_CALL(log, Log(INFO, __FILE__, "macro version"));
+
+ int severity = WARNING;
+ LogAtLevel(severity, "function version");
+
+ severity = INFO;
+ // We can use the macro version as a C++ stream.
+ LOG_AT_LEVEL(severity) << "macro" << ' ' << "version";
+}
+
+TEST(TestExitOnDFatal, ToBeOrNotToBe) {
+ // Check the default setting...
+ EXPECT_TRUE(base_ns::internal_ns::GetExitOnDFatal());
+
+ // Turn off...
+ base_ns::internal_ns::SetExitOnDFatal(false);
+ EXPECT_FALSE(base_ns::internal_ns::GetExitOnDFatal());
+
+ // We don't die.
+ {
+ ScopedMockLog log;
+ //EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
+ // LOG(DFATAL) has severity FATAL if debugging, but is
+ // downgraded to ERROR if not debugging.
+ const LogSeverity severity =
+#ifdef NDEBUG
+ ERROR;
+#else
+ FATAL;
+#endif
+ EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
+ LOG(DFATAL) << "This should not be fatal";
+ }
+
+ // Turn back on...
+ base_ns::internal_ns::SetExitOnDFatal(true);
+ EXPECT_TRUE(base_ns::internal_ns::GetExitOnDFatal());
+
+#ifdef GTEST_HAS_DEATH_TEST
+ // Death comes on little cats' feet.
+ EXPECT_DEBUG_DEATH({
+ LOG(DFATAL) << "This should be fatal in debug mode";
+ }, "This should be fatal in debug mode");
+#endif
+}
+
+#ifdef HAVE_STACKTRACE
+
+static void BacktraceAtHelper() {
+ LOG(INFO) << "Not me";
+
+// The vertical spacing of the next 3 lines is significant.
+ LOG(INFO) << "Backtrace me";
+}
+static int kBacktraceAtLine = __LINE__ - 2; // The line of the LOG(INFO) above
+
+TEST(LogBacktraceAt, DoesNotBacktraceWhenDisabled) {
+ StrictMock<ScopedMockLog> log;
+
+ FLAGS_log_backtrace_at = "";
+
+ EXPECT_CALL(log, Log(_, _, "Backtrace me"));
+ EXPECT_CALL(log, Log(_, _, "Not me"));
+
+ BacktraceAtHelper();
+}
+
+TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
+ StrictMock<ScopedMockLog> log;
+
+ char where[100];
+ snprintf(where, 100, "%s:%d", const_basename(__FILE__), kBacktraceAtLine);
+ FLAGS_log_backtrace_at = where;
+
+ // The LOG at the specified line should include a stacktrace which includes
+ // the name of the containing function, followed by the log message.
+ // We use HasSubstr()s instead of ContainsRegex() for environments
+ // which don't have regexp.
+ EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"),
+ HasSubstr("BacktraceAtHelper"),
+ HasSubstr("main"),
+ HasSubstr("Backtrace me"))));
+ // Other LOGs should not include a backtrace.
+ EXPECT_CALL(log, Log(_, _, "Not me"));
+
+ BacktraceAtHelper();
+}
+
+#endif // HAVE_STACKTRACE
+
+#endif // HAVE_LIB_GMOCK
+
+struct UserDefinedClass {
+ bool operator==(const UserDefinedClass&) const { return true; }
+};
+
+inline ostream& operator<<(ostream& out, const UserDefinedClass&) {
+ out << "OK";
+ return out;
+}
+
+TEST(UserDefinedClass, logging) {
+ UserDefinedClass u;
+ vector<string> buf;
+ LOG_STRING(INFO, &buf) << u;
+ CHECK_EQ(1UL, buf.size());
+ CHECK(buf[0].find("OK") != string::npos);
+
+ // We must be able to compile this.
+ CHECK_EQ(u, u);
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/logging_unittest.err b/thirdparty/glog/glog-0.3.4/src/logging_unittest.err
new file mode 100644
index 0000000..4f80bf5
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/logging_unittest.err
@@ -0,0 +1,305 @@
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+WARNING: Logging before InitGoogleLogging() is written to STDERR
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] foo bar 10 3.4
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 1
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 1
+WDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 1
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 2
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 3
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 4
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 4
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 5
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 5
+WDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 6
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 6
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 7
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 7
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 8
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 9
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 9
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 10
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 10
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
+IDATE TIME__ THREADID logging_unittest.cc:LINE] array
+IDATE TIME__ THREADID logging_unittest.cc:LINE] const array
+EDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 0000001000 3e8
+no prefix
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: const array
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr 0x12345678
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __NULLP__
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0 on
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1 on
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 2 on
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
+WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
+EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
diff --git a/thirdparty/glog/glog-0.3.4/src/mock-log.h b/thirdparty/glog/glog-0.3.4/src/mock-log.h
new file mode 100644
index 0000000..8d0234a
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/mock-log.h
@@ -0,0 +1,158 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Zhanyong Wan
+//
+// Defines the ScopedMockLog class (using Google C++ Mocking
+// Framework), which is convenient for testing code that uses LOG().
+
+#ifndef GLOG_SRC_MOCK_LOG_H_
+#define GLOG_SRC_MOCK_LOG_H_
+
+// For GOOGLE_NAMESPACE. This must go first so we get _XOPEN_SOURCE.
+#include "utilities.h"
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "glog/logging.h"
+
+_START_GOOGLE_NAMESPACE_
+namespace glog_ns_testing {
+
+// A ScopedMockLog object intercepts LOG() messages issued during its
+// lifespan. Using this together with Google C++ Mocking Framework,
+// it's very easy to test how a piece of code calls LOG(). The
+// typical usage:
+//
+// TEST(FooTest, LogsCorrectly) {
+// ScopedMockLog log;
+//
+// // We expect the WARNING "Something bad!" exactly twice.
+// EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
+// .Times(2);
+//
+// // We allow foo.cc to call LOG(INFO) any number of times.
+// EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
+// .Times(AnyNumber());
+//
+// Foo(); // Exercises the code under test.
+// }
+class ScopedMockLog : public GOOGLE_NAMESPACE::LogSink {
+ public:
+ // When a ScopedMockLog object is constructed, it starts to
+ // intercept logs.
+ ScopedMockLog() { AddLogSink(this); }
+
+ // When the object is destructed, it stops intercepting logs.
+ virtual ~ScopedMockLog() { RemoveLogSink(this); }
+
+ // Implements the mock method:
+ //
+ // void Log(LogSeverity severity, const string& file_path,
+ // const string& message);
+ //
+ // The second argument to Send() is the full path of the source file
+ // in which the LOG() was issued.
+ //
+ // Note, that in a multi-threaded environment, all LOG() messages from a
+ // single thread will be handled in sequence, but that cannot be guaranteed
+ // for messages from different threads. In fact, if the same or multiple
+ // expectations are matched on two threads concurrently, their actions will
+ // be executed concurrently as well and may interleave.
+ MOCK_METHOD3(Log, void(GOOGLE_NAMESPACE::LogSeverity severity,
+ const std::string& file_path,
+ const std::string& message));
+
+ private:
+ // Implements the send() virtual function in class LogSink.
+ // Whenever a LOG() statement is executed, this function will be
+ // invoked with information presented in the LOG().
+ //
+ // The method argument list is long and carries much information a
+ // test usually doesn't care about, so we trim the list before
+ // forwarding the call to Log(), which is much easier to use in
+ // tests.
+ //
+ // We still cannot call Log() directly, as it may invoke other LOG()
+ // messages, either due to Invoke, or due to an error logged in
+ // Google C++ Mocking Framework code, which would trigger a deadlock
+ // since a lock is held during send().
+ //
+ // Hence, we save the message for WaitTillSent() which will be called after
+ // the lock on send() is released, and we'll call Log() inside
+ // WaitTillSent(). Since while a single send() call may be running at a
+ // time, multiple WaitTillSent() calls (along with the one send() call) may
+ // be running simultaneously, we ensure thread-safety of the exchange between
+ // send() and WaitTillSent(), and that for each message, LOG(), send(),
+ // WaitTillSent() and Log() are executed in the same thread.
+ virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
+ const char* full_filename,
+ const char* base_filename, int line, const tm* tm_time,
+ const char* message, size_t message_len) {
+ // We are only interested in the log severity, full file name, and
+ // log message.
+ message_info_.severity = severity;
+ message_info_.file_path = full_filename;
+ message_info_.message = std::string(message, message_len);
+ }
+
+ // Implements the WaitTillSent() virtual function in class LogSink.
+ // It will be executed after send() and after the global logging lock is
+ // released, so calls within it (or rather within the Log() method called
+ // within) may also issue LOG() statements.
+ //
+ // LOG(), send(), WaitTillSent() and Log() will occur in the same thread for
+ // a given log message.
+ virtual void WaitTillSent() {
+ // First, and very importantly, we save a copy of the message being
+ // processed before calling Log(), since Log() may indirectly call send()
+ // and WaitTillSent() in the same thread again.
+ MessageInfo message_info = message_info_;
+ Log(message_info.severity, message_info.file_path, message_info.message);
+ }
+
+ // All relevant information about a logged message that needs to be passed
+ // from send() to WaitTillSent().
+ struct MessageInfo {
+ GOOGLE_NAMESPACE::LogSeverity severity;
+ std::string file_path;
+ std::string message;
+ };
+ MessageInfo message_info_;
+};
+
+} // namespace glog_testing
+_END_GOOGLE_NAMESPACE_
+
+#endif // GLOG_SRC_MOCK_LOG_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/mock-log_test.cc b/thirdparty/glog/glog-0.3.4/src/mock-log_test.cc
new file mode 100644
index 0000000..dedb0ce
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/mock-log_test.cc
@@ -0,0 +1,109 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Zhanyong Wan
+
+// Tests the ScopedMockLog class.
+
+#include "mock-log.h"
+
+#include <string>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+using GOOGLE_NAMESPACE::INFO;
+using GOOGLE_NAMESPACE::WARNING;
+using GOOGLE_NAMESPACE::ERROR;
+using GOOGLE_NAMESPACE::glog_ns_testing::ScopedMockLog;
+using std::string;
+using testing::_;
+using testing::HasSubstr;
+using testing::InSequence;
+using testing::InvokeWithoutArgs;
+
+// Tests that ScopedMockLog intercepts LOG()s when it's alive.
+TEST(ScopedMockLogTest, InterceptsLog) {
+ ScopedMockLog log;
+
+ InSequence s;
+ EXPECT_CALL(log, Log(WARNING, HasSubstr("/mock-log_test.cc"), "Fishy."));
+ EXPECT_CALL(log, Log(INFO, _, "Working..."))
+ .Times(2);
+ EXPECT_CALL(log, Log(ERROR, _, "Bad!!"));
+
+ LOG(WARNING) << "Fishy.";
+ LOG(INFO) << "Working...";
+ LOG(INFO) << "Working...";
+ LOG(ERROR) << "Bad!!";
+}
+
+void LogBranch() {
+ LOG(INFO) << "Logging a branch...";
+}
+
+void LogTree() {
+ LOG(INFO) << "Logging the whole tree...";
+}
+
+void LogForest() {
+ LOG(INFO) << "Logging the entire forest.";
+ LOG(INFO) << "Logging the entire forest..";
+ LOG(INFO) << "Logging the entire forest...";
+}
+
+// The purpose of the following test is to verify that intercepting logging
+// continues to work properly if a LOG statement is executed within the scope
+// of a mocked call.
+TEST(ScopedMockLogTest, LogDuringIntercept) {
+ ScopedMockLog log;
+ InSequence s;
+ EXPECT_CALL(log, Log(INFO, __FILE__, "Logging a branch..."))
+ .WillOnce(InvokeWithoutArgs(LogTree));
+ EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the whole tree..."))
+ .WillOnce(InvokeWithoutArgs(LogForest));
+ EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest."));
+ EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest.."));
+ EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest..."));
+ LogBranch();
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ GOOGLE_NAMESPACE::InitGoogleLogging(argv[0]);
+ testing::InitGoogleMock(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/nstack_logging.cc b/thirdparty/glog/glog-0.3.4/src/nstack_logging.cc
new file mode 100644
index 0000000..40b4a7c
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/nstack_logging.cc
@@ -0,0 +1,1066 @@
+/*
+* @file nstack_logging.cc
+* Copyright(C), Huawei Tech. Co., Ltd. ALL RIGHTS RESERVED. \n
+* Description: user define the log. \n
+*
+*/
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <iostream>
+#include <istream>
+#include <streambuf>
+#include <string>
+
+#include "glog/logging.h"
+#include "glog/log_severity.h"
+#include "glog/raw_logging.h"
+#include "glog/stl_logging.h"
+#include "glog/vlog_is_on.h"
+#include "utilities.h"
+#include "glog/nstack_glog_in.h"
+#include "glog/nstack_glog.ph"
+#include "glog/nstack_adapter.ph"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+using namespace std;
+using namespace google_ns;
+using namespace nstack_space;
+
+/**
+* Max length of signal log
+* Prefix: LogNum:LogSerial] max is NSTACK_LOG_PRE_LEN , most character is MAX_NSTACK_LOG_LENGTH-1
+* reference MAX_ROSA_LOG_LEN, need MAX_NSTACK_LOG_LENGTH % (MAX_ROSA_LOG_LEN - NSTACK_LOG_PRE_LEN) can store the log
+*/
+#define MAX_LOG_SERIAL_NUM NSTACK_LOG_TRANSFER_TO_PRODUCE_ITEMS(MAX_NSTACK_LOG_LENGTH)
+
+/**
+* Log record number, atomic operation
+*/
+static glog_atomic_t g_logRecordNum = {0};
+
+/**
+* A signed 32-bit maximum
+*/
+static const int max32BitNum = 0x7FFFFFFF;
+static const int MAX_32BIT_NUM_HEX_LEN = 8;
+
+/**
+* Log messages at a level >= this flag are automatically sent to stderr in addition to log files.
+*/
+unsigned int g_LogLevelPrint = GLOG_LEVEL_BUTT;
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log file number..
+<br/> Functional Description: Set the log file number.
+<br/> use constraint: The default is 10.
+<br/> upgrade effect: no.
+*/
+extern unsigned int log_file_count;
+extern unsigned int modify_path_count;
+
+/**
+* Log messages length
+*/
+static unsigned int g_LogLenPrint = 0;
+
+/**
+* @ingroup GLOG
+* @brief Save user-defined callback interface.
+<br/> Function Description: Save the user-defined callback interface.
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+log_hook_tag_t g_log_hook_tag = {NULL, 0, GLOG_LEVEL_INFO};
+
+/**
+* @ingroup GLOG
+* @brief ROSA callback registration judgment.
+<br/> Function description: Determines whether ROSA is registered.
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+
+#define NSTACK_LOG_VARLEN_CHECK (g_log_hook_tag.log_hook != NULL)
+
+/**
+* @ingroup GLOG
+* @brief HLOG and GLOG log level mapping.
+<br/> Function description: Log level mapping.
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+static const int glogLevelMapping[GLOG_LEVEL_BUTT]
+ = {GLOG_INFO,
+ GLOG_INFO,
+ GLOG_WARNING,
+ GLOG_ERROR,
+ GLOG_FATAL};
+
+/**
+* @ingroup GLOG
+* @brief ROSA log level in env
+<br/> use constraint: NA.
+<br/> upgrade effect: no.
+*/
+static const char* const glogLevelName[GLOG_LEVEL_BUTT] = {"DBG",
+ "INF",
+ "WAR",
+ "ERR",
+ "FTL"};
+/**
+* @ingroup NSTACK_LOG
+* @brief product to NSTACK registration log hook.
+*
+* @verbatim
+ Function Description: Set the log to print the hook.
+ Target users: users who use NSTACK to print logs
+ Use the constraint: log_hook parameter can not be empty, repeat the registration to the last time.
+ Upgrade effect: no
+
+@endverbatim
+* @param log_hook [input] ROSA registered to NSTACK callback function, can not be empty
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: empty, or re-registered
+* @par dependency: Requires product call
+* <li>nstack_glog_in.h The interface declares the header file. </li></ul>
+* @see NA¡£
+*/
+
+int nstack_log_hook_set(nstack_log_hook log_hook)
+{
+#ifndef MPTCP_SUPPORT
+ if (NULL == log_hook || g_log_hook_tag.register_cnt > 0) {
+ return 1;
+ }
+#endif
+
+ g_log_hook_tag.log_hook = log_hook;
+ g_log_hook_tag.register_cnt++;
+
+ return 0;
+}
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log level to be printed, and logs greater than or equal to this level will be printed.
+*
+* @verbatim
+ Function Description: Set the log level to be printed.Support for reading environment variables:
+ NSTACK_LOG_HOOK_LEVEL = DBG / INF / WAR / ERR / FTL,If the value of NSTACK_LOG_HOOK_LEVEL is set
+ incorrectly, the log level is unchanged Dynamically set the level
+ Target users: users who use NSTACK to print logs
+ Use constraint: log level See nstack_log_level.
+ First set the priority level with NSTACK_LOG_HOOK_LEVEL,
+ If the NSTACK_LOG_HOOK_LEVEL environment variable is not set,
+ And then to nstack_log_hook_level_set incoming log_level prevail,
+ The default is INFO level.
+ Note the use of environment variable NSTACK_LOG_HOOK_LEVEL settings and clear.
+ Upgrade effect: no
+@endverbatim
+* @param log_level [input] log level, see enum nstack_log_level
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: level is not in the range, before the log level unchanged
+* @par dependency:NA
+* @see NA
+*/
+
+
+int nstack_log_hook_level_set(unsigned int log_level)
+{
+ if (log_level >= GLOG_LEVEL_BUTT)
+ {
+ return 1;
+ }
+
+ /* accept the log_level set by nstack_log_hook_level_set().
+ Otherwise, ignore the log_level.
+ */
+ g_log_hook_tag.level = log_level;
+
+ return 0;
+}
+
+/**
+* @ingroup NSTACK_LOG£¬init the hook
+
+* @see NA
+*/
+
+void nstack_log_hook_init()
+{
+ unsigned int i;
+ char *pst_temp = NULL;
+
+ pst_temp = getenv(NSTACK_LOG_HOOK_LEVEL);
+ if (NULL == pst_temp) {
+ return ;
+ }
+
+ for(i = 0; i < GLOG_LEVEL_BUTT; i++) {
+ if ((glogLevelName[i][0] == pst_temp[0])
+ && (0 == strncmp(pst_temp,
+ glogLevelName[i],
+ strlen(glogLevelName[i])))) {
+ g_log_hook_tag.level = i;
+ return;
+ }
+ }
+
+ return ;
+
+}
+
+/**
+* @ingroup NSTACK_LOG
+* @brief Set the log file number.
+*
+* @verbatim
+ Function Description: Set the log file number.
+ Target users: users who use NSTACK to print logs
+ Use constraint: The default is 10
+ Upgrade effect: no
+@endverbatim
+* @param count [input] log file number,
+*
+* @return NA
+* @par dependency:NA
+*/
+void nstack_log_count_set(unsigned int count)
+{
+ log_file_count = count;
+}
+
+
+/**
+* @ingroup GLOG
+* @brief Set the log level to be printed, and logs greater than or equal to this level will be printed.
+*
+* @verbatim
+ Function Description: Set the log level to be printed.
+ Support for reading environment variables NSTACK_LOG_LEVEL_ENABLE = DEBUG / INFO / WARNING / ERROR / FATAL,
+ Dynamically set the level
+ Target users: users who use the NSTACK software to print logs
+ Use constraint: log level See nstack_log_level, which must be called when NSTACK_LOG_LEVEL_ENABLE is used.
+ First to NSTACK_LOG_LEVEL_ENABLE set the level prevail, again with the incoming logLevel prevail,
+ The default is INFO level. Please note that the environment variable NSTACK_LOG_LEVEL_ENABLE settings and clear.
+ Upgrade effect: no
+@endverbatim
+* @param logLevel [input] log level, see nstack_log_level
+*
+* @return 0 The function returns success
+* @return 1 parameter passed in error: the rank is not in range
+* @par dependency:
+* <li>nstack_glog_in.h£ºThe interface declares the header file. </li></ul>
+*/
+int glogLevelSet(unsigned int logLevel)
+{
+ int levelEnable;
+
+ if (logLevel >= GLOG_LEVEL_BUTT) {
+ return 1;
+ }
+
+ levelEnable = glogLevelGet();
+ g_LogLevelPrint = (GLOG_LEVEL_BUTT == levelEnable) ? logLevel : levelEnable;
+
+
+ n_glogLevelSet(g_LogLevelPrint);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Function name: glogPrintLengthSet
+ Function Description: Set the number of characters to print for each log, up to 256
+ Input parameters: len: character length
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogPrintLengthSet(unsigned int len)
+{
+ char *envPrintLen = NULL;
+ unsigned int envLen = 0;
+
+ if (0 == len) {
+ return;
+ }
+
+ envPrintLen = getenv(ENV_LOG_PRINT_LEN_FLAG);
+ if (NULL == envPrintLen) {
+ g_LogLenPrint = len > MAX_NSTACK_LOG_LENGTH ? MAX_NSTACK_LOG_LENGTH : len;
+ return;
+ }
+
+ envLen = (unsigned int)atoi(envPrintLen);
+ if (envLen > 0) {
+ g_LogLenPrint = envLen > MAX_NSTACK_LOG_LENGTH ? MAX_NSTACK_LOG_LENGTH : envLen;
+ return;
+ }
+
+ return;
+}
+
+/*****************************************************************************
+ Function name: glogLevelGet
+ Function Description: Get the log print level
+ Input parameters: NA
+ Output parameters: NA
+ Return Value: Success: Log level
+ Failed: GLOG_LEVEL_BUTT
+*****************************************************************************/
+int glogLevelGet(void)
+{
+ unsigned int i;
+ char *enableLevel = NULL;
+
+ enableLevel = getenv(ENV_LOG_LEVEL_ENABLE_FLAG);
+ if (NULL == enableLevel) {
+ return GLOG_LEVEL_BUTT;
+ }
+
+ for(i = 0; i < GLOG_LEVEL_BUTT; i++) {
+ if ((glogLevelName[i][0] == enableLevel[0])
+ && (0 == strncmp(enableLevel,
+ glogLevelName[i],
+ strlen(glogLevelName[i])))) {
+ return i;
+ }
+ }
+
+ return GLOG_LEVEL_BUTT;
+
+}
+
+/*****************************************************************************
+ Function name: glogInit
+ Function description: Hlog initialization.
+ Input parameters: param incoming parameters that can make module ID and so on
+ Output parameters: NA
+ Return value: NA
+*****************************************************************************/
+void glogInit(char *param)
+{
+ InitGoogleLogging(param);
+
+ return ;
+}
+
+/*****************************************************************************
+ Function name: glogExit
+ Function description: Hlog exits
+ Input parameters: NA
+ Output parameters: NA
+ Return value: NA
+*****************************************************************************/
+void glogExit(void)
+{
+ ShutdownGoogleLogging();
+}
+
+/*****************************************************************************
+Function name: glogDestinationSet
+Function Description: Set different files based on different levels of log basename.
+Input parameters: logLevel log level
+ base_filename file
+Output parameters: NA
+Return Value: NA
+*****************************************************************************/
+void glogDestinationSet(unsigned int logLevel, const char* base_filename)
+{
+ if (logLevel >= GLOG_LEVEL_BUTT) {
+ return;
+ }
+ SetLogDestination(glogLevelMapping[logLevel], base_filename);
+}
+
+/**
+* @ingroup GLOG
+* @brief Set the log level to be printed.
+*
+* @verbatim
+ Function Description: Set the log level to be printed.
+ Target users: users who use the glog software to print logs
+ Use constraint: log level See nstack_log_level
+ Upgrade effect: no
+
+@endverbatim
+* @param logLevel [input] log level, see nstack_log_level
+*
+* @return NA
+* @par dependency:
+* <li>nstack_glog.ph£º This interface declares the header file. </li></ul>
+*/
+void n_glogLevelSet(unsigned int logLevel)
+{
+ FLAGS_minloglevel = glogLevelMapping[logLevel];
+}
+
+/*****************************************************************************
+ Function name: glogToStderrSet
+ Function Description: Set whether the log print standard output, the default need to print the file
+ Input parameters: logToStderr is valid, 1: print standard output, do not print the file
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogToStderrSet(int logToStderr)
+{
+ FLAGS_logtostderr = (1 == logToStderr) ? true : false;
+}
+
+/*****************************************************************************
+ Function name: glogFlushLogSecsSet
+ Function Description: Sets the maximum number of seconds which logs may be buffered for.
+ Enter the parameters: secs seconds
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogFlushLogSecsSet(int secs)
+{
+ FLAGS_logbufsecs = secs;
+}
+
+/*****************************************************************************
+ Function name: glogMaxLogSizeSet
+ Function Description: Sets the maximum log file size (in MB).
+ Input parameters: maxSize the maximum log file size (in MB)
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogMaxLogSizeSet(int maxSize)
+{
+ FLAGS_max_log_size = maxSize;
+}
+
+
+/*****************************************************************************
+ Function name: glogDir
+ Function Description: If specified, logfiles are written into this directory instead of
+ the default logging directory
+ Enter the parameters: logDir: directory
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogDir(char *logDir)
+{
+ FLAGS_log_dir = logDir;
+}
+
+/**
+* @ingroup GLOG
+* @brief Set the log level to be printed.
+*
+* @verbatim
+ Function Description: When the log level is greater than this level will immediately output,
+ without caching. Buffer log messages logged at this level or lower ,
+ Target users: users who use the glog software to print logs
+ Use constraint: log level See nstack_log_level, and cannot bigger than GLOG_LEVEL_ERROR.
+ Upgrade effect: no
+
+@endverbatim
+* @param logLevel [input] log level, see nstack_log_level
+*
+* DTS2017110310251
+* @return NA
+* @par dependency:
+* <li>nstack_glog.ph£º This interface declares the header file. </li></ul>
+*/
+void glogBufLevelSet(unsigned int logLevel)
+{
+ if(logLevel > GLOG_LEVEL_ERROR)
+ {
+ return;
+ }
+
+ FLAGS_logbuflevel = glogLevelMapping[logLevel];
+}
+
+/*****************************************************************************
+ Function name: nstack_modify_log_dir
+ Function Description: If specified, modify the glog prit path dynamic.
+ Enter the parameters: logDir: directory
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void nstack_modify_log_dir(char *log_dir)
+{
+ if(NULL == log_dir)
+ return;
+ FLAGS_log_dir = log_dir;
+ modify_path_count = 1;
+ return;
+}
+
+/*****************************************************************************
+ Function name: release the lock of glog when fork
+ Function Description: release the lock of glog when fork.
+ Enter the parameters: NA
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void nstack_log_lock_release(void)
+{
+ glog_release_rw_lock();
+ RleaseLogSinkLock(GLOG_INFO);
+ return;
+}
+
+/*****************************************************************************
+ Function name: glogInstallFailureSignalHandler
+ Function Description: Install a signal handler that will dump signal information and a stack
+ trace when the program crashes on certain signals. We'll install the
+ signal handler for the following signals.
+
+ SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
+
+ By default, the signal handler will write the failure dump to the
+ standard error. You can customize the destination by installing your
+ own writer function by InstallFailureWriter() below.
+
+ Note on threading:
+
+ The function should be called before threads are created, if you want
+ to use the failure signal handler for all threads. The stack trace
+ will be shown only for the thread that receives the signal. In other
+ words, stack traces of other threads won't be shown.
+ Enter the parameters: NA
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogInstallFailureSignalHandler(void)
+{
+ InstallFailureSignalHandler();
+}
+
+/*****************************************************************************
+ Function name: glogInstallFailureWriter
+ Function Description: By default, the signal handler writes the failure dump to the standard error.
+ You can customize the destination by glogInstallFailureWriter().
+ Enter the parameters: hook: the signal handler writes the failure dump to the destination you want.
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogInstallFailureWriter(glogInstallFailureWriterHook hook)
+{
+ InstallFailureWriter(hook);
+}
+
+
+/*****************************************************************************
+ Function name: glogInstallFailureFunction
+ Function Description: Install a function which will be called after LOG(FATAL).
+ Enter the parameters: hook: function you want to call after LOG(FATAL).
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogInstallFailureFunction(glogFailfuncHook hook)
+{
+ InstallFailureFunction(hook);
+}
+
+/*****************************************************************************
+ Function name: glogSetLogSymlink
+ Function Description: Set the basename of the symlink to the latest log file at a given
+ severity. If symlink_basename is empty, do not make a symlink
+ you do not call this function, the symlink basename is the
+ invocation name of the program. Thread-safe.
+ Input parameters: level: log level, such as nstack_log_level
+ symlink_basename: link basename, NULL is no link
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogSetLogSymlink(unsigned int level, const char* symlink_basename)
+{
+ SetLogSymlink(glogLevelMapping[level], symlink_basename);
+}
+
+/*****************************************************************************
+ Function name: glogFlushLogFiles
+ Function Description: Flushes all log files that contains messages that are at least of
+ the specified severity level. Thread-safe.
+ Input parameters: min_level: log level, such as nstack_log_level
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogFlushLogFiles(unsigned int min_level)
+{
+ FlushLogFiles(glogLevelMapping[min_level]);
+}
+
+/*****************************************************************************
+ Function name: glogSetLogFilenameExtension
+ Function Description: Specify an "extension" added to the filename specified via
+ SetLogDestination. This applies to all severity levels. It's
+ often used to append the port we're listening on to the logfile
+ name. Thread-safe.
+ Input parameters: filename_extension: extension filename of log file
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogSetLogFilenameExtension(const char* filename_extension)
+{
+ SetLogFilenameExtension(filename_extension);
+}
+
+/**
+* Define HlogAllocator type of global variables, initialized to the system malloc, free
+*/
+void* glogDefaultMalloc(size_t size)
+{
+ if (0 == size) {
+ return NULL;
+ }
+
+ return malloc(size);
+}
+
+/**
+* Define HlogAllocator type of global variables, initialized to the system malloc, free
+*/
+void glogDefaultFree(void *pointer)
+{
+ if (NULL != pointer) {
+ free(pointer);
+ }
+}
+
+/**
+* Defines a global variable of type HlogAllocator
+*/
+glog_allocator_s glogMemAllocator = {
+ glogDefaultMalloc,
+ glogDefaultFree
+};
+
+/**
+* Whether it has been registered
+*/
+bool glogMemAllocatorReged = false;
+
+/*****************************************************************************
+ Function name: glogMemAllocatorReg
+ Function Description: Register the memory application function.
+ Input parameters: allocator: memory request and release interface callback registration
+ Output parameters: NA
+ Return value: function returned successfully 0; unsuccessful return -1
+*****************************************************************************/
+int glogMemAllocatorReg(glog_allocator_s *allocator)
+{
+ if (false != glogMemAllocatorReged) {
+ return -1;
+ }
+
+ if (NULL == allocator) {
+ return -1;
+ }
+
+ if ((NULL == allocator->allocCb) || (NULL == allocator->freeCb)) {
+ return -1;
+ }
+
+ glogMemAllocatorReged = true;
+ glogMemAllocator.allocCb = allocator->allocCb;
+ glogMemAllocator.freeCb = allocator->freeCb;
+ return 0;
+}
+
+/*****************************************************************************
+Function name: glogMalloc
+Function Description: Memory application function.
+Enter the size of the memory request
+Output parameters: NA
+Return Value: The function executed successfully to return to the requested memory address;
+ returned NULL without success
+*****************************************************************************/
+
+void *glogMalloc(unsigned int size)
+{
+ return glogMemAllocator.allocCb(size);
+}
+
+/*****************************************************************************
+ Function name: glogFree
+ Function Description: Memory release function.
+ Input parameter: pointer: memory release pointer
+ Output parameters: NA
+ Return Value: NA
+*****************************************************************************/
+void glogFree(void *pointer)
+{
+ if (NULL != pointer) {
+ glogMemAllocator.freeCb(pointer);
+
+ }
+}
+
+/*****************************************************************************
+ Function name: glogRecordNumGet
+ Function Description: Generates a log record number to distinguish the log from the combination
+ Input parameters: NA
+ Output parameters: NA
+ Return value: return logging number
+*****************************************************************************/
+int glogRecordNumGet(void)
+{
+ int ret = glogAtomicRead(&g_logRecordNum) & max32BitNum;
+ glogAtomicInc(&g_logRecordNum);
+ return ret;
+}
+
+/*****************************************************************************
+ Function name: glogRavage
+ Functional Description: Segment the NSTACK log to suit the product log mode for easy integration
+ Enter the file name: fileName
+ fileLine file line number
+ funcName function name
+ fmtString NSTACK prints content
+ Output Parameters: pLogString: Returns the formatted log
+ Return Value: NA
+*****************************************************************************/
+void glogRavage(char *fileName,
+ const unsigned int fileLine,
+ const char *funcName,
+ const char *fmtString,
+ char *pLogString)
+{
+ int logNumLen = 0;
+ int len = strlen(fmtString);
+ int items = NSTACK_LOG_TRANSFER_TO_PRODUCE_ITEMS(len);
+ char tmpMsgBuff[MAX_ROSA_LOG_LEN +1] = "\0";
+ int logNum = 0;
+ int j = 0;
+
+ logNum = glogRecordNumGet();
+ logNumLen = snprintf(tmpMsgBuff,
+ MAX_32BIT_NUM_HEX_LEN +1,
+ "%x",
+ logNum);
+
+ for (int i= 0; i < items; i++) {
+ int item = i * MAX_ROSA_LOG_LEN;
+ int k = snprintf(tmpMsgBuff +logNumLen,
+ MAX_ROSA_LOG_LEN -logNumLen,
+ ":%x]",
+ i);
+
+ snprintf(pLogString +item,
+ MAX_ROSA_LOG_LEN +1,
+ "%s%s",
+ tmpMsgBuff,
+ fmtString +j);
+
+ j += MAX_ROSA_LOG_LEN -logNumLen -k;
+ if (j >= len) {
+ break;
+ }
+ }
+
+ return;
+}
+
+
+/**
+* @ingroup GLOG
+* @brief glog provides C interface print log.
+*
+* @verbatim
+ Function Description: Print the log.
+ Target users: LITESERVICE
+ Use the constraint: the user guarantees the correctness of the entry
+ Upgrade effect: no
+@endverbatim
+* @param type [input] print type
+* @param prestr [input] pre string
+* @param level [input] real level
+* @param count [input] repeat count
+* @param fileName [input] file name
+* @param fileLine [input] file line number
+* @param funcName [input] function name
+* @param format [input] accepts arguments
+*
+* @return NA
+* @par dependency:
+* <li>nstack_glog.ph£ºThis interface declares the header file.</li></ul>
+*/
+
+void glog_print(unsigned int type,
+ const char *prestr,
+ unsigned int level,
+ int count,
+ char *fileName,
+ const unsigned int fileLine,
+ const char *funcName,
+ const char *format,
+ ...)
+{
+ va_list ap;
+ char pMsgBuf[MAX_LOG_TRANSITIONAL_LEN] = "\0";
+ char *pRavageBuf = NULL;
+ char premodule[MAX_ROSA_LOG_LEN] = "\0";
+ char baseFile[MAX_ROSA_LOG_LEN +1] = "\0";
+ int buffLen = 0;
+ int prebuffLen = 0;
+ int print_type = 0;
+
+ /**
+ * default is GLOG_LEVEL_INFO
+ */
+ if((type > GLOG_LEVEL_FATAL) || (level > GLOG_LEVEL_FATAL)){
+ return;
+ }
+ if (GLOG_LEVEL_BUTT == g_LogLevelPrint) {
+ (void)glogLevelSet(GLOG_LEVEL_INFO);
+ }
+
+ if (NULL != strrchr(fileName, '/')) {
+ snprintf(baseFile, MAX_ROSA_LOG_LEN, "%s", strrchr(fileName, '/') + 1);
+ } else {
+ snprintf(baseFile, MAX_ROSA_LOG_LEN, "%s", fileName);
+ }
+
+ if((NULL != prestr) && (0 != strlen(prestr))){
+ if(count < 0){
+ snprintf(premodule, MAX_ROSA_LOG_LEN - 1, "<%s>", prestr);
+ }
+ else{
+ snprintf(premodule, MAX_ROSA_LOG_LEN - 1, " %d <%s>", count, prestr);
+ }
+ }
+
+
+ print_type = (g_log_hook_tag.log_hook != NULL) ? HLOG_PRINT_TYPE_HOOK : HLOG_PRINT_TYPE_GLOG;
+ if (HLOG_PRINT_TYPE_GLOG != print_type ) {
+
+ if(level < g_log_hook_tag.level){
+ return;
+ }
+ /**
+ * log premessage
+ */
+ prebuffLen = snprintf(pMsgBuf,
+ MAX_LOG_TRANSITIONAL_LEN,
+ "%ld %s:%d]%d,%s]",
+ syscall(__NR_gettid),
+ baseFile,
+ fileLine,
+ getpid(),
+ funcName);
+ if (prebuffLen <= 0) {
+ printf("ERROR: get prefix log failed]level=%d,fileName=%s,fileLine=%d,funcName=%s,msg=%s\n",
+ level, baseFile, fileLine, funcName, pMsgBuf);
+ return;
+ }
+ prebuffLen = (prebuffLen >= MAX_LOG_TRANSITIONAL_LEN) ? (MAX_LOG_TRANSITIONAL_LEN - 1) : prebuffLen;
+ }
+
+ /**
+ * log message
+ */
+ va_start(ap, format);
+ buffLen = vsnprintf(pMsgBuf +prebuffLen,
+ MAX_LOG_TRANSITIONAL_LEN -prebuffLen,
+ format,
+ ap);
+ if (buffLen <= 0) {
+ printf("ERROR: get message failed]level=%d,fileName=%s,fileLine=%d,funcName=%s,msg=%s\n",
+ level, baseFile, fileLine, funcName, pMsgBuf);
+ va_end(ap);
+ return;
+ }
+ va_end(ap);
+ buffLen = (buffLen +prebuffLen >= MAX_LOG_TRANSITIONAL_LEN) ? (MAX_LOG_TRANSITIONAL_LEN -prebuffLen -1) : buffLen;
+
+ switch (print_type) {
+
+ case HLOG_PRINT_TYPE_HOOK: {
+ int ravageBufLen = NSTACK_LOG_TRANSFER_TO_PRODUCE_ITEMS(prebuffLen +buffLen) * MAX_ROSA_LOG_LEN +1;
+ pRavageBuf = (char *)glogMalloc(ravageBufLen);
+ if (NULL == pRavageBuf) {
+ printf("ERROR: malloc failed]level=%d,fileName=%s,fileLine=%d,funcName=%s,msg=%s\n",
+ level, baseFile, fileLine, funcName, pMsgBuf);
+ return;
+ }
+ memset(pRavageBuf, 0, ravageBufLen);
+
+ glogRavage(baseFile, fileLine, funcName, pMsgBuf, pRavageBuf);
+ g_log_hook_tag.log_hook(LOG_CODE,
+ level,
+ (void*)"%s",
+ (void*)pRavageBuf);
+ glogFree(pRavageBuf);
+ break;
+ }
+
+ default: {
+ LogMessage(baseFile,
+ fileLine,
+ glogLevelMapping[type],
+ level).stream()
+ << getpid()
+ << ","
+ << funcName
+ << premodule
+ << pMsgBuf;
+ break;
+ }
+ }
+
+ return;
+}
+
+
+// overload new: use ram management of user
+void *LogMessageAdapter::LogRamMgnt::operator new(size_t size)
+{
+ if (0 == size) {
+ throw bad_alloc();
+ }
+ void *mem = glogMalloc(size);
+ if (mem != NULL) {
+ return mem;
+ } else {
+ throw bad_alloc();
+ }
+}
+
+// overload delete: use ram management of user
+void LogMessageAdapter::LogRamMgnt::operator delete(void *ptr)
+{
+ if (ptr != NULL) {
+ glogFree(ptr);
+ }
+}
+
+LogMessageAdapter::LogMsgAdpData::~LogMsgAdpData()
+{
+ delete pMsgBuff;
+ pMsgBuff = NULL;
+ delete stream_alloc_;
+ stream_alloc_ = NULL;
+}
+
+// mapping glog level to glog level
+static const unsigned int HLogMapping[NUM_SEVERITIES] =
+ {GLOG_LEVEL_INFO, GLOG_LEVEL_WARNING, GLOG_LEVEL_ERROR, GLOG_LEVEL_FATAL};
+
+LogMessageAdapter::LogMessageAdapter(const char *file,
+ int line,
+ const char *funcName,
+ int logLevel)
+{
+ /**
+ * must be here before return, if not you will be happy to cool
+ */
+ allocated = NULL;
+ data = NULL;
+
+ /**
+ * default is GLOG_LEVEL_INFO
+ */
+ if (GLOG_LEVEL_BUTT == g_LogLevelPrint) {
+ int safe_minloglevel = 0;
+ if (FLAGS_minloglevel > 0) {
+ safe_minloglevel = (FLAGS_minloglevel >= NUM_SEVERITIES) ? (NUM_SEVERITIES -1) : FLAGS_minloglevel;
+ }
+ (void)glogLevelSet(HLogMapping[safe_minloglevel]);
+ }
+
+ if ((HLogMapping[logLevel] < g_LogLevelPrint) && (GLOG_LEVEL_BUTT != g_LogLevelPrint)) {
+ return;
+ }
+
+ if (0 == g_LogLenPrint) {
+ glogPrintLengthSet(MAX_LOG_TRANSITIONAL_LEN);
+ }
+
+ try {
+ allocated = new LogMsgAdpData();
+ data = allocated;
+
+ data->pMsgBuff = NULL;
+ data->pMsgBuff = new char[g_LogLenPrint +1];
+ memset(data->pMsgBuff, 0, g_LogLenPrint +1);
+
+ data->stream_alloc_ = NULL;
+ data->stream_ = NULL;
+ data->stream_alloc_ = new LogStream(data->pMsgBuff, g_LogLenPrint, 0);
+ data->stream_ = data->stream_alloc_;
+
+ if (NULL != strrchr(const_cast<char*>(file), '/')) {
+ snprintf(data->fileName, MAX_ROSA_LOG_LEN, "%s", strrchr(const_cast<char*>(file), '/') + 1);
+ } else {
+ snprintf(data->fileName, MAX_ROSA_LOG_LEN, "%s", const_cast<char*>(file));
+ }
+
+ snprintf(data->func, MAX_ROSA_LOG_LEN, "%s", const_cast<char*>(funcName));
+
+ data->line = line;
+ data->level = logLevel;
+
+ stream().fill('0');
+ } catch (exception& e) {
+ std::cerr << "malloc failed]file=" << file <<",line=" << line
+ << ",funcName" << funcName << ",exception=" << e.what() << endl;
+ return;
+ }
+
+}
+
+LogMessageAdapter::~LogMessageAdapter()
+{
+ if (NULL == data) {
+ return;
+ }
+
+ unsigned int printType = (g_log_hook_tag.log_hook != NULL) ? HLOG_PRINT_TYPE_HOOK : HLOG_PRINT_TYPE_GLOG;
+ if (HLOG_PRINT_TYPE_GLOG != printType) {
+ glog_print(GLOG_LEVEL_INFO,
+ "GLOG",
+ HLogMapping[data->level],
+ -1,
+ data->fileName,
+ data->line,
+ data->func,
+ "%s",
+ data->pMsgBuff);
+ } else {
+ LogMessage(data->fileName,
+ data->line,
+ GLOG_INFO,
+ (data->level + 1)).stream() << getpid() << "," << data->func << "(GLOG) " << data->pMsgBuff;
+ }
+
+
+ delete allocated;
+ allocated = NULL;
+}
+
+static ostream glogNullStream(NULL);
+ostream& LogMessageAdapter::stream()
+{
+ if((NULL == data) || (NULL == data->stream_)) {
+ return glogNullStream;
+ }
+
+ return *(data->stream_);
+}
+
+
+void SetGlogCtrlOpt(int opt)
+{
+ glogCtrlOpt = opt;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/raw_logging.cc b/thirdparty/glog/glog-0.3.4/src/raw_logging.cc
new file mode 100644
index 0000000..7a7409b
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/raw_logging.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Maxim Lifantsev
+//
+// logging_unittest.cc covers the functionality herein
+
+#include "utilities.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> // for close() and write()
+#endif
+#include <fcntl.h> // for open()
+#include <time.h>
+#include "config.h"
+#include "glog/logging.h" // To pick up flag settings etc.
+#include "glog/raw_logging.h"
+#include "base/commandlineflags.h"
+
+#ifdef HAVE_STACKTRACE
+# include "stacktrace.h"
+#endif
+
+#if defined(HAVE_SYSCALL_H)
+#include <syscall.h> // for syscall()
+#elif defined(HAVE_SYS_SYSCALL_H)
+#include <sys/syscall.h> // for syscall()
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
+# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
+#else
+ // Not so safe, but what can you do?
+# define safe_write(fd, s, len) write(fd, s, len)
+#endif
+
+_START_GOOGLE_NAMESPACE_
+
+// Data for RawLog__ below. We simply pick up the latest
+// time data created by a normal log message to avoid calling
+// localtime_r which can allocate memory.
+static struct ::tm last_tm_time_for_raw_log;
+static int last_usecs_for_raw_log;
+
+void RawLog__SetLastTime(const struct ::tm& t, int usecs) {
+ memcpy(&last_tm_time_for_raw_log, &t, sizeof(last_tm_time_for_raw_log));
+ last_usecs_for_raw_log = usecs;
+}
+
+// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
+// that invoke malloc() and getenv() that might acquire some locks.
+// If this becomes a problem we should reimplement a subset of vsnprintf
+// that does not need locks and malloc.
+
+// Helper for RawLog__ below.
+// *DoRawLog writes to *buf of *size and move them past the written portion.
+// It returns true iff there was no overflow or error.
+static bool DoRawLog(char** buf, int* size, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ int n = vsnprintf(*buf, *size, format, ap);
+ va_end(ap);
+ if (n < 0 || n > *size) return false;
+ *size -= n;
+ *buf += n;
+ return true;
+}
+
+// Helper for RawLog__ below.
+inline static bool VADoRawLog(char** buf, int* size,
+ const char* format, va_list ap) {
+ int n = vsnprintf(*buf, *size, format, ap);
+ if (n < 0 || n > *size) return false;
+ *size -= n;
+ *buf += n;
+ return true;
+}
+
+static const int kLogBufSize = 3000;
+static bool crashed = false;
+static CrashReason crash_reason;
+static char crash_buf[kLogBufSize + 1] = { 0 }; // Will end in '\0'
+
+void RawLog__(LogSeverity severity, const char* file, int line,
+ const char* format, ...) {
+ if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
+ FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
+ return; // this stderr log message is suppressed
+ }
+ // can't call localtime_r here: it can allocate
+ struct ::tm& t = last_tm_time_for_raw_log;
+ char buffer[kLogBufSize];
+ char* buf = buffer;
+ int size = sizeof(buffer);
+
+ // NOTE: this format should match the specification in base/logging.h
+ DoRawLog(&buf, &size, "%c%02d%02d %02d:%02d:%02d.%06d %5u %s:%d] RAW: ",
+ LogSeverityNames[severity][0],
+ 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
+ last_usecs_for_raw_log,
+ static_cast<unsigned int>(GetTID()),
+ const_basename(const_cast<char *>(file)), line);
+
+ // Record the position and size of the buffer after the prefix
+ const char* msg_start = buf;
+ const int msg_size = size;
+
+ va_list ap;
+ va_start(ap, format);
+ bool no_chop = VADoRawLog(&buf, &size, format, ap);
+ va_end(ap);
+ if (no_chop) {
+ DoRawLog(&buf, &size, "\n");
+ } else {
+ DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
+ }
+ // We make a raw syscall to write directly to the stderr file descriptor,
+ // avoiding FILE buffering (to avoid invoking malloc()), and bypassing
+ // libc (to side-step any libc interception).
+ // We write just once to avoid races with other invocations of RawLog__.
+ safe_write(STDERR_FILENO, buffer, strlen(buffer));
+ if (severity == GLOG_FATAL) {
+ if (!sync_val_compare_and_swap(&crashed, false, true)) {
+ crash_reason.filename = file;
+ crash_reason.line_number = line;
+ memcpy(crash_buf, msg_start, msg_size); // Don't include prefix
+ crash_reason.message = crash_buf;
+#ifdef HAVE_STACKTRACE
+ crash_reason.depth =
+ GetStackTrace(crash_reason.stack, ARRAYSIZE(crash_reason.stack), 1);
+#else
+ crash_reason.depth = 0;
+#endif
+ SetCrashReason(&crash_reason);
+ }
+ LogMessage::Fail(); // abort()
+ }
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/signalhandler.cc b/thirdparty/glog/glog-0.3.4/src/signalhandler.cc
new file mode 100644
index 0000000..3759580
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/signalhandler.cc
@@ -0,0 +1,362 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// Implementation of InstallFailureSignalHandler().
+
+#include "utilities.h"
+#include "stacktrace.h"
+#include "symbolize.h"
+#include "glog/logging.h"
+
+#include <signal.h>
+#include <time.h>
+#ifdef HAVE_UCONTEXT_H
+# include <ucontext.h>
+#endif
+#ifdef HAVE_SYS_UCONTEXT_H
+# include <sys/ucontext.h>
+#endif
+#include <algorithm>
+
+_START_GOOGLE_NAMESPACE_
+
+// TOOD(hamaji): Use signal instead of sigaction?
+#ifdef HAVE_SIGACTION
+
+namespace {
+
+// We'll install the failure signal handler for these signals. We could
+// use strsignal() to get signal names, but we don't use it to avoid
+// introducing yet another #ifdef complication.
+//
+// The list should be synced with the comment in signalhandler.h.
+const struct {
+ int number;
+ const char *name;
+} kFailureSignals[] = {
+ { SIGSEGV, "SIGSEGV" },
+ { SIGILL, "SIGILL" },
+ { SIGFPE, "SIGFPE" },
+ { SIGABRT, "SIGABRT" },
+ { SIGBUS, "SIGBUS" },
+ { SIGTERM, "SIGTERM" },
+};
+
+// Returns the program counter from signal context, NULL if unknown.
+void* GetPC(void* ucontext_in_void) {
+#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
+ if (ucontext_in_void != NULL) {
+ ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
+ return (void*)context->PC_FROM_UCONTEXT;
+ }
+#endif
+ return NULL;
+}
+
+// The class is used for formatting error messages. We don't use printf()
+// as it's not async signal safe.
+class MinimalFormatter {
+ public:
+ MinimalFormatter(char *buffer, int size)
+ : buffer_(buffer),
+ cursor_(buffer),
+ end_(buffer + size) {
+ }
+
+ // Returns the number of bytes written in the buffer.
+ int num_bytes_written() const { return cursor_ - buffer_; }
+
+ // Appends string from "str" and updates the internal cursor.
+ void AppendString(const char* str) {
+ int i = 0;
+ while (str[i] != '\0' && cursor_ + i < end_) {
+ cursor_[i] = str[i];
+ ++i;
+ }
+ cursor_ += i;
+ }
+
+ // Formats "number" in "radix" and updates the internal cursor.
+ // Lowercase letters are used for 'a' - 'z'.
+ void AppendUint64(uint64 number, int radix) {
+ int i = 0;
+ while (cursor_ + i < end_) {
+ const int tmp = number % radix;
+ number /= radix;
+ cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
+ ++i;
+ if (number == 0) {
+ break;
+ }
+ }
+ // Reverse the bytes written.
+ std::reverse(cursor_, cursor_ + i);
+ cursor_ += i;
+ }
+
+ // Formats "number" as hexadecimal number, and updates the internal
+ // cursor. Padding will be added in front if needed.
+ void AppendHexWithPadding(uint64 number, int width) {
+ char* start = cursor_;
+ AppendString("0x");
+ AppendUint64(number, 16);
+ // Move to right and add padding in front if needed.
+ if (cursor_ < start + width) {
+ const int64 delta = start + width - cursor_;
+ std::copy(start, cursor_, start + delta);
+ std::fill(start, start + delta, ' ');
+ cursor_ = start + width;
+ }
+ }
+
+ private:
+ char *buffer_;
+ char *cursor_;
+ const char * const end_;
+};
+
+// Writes the given data with the size to the standard error.
+void WriteToStderr(const char* data, int size) {
+ if (write(STDERR_FILENO, data, size) < 0) {
+ // Ignore errors.
+ }
+}
+
+// The writer function can be changed by InstallFailureWriter().
+void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
+
+// Dumps time information. We don't dump human-readable time information
+// as localtime() is not guaranteed to be async signal safe.
+void DumpTimeInfo() {
+ time_t time_in_sec = time(NULL);
+ char buf[256]; // Big enough for time info.
+ MinimalFormatter formatter(buf, sizeof(buf));
+ formatter.AppendString("*** Aborted at ");
+ formatter.AppendUint64(time_in_sec, 10);
+ formatter.AppendString(" (unix time)");
+ formatter.AppendString(" try \"date -d @");
+ formatter.AppendUint64(time_in_sec, 10);
+ formatter.AppendString("\" if you are using GNU date ***\n");
+ g_failure_writer(buf, formatter.num_bytes_written());
+}
+
+// Dumps information about the signal to STDERR.
+void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
+ // Get the signal name.
+ const char* signal_name = NULL;
+ for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
+ if (signal_number == kFailureSignals[i].number) {
+ signal_name = kFailureSignals[i].name;
+ }
+ }
+
+ char buf[256]; // Big enough for signal info.
+ MinimalFormatter formatter(buf, sizeof(buf));
+
+ formatter.AppendString("*** ");
+ if (signal_name) {
+ formatter.AppendString(signal_name);
+ } else {
+ // Use the signal number if the name is unknown. The signal name
+ // should be known, but just in case.
+ formatter.AppendString("Signal ");
+ formatter.AppendUint64(signal_number, 10);
+ }
+ formatter.AppendString(" (@0x");
+ formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
+ formatter.AppendString(")");
+ formatter.AppendString(" received by PID ");
+ formatter.AppendUint64(getpid(), 10);
+ formatter.AppendString(" (TID 0x");
+ // We assume pthread_t is an integral number or a pointer, rather
+ // than a complex struct. In some environments, pthread_self()
+ // returns an uint64 but in some other environments pthread_self()
+ // returns a pointer. Hence we use C-style cast here, rather than
+ // reinterpret/static_cast, to support both types of environments.
+ formatter.AppendUint64((uintptr_t)pthread_self(), 16);
+ formatter.AppendString(") ");
+ // Only linux has the PID of the signal sender in si_pid.
+#ifdef OS_LINUX
+ formatter.AppendString("from PID ");
+ formatter.AppendUint64(siginfo->si_pid, 10);
+ formatter.AppendString("; ");
+#endif
+ formatter.AppendString("stack trace: ***\n");
+ g_failure_writer(buf, formatter.num_bytes_written());
+}
+
+// Dumps information about the stack frame to STDERR.
+void DumpStackFrameInfo(const char* prefix, void* pc) {
+ // Get the symbol name.
+ const char *symbol = "(unknown)";
+ char symbolized[1024]; // Big enough for a sane symbol.
+ // Symbolizes the previous address of pc because pc may be in the
+ // next function.
+ if (Symbolize(reinterpret_cast<char *>(pc) - 1,
+ symbolized, sizeof(symbolized))) {
+ symbol = symbolized;
+ }
+
+ char buf[1024]; // Big enough for stack frame info.
+ MinimalFormatter formatter(buf, sizeof(buf));
+
+ formatter.AppendString(prefix);
+ formatter.AppendString("@ ");
+ const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
+ formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
+ formatter.AppendString(" ");
+ formatter.AppendString(symbol);
+ formatter.AppendString("\n");
+ g_failure_writer(buf, formatter.num_bytes_written());
+}
+
+// Invoke the default signal handler.
+void InvokeDefaultSignalHandler(int signal_number) {
+ struct sigaction sig_action;
+ memset(&sig_action, 0, sizeof(sig_action));
+ sigemptyset(&sig_action.sa_mask);
+ sig_action.sa_handler = SIG_DFL;
+ sigaction(signal_number, &sig_action, NULL);
+ kill(getpid(), signal_number);
+}
+
+// This variable is used for protecting FailureSignalHandler() from
+// dumping stuff while another thread is doing it. Our policy is to let
+// the first thread dump stuff and let other threads wait.
+// See also comments in FailureSignalHandler().
+static pthread_t* g_entered_thread_id_pointer = NULL;
+
+// Dumps signal and stack frame information, and invokes the default
+// signal handler once our job is done.
+void FailureSignalHandler(int signal_number,
+ siginfo_t *signal_info,
+ void *ucontext) {
+ // First check if we've already entered the function. We use an atomic
+ // compare and swap operation for platforms that support it. For other
+ // platforms, we use a naive method that could lead to a subtle race.
+
+ // We assume pthread_self() is async signal safe, though it's not
+ // officially guaranteed.
+ pthread_t my_thread_id = pthread_self();
+ // NOTE: We could simply use pthread_t rather than pthread_t* for this,
+ // if pthread_self() is guaranteed to return non-zero value for thread
+ // ids, but there is no such guarantee. We need to distinguish if the
+ // old value (value returned from __sync_val_compare_and_swap) is
+ // different from the original value (in this case NULL).
+ pthread_t* old_thread_id_pointer =
+ glog_ns_internal_namespace_::sync_val_compare_and_swap(
+ &g_entered_thread_id_pointer,
+ static_cast<pthread_t*>(NULL),
+ &my_thread_id);
+ if (old_thread_id_pointer != NULL) {
+ // We've already entered the signal handler. What should we do?
+ if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
+ // It looks the current thread is reentering the signal handler.
+ // Something must be going wrong (maybe we are reentering by another
+ // type of signal?). Kill ourself by the default signal handler.
+ InvokeDefaultSignalHandler(signal_number);
+ }
+ // Another thread is dumping stuff. Let's wait until that thread
+ // finishes the job and kills the process.
+ while (true) {
+ sleep(1);
+ }
+ }
+ // This is the first time we enter the signal handler. We are going to
+ // do some interesting stuff from here.
+ // TODO(satorux): We might want to set timeout here using alarm(), but
+ // mixing alarm() and sleep() can be a bad idea.
+
+ // First dump time info.
+ DumpTimeInfo();
+
+ // Get the program counter from ucontext.
+ void *pc = GetPC(ucontext);
+ DumpStackFrameInfo("PC: ", pc);
+
+#ifdef HAVE_STACKTRACE
+ // Get the stack traces.
+ void *stack[32];
+ // +1 to exclude this function.
+ const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
+ DumpSignalInfo(signal_number, signal_info);
+ // Dump the stack traces.
+ for (int i = 0; i < depth; ++i) {
+ DumpStackFrameInfo(" ", stack[i]);
+ }
+#endif
+
+ // *** TRANSITION ***
+ //
+ // BEFORE this point, all code must be async-termination-safe!
+ // (See WARNING above.)
+ //
+ // AFTER this point, we do unsafe things, like using LOG()!
+ // The process could be terminated or hung at any time. We try to
+ // do more useful things first and riskier things later.
+
+ // Flush the logs before we do anything in case 'anything'
+ // causes problems.
+ FlushLogFilesUnsafe(0);
+
+ // Kill ourself by the default signal handler.
+ InvokeDefaultSignalHandler(signal_number);
+}
+
+} // namespace
+
+#endif // HAVE_SIGACTION
+
+void InstallFailureSignalHandler() {
+#ifdef HAVE_SIGACTION
+ // Build the sigaction struct.
+ struct sigaction sig_action;
+ memset(&sig_action, 0, sizeof(sig_action));
+ sigemptyset(&sig_action.sa_mask);
+ sig_action.sa_flags |= SA_SIGINFO;
+ sig_action.sa_sigaction = &FailureSignalHandler;
+
+ for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
+ CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
+ }
+#endif // HAVE_SIGACTION
+}
+
+void InstallFailureWriter(void (*writer)(const char* data, int size)) {
+#ifdef HAVE_SIGACTION
+ g_failure_writer = writer;
+#endif // HAVE_SIGACTION
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.cc b/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.cc
new file mode 100644
index 0000000..1cd0fa0
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// This is a helper binary for testing signalhandler.cc. The actual test
+// is done in signalhandler_unittest.sh.
+
+#include "utilities.h"
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include "glog/logging.h"
+
+using namespace GOOGLE_NAMESPACE;
+
+void* DieInThread(void*) {
+ // We assume pthread_t is an integral number or a pointer, rather
+ // than a complex struct. In some environments, pthread_self()
+ // returns an uint64 but in some other environments pthread_self()
+ // returns a pointer. Hence we use C-style cast here, rather than
+ // reinterpret/static_cast, to support both types of environments.
+ fprintf(stderr, "0x%lx is dying\n", (long)pthread_self());
+ // Use volatile to prevent from these to be optimized away.
+ volatile int a = 0;
+ volatile int b = 1 / a;
+ fprintf(stderr, "We should have died: b=%d\n", b);
+ return NULL;
+}
+
+void WriteToStdout(const char* data, int size) {
+ if (write(STDOUT_FILENO, data, size) < 0) {
+ // Ignore errors.
+ }
+}
+
+int main(int argc, char **argv) {
+#if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE)
+ InitGoogleLogging(argv[0]);
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ InstallFailureSignalHandler();
+ const std::string command = argc > 1 ? argv[1] : "none";
+ if (command == "segv") {
+ // We'll check if this is outputted.
+ LOG(INFO) << "create the log file";
+ LOG(INFO) << "a message before segv";
+ // We assume 0xDEAD is not writable.
+ int *a = (int*)0xDEAD;
+ *a = 0;
+ } else if (command == "loop") {
+ fprintf(stderr, "looping\n");
+ while (true);
+ } else if (command == "die_in_thread") {
+ pthread_t thread;
+ pthread_create(&thread, NULL, &DieInThread, NULL);
+ pthread_join(thread, NULL);
+ } else if (command == "dump_to_stdout") {
+ InstallFailureWriter(WriteToStdout);
+ abort();
+ } else {
+ // Tell the shell script
+ puts("OK");
+ }
+#endif
+ return 0;
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.sh b/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.sh
new file mode 100644
index 0000000..265cd45
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/signalhandler_unittest.sh
@@ -0,0 +1,131 @@
+#! /bin/sh
+#
+# Copyright (c) 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: Satoru Takabayashi
+#
+# Unit tests for signalhandler.cc.
+
+die () {
+ echo $1
+ exit 1
+}
+
+BINDIR=".libs"
+LIBGLOG="$BINDIR/libglog.so"
+
+BINARY="$BINDIR/signalhandler_unittest"
+LOG_INFO="./signalhandler_unittest.INFO"
+
+# Remove temporary files.
+rm -f signalhandler.out*
+
+if test -e "$BINARY"; then
+ # We need shared object.
+ export LD_LIBRARY_PATH=$BINDIR
+ export DYLD_LIBRARY_PATH=$BINDIR
+else
+ # For windows
+ BINARY="./signalhandler_unittest.exe"
+ if ! test -e "$BINARY"; then
+ echo "We coundn't find demangle_unittest binary."
+ exit 1
+ fi
+fi
+
+if [ x`$BINARY` != 'xOK' ]; then
+ echo "PASS (No stacktrace support. We don't run this test.)"
+ exit 0
+fi
+
+# The PC cannot be obtained in signal handlers on PowerPC correctly.
+# We just skip the test for PowerPC.
+if [ x`uname -p` = x"powerpc" ]; then
+ echo "PASS (We don't test the signal handler on PowerPC.)"
+ exit 0
+fi
+
+# Test for a case the program kills itself by SIGSEGV.
+GOOGLE_LOG_DIR=. $BINARY segv 2> signalhandler.out1
+for pattern in SIGSEGV 0xdead main "Aborted at [0-9]"; do
+ if ! grep --quiet "$pattern" signalhandler.out1; then
+ die "'$pattern' should appear in the output"
+ fi
+done
+if ! grep --quiet "a message before segv" $LOG_INFO; then
+ die "'a message before segv' should appear in the INFO log"
+fi
+rm -f $LOG_INFO
+
+# Test for a case the program is killed by this shell script.
+# $! = the process id of the last command run in the background.
+# $$ = the process id of this shell.
+$BINARY loop 2> signalhandler.out2 &
+# Wait until "looping" is written in the file. This indicates the program
+# is ready to accept signals.
+while true; do
+ if grep --quiet looping signalhandler.out2; then
+ break
+ fi
+done
+kill -TERM $!
+wait $!
+
+from_pid=''
+# Only linux has the process ID of the signal sender.
+if [ x`uname` = "xLinux" ]; then
+ from_pid="from PID $$"
+fi
+for pattern in SIGTERM "by PID $!" "$from_pid" main "Aborted at [0-9]"; do
+ if ! grep --quiet "$pattern" signalhandler.out2; then
+ die "'$pattern' should appear in the output"
+ fi
+done
+
+# Test for a case the program dies in a non-main thread.
+$BINARY die_in_thread 2> signalhandler.out3
+EXPECTED_TID="`sed 's/ .*//; q' signalhandler.out3`"
+
+for pattern in SIGFPE DieInThread "TID $EXPECTED_TID" "Aborted at [0-9]"; do
+ if ! grep --quiet "$pattern" signalhandler.out3; then
+ die "'$pattern' should appear in the output"
+ fi
+done
+
+# Test for a case the program installs a custom failure writer that writes
+# stuff to stdout instead of stderr.
+$BINARY dump_to_stdout 1> signalhandler.out4
+for pattern in SIGABRT main "Aborted at [0-9]"; do
+ if ! grep --quiet "$pattern" signalhandler.out4; then
+ die "'$pattern' should appear in the output"
+ fi
+done
+
+echo PASS
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace.h b/thirdparty/glog/glog-0.3.4/src/stacktrace.h
new file mode 100644
index 0000000..8c3e8fe
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2000 - 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Routines to extract the current stack trace. These functions are
+// thread-safe.
+
+#ifndef BASE_STACKTRACE_H_
+#define BASE_STACKTRACE_H_
+
+#include "config.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// This is similar to the GetStackFrames routine, except that it returns
+// the stack trace only, and not the stack frame sizes as well.
+// Example:
+// main() { foo(); }
+// foo() { bar(); }
+// bar() {
+// void* result[10];
+// int depth = GetStackFrames(result, 10, 1);
+// }
+//
+// This produces:
+// result[0] foo
+// result[1] main
+// .... ...
+//
+// "result" must not be NULL.
+extern int GetStackTrace(void** result, int max_depth, int skip_count);
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // BASE_STACKTRACE_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_generic-inl.h b/thirdparty/glog/glog-0.3.4/src/stacktrace_generic-inl.h
new file mode 100644
index 0000000..fad81d3
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_generic-inl.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2000 - 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Portable implementation - just use glibc
+//
+// Note: The glibc implementation may cause a call to malloc.
+// This can cause a deadlock in HeapProfiler.
+#include <execinfo.h>
+#include <string.h>
+#include "stacktrace.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// If you change this function, also change GetStackFrames below.
+int GetStackTrace(void** result, int max_depth, int skip_count) {
+ static const int kStackLength = 64;
+ void * stack[kStackLength];
+ int size;
+
+ size = backtrace(stack, kStackLength);
+ skip_count++; // we want to skip the current frame as well
+ int result_count = size - skip_count;
+ if (result_count < 0)
+ result_count = 0;
+ if (result_count > max_depth)
+ result_count = max_depth;
+ for (int i = 0; i < result_count; i++)
+ result[i] = stack[i + skip_count];
+
+ return result_count;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_libunwind-inl.h b/thirdparty/glog/glog-0.3.4/src/stacktrace_libunwind-inl.h
new file mode 100644
index 0000000..0dc14c6
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_libunwind-inl.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2005 - 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Arun Sharma
+//
+// Produce stack trace using libunwind
+
+#include "utilities.h"
+
+extern "C" {
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+}
+#include "glog/raw_logging.h"
+#include "stacktrace.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// Sometimes, we can try to get a stack trace from within a stack
+// trace, because libunwind can call mmap (maybe indirectly via an
+// internal mmap based memory allocator), and that mmap gets trapped
+// and causes a stack-trace request. If were to try to honor that
+// recursive request, we'd end up with infinite recursion or deadlock.
+// Luckily, it's safe to ignore those subsequent traces. In such
+// cases, we return 0 to indicate the situation.
+static bool g_now_entering = false;
+
+// If you change this function, also change GetStackFrames below.
+int GetStackTrace(void** result, int max_depth, int skip_count) {
+ void *ip;
+ int n = 0;
+ unw_cursor_t cursor;
+ unw_context_t uc;
+
+ if (sync_val_compare_and_swap(&g_now_entering, false, true)) {
+ return 0;
+ }
+
+ unw_getcontext(&uc);
+ RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed");
+ skip_count++; // Do not include the "GetStackTrace" frame
+
+ while (n < max_depth) {
+ int ret = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip);
+ if (ret < 0)
+ break;
+ if (skip_count > 0) {
+ skip_count--;
+ } else {
+ result[n++] = ip;
+ }
+ ret = unw_step(&cursor);
+ if (ret <= 0)
+ break;
+ }
+
+ g_now_entering = false;
+ return n;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_powerpc-inl.h b/thirdparty/glog/glog-0.3.4/src/stacktrace_powerpc-inl.h
new file mode 100644
index 0000000..83f6cf2
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_powerpc-inl.h
@@ -0,0 +1,133 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Craig Silverstein
+//
+// Produce stack trace. I'm guessing (hoping!) the code is much like
+// for x86. For apple machines, at least, it seems to be; see
+// http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
+// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
+// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
+
+#include <stdio.h>
+#include <stdint.h> // for uintptr_t
+#include "stacktrace.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// Given a pointer to a stack frame, locate and return the calling
+// stackframe, or return NULL if no stackframe can be found. Perform sanity
+// checks (the strictness of which is controlled by the boolean parameter
+// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
+template<bool STRICT_UNWINDING>
+static void **NextStackFrame(void **old_sp) {
+ void **new_sp = (void **) *old_sp;
+
+ // Check that the transition from frame pointer old_sp to frame
+ // pointer new_sp isn't clearly bogus
+ if (STRICT_UNWINDING) {
+ // With the stack growing downwards, older stack frame must be
+ // at a greater address that the current one.
+ if (new_sp <= old_sp) return NULL;
+ // Assume stack frames larger than 100,000 bytes are bogus.
+ if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
+ } else {
+ // In the non-strict mode, allow discontiguous stack frames.
+ // (alternate-signal-stacks for example).
+ if (new_sp == old_sp) return NULL;
+ // And allow frames upto about 1MB.
+ if ((new_sp > old_sp)
+ && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
+ }
+ if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
+ return new_sp;
+}
+
+// This ensures that GetStackTrace stes up the Link Register properly.
+void StacktracePowerPCDummyFunction() __attribute__((noinline));
+void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
+
+// If you change this function, also change GetStackFrames below.
+int GetStackTrace(void** result, int max_depth, int skip_count) {
+ void **sp;
+ // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
+ // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
+ // different asm syntax. I don't know quite the best way to discriminate
+ // systems using the old as from the new one; I've gone with __APPLE__.
+#ifdef __APPLE__
+ __asm__ volatile ("mr %0,r1" : "=r" (sp));
+#else
+ __asm__ volatile ("mr %0,1" : "=r" (sp));
+#endif
+
+ // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack
+ // entry that holds the return address of the subroutine call (what
+ // instruction we run after our function finishes). This is the
+ // same as the stack-pointer of our parent routine, which is what we
+ // want here. While the compiler will always(?) set up LR for
+ // subroutine calls, it may not for leaf functions (such as this one).
+ // This routine forces the compiler (at least gcc) to push it anyway.
+ StacktracePowerPCDummyFunction();
+
+ // The LR save area is used by the callee, so the top entry is bogus.
+ skip_count++;
+
+ int n = 0;
+ while (sp && n < max_depth) {
+ if (skip_count > 0) {
+ skip_count--;
+ } else {
+ // PowerPC has 3 main ABIs, which say where in the stack the
+ // Link Register is. For DARWIN and AIX (used by apple and
+ // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc),
+ // it's in sp[1].
+#if defined(_CALL_AIX) || defined(_CALL_DARWIN)
+ result[n++] = *(sp+2);
+#elif defined(_CALL_SYSV)
+ result[n++] = *(sp+1);
+#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
+ // This check is in case the compiler doesn't define _CALL_AIX/etc.
+ result[n++] = *(sp+2);
+#elif defined(__linux)
+ // This check is in case the compiler doesn't define _CALL_SYSV.
+ result[n++] = *(sp+1);
+#else
+#error Need to specify the PPC ABI for your archiecture.
+#endif
+ }
+ // Use strict unwinding rules.
+ sp = NextStackFrame<true>(sp);
+ }
+ return n;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_unittest.cc b/thirdparty/glog/glog-0.3.4/src/stacktrace_unittest.cc
new file mode 100644
index 0000000..c1b3b36
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_unittest.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2004, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utilities.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "base/commandlineflags.h"
+#include "glog/logging.h"
+#include "stacktrace.h"
+
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
+
+using namespace GOOGLE_NAMESPACE;
+
+#ifdef HAVE_STACKTRACE
+
+// Obtain a backtrace, verify that the expected callers are present in the
+// backtrace, and maybe print the backtrace to stdout.
+
+// The sequence of functions whose return addresses we expect to see in the
+// backtrace.
+const int BACKTRACE_STEPS = 6;
+
+struct AddressRange {
+ const void *start, *end;
+};
+
+// Expected function [start,end] range.
+AddressRange expected_range[BACKTRACE_STEPS];
+
+#if __GNUC__
+// Using GCC extension: address of a label can be taken with '&&label'.
+// Start should be a label somewhere before recursive call, end somewhere
+// after it.
+#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
+ do { \
+ (prange)->start = &&start_label; \
+ (prange)->end = &&end_label; \
+ CHECK_LT((prange)->start, (prange)->end); \
+ } while (0)
+// This macro expands into "unmovable" code (opaque to GCC), and that
+// prevents GCC from moving a_label up or down in the code.
+// Without it, there is no code following the 'end' label, and GCC
+// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
+// the recursive call.
+#define DECLARE_ADDRESS_LABEL(a_label) \
+ a_label: do { __asm__ __volatile__(""); } while (0)
+// Gcc 4.4.0 may split function into multiple chunks, and the chunk
+// performing recursive call may end up later in the code then the return
+// instruction (this actually happens with FDO).
+// Adjust function range from __builtin_return_address.
+#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
+ do { \
+ void *ra = __builtin_return_address(0); \
+ CHECK_LT((prange)->start, ra); \
+ if (ra > (prange)->end) { \
+ printf("Adjusting range from %p..%p to %p..%p\n", \
+ (prange)->start, (prange)->end, \
+ (prange)->start, ra); \
+ (prange)->end = ra; \
+ } \
+ } while (0)
+#else
+// Assume the Check* functions below are not longer than 256 bytes.
+#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
+ do { \
+ (prange)->start = reinterpret_cast<const void *>(&fn); \
+ (prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
+ } while (0)
+#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
+#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
+#endif // __GNUC__
+
+//-----------------------------------------------------------------------//
+
+void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range)
+{
+ CHECK_GE(ret_addr, range.start);
+ CHECK_LE(ret_addr, range.end);
+}
+
+//-----------------------------------------------------------------------//
+
+void ATTRIBUTE_NOINLINE CheckStackTrace(int);
+void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
+ const int STACK_LEN = 10;
+ void *stack[STACK_LEN];
+ int size;
+
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
+ INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
+ DECLARE_ADDRESS_LABEL(start);
+ size = GetStackTrace(stack, STACK_LEN, 0);
+ printf("Obtained %d stack frames.\n", size);
+ CHECK_GE(size, 1);
+ CHECK_LE(size, STACK_LEN);
+
+ if (1) {
+#ifdef HAVE_EXECINFO_H
+ char **strings = backtrace_symbols(stack, size);
+ printf("Obtained %d stack frames.\n", size);
+ for (int i = 0; i < size; i++)
+ printf("%s %p\n", strings[i], stack[i]);
+ printf("CheckStackTrace() addr: %p\n", &CheckStackTrace);
+ free(strings);
+#endif
+ }
+ for (int i = 0; i < BACKTRACE_STEPS; i++) {
+ printf("Backtrace %d: expected: %p..%p actual: %p ... ",
+ i, expected_range[i].start, expected_range[i].end, stack[i]);
+ fflush(stdout);
+ CheckRetAddrIsInFunction(stack[i], expected_range[i]);
+ printf("OK\n");
+ }
+ DECLARE_ADDRESS_LABEL(end);
+}
+
+//-----------------------------------------------------------------------//
+
+/* Dummy functions to make the backtrace more interesting. */
+void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
+ INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
+ DECLARE_ADDRESS_LABEL(start);
+ for (int j = i; j >= 0; j--)
+ CheckStackTraceLeaf();
+ DECLARE_ADDRESS_LABEL(end);
+}
+void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
+ INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
+ DECLARE_ADDRESS_LABEL(start);
+ for (int j = i; j >= 0; j--)
+ CheckStackTrace4(j);
+ DECLARE_ADDRESS_LABEL(end);
+}
+void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
+ INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
+ DECLARE_ADDRESS_LABEL(start);
+ for (int j = i; j >= 0; j--)
+ CheckStackTrace3(j);
+ DECLARE_ADDRESS_LABEL(end);
+}
+void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
+ INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
+ DECLARE_ADDRESS_LABEL(start);
+ for (int j = i; j >= 0; j--)
+ CheckStackTrace2(j);
+ DECLARE_ADDRESS_LABEL(end);
+}
+void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
+ INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
+ DECLARE_ADDRESS_LABEL(start);
+ for (int j = i; j >= 0; j--)
+ CheckStackTrace1(j);
+ DECLARE_ADDRESS_LABEL(end);
+}
+
+//-----------------------------------------------------------------------//
+
+int main(int, char ** argv) {
+ FLAGS_logtostderr = true;
+ InitGoogleLogging(argv[0]);
+
+ CheckStackTrace(0);
+
+ printf("PASS\n");
+ return 0;
+}
+
+#else
+int main() {
+ printf("PASS (no stacktrace support)\n");
+ return 0;
+}
+#endif // HAVE_STACKTRACE
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_x86-inl.h b/thirdparty/glog/glog-0.3.4/src/stacktrace_x86-inl.h
new file mode 100644
index 0000000..cfd31f7
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_x86-inl.h
@@ -0,0 +1,139 @@
+// Copyright (c) 2000 - 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Produce stack trace
+
+#include <stdint.h> // for uintptr_t
+
+#include "utilities.h" // for OS_* macros
+
+#if !defined(OS_WINDOWS)
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
+#include <stdio.h> // for NULL
+#include "stacktrace.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// Given a pointer to a stack frame, locate and return the calling
+// stackframe, or return NULL if no stackframe can be found. Perform sanity
+// checks (the strictness of which is controlled by the boolean parameter
+// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
+template<bool STRICT_UNWINDING>
+static void **NextStackFrame(void **old_sp) {
+ void **new_sp = (void **) *old_sp;
+
+ // Check that the transition from frame pointer old_sp to frame
+ // pointer new_sp isn't clearly bogus
+ if (STRICT_UNWINDING) {
+ // With the stack growing downwards, older stack frame must be
+ // at a greater address that the current one.
+ if (new_sp <= old_sp) return NULL;
+ // Assume stack frames larger than 100,000 bytes are bogus.
+ if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
+ } else {
+ // In the non-strict mode, allow discontiguous stack frames.
+ // (alternate-signal-stacks for example).
+ if (new_sp == old_sp) return NULL;
+ // And allow frames upto about 1MB.
+ if ((new_sp > old_sp)
+ && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
+ }
+ if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
+#ifdef __i386__
+ // On 64-bit machines, the stack pointer can be very close to
+ // 0xffffffff, so we explicitly check for a pointer into the
+ // last two pages in the address space
+ if ((uintptr_t)new_sp >= 0xffffe000) return NULL;
+#endif
+#if !defined(OS_WINDOWS)
+ if (!STRICT_UNWINDING) {
+ // Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
+ // on AMD-based machines with VDSO-enabled kernels.
+ // Make an extra sanity check to insure new_sp is readable.
+ // Note: NextStackFrame<false>() is only called while the program
+ // is already on its last leg, so it's ok to be slow here.
+ static int page_size = getpagesize();
+ void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1));
+ if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1)
+ return NULL;
+ }
+#endif
+ return new_sp;
+}
+
+// If you change this function, also change GetStackFrames below.
+int GetStackTrace(void** result, int max_depth, int skip_count) {
+ void **sp;
+#ifdef __i386__
+ // Stack frame format:
+ // sp[0] pointer to previous frame
+ // sp[1] caller address
+ // sp[2] first argument
+ // ...
+ sp = (void **)&result - 2;
+#endif
+
+#ifdef __x86_64__
+ // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8
+ unsigned long rbp;
+ // Move the value of the register %rbp into the local variable rbp.
+ // We need 'volatile' to prevent this instruction from getting moved
+ // around during optimization to before function prologue is done.
+ // An alternative way to achieve this
+ // would be (before this __asm__ instruction) to call Noop() defined as
+ // static void Noop() __attribute__ ((noinline)); // prevent inlining
+ // static void Noop() { asm(""); } // prevent optimizing-away
+ __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
+ // Arguments are passed in registers on x86-64, so we can't just
+ // offset from &result
+ sp = (void **) rbp;
+#endif
+
+ int n = 0;
+ while (sp && n < max_depth) {
+ if (*(sp+1) == (void *)0) {
+ // In 64-bit code, we often see a frame that
+ // points to itself and has a return address of 0.
+ break;
+ }
+ if (skip_count > 0) {
+ skip_count--;
+ } else {
+ result[n++] = *(sp+1);
+ }
+ // Use strict unwinding rules.
+ sp = NextStackFrame<true>(sp);
+ }
+ return n;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/stacktrace_x86_64-inl.h b/thirdparty/glog/glog-0.3.4/src/stacktrace_x86_64-inl.h
new file mode 100644
index 0000000..f7d1dca
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stacktrace_x86_64-inl.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2005 - 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Arun Sharma
+//
+// Produce stack trace using libgcc
+
+extern "C" {
+#include <stdlib.h> // for NULL
+#include <unwind.h> // ABI defined unwinder
+}
+#include "stacktrace.h"
+
+_START_GOOGLE_NAMESPACE_
+
+typedef struct {
+ void **result;
+ int max_depth;
+ int skip_count;
+ int count;
+} trace_arg_t;
+
+
+// Workaround for the malloc() in _Unwind_Backtrace() issue.
+static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context *uc, void *opq) {
+ return _URC_NO_REASON;
+}
+
+
+// This code is not considered ready to run until
+// static initializers run so that we are guaranteed
+// that any malloc-related initialization is done.
+static bool ready_to_run = false;
+class StackTraceInit {
+ public:
+ StackTraceInit() {
+ // Extra call to force initialization
+ _Unwind_Backtrace(nop_backtrace, NULL);
+ ready_to_run = true;
+ }
+};
+
+static StackTraceInit module_initializer; // Force initialization
+
+static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context *uc, void *opq) {
+ trace_arg_t *targ = (trace_arg_t *) opq;
+
+ if (targ->skip_count > 0) {
+ targ->skip_count--;
+ } else {
+ targ->result[targ->count++] = (void *) _Unwind_GetIP(uc);
+ }
+
+ if (targ->count == targ->max_depth)
+ return _URC_END_OF_STACK;
+
+ return _URC_NO_REASON;
+}
+
+// If you change this function, also change GetStackFrames below.
+int GetStackTrace(void** result, int max_depth, int skip_count) {
+ if (!ready_to_run)
+ return 0;
+
+ trace_arg_t targ;
+
+ skip_count += 1; // Do not include the "GetStackTrace" frame
+
+ targ.result = result;
+ targ.max_depth = max_depth;
+ targ.skip_count = skip_count;
+ targ.count = 0;
+
+ _Unwind_Backtrace(GetOneFrame, &targ);
+
+ return targ.count;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/stl_logging_unittest.cc b/thirdparty/glog/glog-0.3.4/src/stl_logging_unittest.cc
new file mode 100644
index 0000000..20f23b3
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/stl_logging_unittest.cc
@@ -0,0 +1,188 @@
+// Copyright (c) 2003, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "config.h"
+
+#ifdef HAVE_USING_OPERATOR
+
+#include <iostream>
+#include <map>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#ifdef __GNUC__
+// C++0x isn't enabled by default in GCC and libc++ does not have
+// non-standard ext/* and tr1/unordered_*.
+# if defined(_LIBCPP_VERSION)
+# define GLOG_STL_LOGGING_FOR_UNORDERED
+# else
+# define GLOG_STL_LOGGING_FOR_EXT_HASH
+# define GLOG_STL_LOGGING_FOR_EXT_SLIST
+# define GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+# endif
+#endif
+
+#include "glog/logging.h"
+#include "glog/stl_logging.h"
+#include "googletest.h"
+
+using namespace std;
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+using namespace __gnu_cxx;
+#endif
+
+struct user_hash {
+ size_t operator()(int x) const { return x; }
+};
+
+void TestSTLLogging() {
+ {
+ // Test a sequence.
+ vector<int> v;
+ v.push_back(10);
+ v.push_back(20);
+ v.push_back(30);
+ ostringstream ss;
+ ss << v;
+ EXPECT_EQ(ss.str(), "10 20 30");
+ vector<int> copied_v(v);
+ CHECK_EQ(v, copied_v); // This must compile.
+ }
+
+ {
+ // Test a sorted pair associative container.
+ map< int, string > m;
+ m[20] = "twenty";
+ m[10] = "ten";
+ m[30] = "thirty";
+ ostringstream ss;
+ ss << m;
+ EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
+ map< int, string > copied_m(m);
+ CHECK_EQ(m, copied_m); // This must compile.
+ }
+
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+ {
+ // Test a hashed simple associative container.
+ hash_set<int> hs;
+ hs.insert(10);
+ hs.insert(20);
+ hs.insert(30);
+ ostringstream ss;
+ ss << hs;
+ EXPECT_EQ(ss.str(), "10 20 30");
+ hash_set<int> copied_hs(hs);
+ CHECK_EQ(hs, copied_hs); // This must compile.
+ }
+#endif
+
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+ {
+ // Test a hashed pair associative container.
+ hash_map<int, string> hm;
+ hm[10] = "ten";
+ hm[20] = "twenty";
+ hm[30] = "thirty";
+ ostringstream ss;
+ ss << hm;
+ EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
+ hash_map<int, string> copied_hm(hm);
+ CHECK_EQ(hm, copied_hm); // this must compile
+ }
+#endif
+
+ {
+ // Test a long sequence.
+ vector<int> v;
+ string expected;
+ for (int i = 0; i < 100; i++) {
+ v.push_back(i);
+ if (i > 0) expected += ' ';
+ char buf[256];
+ sprintf(buf, "%d", i);
+ expected += buf;
+ }
+ v.push_back(100);
+ expected += " ...";
+ ostringstream ss;
+ ss << v;
+ CHECK_EQ(ss.str(), expected.c_str());
+ }
+
+ {
+ // Test a sorted pair associative container.
+ // Use a non-default comparison functor.
+ map< int, string, greater<int> > m;
+ m[20] = "twenty";
+ m[10] = "ten";
+ m[30] = "thirty";
+ ostringstream ss;
+ ss << m;
+ EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)");
+ map< int, string, greater<int> > copied_m(m);
+ CHECK_EQ(m, copied_m); // This must compile.
+ }
+
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+ {
+ // Test a hashed simple associative container.
+ // Use a user defined hash function.
+ hash_set<int, user_hash> hs;
+ hs.insert(10);
+ hs.insert(20);
+ hs.insert(30);
+ ostringstream ss;
+ ss << hs;
+ EXPECT_EQ(ss.str(), "10 20 30");
+ hash_set<int, user_hash> copied_hs(hs);
+ CHECK_EQ(hs, copied_hs); // This must compile.
+ }
+#endif
+}
+
+int main(int, char**) {
+ TestSTLLogging();
+ std::cout << "PASS\n";
+ return 0;
+}
+
+#else
+
+#include <iostream>
+
+int main(int, char**) {
+ std::cout << "We don't support stl_logging for this compiler.\n"
+ << "(we need compiler support of 'using ::operator<<' "
+ << "for this feature.)\n";
+ return 0;
+}
+
+#endif // HAVE_USING_OPERATOR
diff --git a/thirdparty/glog/glog-0.3.4/src/symbolize.cc b/thirdparty/glog/glog-0.3.4/src/symbolize.cc
new file mode 100644
index 0000000..901ba98
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/symbolize.cc
@@ -0,0 +1,851 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+// Stack-footprint reduction work done by Raksit Ashok
+//
+// Implementation note:
+//
+// We don't use heaps but only use stacks. We want to reduce the
+// stack consumption so that the symbolizer can run on small stacks.
+//
+// Here are some numbers collected with GCC 4.1.0 on x86:
+// - sizeof(Elf32_Sym) = 16
+// - sizeof(Elf32_Shdr) = 40
+// - sizeof(Elf64_Sym) = 24
+// - sizeof(Elf64_Shdr) = 64
+//
+// This implementation is intended to be async-signal-safe but uses
+// some functions which are not guaranteed to be so, such as memchr()
+// and memmove(). We assume they are async-signal-safe.
+//
+// Additional header can be specified by the GLOG_BUILD_CONFIG_INCLUDE
+// macro to add platform specific defines (e.g. OS_OPENBSD).
+
+#ifdef GLOG_BUILD_CONFIG_INCLUDE
+#include GLOG_BUILD_CONFIG_INCLUDE
+#endif // GLOG_BUILD_CONFIG_INCLUDE
+
+#include "utilities.h"
+
+#if defined(HAVE_SYMBOLIZE)
+
+#include <limits>
+
+#include "symbolize.h"
+#include "demangle.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// We don't use assert() since it's not guaranteed to be
+// async-signal-safe. Instead we define a minimal assertion
+// macro. So far, we don't need pretty printing for __FILE__, etc.
+
+// A wrapper for abort() to make it callable in ? :.
+static int AssertFail() {
+ abort();
+ return 0; // Should not reach.
+}
+
+#define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail())
+
+static SymbolizeCallback g_symbolize_callback = NULL;
+void InstallSymbolizeCallback(SymbolizeCallback callback) {
+ g_symbolize_callback = callback;
+}
+
+static SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback =
+ NULL;
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback) {
+ g_symbolize_open_object_file_callback = callback;
+}
+
+// This function wraps the Demangle function to provide an interface
+// where the input symbol is demangled in-place.
+// To keep stack consumption low, we would like this function to not
+// get inlined.
+static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size) {
+ char demangled[256]; // Big enough for sane demangled symbols.
+ if (Demangle(out, demangled, sizeof(demangled))) {
+ // Demangling succeeded. Copy to out if the space allows.
+ size_t len = strlen(demangled);
+ if (len + 1 <= (size_t)out_size) { // +1 for '\0'.
+ SAFE_ASSERT(len < sizeof(demangled));
+ memmove(out, demangled, len + 1);
+ }
+ }
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#if defined(__ELF__)
+
+#include <dlfcn.h>
+#if defined(OS_OPENBSD)
+#include <sys/exec_elf.h>
+#else
+#include <elf.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "symbolize.h"
+#include "config.h"
+#include "glog/raw_logging.h"
+
+// Re-runs fn until it doesn't cause EINTR.
+#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
+
+_START_GOOGLE_NAMESPACE_
+
+// Read up to "count" bytes from file descriptor "fd" into the buffer
+// starting at "buf" while handling short reads and EINTR. On
+// success, return the number of bytes read. Otherwise, return -1.
+static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) {
+ SAFE_ASSERT(fd >= 0);
+ SAFE_ASSERT(count <= std::numeric_limits<ssize_t>::max());
+ char *buf0 = reinterpret_cast<char *>(buf);
+ ssize_t num_bytes = 0;
+ while (num_bytes < count) {
+ ssize_t len;
+ NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes));
+ if (len < 0) { // There was an error other than EINTR.
+ return -1;
+ }
+ if (len == 0) { // Reached EOF.
+ break;
+ }
+ num_bytes += len;
+ }
+ SAFE_ASSERT(num_bytes <= count);
+ return num_bytes;
+}
+
+// Read up to "count" bytes from "offset" in the file pointed by file
+// descriptor "fd" into the buffer starting at "buf". On success,
+// return the number of bytes read. Otherwise, return -1.
+static ssize_t ReadFromOffset(const int fd, void *buf,
+ const size_t count, const off_t offset) {
+ off_t off = lseek(fd, offset, SEEK_SET);
+ if (off == (off_t)-1) {
+ return -1;
+ }
+ return ReadPersistent(fd, buf, count);
+}
+
+// Try reading exactly "count" bytes from "offset" bytes in a file
+// pointed by "fd" into the buffer starting at "buf" while handling
+// short reads and EINTR. On success, return true. Otherwise, return
+// false.
+static bool ReadFromOffsetExact(const int fd, void *buf,
+ const size_t count, const off_t offset) {
+ ssize_t len = ReadFromOffset(fd, buf, count, offset);
+ return len == count;
+}
+
+// Returns elf_header.e_type if the file pointed by fd is an ELF binary.
+static int FileGetElfType(const int fd) {
+ ElfW(Ehdr) elf_header;
+ if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
+ return -1;
+ }
+ if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) {
+ return -1;
+ }
+ return elf_header.e_type;
+}
+
+// Read the section headers in the given ELF binary, and if a section
+// of the specified type is found, set the output to this section header
+// and return true. Otherwise, return false.
+// To keep stack consumption low, we would like this function to not get
+// inlined.
+static ATTRIBUTE_NOINLINE bool
+GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const off_t sh_offset,
+ ElfW(Word) type, ElfW(Shdr) *out) {
+ // Read at most 16 section headers at a time to save read calls.
+ ElfW(Shdr) buf[16];
+ for (int i = 0; i < sh_num;) {
+ const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]);
+ const ssize_t num_bytes_to_read =
+ (sizeof(buf) > num_bytes_left) ? num_bytes_left : sizeof(buf);
+ const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read,
+ sh_offset + i * sizeof(buf[0]));
+ SAFE_ASSERT(len % sizeof(buf[0]) == 0);
+ const ssize_t num_headers_in_buf = len / sizeof(buf[0]);
+ SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0]));
+ for (int j = 0; j < num_headers_in_buf; ++j) {
+ if (buf[j].sh_type == type) {
+ *out = buf[j];
+ return true;
+ }
+ }
+ i += num_headers_in_buf;
+ }
+ return false;
+}
+
+// There is no particular reason to limit section name to 63 characters,
+// but there has (as yet) been no need for anything longer either.
+const int kMaxSectionNameLen = 64;
+
+// name_len should include terminating '\0'.
+bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
+ ElfW(Shdr) *out) {
+ ElfW(Ehdr) elf_header;
+ if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
+ return false;
+ }
+
+ ElfW(Shdr) shstrtab;
+ off_t shstrtab_offset = (elf_header.e_shoff +
+ elf_header.e_shentsize * elf_header.e_shstrndx);
+ if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) {
+ return false;
+ }
+
+ for (int i = 0; i < elf_header.e_shnum; ++i) {
+ off_t section_header_offset = (elf_header.e_shoff +
+ elf_header.e_shentsize * i);
+ if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
+ return false;
+ }
+ char header_name[kMaxSectionNameLen];
+ if (sizeof(header_name) < name_len) {
+ RAW_LOG(WARNING, "Section name '%s' is too long (%" PRIuS "); "
+ "section will not be found (even if present).", name, name_len);
+ // No point in even trying.
+ return false;
+ }
+ off_t name_offset = shstrtab.sh_offset + out->sh_name;
+ ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset);
+ if (n_read == -1) {
+ return false;
+ } else if (n_read != name_len) {
+ // Short read -- name could be at end of file.
+ continue;
+ }
+ if (memcmp(header_name, name, name_len) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Read a symbol table and look for the symbol containing the
+// pc. Iterate over symbols in a symbol table and look for the symbol
+// containing "pc". On success, return true and write the symbol name
+// to out. Otherwise, return false.
+// To keep stack consumption low, we would like this function to not get
+// inlined.
+static ATTRIBUTE_NOINLINE bool
+FindSymbol(uint64_t pc, const int fd, char *out, int out_size,
+ uint64_t symbol_offset, const ElfW(Shdr) *strtab,
+ const ElfW(Shdr) *symtab) {
+ if (symtab == NULL) {
+ return false;
+ }
+ const int num_symbols = symtab->sh_size / symtab->sh_entsize;
+ for (int i = 0; i < num_symbols;) {
+ off_t offset = symtab->sh_offset + i * symtab->sh_entsize;
+
+ // If we are reading Elf64_Sym's, we want to limit this array to
+ // 32 elements (to keep stack consumption low), otherwise we can
+ // have a 64 element Elf32_Sym array.
+#if __WORDSIZE == 64
+#define NUM_SYMBOLS 32
+#else
+#define NUM_SYMBOLS 64
+#endif
+
+ // Read at most NUM_SYMBOLS symbols at once to save read() calls.
+ ElfW(Sym) buf[NUM_SYMBOLS];
+ const ssize_t len = ReadFromOffset(fd, &buf, sizeof(buf), offset);
+ SAFE_ASSERT(len % sizeof(buf[0]) == 0);
+ const ssize_t num_symbols_in_buf = len / sizeof(buf[0]);
+ SAFE_ASSERT(num_symbols_in_buf <= sizeof(buf)/sizeof(buf[0]));
+ for (int j = 0; j < num_symbols_in_buf; ++j) {
+ const ElfW(Sym)& symbol = buf[j];
+ uint64_t start_address = symbol.st_value;
+ start_address += symbol_offset;
+ uint64_t end_address = start_address + symbol.st_size;
+ if (symbol.st_value != 0 && // Skip null value symbols.
+ symbol.st_shndx != 0 && // Skip undefined symbols.
+ start_address <= pc && pc < end_address) {
+ ssize_t len1 = ReadFromOffset(fd, out, out_size,
+ strtab->sh_offset + symbol.st_name);
+ if (len1 <= 0 || memchr(out, '\0', out_size) == NULL) {
+ return false;
+ }
+ return true; // Obtained the symbol name.
+ }
+ }
+ i += num_symbols_in_buf;
+ }
+ return false;
+}
+
+// Get the symbol name of "pc" from the file pointed by "fd". Process
+// both regular and dynamic symbol tables if necessary. On success,
+// write the symbol name to "out" and return true. Otherwise, return
+// false.
+static bool GetSymbolFromObjectFile(const int fd, uint64_t pc,
+ char *out, int out_size,
+ uint64_t map_start_address) {
+ // Read the ELF header.
+ ElfW(Ehdr) elf_header;
+ if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
+ return false;
+ }
+
+ uint64_t symbol_offset = 0;
+ if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment.
+ symbol_offset = map_start_address;
+ }
+
+ ElfW(Shdr) symtab, strtab;
+
+ // Consult a regular symbol table first.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_SYMTAB, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a regular symbol table.
+ }
+ }
+
+ // If the symbol is not found, then consult a dynamic symbol table.
+ if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
+ SHT_DYNSYM, &symtab)) {
+ if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab))) {
+ return false;
+ }
+ if (FindSymbol(pc, fd, out, out_size, symbol_offset,
+ &strtab, &symtab)) {
+ return true; // Found the symbol in a dynamic symbol table.
+ }
+ }
+
+ return false;
+}
+
+namespace {
+// Thin wrapper around a file descriptor so that the file descriptor
+// gets closed for sure.
+struct FileDescriptor {
+ const int fd_;
+ explicit FileDescriptor(int fd) : fd_(fd) {}
+ ~FileDescriptor() {
+ if (fd_ >= 0) {
+ NO_INTR(close(fd_));
+ }
+ }
+ int get() { return fd_; }
+
+ private:
+ explicit FileDescriptor(const FileDescriptor&);
+ void operator=(const FileDescriptor&);
+};
+
+// Helper class for reading lines from file.
+//
+// Note: we don't use ProcMapsIterator since the object is big (it has
+// a 5k array member) and uses async-unsafe functions such as sscanf()
+// and snprintf().
+class LineReader {
+ public:
+ explicit LineReader(int fd, char *buf, int buf_len) : fd_(fd),
+ buf_(buf), buf_len_(buf_len), bol_(buf), eol_(buf), eod_(buf) {
+ }
+
+ // Read '\n'-terminated line from file. On success, modify "bol"
+ // and "eol", then return true. Otherwise, return false.
+ //
+ // Note: if the last line doesn't end with '\n', the line will be
+ // dropped. It's an intentional behavior to make the code simple.
+ bool ReadLine(const char **read_bol, const char **read_eol) {
+ if (BufferIsEmpty()) { // First time.
+ const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_);
+ if (num_bytes <= 0) { // EOF or error.
+ return false;
+ }
+ eod_ = buf_ + num_bytes;
+ bol_ = buf_;
+ } else {
+ bol_ = eol_ + 1; // Advance to the next line in the buffer.
+ SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
+ if (!HasCompleteLine()) {
+ const int incomplete_line_length = eod_ - bol_;
+ // Move the trailing incomplete line to the beginning.
+ memmove(buf_, bol_, incomplete_line_length);
+ // Read text from file and append it.
+ char * const append_pos = buf_ + incomplete_line_length;
+ const int capacity_left = buf_len_ - incomplete_line_length;
+ const ssize_t num_bytes = ReadPersistent(fd_, append_pos,
+ capacity_left);
+ if (num_bytes <= 0) { // EOF or error.
+ return false;
+ }
+ eod_ = append_pos + num_bytes;
+ bol_ = buf_;
+ }
+ }
+ eol_ = FindLineFeed();
+ if (eol_ == NULL) { // '\n' not found. Malformed line.
+ return false;
+ }
+ *eol_ = '\0'; // Replace '\n' with '\0'.
+
+ *read_bol = bol_;
+ *read_eol = eol_;
+ return true;
+ }
+
+ // Beginning of line.
+ const char *bol() {
+ return bol_;
+ }
+
+ // End of line.
+ const char *eol() {
+ return eol_;
+ }
+
+ private:
+ explicit LineReader(const LineReader&);
+ void operator=(const LineReader&);
+
+ char *FindLineFeed() {
+ return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_));
+ }
+
+ bool BufferIsEmpty() {
+ return buf_ == eod_;
+ }
+
+ bool HasCompleteLine() {
+ return !BufferIsEmpty() && FindLineFeed() != NULL;
+ }
+
+ const int fd_;
+ char * const buf_;
+ const int buf_len_;
+ char *bol_;
+ char *eol_;
+ const char *eod_; // End of data in "buf_".
+};
+} // namespace
+
+// Place the hex number read from "start" into "*hex". The pointer to
+// the first non-hex character or "end" is returned.
+static char *GetHex(const char *start, const char *end, uint64_t *hex) {
+ *hex = 0;
+ const char *p;
+ for (p = start; p < end; ++p) {
+ int ch = *p;
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
+ *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
+ } else { // Encountered the first non-hex character.
+ break;
+ }
+ }
+ SAFE_ASSERT(p <= end);
+ return const_cast<char *>(p);
+}
+
+// Searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
+static ATTRIBUTE_NOINLINE int
+OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size) {
+ int object_fd;
+
+ // Open /proc/self/maps.
+ int maps_fd;
+ NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY));
+ FileDescriptor wrapped_maps_fd(maps_fd);
+ if (wrapped_maps_fd.get() < 0) {
+ return -1;
+ }
+
+ // Iterate over maps and look for the map containing the pc. Then
+ // look into the symbol tables inside.
+ char buf[1024]; // Big enough for line of sane /proc/self/maps
+ int num_maps = 0;
+ LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf));
+ while (true) {
+ num_maps++;
+ const char *cursor;
+ const char *eol;
+ if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
+ return -1;
+ }
+
+ // Start parsing line in /proc/self/maps. Here is an example:
+ //
+ // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat
+ //
+ // We want start address (08048000), end address (0804c000), flags
+ // (r-xp) and file name (/bin/cat).
+
+ // Read start address.
+ cursor = GetHex(cursor, eol, &start_address);
+ if (cursor == eol || *cursor != '-') {
+ return -1; // Malformed line.
+ }
+ ++cursor; // Skip '-'.
+
+ // Read end address.
+ uint64_t end_address;
+ cursor = GetHex(cursor, eol, &end_address);
+ if (cursor == eol || *cursor != ' ') {
+ return -1; // Malformed line.
+ }
+ ++cursor; // Skip ' '.
+
+ // Check start and end addresses.
+ if (!(start_address <= pc && pc < end_address)) {
+ continue; // We skip this map. PC isn't in this map.
+ }
+
+ // Read flags. Skip flags until we encounter a space or eol.
+ const char * const flags_start = cursor;
+ while (cursor < eol && *cursor != ' ') {
+ ++cursor;
+ }
+ // We expect at least four letters for flags (ex. "r-xp").
+ if (cursor == eol || cursor < flags_start + 4) {
+ return -1; // Malformed line.
+ }
+
+ // Check flags. We are only interested in "r-x" maps.
+ if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map.
+ continue; // We skip this map.
+ }
+ ++cursor; // Skip ' '.
+
+ // Read file offset.
+ uint64_t file_offset;
+ cursor = GetHex(cursor, eol, &file_offset);
+ if (cursor == eol || *cursor != ' ') {
+ return -1; // Malformed line.
+ }
+ ++cursor; // Skip ' '.
+
+ // Don't subtract 'start_address' from the first entry:
+ // * If a binary is compiled w/o -pie, then the first entry in
+ // process maps is likely the binary itself (all dynamic libs
+ // are mapped higher in address space). For such a binary,
+ // instruction offset in binary coincides with the actual
+ // instruction address in virtual memory (as code section
+ // is mapped to a fixed memory range).
+ // * If a binary is compiled with -pie, all the modules are
+ // mapped high at address space (in particular, higher than
+ // shadow memory of the tool), so the module can't be the
+ // first entry.
+ base_address = ((num_maps == 1) ? 0U : start_address) - file_offset;
+
+ // Skip to file name. "cursor" now points to dev. We need to
+ // skip at least two spaces for dev and inode.
+ int num_spaces = 0;
+ while (cursor < eol) {
+ if (*cursor == ' ') {
+ ++num_spaces;
+ } else if (num_spaces >= 2) {
+ // The first non-space character after skipping two spaces
+ // is the beginning of the file name.
+ break;
+ }
+ ++cursor;
+ }
+ if (cursor == eol) {
+ return -1; // Malformed line.
+ }
+
+ // Finally, "cursor" now points to file name of our interest.
+ NO_INTR(object_fd = open(cursor, O_RDONLY));
+ if (object_fd < 0) {
+ // Failed to open object file. Copy the object file name to
+ // |out_file_name|.
+ strncpy(out_file_name, cursor, out_file_name_size);
+ // Making sure |out_file_name| is always null-terminated.
+ out_file_name[out_file_name_size - 1] = '\0';
+ return -1;
+ }
+ return object_fd;
+ }
+}
+
+// POSIX doesn't define any async-signal safe function for converting
+// an integer to ASCII. We'll have to define our own version.
+// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
+// conversion was successful or NULL otherwise. It never writes more than "sz"
+// bytes. Output will be truncated as needed, and a NUL character is always
+// appended.
+// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
+char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
+ // Make sure we can write at least one NUL byte.
+ size_t n = 1;
+ if (n > sz)
+ return NULL;
+
+ if (base < 2 || base > 16) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ char *start = buf;
+
+ uintptr_t j = i;
+
+ // Handle negative numbers (only for base 10).
+ if (i < 0 && base == 10) {
+ j = -i;
+
+ // Make sure we can write the '-' character.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+ *start++ = '-';
+ }
+
+ // Loop until we have converted the entire number. Output at least one
+ // character (i.e. '0').
+ char *ptr = start;
+ do {
+ // Make sure there is still enough space left in our output buffer.
+ if (++n > sz) {
+ buf[0] = '\000';
+ return NULL;
+ }
+
+ // Output the next digit.
+ *ptr++ = "0123456789abcdef"[j % base];
+ j /= base;
+
+ if (padding > 0)
+ padding--;
+ } while (j > 0 || padding > 0);
+
+ // Terminate the output with a NUL character.
+ *ptr = '\000';
+
+ // Conversion to ASCII actually resulted in the digits being in reverse
+ // order. We can't easily generate them in forward order, as we can't tell
+ // the number of characters needed until we are done converting.
+ // So, now, we reverse the string (except for the possible "-" sign).
+ while (--ptr > start) {
+ char ch = *ptr;
+ *ptr = *start;
+ *start++ = ch;
+ }
+ return buf;
+}
+
+// Safely appends string |source| to string |dest|. Never writes past the
+// buffer size |dest_size| and guarantees that |dest| is null-terminated.
+void SafeAppendString(const char* source, char* dest, int dest_size) {
+ int dest_string_length = strlen(dest);
+ SAFE_ASSERT(dest_string_length < dest_size);
+ dest += dest_string_length;
+ dest_size -= dest_string_length;
+ strncpy(dest, source, dest_size);
+ // Making sure |dest| is always null-terminated.
+ dest[dest_size - 1] = '\0';
+}
+
+// Converts a 64-bit value into a hex string, and safely appends it to |dest|.
+// Never writes past the buffer size |dest_size| and guarantees that |dest| is
+// null-terminated.
+void SafeAppendHexNumber(uint64_t value, char* dest, int dest_size) {
+ // 64-bit numbers in hex can have up to 16 digits.
+ char buf[17] = {'\0'};
+ SafeAppendString(itoa_r(value, buf, sizeof(buf), 16, 0), dest, dest_size);
+}
+
+// The implementation of our symbolization routine. If it
+// successfully finds the symbol containing "pc" and obtains the
+// symbol name, returns true and write the symbol name to "out".
+// Otherwise, returns false. If Callback function is installed via
+// InstallSymbolizeCallback(), the function is also called in this function,
+// and "out" is used as its output.
+// To keep stack consumption low, we would like this function to not
+// get inlined.
+static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
+ int out_size) {
+ uint64_t pc0 = reinterpret_cast<uintptr_t>(pc);
+ uint64_t start_address = 0;
+ uint64_t base_address = 0;
+ int object_fd = -1;
+
+ if (out_size < 1) {
+ return false;
+ }
+ out[0] = '\0';
+ SafeAppendString("(", out, out_size);
+
+ if (g_symbolize_open_object_file_callback) {
+ object_fd = g_symbolize_open_object_file_callback(pc0, start_address,
+ base_address, out + 1,
+ out_size - 1);
+ } else {
+ object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address,
+ base_address,
+ out + 1,
+ out_size - 1);
+ }
+
+ // Check whether a file name was returned.
+ if (object_fd < 0) {
+ if (out[1]) {
+ // The object file containing PC was determined successfully however the
+ // object file was not opened successfully. This is still considered
+ // success because the object file name and offset are known and tools
+ // like asan_symbolize.py can be used for the symbolization.
+ out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
+ SafeAppendString("+0x", out, out_size);
+ SafeAppendHexNumber(pc0 - base_address, out, out_size);
+ SafeAppendString(")", out, out_size);
+ return true;
+ }
+ // Failed to determine the object file containing PC. Bail out.
+ return false;
+ }
+ FileDescriptor wrapped_object_fd(object_fd);
+ int elf_type = FileGetElfType(wrapped_object_fd.get());
+ if (elf_type == -1) {
+ return false;
+ }
+ if (g_symbolize_callback) {
+ // Run the call back if it's installed.
+ // Note: relocation (and much of the rest of this code) will be
+ // wrong for prelinked shared libraries and PIE executables.
+ uint64 relocation = (elf_type == ET_DYN) ? start_address : 0;
+ int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(),
+ pc, out, out_size,
+ relocation);
+ if (num_bytes_written > 0) {
+ out += num_bytes_written;
+ out_size -= num_bytes_written;
+ }
+ }
+ if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0,
+ out, out_size, start_address)) {
+ return false;
+ }
+
+ // Symbolization succeeded. Now we try to demangle the symbol.
+ DemangleInplace(out, out_size);
+ return true;
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
+
+#include <dlfcn.h>
+#include <string.h>
+
+_START_GOOGLE_NAMESPACE_
+
+static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
+ int out_size) {
+ Dl_info info;
+ if (dladdr(pc, &info)) {
+ if ((int)strlen(info.dli_sname) < out_size) {
+ strcpy(out, info.dli_sname);
+ // Symbolization succeeded. Now we try to demangle the symbol.
+ DemangleInplace(out, out_size);
+ return true;
+ }
+ }
+ return false;
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#else
+# error BUG: HAVE_SYMBOLIZE was wrongly set
+#endif
+
+_START_GOOGLE_NAMESPACE_
+
+bool Symbolize(void *pc, char *out, int out_size) {
+ SAFE_ASSERT(out_size >= 0);
+ return SymbolizeAndDemangle(pc, out, out_size);
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#else /* HAVE_SYMBOLIZE */
+
+#include <assert.h>
+
+#include "config.h"
+
+_START_GOOGLE_NAMESPACE_
+
+// TODO: Support other environments.
+bool Symbolize(void *pc, char *out, int out_size) {
+ assert(0);
+ return false;
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/symbolize.h b/thirdparty/glog/glog-0.3.4/src/symbolize.h
new file mode 100644
index 0000000..f617184
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/symbolize.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// This library provides Symbolize() function that symbolizes program
+// counters to their corresponding symbol names on linux platforms.
+// This library has a minimal implementation of an ELF symbol table
+// reader (i.e. it doesn't depend on libelf, etc.).
+//
+// The algorithm used in Symbolize() is as follows.
+//
+// 1. Go through a list of maps in /proc/self/maps and find the map
+// containing the program counter.
+//
+// 2. Open the mapped file and find a regular symbol table inside.
+// Iterate over symbols in the symbol table and look for the symbol
+// containing the program counter. If such a symbol is found,
+// obtain the symbol name, and demangle the symbol if possible.
+// If the symbol isn't found in the regular symbol table (binary is
+// stripped), try the same thing with a dynamic symbol table.
+//
+// Note that Symbolize() is originally implemented to be used in
+// FailureSignalHandler() in base/google.cc. Hence it doesn't use
+// malloc() and other unsafe operations. It should be both
+// thread-safe and async-signal-safe.
+
+#ifndef BASE_SYMBOLIZE_H_
+#define BASE_SYMBOLIZE_H_
+
+#include "utilities.h"
+#include "config.h"
+#include "glog/logging.h"
+
+#ifdef HAVE_SYMBOLIZE
+
+#if defined(__ELF__) // defined by gcc
+#if defined(__OpenBSD__)
+#include <sys/exec_elf.h>
+#else
+#include <elf.h>
+#endif
+
+#if !defined(ANDROID)
+#include <link.h> // For ElfW() macro.
+#endif
+
+// For systems where SIZEOF_VOID_P is not defined, determine it
+// based on __LP64__ (defined by gcc on 64-bit systems)
+#if !defined(SIZEOF_VOID_P)
+# if defined(__LP64__)
+# define SIZEOF_VOID_P 8
+# else
+# define SIZEOF_VOID_P 4
+# endif
+#endif
+
+// If there is no ElfW macro, let's define it by ourself.
+#ifndef ElfW
+# if SIZEOF_VOID_P == 4
+# define ElfW(type) Elf32_##type
+# elif SIZEOF_VOID_P == 8
+# define ElfW(type) Elf64_##type
+# else
+# error "Unknown sizeof(void *)"
+# endif
+#endif
+
+_START_GOOGLE_NAMESPACE_
+
+// Gets the section header for the given name, if it exists. Returns true on
+// success. Otherwise, returns false.
+bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
+ ElfW(Shdr) *out);
+
+_END_GOOGLE_NAMESPACE_
+
+#endif /* __ELF__ */
+
+_START_GOOGLE_NAMESPACE_
+
+// Restrictions on the callbacks that follow:
+// - The callbacks must not use heaps but only use stacks.
+// - The callbacks must be async-signal-safe.
+
+// Installs a callback function, which will be called right before a symbol name
+// is printed. The callback is intended to be used for showing a file name and a
+// line number preceding a symbol name.
+// "fd" is a file descriptor of the object file containing the program
+// counter "pc". The callback function should write output to "out"
+// and return the size of the output written. On error, the callback
+// function should return -1.
+typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size,
+ uint64 relocation);
+void InstallSymbolizeCallback(SymbolizeCallback callback);
+
+// Installs a callback function, which will be called instead of
+// OpenObjectFileContainingPcAndGetStartAddress. The callback is expected
+// to searches for the object file (from /proc/self/maps) that contains
+// the specified pc. If found, sets |start_address| to the start address
+// of where this object file is mapped in memory, sets the module base
+// address into |base_address|, copies the object file name into
+// |out_file_name|, and attempts to open the object file. If the object
+// file is opened successfully, returns the file descriptor. Otherwise,
+// returns -1. |out_file_name_size| is the size of the file name buffer
+// (including the null-terminator).
+typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
+ uint64_t &start_address,
+ uint64_t &base_address,
+ char *out_file_name,
+ int out_file_name_size);
+void InstallSymbolizeOpenObjectFileCallback(
+ SymbolizeOpenObjectFileCallback callback);
+
+_END_GOOGLE_NAMESPACE_
+
+#endif
+
+_START_GOOGLE_NAMESPACE_
+
+// Symbolizes a program counter. On success, returns true and write the
+// symbol name to "out". The symbol name is demangled if possible
+// (supports symbols generated by GCC 3.x or newer). Otherwise,
+// returns false.
+bool Symbolize(void *pc, char *out, int out_size);
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // BASE_SYMBOLIZE_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/symbolize_unittest.cc b/thirdparty/glog/glog-0.3.4/src/symbolize_unittest.cc
new file mode 100644
index 0000000..f25909d
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/symbolize_unittest.cc
@@ -0,0 +1,365 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Satoru Takabayashi
+//
+// Unit tests for functions in symbolize.cc.
+
+#include "utilities.h"
+
+#include <signal.h>
+#include <iostream>
+
+#include "glog/logging.h"
+#include "symbolize.h"
+#include "googletest.h"
+#include "config.h"
+
+using namespace std;
+using namespace GOOGLE_NAMESPACE;
+
+#if defined(HAVE_STACKTRACE) && defined(__ELF__)
+
+#define always_inline
+
+// This unit tests make sense only with GCC.
+// Uses lots of GCC specific features.
+#if defined(__GNUC__) && !defined(__OPENCC__)
+# if __GNUC__ >= 4
+# define TEST_WITH_MODERN_GCC
+# if __i386__ // always_inline isn't supported for x86_64 with GCC 4.1.0.
+# undef always_inline
+# define always_inline __attribute__((always_inline))
+# define HAVE_ALWAYS_INLINE
+# endif // __i386__
+# else
+# endif // __GNUC__ >= 4
+# if defined(__i386__) || defined(__x86_64__)
+# define TEST_X86_32_AND_64 1
+# endif // defined(__i386__) || defined(__x86_64__)
+#endif
+
+// A wrapper function for Symbolize() to make the unit test simple.
+static const char *TrySymbolize(void *pc) {
+ static char symbol[4096];
+ if (Symbolize(pc, symbol, sizeof(symbol))) {
+ return symbol;
+ } else {
+ return NULL;
+ }
+}
+
+// Make them C linkage to avoid mangled names.
+extern "C" {
+void nonstatic_func() {
+ volatile int a = 0;
+ ++a;
+}
+
+static void static_func() {
+ volatile int a = 0;
+ ++a;
+}
+}
+
+TEST(Symbolize, Symbolize) {
+ // We do C-style cast since GCC 2.95.3 doesn't allow
+ // reinterpret_cast<void *>(&func).
+
+ // Compilers should give us pointers to them.
+ EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
+ EXPECT_STREQ("static_func", TrySymbolize((void *)(&static_func)));
+
+ EXPECT_TRUE(NULL == TrySymbolize(NULL));
+}
+
+struct Foo {
+ static void func(int x);
+};
+
+void ATTRIBUTE_NOINLINE Foo::func(int x) {
+ volatile int a = x;
+ ++a;
+}
+
+// With a modern GCC, Symbolize() should return demangled symbol
+// names. Function parameters should be omitted.
+#ifdef TEST_WITH_MODERN_GCC
+TEST(Symbolize, SymbolizeWithDemangling) {
+ Foo::func(100);
+ EXPECT_STREQ("Foo::func()", TrySymbolize((void *)(&Foo::func)));
+}
+#endif
+
+// Tests that verify that Symbolize footprint is within some limit.
+
+// To measure the stack footprint of the Symbolize function, we create
+// a signal handler (for SIGUSR1 say) that calls the Symbolize function
+// on an alternate stack. This alternate stack is initialized to some
+// known pattern (0x55, 0x55, 0x55, ...). We then self-send this signal,
+// and after the signal handler returns, look at the alternate stack
+// buffer to see what portion has been touched.
+//
+// This trick gives us the the stack footprint of the signal handler.
+// But the signal handler, even before the call to Symbolize, consumes
+// some stack already. We however only want the stack usage of the
+// Symbolize function. To measure this accurately, we install two signal
+// handlers: one that does nothing and just returns, and another that
+// calls Symbolize. The difference between the stack consumption of these
+// two signals handlers should give us the Symbolize stack foorprint.
+
+static void *g_pc_to_symbolize;
+static char g_symbolize_buffer[4096];
+static char *g_symbolize_result;
+
+static void EmptySignalHandler(int signo) {}
+
+static void SymbolizeSignalHandler(int signo) {
+ if (Symbolize(g_pc_to_symbolize, g_symbolize_buffer,
+ sizeof(g_symbolize_buffer))) {
+ g_symbolize_result = g_symbolize_buffer;
+ } else {
+ g_symbolize_result = NULL;
+ }
+}
+
+const int kAlternateStackSize = 8096;
+const char kAlternateStackFillValue = 0x55;
+
+// These helper functions look at the alternate stack buffer, and figure
+// out what portion of this buffer has been touched - this is the stack
+// consumption of the signal handler running on this alternate stack.
+static ATTRIBUTE_NOINLINE bool StackGrowsDown(int *x) {
+ int y;
+ return &y < x;
+}
+static int GetStackConsumption(const char* alt_stack) {
+ int x;
+ if (StackGrowsDown(&x)) {
+ for (int i = 0; i < kAlternateStackSize; i++) {
+ if (alt_stack[i] != kAlternateStackFillValue) {
+ return (kAlternateStackSize - i);
+ }
+ }
+ } else {
+ for (int i = (kAlternateStackSize - 1); i >= 0; i--) {
+ if (alt_stack[i] != kAlternateStackFillValue) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+#ifdef HAVE_SIGALTSTACK
+
+// Call Symbolize and figure out the stack footprint of this call.
+static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
+
+ g_pc_to_symbolize = pc;
+
+ // The alt-signal-stack cannot be heap allocated because there is a
+ // bug in glibc-2.2 where some signal handler setup code looks at the
+ // current stack pointer to figure out what thread is currently running.
+ // Therefore, the alternate stack must be allocated from the main stack
+ // itself.
+ char altstack[kAlternateStackSize];
+ memset(altstack, kAlternateStackFillValue, kAlternateStackSize);
+
+ // Set up the alt-signal-stack (and save the older one).
+ stack_t sigstk;
+ memset(&sigstk, 0, sizeof(stack_t));
+ stack_t old_sigstk;
+ sigstk.ss_sp = altstack;
+ sigstk.ss_size = kAlternateStackSize;
+ sigstk.ss_flags = 0;
+ CHECK_ERR(sigaltstack(&sigstk, &old_sigstk));
+
+ // Set up SIGUSR1 and SIGUSR2 signal handlers (and save the older ones).
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(struct sigaction));
+ struct sigaction old_sa1, old_sa2;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+
+ // SIGUSR1 maps to EmptySignalHandler.
+ sa.sa_handler = EmptySignalHandler;
+ CHECK_ERR(sigaction(SIGUSR1, &sa, &old_sa1));
+
+ // SIGUSR2 maps to SymbolizeSignalHanlder.
+ sa.sa_handler = SymbolizeSignalHandler;
+ CHECK_ERR(sigaction(SIGUSR2, &sa, &old_sa2));
+
+ // Send SIGUSR1 signal and measure the stack consumption of the empty
+ // signal handler.
+ CHECK_ERR(kill(getpid(), SIGUSR1));
+ int stack_consumption1 = GetStackConsumption(altstack);
+
+ // Send SIGUSR2 signal and measure the stack consumption of the symbolize
+ // signal handler.
+ CHECK_ERR(kill(getpid(), SIGUSR2));
+ int stack_consumption2 = GetStackConsumption(altstack);
+
+ // The difference between the two stack consumption values is the
+ // stack footprint of the Symbolize function.
+ if (stack_consumption1 != -1 && stack_consumption2 != -1) {
+ *stack_consumed = stack_consumption2 - stack_consumption1;
+ } else {
+ *stack_consumed = -1;
+ }
+
+ // Log the stack consumption values.
+ LOG(INFO) << "Stack consumption of empty signal handler: "
+ << stack_consumption1;
+ LOG(INFO) << "Stack consumption of symbolize signal handler: "
+ << stack_consumption2;
+ LOG(INFO) << "Stack consumption of Symbolize: " << *stack_consumed;
+
+ // Now restore the old alt-signal-stack and signal handlers.
+ CHECK_ERR(sigaltstack(&old_sigstk, NULL));
+ CHECK_ERR(sigaction(SIGUSR1, &old_sa1, NULL));
+ CHECK_ERR(sigaction(SIGUSR2, &old_sa2, NULL));
+
+ return g_symbolize_result;
+}
+
+// Symbolize stack consumption should be within 2kB.
+const int kStackConsumptionUpperLimit = 2048;
+
+TEST(Symbolize, SymbolizeStackConsumption) {
+ int stack_consumed;
+ const char* symbol;
+
+ symbol = SymbolizeStackConsumption((void *)(&nonstatic_func),
+ &stack_consumed);
+ EXPECT_STREQ("nonstatic_func", symbol);
+ EXPECT_GT(stack_consumed, 0);
+ EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
+
+ symbol = SymbolizeStackConsumption((void *)(&static_func),
+ &stack_consumed);
+ EXPECT_STREQ("static_func", symbol);
+ EXPECT_GT(stack_consumed, 0);
+ EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
+}
+
+#ifdef TEST_WITH_MODERN_GCC
+TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
+ Foo::func(100);
+ int stack_consumed;
+ const char* symbol;
+
+ symbol = SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed);
+
+ EXPECT_STREQ("Foo::func()", symbol);
+ EXPECT_GT(stack_consumed, 0);
+ EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
+}
+#endif
+
+#endif // HAVE_SIGALTSTACK
+
+// x86 specific tests. Uses some inline assembler.
+extern "C" {
+inline void* always_inline inline_func() {
+ register void *pc = NULL;
+#ifdef TEST_X86_32_AND_64
+ __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#endif
+ return pc;
+}
+
+void* ATTRIBUTE_NOINLINE non_inline_func() {
+ register void *pc = NULL;
+#ifdef TEST_X86_32_AND_64
+ __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#endif
+ return pc;
+}
+
+void ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() {
+#if defined(TEST_X86_32_AND_64) && defined(HAVE_ATTRIBUTE_NOINLINE)
+ void *pc = non_inline_func();
+ const char *symbol = TrySymbolize(pc);
+ CHECK(symbol != NULL);
+ CHECK_STREQ(symbol, "non_inline_func");
+ cout << "Test case TestWithPCInsideNonInlineFunction passed." << endl;
+#endif
+}
+
+void ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {
+#if defined(TEST_X86_32_AND_64) && defined(HAVE_ALWAYS_INLINE)
+ void *pc = inline_func(); // Must be inlined.
+ const char *symbol = TrySymbolize(pc);
+ CHECK(symbol != NULL);
+ CHECK_STREQ(symbol, __FUNCTION__);
+ cout << "Test case TestWithPCInsideInlineFunction passed." << endl;
+#endif
+}
+}
+
+// Test with a return address.
+void ATTRIBUTE_NOINLINE TestWithReturnAddress() {
+#if defined(HAVE_ATTRIBUTE_NOINLINE)
+ void *return_address = __builtin_return_address(0);
+ const char *symbol = TrySymbolize(return_address);
+ CHECK(symbol != NULL);
+ CHECK_STREQ(symbol, "main");
+ cout << "Test case TestWithReturnAddress passed." << endl;
+#endif
+}
+
+int main(int argc, char **argv) {
+ FLAGS_logtostderr = true;
+ InitGoogleLogging(argv[0]);
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_SYMBOLIZE
+ // We don't want to get affected by the callback interface, that may be
+ // used to install some callback function at InitGoogle() time.
+ InstallSymbolizeCallback(NULL);
+
+ TestWithPCInsideInlineFunction();
+ TestWithPCInsideNonInlineFunction();
+ TestWithReturnAddress();
+ return RUN_ALL_TESTS();
+#else
+ return 0;
+#endif
+}
+
+#else
+int main() {
+#ifdef HAVE_SYMBOLIZE
+ printf("PASS (no symbolize_unittest support)\n");
+#else
+ printf("PASS (no symbolize support)\n");
+#endif
+ return 0;
+}
+#endif // HAVE_STACKTRACE
diff --git a/thirdparty/glog/glog-0.3.4/src/utilities.cc b/thirdparty/glog/glog-0.3.4/src/utilities.cc
new file mode 100644
index 0000000..ab6aaea
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/utilities.cc
@@ -0,0 +1,431 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+
+#include "utilities.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <signal.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <time.h>
+#if defined(HAVE_SYSCALL_H)
+#include <syscall.h> // for syscall()
+#elif defined(HAVE_SYS_SYSCALL_H)
+#include <sys/syscall.h> // for syscall()
+#endif
+#ifdef HAVE_SYSLOG_H
+# include <syslog.h>
+#endif
+
+#include "base/googleinit.h"
+
+using std::string;
+
+_START_GOOGLE_NAMESPACE_
+
+static const char* g_program_invocation_short_name = NULL;
+static pthread_t g_main_thread_id;
+
+
+_END_GOOGLE_NAMESPACE_
+
+// The following APIs are all internal.
+#ifdef HAVE_STACKTRACE
+
+#include "stacktrace.h"
+#include "symbolize.h"
+#include "base/commandlineflags.h"
+
+GLOG_DEFINE_bool(symbolize_stacktrace, true,
+ "Symbolize the stack trace in the tombstone");
+
+_START_GOOGLE_NAMESPACE_
+
+typedef void DebugWriter(const char*, void*);
+
+// The %p field width for printf() functions is two characters per byte.
+// For some environments, add two extra bytes for the leading "0x".
+static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
+
+static void DebugWriteToStderr(const char* data, void *) {
+ // This one is signal-safe.
+ if (write(STDERR_FILENO, data, strlen(data)) < 0) {
+ // Ignore errors.
+ }
+}
+
+void DebugWriteToString(const char* data, void *arg) {
+ reinterpret_cast<string*>(arg)->append(data);
+}
+
+#ifdef HAVE_SYMBOLIZE
+// Print a program counter and its symbol name.
+static void DumpPCAndSymbol(DebugWriter *writerfn, void *arg, void *pc,
+ const char * const prefix) {
+ char tmp[1024];
+ const char *symbol = "(unknown)";
+ // Symbolizes the previous address of pc because pc may be in the
+ // next function. The overrun happens when the function ends with
+ // a call to a function annotated noreturn (e.g. CHECK).
+ if (Symbolize(reinterpret_cast<char *>(pc) - 1, tmp, sizeof(tmp))) {
+ symbol = tmp;
+ }
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s@ %*p %s\n",
+ prefix, kPrintfPointerFieldWidth, pc, symbol);
+ writerfn(buf, arg);
+}
+#endif
+
+static void DumpPC(DebugWriter *writerfn, void *arg, void *pc,
+ const char * const prefix) {
+ char buf[100];
+ snprintf(buf, sizeof(buf), "%s@ %*p\n",
+ prefix, kPrintfPointerFieldWidth, pc);
+ writerfn(buf, arg);
+}
+
+// Dump current stack trace as directed by writerfn
+static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) {
+ // Print stack trace
+ void* stack[32];
+ int depth = GetStackTrace(stack, ARRAYSIZE(stack), skip_count+1);
+ for (int i = 0; i < depth; i++) {
+#if defined(HAVE_SYMBOLIZE)
+ if (FLAGS_symbolize_stacktrace) {
+ DumpPCAndSymbol(writerfn, arg, stack[i], " ");
+ } else {
+ DumpPC(writerfn, arg, stack[i], " ");
+ }
+#else
+ DumpPC(writerfn, arg, stack[i], " ");
+#endif
+ }
+}
+
+static void DumpStackTraceAndExit() {
+ DumpStackTrace(1, DebugWriteToStderr, NULL);
+
+ // TOOD(hamaji): Use signal instead of sigaction?
+#ifdef HAVE_SIGACTION
+ // Set the default signal handler for SIGABRT, to avoid invoking our
+ // own signal handler installed by InstallFailedSignalHandler().
+ struct sigaction sig_action;
+ memset(&sig_action, 0, sizeof(sig_action));
+ sigemptyset(&sig_action.sa_mask);
+ sig_action.sa_handler = SIG_DFL;
+ sigaction(SIGABRT, &sig_action, NULL);
+#endif // HAVE_SIGACTION
+
+ abort();
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // HAVE_STACKTRACE
+
+_START_GOOGLE_NAMESPACE_
+
+namespace glog_ns_internal_namespace_ {
+
+const char* ProgramInvocationShortName() {
+ if (g_program_invocation_short_name != NULL) {
+ return g_program_invocation_short_name;
+ } else {
+ // TODO(hamaji): Use /proc/self/cmdline and so?
+ return "UNKNOWN";
+ }
+}
+
+bool IsGoogleLoggingInitialized() {
+ return g_program_invocation_short_name != NULL;
+}
+
+bool is_default_thread() {
+ if (g_program_invocation_short_name == NULL) {
+ // InitGoogleLogging() not yet called, so unlikely to be in a different
+ // thread
+ return true;
+ } else {
+ return pthread_equal(pthread_self(), g_main_thread_id);
+ }
+}
+
+#ifdef OS_WINDOWS
+struct timeval {
+ long tv_sec, tv_usec;
+};
+
+// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
+// See COPYING for copyright information.
+static int gettimeofday(struct timeval *tv, void* tz) {
+#define EPOCHFILETIME (116444736000000000ULL)
+ FILETIME ft;
+ LARGE_INTEGER li;
+ uint64 tt;
+
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ tt = (li.QuadPart - EPOCHFILETIME) / 10;
+ tv->tv_sec = tt / 1000000;
+ tv->tv_usec = tt % 1000000;
+
+ return 0;
+}
+#endif
+
+int64 CycleClock_Now() {
+ // TODO(hamaji): temporary impementation - it might be too slow.
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
+}
+
+int64 UsecToCycles(int64 usec) {
+ return usec;
+}
+
+WallTime WallTime_Now() {
+ // Now, cycle clock is retuning microseconds since the epoch.
+ return CycleClock_Now() * 0.000001;
+}
+
+static int32 g_main_thread_pid = getpid();
+int32 GetMainThreadPid() {
+ return g_main_thread_pid;
+}
+
+bool PidHasChanged() {
+ int32 pid = getpid();
+ if (g_main_thread_pid == pid) {
+ return false;
+ }
+ g_main_thread_pid = pid;
+ return true;
+}
+
+pid_t GetTID() {
+ // On Linux and MacOSX, we try to use gettid().
+#if defined OS_LINUX || defined OS_MACOSX
+#ifndef __NR_gettid
+#ifdef OS_MACOSX
+#define __NR_gettid SYS_gettid
+#elif ! defined __i386__
+#error "Must define __NR_gettid for non-x86 platforms"
+#else
+#define __NR_gettid 224
+#endif
+#endif
+ static bool lacks_gettid = false;
+ if (!lacks_gettid) {
+ pid_t tid = syscall(__NR_gettid);
+ if (tid != -1) {
+ return tid;
+ }
+ // Technically, this variable has to be volatile, but there is a small
+ // performance penalty in accessing volatile variables and there should
+ // not be any serious adverse effect if a thread does not immediately see
+ // the value change to "true".
+ lacks_gettid = true;
+ }
+#endif // OS_LINUX || OS_MACOSX
+
+ // If gettid() could not be used, we use one of the following.
+#if defined OS_LINUX
+ return getpid(); // Linux: getpid returns thread ID when gettid is absent
+#elif defined OS_WINDOWS || defined OS_CYGWIN
+ return GetCurrentThreadId();
+#else
+ // If none of the techniques above worked, we use pthread_self().
+ return (pid_t)(uintptr_t)pthread_self();
+#endif
+}
+
+const char* const_basename(const char* filepath) {
+ const char* base = strrchr(filepath, '/');
+#ifdef OS_WINDOWS // Look for either path separator in Windows
+ if (!base)
+ base = strrchr(filepath, '\\');
+#endif
+ return base ? (base+1) : filepath;
+}
+
+static string g_my_user_name;
+const string& MyUserName() {
+ return g_my_user_name;
+}
+static void MyUserNameInitializer() {
+ // TODO(hamaji): Probably this is not portable.
+#if defined(OS_WINDOWS)
+ const char* user = getenv("USERNAME");
+#else
+ const char* user = getenv("USER");
+#endif
+ if (user != NULL) {
+ g_my_user_name = user;
+ } else {
+ g_my_user_name = "invalid-user";
+ }
+}
+REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer());
+
+#ifdef HAVE_STACKTRACE
+void DumpStackTraceToString(string* stacktrace) {
+ DumpStackTrace(1, DebugWriteToString, stacktrace);
+}
+#endif
+
+// We use an atomic operation to prevent problems with calling CrashReason
+// from inside the Mutex implementation (potentially through RAW_CHECK).
+static const CrashReason* g_reason = 0;
+
+void SetCrashReason(const CrashReason* r) {
+ sync_val_compare_and_swap(&g_reason,
+ reinterpret_cast<const CrashReason*>(0),
+ r);
+}
+
+void InitGoogleLoggingUtilities(const char* argv0) {
+ CHECK(!IsGoogleLoggingInitialized())
+ << "You called InitGoogleLogging() twice!";
+ const char* slash = strrchr(argv0, '/');
+#ifdef OS_WINDOWS
+ if (!slash) slash = strrchr(argv0, '\\');
+#endif
+ g_program_invocation_short_name = slash ? slash + 1 : argv0;
+ g_main_thread_id = pthread_self();
+
+#ifdef HAVE_STACKTRACE
+ InstallFailureFunction(&DumpStackTraceAndExit);
+#endif
+}
+
+void ShutdownGoogleLoggingUtilities() {
+ CHECK(IsGoogleLoggingInitialized())
+ << "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
+ g_program_invocation_short_name = NULL;
+#ifdef HAVE_SYSLOG_H
+ closelog();
+#endif
+}
+
+
+
+
+inline int get_day_of_month(int mon, int is_leap);
+inline int get_day_of_month(int mon, int is_leap)
+{
+ int table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ if (mon==1 && is_leap) {
+ return 29;
+ }
+ return table[mon];
+}
+
+/* Implement glibc's gmtime_r function with no locks what so ever */
+struct tm *my_gmtime_r(const time_t *timep, struct tm *result)
+{
+ int isdst = 0; //not implemented
+ time_t t = *timep;
+ if (t < 0) {
+ t = 0; //ignore time before 1970-01-01 00:00:00
+ }
+ int sec = t % 60;
+ t /= 60;
+ int min = t % 60;
+ t /= 60;
+ int hour = t % 24;
+ t /= 24;
+
+ int wday = t % 7 + 4;
+ wday = (wday>7) ? (wday-7) : wday;
+
+ int year = 1970;
+ int is_leap;
+
+ /* cheat first */
+ if (t > 1483228800) // 2017-01-01 00:00:00
+ {
+ t -= 1483228800;
+ year = 2017;
+ }
+ for (;;year++) {
+ is_leap = ((year%4 == 0 && year%100 != 0) || year%400 == 0);
+ if (t < 365 + is_leap) {
+ break;
+ }
+ else {
+ t -= (365 + is_leap);
+ }
+ }
+ int yday = t;
+
+ int mon = 0;
+ for (;;mon++) {
+ if (t < get_day_of_month(mon, is_leap)) {
+ break;
+ }
+ else {
+ t -= get_day_of_month(mon, is_leap);
+ }
+ }
+
+ int mday = t;
+
+ result->tm_sec = sec;
+ result->tm_min = min;
+ result->tm_hour = hour;
+ result->tm_mday = mday+1;
+ result->tm_year = year-1900;
+ result->tm_mon = mon;
+ result->tm_wday = wday;
+ result->tm_yday = yday;
+ result->tm_isdst = isdst;
+
+ return result;
+
+}
+
+} // namespace glog_internal_namespace_
+
+_END_GOOGLE_NAMESPACE_
+
+// Make an implementation of stacktrace compiled.
+#ifdef STACKTRACE_H
+# include STACKTRACE_H
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/utilities.h b/thirdparty/glog/glog-0.3.4/src/utilities.h
new file mode 100644
index 0000000..c500a0b
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/utilities.h
@@ -0,0 +1,230 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+//
+// Define utilties for glog internal usage.
+
+#ifndef UTILITIES_H__
+#define UTILITIES_H__
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+# define OS_WINDOWS
+#elif defined(__CYGWIN__) || defined(__CYGWIN32__)
+# define OS_CYGWIN
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+# define OS_LINUX
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+# define OS_MACOSX
+#elif defined(__FreeBSD__)
+# define OS_FREEBSD
+#elif defined(__NetBSD__)
+# define OS_NETBSD
+#elif defined(__OpenBSD__)
+# define OS_OPENBSD
+#else
+// TODO(hamaji): Add other platforms.
+#endif
+
+// printf macros for size_t, in the style of inttypes.h
+#ifdef _LP64
+#define __PRIS_PREFIX "z"
+#else
+#define __PRIS_PREFIX
+#endif
+
+// Use these macros after a % in a printf format string
+// to get correct 32/64 bit behavior, like this:
+// size_t size = records.size();
+// printf("%"PRIuS"\n", size);
+
+#define PRIdS __PRIS_PREFIX "d"
+#define PRIxS __PRIS_PREFIX "x"
+#define PRIuS __PRIS_PREFIX "u"
+#define PRIXS __PRIS_PREFIX "X"
+#define PRIoS __PRIS_PREFIX "o"
+
+#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
+
+#include <string>
+
+#if defined(OS_WINDOWS)
+# include "port.h"
+#endif
+
+#include "config.h"
+#include "glog/logging.h"
+
+// There are three different ways we can try to get the stack trace:
+//
+// 1) The libunwind library. This is still in development, and as a
+// separate library adds a new dependency, but doesn't need a frame
+// pointer. It also doesn't call malloc.
+//
+// 2) Our hand-coded stack-unwinder. This depends on a certain stack
+// layout, which is used by gcc (and those systems using a
+// gcc-compatible ABI) on x86 systems, at least since gcc 2.95.
+// It uses the frame pointer to do its work.
+//
+// 3) The gdb unwinder -- also the one used by the c++ exception code.
+// It's obviously well-tested, but has a fatal flaw: it can call
+// malloc() from the unwinder. This is a problem because we're
+// trying to use the unwinder to instrument malloc().
+//
+// Note: if you add a new implementation here, make sure it works
+// correctly when GetStackTrace() is called with max_depth == 0.
+// Some code may do that.
+
+#if defined(HAVE_LIB_UNWIND)
+# define STACKTRACE_H "stacktrace_libunwind-inl.h"
+#elif !defined(NO_FRAME_POINTER)
+# if defined(__i386__) && __GNUC__ >= 2
+# define STACKTRACE_H "stacktrace_x86-inl.h"
+# elif defined(__x86_64__) && __GNUC__ >= 2 && HAVE_UNWIND_H
+# define STACKTRACE_H "stacktrace_x86_64-inl.h"
+# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
+# define STACKTRACE_H "stacktrace_powerpc-inl.h"
+# endif
+#endif
+
+#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_H)
+# define STACKTRACE_H "stacktrace_generic-inl.h"
+#endif
+
+#if defined(STACKTRACE_H)
+# define HAVE_STACKTRACE
+#endif
+
+// defined by gcc
+#if defined(__ELF__) && defined(OS_LINUX)
+# define HAVE_SYMBOLIZE
+#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
+// Use dladdr to symbolize.
+# define HAVE_SYMBOLIZE
+#endif
+
+#ifndef ARRAYSIZE
+// There is a better way, but this is good enough for our purpose.
+# define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
+#endif
+
+_START_GOOGLE_NAMESPACE_
+
+namespace glog_ns_internal_namespace_ {
+
+#ifdef HAVE___ATTRIBUTE__
+# define ATTRIBUTE_NOINLINE __attribute__ ((noinline))
+# define HAVE_ATTRIBUTE_NOINLINE
+#else
+# define ATTRIBUTE_NOINLINE
+#endif
+
+const char* ProgramInvocationShortName();
+
+bool IsGoogleLoggingInitialized();
+
+bool is_default_thread();
+
+int64 CycleClock_Now();
+
+int64 UsecToCycles(int64 usec);
+
+typedef double WallTime;
+WallTime WallTime_Now();
+struct tm *my_gmtime_r(const time_t *timep, struct tm *result);
+
+int32 GetMainThreadPid();
+bool PidHasChanged();
+
+pid_t GetTID();
+
+const std::string& MyUserName();
+
+// Get the part of filepath after the last path separator.
+// (Doesn't modify filepath, contrary to basename() in libgen.h.)
+const char* const_basename(const char* filepath);
+
+// Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't
+// defined, we try the CPU specific logics (we only support x86 and
+// x86_64 for now) first, then use a naive implementation, which has a
+// race condition.
+template<typename T>
+inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) {
+#if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP)
+ return __sync_val_compare_and_swap(ptr, oldval, newval);
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ T ret;
+ __asm__ __volatile__("lock; cmpxchg %1, (%2);"
+ :"=a"(ret)
+ // GCC may produces %sil or %dil for
+ // constraint "r", but some of apple's gas
+ // dosn't know the 8 bit registers.
+ // We use "q" to avoid these registers.
+ :"q"(newval), "q"(ptr), "a"(oldval)
+ :"memory", "cc");
+ return ret;
+#else
+ T ret = *ptr;
+ if (ret == oldval) {
+ *ptr = newval;
+ }
+ return ret;
+#endif
+}
+
+void DumpStackTraceToString(std::string* stacktrace);
+
+struct CrashReason {
+ CrashReason() : filename(0), line_number(0), message(0), depth(0) {}
+
+ const char* filename;
+ int line_number;
+ const char* message;
+
+ // We'll also store a bit of stack trace context at the time of crash as
+ // it may not be available later on.
+ void* stack[32];
+ int depth;
+};
+
+void SetCrashReason(const CrashReason* r);
+
+void InitGoogleLoggingUtilities(const char* argv0);
+void ShutdownGoogleLoggingUtilities();
+
+} // namespace glog_internal_namespace_
+
+_END_GOOGLE_NAMESPACE_
+
+using namespace GOOGLE_NAMESPACE::glog_ns_internal_namespace_;
+
+#endif // UTILITIES_H__
diff --git a/thirdparty/glog/glog-0.3.4/src/utilities_unittest.cc b/thirdparty/glog/glog-0.3.4/src/utilities_unittest.cc
new file mode 100644
index 0000000..7b79619
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/utilities_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+
+#include "utilities.h"
+#include "googletest.h"
+#include "glog/logging.h"
+
+using namespace GOOGLE_NAMESPACE;
+
+TEST(utilities, sync_val_compare_and_swap) {
+ bool now_entering = false;
+ EXPECT_FALSE(sync_val_compare_and_swap(&now_entering, false, true));
+ EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true));
+ EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true));
+}
+
+TEST(utilities, InitGoogleLoggingDeathTest) {
+ ASSERT_DEATH(InitGoogleLogging("foobar"), "");
+}
+
+int main(int argc, char **argv) {
+ InitGoogleLogging(argv[0]);
+ InitGoogleTest(&argc, argv);
+
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/vlog_is_on.cc b/thirdparty/glog/glog-0.3.4/src/vlog_is_on.cc
new file mode 100644
index 0000000..23741e8
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/vlog_is_on.cc
@@ -0,0 +1,252 @@
+// This file has been modified by Huawei.
+// Copyright (C) 2018£¬ Huawei.
+//
+// Copyright (c) 1999, 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney and many others
+//
+// Broken out from logging.cc by Soren Lassen
+// logging_unittest.cc covers the functionality herein
+
+#include "utilities.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cstdio>
+#include <string>
+#include "base/commandlineflags.h"
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
+#include "base/googleinit.h"
+
+// glog doesn't have annotation
+#define ANNOTATE_BENIGN_RACE(address, description)
+
+using std::string;
+
+GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this."
+" Overridable by --vmodule.");
+
+GLOG_DEFINE_string(vmodule, "", "per-module verbose level."
+" Argument is a comma-separated list of <module name>=<log level>."
+" <module name> is a glob pattern, matched against the filename base"
+" (that is, name ignoring .cc/.h./-inl.h)."
+" <log level> overrides any value given by --v.");
+
+_START_GOOGLE_NAMESPACE_
+
+namespace glog_ns_internal_namespace_ {
+
+// Implementation of fnmatch that does not need 0-termination
+// of arguments and does not allocate any memory,
+// but we only support "*" and "?" wildcards, not the "[...]" patterns.
+// It's not a static function for the unittest.
+GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
+ size_t patt_len,
+ const char* str,
+ size_t str_len) {
+ size_t p = 0;
+ size_t s = 0;
+ while (1) {
+ if (p == patt_len && s == str_len) return true;
+ if (p == patt_len) return false;
+ if (s == str_len) return p+1 == patt_len && pattern[p] == '*';
+ if (pattern[p] == str[s] || pattern[p] == '?') {
+ p += 1;
+ s += 1;
+ continue;
+ }
+ if (pattern[p] == '*') {
+ if (p+1 == patt_len) return true;
+ do {
+ if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) {
+ return true;
+ }
+ s += 1;
+ } while (s != str_len);
+ return false;
+ }
+ return false;
+ }
+}
+
+} // namespace glog_internal_namespace_
+
+using glog_ns_internal_namespace_::SafeFNMatch_;
+
+int32 kLogSiteUninitialized = 1000;
+
+// List of per-module log levels from FLAGS_vmodule.
+// Once created each element is never deleted/modified
+// except for the vlog_level: other threads will read VModuleInfo blobs
+// w/o locks and we'll store pointers to vlog_level at VLOG locations
+// that will never go away.
+// We can't use an STL struct here as we wouldn't know
+// when it's safe to delete/update it: other threads need to use it w/o locks.
+struct VModuleInfo {
+ string module_pattern;
+ mutable int32 vlog_level; // Conceptually this is an AtomicWord, but it's
+ // too much work to use AtomicWord type here
+ // w/o much actual benefit.
+ const VModuleInfo* next;
+};
+
+// This protects the following global variables.
+static Mutex vmodule_lock;
+// Pointer to head of the VModuleInfo list.
+// It's a map from module pattern to logging level for those module(s).
+static VModuleInfo* vmodule_list = 0;
+// Boolean initialization flag.
+static bool inited_vmodule = false;
+
+// L >= vmodule_lock.
+static void VLOG2Initializer() {
+ vmodule_lock.AssertHeld();
+ // Can now parse --vmodule flag and initialize mapping of module-specific
+ // logging levels.
+ inited_vmodule = false;
+ const char* vmodule = FLAGS_vmodule.c_str();
+ const char* sep;
+ VModuleInfo* head = NULL;
+ VModuleInfo* tail = NULL;
+ while ((sep = strchr(vmodule, '=')) != NULL) {
+ string pattern(vmodule, sep - vmodule);
+ int module_level;
+ if (sscanf(sep, "=%d", &module_level) == 1) {
+ VModuleInfo* info = new VModuleInfo;
+ info->module_pattern = pattern;
+ info->vlog_level = module_level;
+ if (head) tail->next = info;
+ else head = info;
+ tail = info;
+ }
+ // Skip past this entry
+ vmodule = strchr(sep, ',');
+ if (vmodule == NULL) break;
+ vmodule++; // Skip past ","
+ }
+ if (head) { // Put them into the list at the head:
+ tail->next = vmodule_list;
+ vmodule_list = head;
+ }
+ inited_vmodule = true;
+}
+
+// This can be called very early, so we use SpinLock and RAW_VLOG here.
+int SetVLOGLevel(const char* module_pattern, int log_level) {
+ int result = FLAGS_v;
+ int const pattern_len = strlen(module_pattern);
+ bool found = false;
+ MutexLock l(&vmodule_lock); // protect whole read-modify-write
+ for (const VModuleInfo* info = vmodule_list;
+ info != NULL; info = info->next) {
+ if (info->module_pattern == module_pattern) {
+ if (!found) {
+ result = info->vlog_level;
+ found = true;
+ }
+ info->vlog_level = log_level;
+ } else if (!found &&
+ SafeFNMatch_(info->module_pattern.c_str(),
+ info->module_pattern.size(),
+ module_pattern, pattern_len)) {
+ result = info->vlog_level;
+ found = true;
+ }
+ }
+ if (!found) {
+ VModuleInfo* info = new VModuleInfo;
+ info->module_pattern = module_pattern;
+ info->vlog_level = log_level;
+ info->next = vmodule_list;
+ vmodule_list = info;
+ }
+ RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
+ return result;
+}
+
+// NOTE: Individual VLOG statements cache the integer log level pointers.
+// NOTE: This function must not allocate memory or require any locks.
+bool InitVLOG3__(int32** site_flag, int32* site_default,
+ const char* fname, int32 verbose_level) {
+ MutexLock l(&vmodule_lock);
+ bool read_vmodule_flag = inited_vmodule;
+ if (!read_vmodule_flag) {
+ VLOG2Initializer();
+ }
+
+ // protect the errno global in case someone writes:
+ // VLOG(..) << "The last error was " << strerror(errno)
+ int old_errno = errno;
+
+ // site_default normally points to FLAGS_v
+ int32* site_flag_value = site_default;
+
+ // Get basename for file
+ const char* base = strrchr(fname, '/');
+ base = base ? (base+1) : fname;
+ const char* base_end = strchr(base, '.');
+ size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
+
+ // Trim out trailing "-inl" if any
+ if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) {
+ base_length -= 4;
+ }
+
+ // TODO: Trim out _unittest suffix? Perhaps it is better to have
+ // the extra control and just leave it there.
+
+ // find target in vector of modules, replace site_flag_value with
+ // a module-specific verbose level, if any.
+ for (const VModuleInfo* info = vmodule_list;
+ info != NULL; info = info->next) {
+ if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
+ base, base_length)) {
+ site_flag_value = &info->vlog_level;
+ // value at info->vlog_level is now what controls
+ // the VLOG at the caller site forever
+ break;
+ }
+ }
+
+ // Cache the vlog value pointer if --vmodule flag has been parsed.
+ ANNOTATE_BENIGN_RACE(site_flag,
+ "*site_flag may be written by several threads,"
+ " but the value will be the same");
+ if (read_vmodule_flag) *site_flag = site_flag_value;
+
+ // restore the errno in case something recoverable went wrong during
+ // the initialization of the VLOG mechanism (see above note "protect the..")
+ errno = old_errno;
+ return *site_flag_value >= verbose_level;
+}
+
+_END_GOOGLE_NAMESPACE_
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/config.h b/thirdparty/glog/glog-0.3.4/src/windows/config.h
new file mode 100644
index 0000000..2d23fb0
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/config.h
@@ -0,0 +1,21 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Namespace for Google classes */
+#define GOOGLE_NAMESPACE google
+
+/* Stops putting the code inside the Google namespace */
+#define _END_GOOGLE_NAMESPACE_ }
+
+/* Puts following code inside the Google namespace */
+#define _START_GOOGLE_NAMESPACE_ namespace google {
+
+/* Always the empty-string on non-windows systems. On windows, should be
+ "__declspec(dllexport)". This way, when we compile the dll, we export our
+ functions/classes. It's safe to define this here because config.h is only
+ used internally, to compile the DLL, and every DLL source file #includes
+ "config.h" before anything else. */
+#ifndef GOOGLE_GLOG_DLL_DECL
+# define GOOGLE_GLOG_IS_A_DLL 1 /* not set if you're statically linking */
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllexport)
+# define GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+#endif
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/glog/log_severity.h b/thirdparty/glog/glog-0.3.4/src/windows/glog/log_severity.h
new file mode 100644
index 0000000..22a4191
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/glog/log_severity.h
@@ -0,0 +1,96 @@
+// This file is automatically generated from src/glog/log_severity.h
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef BASE_LOG_SEVERITY_H__
+#define BASE_LOG_SEVERITY_H__
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+// Variables of type LogSeverity are widely taken to lie in the range
+// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
+// you ever need to change their values or add a new severity.
+typedef int LogSeverity;
+
+const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
+ NUM_SEVERITIES = 4;
+#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
+# ifdef ERROR
+# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
+# endif
+const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
+ ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
+#endif
+
+// DFATAL is FATAL in debug mode, ERROR in normal mode
+#ifdef NDEBUG
+#define DFATAL_LEVEL ERROR
+#else
+#define DFATAL_LEVEL FATAL
+#endif
+
+extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
+
+// NDEBUG usage helpers related to (RAW_)DCHECK:
+//
+// DEBUG_MODE is for small !NDEBUG uses like
+// if (DEBUG_MODE) foo.CheckThatFoo();
+// instead of substantially more verbose
+// #ifndef NDEBUG
+// foo.CheckThatFoo();
+// #endif
+//
+// IF_DEBUG_MODE is for small !NDEBUG uses like
+// IF_DEBUG_MODE( string error; )
+// DCHECK(Foo(&error)) << error;
+// instead of substantially more verbose
+// #ifndef NDEBUG
+// string error;
+// DCHECK(Foo(&error)) << error;
+// #endif
+//
+#ifdef NDEBUG
+enum { DEBUG_MODE = 0 };
+#define IF_DEBUG_MODE(x)
+#else
+enum { DEBUG_MODE = 1 };
+#define IF_DEBUG_MODE(x) x
+#endif
+
+#endif // BASE_LOG_SEVERITY_H__
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/glog/logging.h b/thirdparty/glog/glog-0.3.4/src/windows/glog/logging.h
new file mode 100644
index 0000000..bab8c61
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/glog/logging.h
@@ -0,0 +1,1607 @@
+// This file is automatically generated from src/glog/logging.h.in
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+
+// Copyright (c) 1999, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney
+//
+// This file contains #include information about logging-related stuff.
+// Pretty much everybody needs to #include this file so that they can
+// log various happenings.
+//
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <iosfwd>
+#include <ostream>
+#include <sstream>
+#include <string>
+#if 0
+# include <unistd.h>
+#endif
+#include <vector>
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+#if defined(_MSC_VER)
+#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
+ __pragma(warning(disable:n))
+#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
+#else
+#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
+#define GLOG_MSVC_POP_WARNING()
+#endif
+
+// We care a lot about number of bits things take up. Unfortunately,
+// systems define their bit-specific ints in a lot of different ways.
+// We use our own way, and have a typedef to get there.
+// Note: these commands below may look like "#if 1" or "#if 0", but
+// that's because they were constructed that way at ./configure time.
+// Look at logging.h.in to see how they're calculated (based on your config).
+#if 0
+#include <stdint.h> // the normal place uint16_t is defined
+#endif
+#if 0
+#include <sys/types.h> // the normal place u_int16_t is defined
+#endif
+#if 0
+#include <inttypes.h> // a third place for uint16_t or u_int16_t
+#endif
+
+#if 0
+#include <gflags/gflags.h>
+#endif
+
+namespace google {
+
+#if 0 // the C99 format
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#elif 0 // the BSD format
+typedef int32_t int32;
+typedef u_int32_t uint32;
+typedef int64_t int64;
+typedef u_int64_t uint64;
+#elif 1 // the windows (vc7) format
+typedef __int32 int32;
+typedef unsigned __int32 uint32;
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+#else
+#error Do not know how to define a 32-bit integer quantity on your system
+#endif
+
+}
+
+// The global value of GOOGLE_STRIP_LOG. All the messages logged to
+// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
+// If it can be determined at compile time that the message will not be
+// printed, the statement will be compiled out.
+//
+// Example: to strip out all INFO and WARNING messages, use the value
+// of 2 below. To make an exception for WARNING messages from a single
+// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
+// base/logging.h
+#ifndef GOOGLE_STRIP_LOG
+#define GOOGLE_STRIP_LOG 0
+#endif
+
+// GCC can be told that a certain branch is not likely to be taken (for
+// instance, a CHECK failure), and use that information in static analysis.
+// Giving it this information can help it optimize for the common case in
+// the absence of better information (ie. -fprofile-arcs).
+//
+#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
+#if 0
+#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
+#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
+#define GOOGLE_PREDICT_FALSE(x) x
+#define GOOGLE_PREDICT_TRUE(x) x
+#endif
+#endif
+
+// Make a bunch of macros for logging. The way to log things is to stream
+// things to LOG(<a particular severity level>). E.g.,
+//
+// LOG(INFO) << "Found " << num_cookies << " cookies";
+//
+// You can capture log messages in a string, rather than reporting them
+// immediately:
+//
+// vector<string> errors;
+// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
+//
+// This pushes back the new error onto 'errors'; if given a NULL pointer,
+// it reports the error via LOG(ERROR).
+//
+// You can also do conditional logging:
+//
+// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// You can also do occasional logging (log every n'th occurrence of an
+// event):
+//
+// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
+//
+// The above will cause log messages to be output on the 1st, 11th, 21st, ...
+// times it is executed. Note that the special google::COUNTER value is used
+// to identify which repetition is happening.
+//
+// You can also do occasional conditional logging (log every n'th
+// occurrence of an event, when condition is satisfied):
+//
+// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
+// << "th big cookie";
+//
+// You can log messages the first N times your code executes a line. E.g.
+//
+// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
+//
+// Outputs log messages for the first 20 times it is executed.
+//
+// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
+// These log to syslog as well as to the normal logs. If you use these at
+// all, you need to be aware that syslog can drastically reduce performance,
+// especially if it is configured for remote logging! Don't use these
+// unless you fully understand this and have a concrete need to use them.
+// Even then, try to minimize your use of them.
+//
+// There are also "debug mode" logging macros like the ones above:
+//
+// DLOG(INFO) << "Found cookies";
+//
+// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+//
+// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
+//
+// All "debug mode" logging is compiled away to nothing for non-debug mode
+// compiles.
+//
+// We also have
+//
+// LOG_ASSERT(assertion);
+// DLOG_ASSERT(assertion);
+//
+// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
+//
+// There are "verbose level" logging macros. They look like
+//
+// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
+// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
+//
+// These always log at the INFO log level (when they log at all).
+// The verbose logging can also be turned on module-by-module. For instance,
+// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
+// will cause:
+// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
+// b. VLOG(1) and lower messages to be printed from file.{h,cc}
+// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
+// d. VLOG(0) and lower messages to be printed from elsewhere
+//
+// The wildcarding functionality shown by (c) supports both '*' (match
+// 0 or more characters) and '?' (match any single character) wildcards.
+//
+// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
+//
+// if (VLOG_IS_ON(2)) {
+// // do some logging preparation and logging
+// // that can't be accomplished with just VLOG(2) << ...;
+// }
+//
+// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
+// condition macros for sample cases, when some extra computation and
+// preparation for logs is not needed.
+// VLOG_IF(1, (size > 1024))
+// << "I'm printed when size is more than 1024 and when you run the "
+// "program with --v=1 or more";
+// VLOG_EVERY_N(1, 10)
+// << "I'm printed every 10th occurrence, and when you run the program "
+// "with --v=1 or more. Present occurence is " << google::COUNTER;
+// VLOG_IF_EVERY_N(1, (size > 1024), 10)
+// << "I'm printed on every 10th occurence of case when size is more "
+// " than 1024, when you run the program with --v=1 or more. ";
+// "Present occurence is " << google::COUNTER;
+//
+// The supported severity levels for macros that allow you to specify one
+// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
+// Note that messages of a given severity are logged not only in the
+// logfile for that severity, but also in all logfiles of lower severity.
+// E.g., a message of severity FATAL will be logged to the logfiles of
+// severity FATAL, ERROR, WARNING, and INFO.
+//
+// There is also the special severity of DFATAL, which logs FATAL in
+// debug mode, ERROR in normal mode.
+//
+// Very important: logging a message at the FATAL severity level causes
+// the program to terminate (after the message is logged).
+//
+// Unless otherwise specified, logs will be written to the filename
+// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
+// by the date, time, and pid (you can't prevent the date, time, and pid
+// from being in the filename).
+//
+// The logging code takes two flags:
+// --v=# set the verbose level
+// --logtostderr log all the messages to stderr instead of to logfiles
+
+// LOG LINE PREFIX FORMAT
+//
+// Log lines have this form:
+//
+// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
+//
+// where the fields are defined as follows:
+//
+// L A single character, representing the log level
+// (eg 'I' for INFO)
+// mm The month (zero padded; ie May is '05')
+// dd The day (zero padded)
+// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
+// threadid The space-padded thread ID as returned by GetTID()
+// (this matches the PID on Linux)
+// file The file name
+// line The line number
+// msg The user-supplied message
+//
+// Example:
+//
+// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
+// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
+//
+// NOTE: although the microseconds are useful for comparing events on
+// a single machine, clocks on different machines may not be well
+// synchronized. Hence, use caution when comparing the low bits of
+// timestamps from different machines.
+
+#ifndef DECLARE_VARIABLE
+#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#define DECLARE_VARIABLE(type, shorttype, name, tn) \
+ namespace fL##shorttype { \
+ extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
+ } \
+ using fL##shorttype::FLAGS_##name
+
+// bool specialization
+#define DECLARE_bool(name) \
+ DECLARE_VARIABLE(bool, B, name, bool)
+
+// int32 specialization
+#define DECLARE_int32(name) \
+ DECLARE_VARIABLE(google::int32, I, name, int32)
+
+// Special case for string, because we have to specify the namespace
+// std::string, which doesn't play nicely with our FLAG__namespace hackery.
+#define DECLARE_string(name) \
+ namespace fLS { \
+ extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
+ } \
+ using fLS::FLAGS_##name
+#endif
+
+// Set whether log messages go to stderr instead of logfiles
+DECLARE_bool(logtostderr);
+
+// Set whether log messages go to stderr in addition to logfiles.
+DECLARE_bool(alsologtostderr);
+
+// Set color messages logged to stderr (if supported by terminal).
+DECLARE_bool(colorlogtostderr);
+
+// Log messages at a level >= this flag are automatically sent to
+// stderr in addition to log files.
+DECLARE_int32(stderrthreshold);
+
+// Set whether the log prefix should be prepended to each line of output.
+DECLARE_bool(log_prefix);
+
+// Log messages at a level <= this flag are buffered.
+// Log messages at a higher level are flushed immediately.
+DECLARE_int32(logbuflevel);
+
+// Sets the maximum number of seconds which logs may be buffered for.
+DECLARE_int32(logbufsecs);
+
+// Log suppression level: messages logged at a lower level than this
+// are suppressed.
+DECLARE_int32(minloglevel);
+
+// If specified, logfiles are written into this directory instead of the
+// default logging directory.
+DECLARE_string(log_dir);
+
+// Sets the path of the directory into which to put additional links
+// to the log files.
+DECLARE_string(log_link);
+
+DECLARE_int32(v); // in vlog_is_on.cc
+
+// Sets the maximum log file size (in MB).
+DECLARE_int32(max_log_size);
+
+// Sets whether to avoid logging to the disk if the disk is full.
+DECLARE_bool(stop_logging_if_full_disk);
+
+#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS
+#undef DECLARE_VARIABLE
+#undef DECLARE_bool
+#undef DECLARE_int32
+#undef DECLARE_string
+#endif
+
+// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
+// security reasons. See LOG(severtiy) below.
+
+// A few definitions of macros that don't generate much code. Since
+// LOG(INFO) and its ilk are used all over our code, it's
+// better to have compact code for these operations.
+
+#if GOOGLE_STRIP_LOG == 0
+#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
+ __FILE__, __LINE__)
+#define LOG_TO_STRING_INFO(message) google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_INFO, message)
+#else
+#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
+#define LOG_TO_STRING_INFO(message) google::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 1
+#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_WARNING)
+#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_WARNING, message)
+#else
+#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
+#define LOG_TO_STRING_WARNING(message) google::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 2
+#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_ERROR)
+#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_ERROR, message)
+#else
+#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
+#define LOG_TO_STRING_ERROR(message) google::NullStream()
+#endif
+
+#if GOOGLE_STRIP_LOG <= 3
+#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
+ __FILE__, __LINE__)
+#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_FATAL, message)
+#else
+#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
+#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
+#endif
+
+// For DFATAL, we want to use LogMessage (as opposed to
+// LogMessageFatal), to be consistent with the original behavior.
+#ifdef NDEBUG
+#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
+#elif GOOGLE_STRIP_LOG <= 3
+#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_FATAL)
+#else
+#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
+#endif
+
+#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
+#define SYSLOG_INFO(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
+ &google::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_WARNING(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
+ &google::LogMessage::SendToLog)
+#define SYSLOG_WARNING(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
+ &google::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_ERROR(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
+ &google::LogMessage::SendToLog)
+#define SYSLOG_ERROR(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
+ &google::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_FATAL(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
+ &google::LogMessage::SendToLog)
+#define SYSLOG_FATAL(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
+ &google::LogMessage::SendToSyslogAndLog)
+#define GOOGLE_LOG_DFATAL(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
+ &google::LogMessage::SendToLog)
+#define SYSLOG_DFATAL(counter) \
+ google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
+ &google::LogMessage::SendToSyslogAndLog)
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+// A very useful logging macro to log windows errors:
+#define LOG_SYSRESULT(result) \
+ if (FAILED(HRESULT_FROM_WIN32(result))) { \
+ LPSTR message = NULL; \
+ LPSTR msg = reinterpret_cast<LPSTR>(&message); \
+ DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
+ FORMAT_MESSAGE_FROM_SYSTEM, \
+ 0, result, 0, msg, 100, NULL); \
+ if (message_length > 0) { \
+ google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
+ &google::LogMessage::SendToLog).stream() \
+ << reinterpret_cast<const char*>(message); \
+ LocalFree(message); \
+ } \
+ }
+#endif
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
+#define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
+
+namespace google {
+
+// They need the definitions of integer types.
+#include "glog/log_severity.h"
+#include "glog/vlog_is_on.h"
+
+// Initialize google's logging library. You will see the program name
+// specified by argv0 in log outputs.
+GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
+
+// Shutdown google's logging library.
+GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
+
+// Install a function which will be called after LOG(FATAL).
+GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)());
+
+class LogSink; // defined below
+
+// If a non-NULL sink pointer is given, we push this message to that sink.
+// For LOG_TO_SINK we then do normal LOG(severity) logging as well.
+// This is useful for capturing messages and passing/storing them
+// somewhere more specific than the global log of the process.
+// Argument types:
+// LogSink* sink;
+// LogSeverity severity;
+// The cast is to disambiguate NULL arguments.
+#define LOG_TO_SINK(sink, severity) \
+ google::LogMessage( \
+ __FILE__, __LINE__, \
+ google::GLOG_ ## severity, \
+ static_cast<google::LogSink*>(sink), true).stream()
+#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
+ google::LogMessage( \
+ __FILE__, __LINE__, \
+ google::GLOG_ ## severity, \
+ static_cast<google::LogSink*>(sink), false).stream()
+
+// If a non-NULL string pointer is given, we write this message to that string.
+// We then do normal LOG(severity) logging as well.
+// This is useful for capturing messages and storing them somewhere more
+// specific than the global log of the process.
+// Argument types:
+// string* message;
+// LogSeverity severity;
+// The cast is to disambiguate NULL arguments.
+// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
+// severity.
+#define LOG_TO_STRING(severity, message) \
+ LOG_TO_STRING_##severity(static_cast<string*>(message)).stream()
+
+// If a non-NULL pointer is given, we push the message onto the end
+// of a vector of strings; otherwise, we report it with LOG(severity).
+// This is handy for capturing messages and perhaps passing them back
+// to the caller, rather than reporting them immediately.
+// Argument types:
+// LogSeverity severity;
+// vector<string> *outvec;
+// The cast is to disambiguate NULL arguments.
+#define LOG_STRING(severity, outvec) \
+ LOG_TO_STRING_##severity(static_cast<vector<string>*>(outvec)).stream()
+
+#define LOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
+#define SYSLOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity)
+
+#define LOG_ASSERT(condition) \
+ LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
+#define SYSLOG_ASSERT(condition) \
+ SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
+
+// CHECK dies with a fatal error if condition is not true. It is *not*
+// controlled by NDEBUG, so the check will be executed regardless of
+// compilation mode. Therefore, it is safe to do things like:
+// CHECK(fp->Write(x) == 4)
+#define CHECK(condition) \
+ LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
+ << "Check failed: " #condition " "
+
+// A container for a string pointer which can be evaluated to a bool -
+// true iff the pointer is NULL.
+struct CheckOpString {
+ CheckOpString(std::string* str) : str_(str) { }
+ // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
+ // so there's no point in cleaning up str_.
+ operator bool() const {
+ return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL);
+ }
+ std::string* str_;
+};
+
+// Function is overloaded for integral types to allow static const
+// integrals declared in classes and not defined to be used as arguments to
+// CHECK* macros. It's not encouraged though.
+template <class T>
+inline const T& GetReferenceableValue(const T& t) { return t; }
+inline char GetReferenceableValue(char t) { return t; }
+inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
+inline signed char GetReferenceableValue(signed char t) { return t; }
+inline short GetReferenceableValue(short t) { return t; }
+inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
+inline int GetReferenceableValue(int t) { return t; }
+inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
+inline long GetReferenceableValue(long t) { return t; }
+inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
+inline long long GetReferenceableValue(long long t) { return t; }
+inline unsigned long long GetReferenceableValue(unsigned long long t) {
+ return t;
+}
+
+// This is a dummy class to define the following operator.
+struct DummyClassToDefineOperator {};
+
+}
+
+// Define global operator<< to declare using ::operator<<.
+// This declaration will allow use to use CHECK macros for user
+// defined classes which have operator<< (e.g., stl_logging.h).
+inline std::ostream& operator<<(
+ std::ostream& out, const google::DummyClassToDefineOperator&) {
+ return out;
+}
+
+namespace google {
+
+// This formats a value for a failing CHECK_XX statement. Ordinarily,
+// it uses the definition for operator<<, with a few special cases below.
+template <typename T>
+inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
+ (*os) << v;
+}
+
+// Overrides for char types provide readable values for unprintable
+// characters.
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const char& v);
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const signed char& v);
+template <> GOOGLE_GLOG_DLL_DECL
+void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
+
+// Build the error message string. Specify no inlining for code size.
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
+ ;
+
+namespace base {
+namespace internal {
+
+// If "s" is less than base_logging::INFO, returns base_logging::INFO.
+// If "s" is greater than base_logging::FATAL, returns
+// base_logging::ERROR. Otherwise, returns "s".
+LogSeverity NormalizeSeverity(LogSeverity s);
+
+} // namespace internal
+
+// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
+// statement. See MakeCheckOpString for sample usage. Other
+// approaches were considered: use of a template method (e.g.,
+// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
+// base::Print<T2>, &v2), however this approach has complications
+// related to volatile arguments and function-pointer arguments).
+class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
+ public:
+ // Inserts "exprtext" and " (" to the stream.
+ explicit CheckOpMessageBuilder(const char *exprtext);
+ // Deletes "stream_".
+ ~CheckOpMessageBuilder();
+ // For inserting the first variable.
+ std::ostream* ForVar1() { return stream_; }
+ // For inserting the second variable (adds an intermediate " vs. ").
+ std::ostream* ForVar2();
+ // Get the result (inserts the closing ")").
+ std::string* NewString();
+
+ private:
+ std::ostringstream *stream_;
+};
+
+} // namespace base
+
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
+ base::CheckOpMessageBuilder comb(exprtext);
+ MakeCheckOpValueString(comb.ForVar1(), v1);
+ MakeCheckOpValueString(comb.ForVar2(), v2);
+ return comb.NewString();
+}
+
+// Helper functions for CHECK_OP macro.
+// The (int, int) specialization works around the issue that the compiler
+// will not instantiate the template version of the function on values of
+// unnamed enum type - see comment below.
+#define DEFINE_CHECK_OP_IMPL(name, op) \
+ template <typename T1, typename T2> \
+ inline std::string* name##Impl(const T1& v1, const T2& v2, \
+ const char* exprtext) { \
+ if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
+ else return MakeCheckOpString(v1, v2, exprtext); \
+ } \
+ inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
+ return name##Impl<int, int>(v1, v2, exprtext); \
+ }
+
+// We use the full name Check_EQ, Check_NE, etc. in case the file including
+// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
+// This happens if, for example, those are used as token names in a
+// yacc grammar.
+DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
+DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
+DEFINE_CHECK_OP_IMPL(Check_LE, <=)
+DEFINE_CHECK_OP_IMPL(Check_LT, < )
+DEFINE_CHECK_OP_IMPL(Check_GE, >=)
+DEFINE_CHECK_OP_IMPL(Check_GT, > )
+#undef DEFINE_CHECK_OP_IMPL
+
+// Helper macro for binary operators.
+// Don't use this macro directly in your code, use CHECK_EQ et al below.
+
+#if defined(STATIC_ANALYSIS)
+// Only for static analysis tool to know that it is equivalent to assert
+#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
+#elif !defined(NDEBUG)
+// In debug mode, avoid constructing CheckOpStrings if possible,
+// to reduce the overhead of CHECK statments by 2x.
+// Real DCHECK-heavy tests have seen 1.5x speedups.
+
+// The meaning of "string" might be different between now and
+// when this macro gets invoked (e.g., if someone is experimenting
+// with other string implementations that get defined after this
+// file is included). Save the current meaning now and use it
+// in the macro.
+typedef std::string _Check_string;
+#define CHECK_OP_LOG(name, op, val1, val2, log) \
+ while (google::_Check_string* _result = \
+ google::Check##name##Impl( \
+ google::GetReferenceableValue(val1), \
+ google::GetReferenceableValue(val2), \
+ #val1 " " #op " " #val2)) \
+ log(__FILE__, __LINE__, \
+ google::CheckOpString(_result)).stream()
+#else
+// In optimized mode, use CheckOpString to hint to compiler that
+// the while condition is unlikely.
+#define CHECK_OP_LOG(name, op, val1, val2, log) \
+ while (google::CheckOpString _result = \
+ google::Check##name##Impl( \
+ google::GetReferenceableValue(val1), \
+ google::GetReferenceableValue(val2), \
+ #val1 " " #op " " #val2)) \
+ log(__FILE__, __LINE__, _result).stream()
+#endif // STATIC_ANALYSIS, !NDEBUG
+
+#if GOOGLE_STRIP_LOG <= 3
+#define CHECK_OP(name, op, val1, val2) \
+ CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
+#else
+#define CHECK_OP(name, op, val1, val2) \
+ CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
+#endif // STRIP_LOG <= 3
+
+// Equality/Inequality checks - compare two values, and log a FATAL message
+// including the two values when the result is not as expected. The values
+// must have operator<<(ostream, ...) defined.
+//
+// You may append to the error message like so:
+// CHECK_NE(1, 2) << ": The world must be ending!";
+//
+// We are very careful to ensure that each argument is evaluated exactly
+// once, and that anything which is legal to pass as a function argument is
+// legal here. In particular, the arguments may be temporary expressions
+// which will end up being destroyed at the end of the apparent statement,
+// for example:
+// CHECK_EQ(string("abc")[1], 'b');
+//
+// WARNING: These don't compile correctly if one of the arguments is a pointer
+// and the other is NULL. To work around this, simply static_cast NULL to the
+// type of the desired pointer.
+
+#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
+#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
+#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
+#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
+#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
+#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
+
+// Check that the input is non NULL. This very useful in constructor
+// initializer lists.
+
+#define CHECK_NOTNULL(val) \
+ google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
+
+// Helper functions for string comparisons.
+// To avoid bloat, the definitions are in logging.cc.
+#define DECLARE_CHECK_STROP_IMPL(func, expected) \
+ GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \
+ const char* s1, const char* s2, const char* names);
+DECLARE_CHECK_STROP_IMPL(strcmp, true)
+DECLARE_CHECK_STROP_IMPL(strcmp, false)
+DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
+DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
+#undef DECLARE_CHECK_STROP_IMPL
+
+// Helper macro for string comparisons.
+// Don't use this macro directly in your code, use CHECK_STREQ et al below.
+#define CHECK_STROP(func, op, expected, s1, s2) \
+ while (google::CheckOpString _result = \
+ google::Check##func##expected##Impl((s1), (s2), \
+ #s1 " " #op " " #s2)) \
+ LOG(FATAL) << *_result.str_
+
+
+// String (char*) equality/inequality checks.
+// CASE versions are case-insensitive.
+//
+// Note that "s1" and "s2" may be temporary strings which are destroyed
+// by the compiler at the end of the current "full expression"
+// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())).
+
+#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2)
+#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2)
+#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2)
+#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2)
+
+#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0])))
+#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0])))
+
+#define CHECK_DOUBLE_EQ(val1, val2) \
+ do { \
+ CHECK_LE((val1), (val2)+0.000000000000001L); \
+ CHECK_GE((val1), (val2)-0.000000000000001L); \
+ } while (0)
+
+#define CHECK_NEAR(val1, val2, margin) \
+ do { \
+ CHECK_LE((val1), (val2)+(margin)); \
+ CHECK_GE((val1), (val2)-(margin)); \
+ } while (0)
+
+// perror()..googly style!
+//
+// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and
+// CHECK equivalents with the addition that they postpend a description
+// of the current state of errno to their output lines.
+
+#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()
+
+#define GOOGLE_PLOG(severity, counter) \
+ google::ErrnoLogMessage( \
+ __FILE__, __LINE__, google::GLOG_ ## severity, counter, \
+ &google::LogMessage::SendToLog)
+
+#define PLOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity)
+
+// A CHECK() macro that postpends errno if the condition is false. E.g.
+//
+// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... }
+#define PCHECK(condition) \
+ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
+ << "Check failed: " #condition " "
+
+// A CHECK() macro that lets you assert the success of a function that
+// returns -1 and sets errno in case of an error. E.g.
+//
+// CHECK_ERR(mkdir(path, 0700));
+//
+// or
+//
+// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename;
+#define CHECK_ERR(invocation) \
+PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
+ << #invocation
+
+// Use macro expansion to create, for each use of LOG_EVERY_N(), static
+// variables with the __LINE__ expansion as part of the variable name.
+#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line)
+#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line
+
+#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
+#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
+
+#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (condition && \
+ ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
+ google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ ++LOG_OCCURRENCES; \
+ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ google::ErrnoLogMessage( \
+ __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0; \
+ if (LOG_OCCURRENCES <= n) \
+ ++LOG_OCCURRENCES; \
+ if (LOG_OCCURRENCES <= n) \
+ google::LogMessage( \
+ __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+namespace glog_internal_namespace_ {
+template <bool>
+struct CompileAssert {
+};
+struct CrashReason;
+} // namespace glog_internal_namespace_
+
+#define GOOGLE_GLOG_COMPILE_ASSERT(expr, msg) \
+ typedef google::glog_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+#define LOG_EVERY_N(severity, n) \
+ GOOGLE_GLOG_COMPILE_ASSERT(google::GLOG_ ## severity < \
+ google::NUM_SEVERITIES, \
+ INVALID_REQUESTED_LOG_SEVERITY); \
+ SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
+
+#define SYSLOG_EVERY_N(severity, n) \
+ SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog)
+
+#define PLOG_EVERY_N(severity, n) \
+ SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
+
+#define LOG_FIRST_N(severity, n) \
+ SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog)
+
+#define LOG_IF_EVERY_N(severity, condition, n) \
+ SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog)
+
+// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
+enum PRIVATE_Counter {COUNTER};
+
+#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
+// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
+// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
+// to keep using this syntax, we define this macro to do the same thing
+// as COMPACT_GOOGLE_LOG_ERROR.
+#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
+#define SYSLOG_0 SYSLOG_ERROR
+#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
+// Needed for LOG_IS_ON(ERROR).
+const LogSeverity GLOG_0 = GLOG_ERROR;
+#else
+// Users may include windows.h after logging.h without
+// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
+// For this case, we cannot detect if ERROR is defined before users
+// actually use ERROR. Let's make an undefined symbol to warn users.
+# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
+# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
+# define SYSLOG_0 GLOG_ERROR_MSG
+# define LOG_TO_STRING_0 GLOG_ERROR_MSG
+# define GLOG_0 GLOG_ERROR_MSG
+#endif
+
+// Plus some debug-logging macros that get compiled to nothing for production
+
+#ifndef NDEBUG
+
+#define DLOG(severity) LOG(severity)
+#define DVLOG(verboselevel) VLOG(verboselevel)
+#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
+#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
+#define DLOG_IF_EVERY_N(severity, condition, n) \
+ LOG_IF_EVERY_N(severity, condition, n)
+#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
+
+// debug-only checking. not executed in NDEBUG mode.
+#define DCHECK(condition) CHECK(condition)
+#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
+#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
+#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
+#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
+#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
+#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
+#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
+#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
+#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
+#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
+#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
+
+#else // NDEBUG
+
+#define DLOG(severity) \
+ true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
+
+#define DVLOG(verboselevel) \
+ (true || !VLOG_IS_ON(verboselevel)) ?\
+ (void) 0 : google::LogMessageVoidify() & LOG(INFO)
+
+#define DLOG_IF(severity, condition) \
+ (true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_EVERY_N(severity, n) \
+ true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_IF_EVERY_N(severity, condition, n) \
+ (true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity)
+
+#define DLOG_ASSERT(condition) \
+ true ? (void) 0 : LOG_ASSERT(condition)
+
+// MSVC warning C4127: conditional expression is constant
+#define DCHECK(condition) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK(condition)
+
+#define DCHECK_EQ(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
+
+#define DCHECK_NE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
+
+#define DCHECK_LE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
+
+#define DCHECK_LT(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
+
+#define DCHECK_GE(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
+
+#define DCHECK_GT(val1, val2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
+
+// You may see warnings in release mode if you don't use the return
+// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
+#define DCHECK_NOTNULL(val) (val)
+
+#define DCHECK_STREQ(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
+
+#define DCHECK_STRCASEEQ(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
+
+#define DCHECK_STRNE(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
+
+#define DCHECK_STRCASENE(str1, str2) \
+ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
+ while (false) \
+ GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
+
+#endif // NDEBUG
+
+// Log only in verbose mode.
+
+#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
+
+#define VLOG_IF(verboselevel, condition) \
+ LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
+
+#define VLOG_EVERY_N(verboselevel, n) \
+ LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n)
+
+#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
+ LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
+
+namespace base_logging {
+
+// LogMessage::LogStream is a std::ostream backed by this streambuf.
+// This class ignores overflow and leaves two bytes at the end of the
+// buffer to allow for a '\n' and '\0'.
+class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
+ public:
+ // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
+ LogStreamBuf(char *buf, int len) {
+ setp(buf, buf + len - 2);
+ }
+ // This effectively ignores overflow.
+ virtual int_type overflow(int_type ch) {
+ return ch;
+ }
+
+ // Legacy public ostrstream method.
+ size_t pcount() const { return pptr() - pbase(); }
+ char* pbase() const { return std::streambuf::pbase(); }
+};
+
+} // namespace base_logging
+
+//
+// This class more or less represents a particular log message. You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though. You should use the LOG() macro (and variants thereof)
+// above.
+class GOOGLE_GLOG_DLL_DECL LogMessage {
+public:
+ enum {
+ // Passing kNoLogPrefix for the line number disables the
+ // log-message prefix. Useful for using the LogMessage
+ // infrastructure as a printing utility. See also the --log_prefix
+ // flag for controlling the log-message prefix on an
+ // application-wide basis.
+ kNoLogPrefix = -1
+ };
+
+ // LogStream inherit from non-DLL-exported class (std::ostrstream)
+ // and VC++ produces a warning for this situation.
+ // However, MSDN says "C4275 can be ignored in Microsoft Visual C++
+ // 2005 if you are deriving from a type in the Standard C++ Library"
+ // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
+ // Let's just ignore the warning.
+#ifdef _MSC_VER
+# pragma warning(disable: 4275)
+#endif
+ class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
+#ifdef _MSC_VER
+# pragma warning(default: 4275)
+#endif
+ public:
+ LogStream(char *buf, int len, int ctr)
+ : std::ostream(NULL),
+ streambuf_(buf, len),
+ ctr_(ctr),
+ self_(this) {
+ rdbuf(&streambuf_);
+ }
+
+ int ctr() const { return ctr_; }
+ void set_ctr(int ctr) { ctr_ = ctr; }
+ LogStream* self() const { return self_; }
+
+ // Legacy std::streambuf methods.
+ size_t pcount() const { return streambuf_.pcount(); }
+ char* pbase() const { return streambuf_.pbase(); }
+ char* str() const { return pbase(); }
+
+ private:
+ base_logging::LogStreamBuf streambuf_;
+ int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
+ LogStream *self_; // Consistency check hack
+ };
+
+public:
+ // icc 8 requires this typedef to avoid an internal compiler error.
+ typedef void (LogMessage::*SendMethod)();
+
+ LogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ SendMethod send_method);
+
+ // Two special constructors that generate reduced amounts of code at
+ // LOG call sites for common cases.
+
+ // Used for LOG(INFO): Implied are:
+ // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog.
+ //
+ // Using this constructor instead of the more complex constructor above
+ // saves 19 bytes per call site.
+ LogMessage(const char* file, int line);
+
+ // Used for LOG(severity) where severity != INFO. Implied
+ // are: ctr = 0, send_method = &LogMessage::SendToLog
+ //
+ // Using this constructor instead of the more complex constructor above
+ // saves 17 bytes per call site.
+ LogMessage(const char* file, int line, LogSeverity severity);
+
+ // Constructor to log this message to a specified sink (if not NULL).
+ // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if
+ // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise.
+ LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink,
+ bool also_send_to_log);
+
+ // Constructor where we also give a vector<string> pointer
+ // for storing the messages (if the pointer is not NULL).
+ // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog.
+ LogMessage(const char* file, int line, LogSeverity severity,
+ std::vector<std::string>* outvec);
+
+ // Constructor where we also give a string pointer for storing the
+ // message (if the pointer is not NULL). Implied are: ctr = 0,
+ // send_method = &LogMessage::WriteToStringAndLog.
+ LogMessage(const char* file, int line, LogSeverity severity,
+ std::string* message);
+
+ // A special constructor used for check failures
+ LogMessage(const char* file, int line, const CheckOpString& result);
+
+ ~LogMessage();
+
+ // Flush a buffered message to the sink set in the constructor. Always
+ // called by the destructor, it may also be called from elsewhere if
+ // needed. Only the first call is actioned; any later ones are ignored.
+ void Flush();
+
+ // An arbitrary limit on the length of a single log message. This
+ // is so that streaming can be done more efficiently.
+ static const size_t kMaxLogMessageLen;
+
+ // Theses should not be called directly outside of logging.*,
+ // only passed as SendMethod arguments to other LogMessage methods:
+ void SendToLog(); // Actually dispatch to the logs
+ void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs
+
+ // Call abort() or similar to perform LOG(FATAL) crash.
+ static void Fail() ;
+
+ std::ostream& stream();
+
+ int preserved_errno() const;
+
+ // Must be called without the log_mutex held. (L < log_mutex)
+ static int64 num_messages(int severity);
+
+ struct LogMessageData;
+
+private:
+ // Fully internal SendMethod cases:
+ void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
+ void SendToSink(); // Send to sink if provided, do nothing otherwise.
+
+ // Write to string if provided and dispatch to the logs.
+ void WriteToStringAndLog();
+
+ void SaveOrSendToLog(); // Save to stringvec if provided, else to logs
+
+ void Init(const char* file, int line, LogSeverity severity,
+ void (LogMessage::*send_method)());
+
+ // Used to fill in crash information during LOG(FATAL) failures.
+ void RecordCrashReason(glog_internal_namespace_::CrashReason* reason);
+
+ // Counts of messages sent at each priority:
+ static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex
+
+ // We keep the data in a separate struct so that each instance of
+ // LogMessage uses less stack space.
+ LogMessageData* allocated_;
+ LogMessageData* data_;
+
+ friend class LogDestination;
+
+ LogMessage(const LogMessage&);
+ void operator=(const LogMessage&);
+};
+
+// This class happens to be thread-hostile because all instances share
+// a single data buffer, but since it can only be created just before
+// the process dies, we don't worry so much.
+class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage {
+ public:
+ LogMessageFatal(const char* file, int line);
+ LogMessageFatal(const char* file, int line, const CheckOpString& result);
+ ~LogMessageFatal() ;
+};
+
+// A non-macro interface to the log facility; (useful
+// when the logging level is not a compile-time constant).
+inline void LogAtLevel(int const severity, std::string const &msg) {
+ LogMessage(__FILE__, __LINE__, severity).stream() << msg;
+}
+
+// A macro alternative of LogAtLevel. New code may want to use this
+// version since there are two advantages: 1. this version outputs the
+// file name and the line number where this macro is put like other
+// LOG macros, 2. this macro can be used as C++ stream.
+#define LOG_AT_LEVEL(severity) google::LogMessage(__FILE__, __LINE__, severity).stream()
+
+// A small helper for CHECK_NOTNULL().
+template <typename T>
+T* CheckNotNull(const char *file, int line, const char *names, T* t) {
+ if (t == NULL) {
+ LogMessageFatal(file, line, new std::string(names));
+ }
+ return t;
+}
+
+// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
+// only works if ostream is a LogStream. If the ostream is not a
+// LogStream you'll get an assert saying as much at runtime.
+GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os,
+ const PRIVATE_Counter&);
+
+
+// Derived class for PLOG*() above.
+class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage {
+ public:
+
+ ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ void (LogMessage::*send_method)());
+
+ // Postpends ": strerror(errno) [errno]".
+ ~ErrnoLogMessage();
+
+ private:
+ ErrnoLogMessage(const ErrnoLogMessage&);
+ void operator=(const ErrnoLogMessage&);
+};
+
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros. This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+
+class GOOGLE_GLOG_DLL_DECL LogMessageVoidify {
+ public:
+ LogMessageVoidify() { }
+ // This has to be an operator with a precedence lower than << but
+ // higher than ?:
+ void operator&(std::ostream&) { }
+};
+
+
+// Flushes all log files that contains messages that are at least of
+// the specified severity level. Thread-safe.
+GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity);
+
+// Flushes all log files that contains messages that are at least of
+// the specified severity level. Thread-hostile because it ignores
+// locking -- used for catastrophic failures.
+GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity);
+
+//
+// Set the destination to which a particular severity level of log
+// messages is sent. If base_filename is "", it means "don't log this
+// severity". Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity,
+ const char* base_filename);
+
+//
+// Set the basename of the symlink to the latest log file at a given
+// severity. If symlink_basename is empty, do not make a symlink. If
+// you don't call this function, the symlink basename is the
+// invocation name of the program. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity,
+ const char* symlink_basename);
+
+//
+// Used to send logs to some other kind of destination
+// Users should subclass LogSink and override send to do whatever they want.
+// Implementations must be thread-safe because a shared instance will
+// be called from whichever thread ran the LOG(XXX) line.
+class GOOGLE_GLOG_DLL_DECL LogSink {
+ public:
+ virtual ~LogSink();
+
+ // Sink's logging logic (message_len is such as to exclude '\n' at the end).
+ // This method can't use LOG() or CHECK() as logging system mutex(s) are held
+ // during this call.
+ virtual void send(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line,
+ const struct ::tm* tm_time,
+ const char* message, size_t message_len) = 0;
+
+ // Redefine this to implement waiting for
+ // the sink's logging logic to complete.
+ // It will be called after each send() returns,
+ // but before that LogMessage exits or crashes.
+ // By default this function does nothing.
+ // Using this function one can implement complex logic for send()
+ // that itself involves logging; and do all this w/o causing deadlocks and
+ // inconsistent rearrangement of log messages.
+ // E.g. if a LogSink has thread-specific actions, the send() method
+ // can simply add the message to a queue and wake up another thread that
+ // handles real logging while itself making some LOG() calls;
+ // WaitTillSent() can be implemented to wait for that logic to complete.
+ // See our unittest for an example.
+ virtual void WaitTillSent();
+
+ // Returns the normal text output of the log message.
+ // Can be useful to implement send().
+ static std::string ToString(LogSeverity severity, const char* file, int line,
+ const struct ::tm* tm_time,
+ const char* message, size_t message_len);
+};
+
+// Add or remove a LogSink as a consumer of logging data. Thread-safe.
+GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
+GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination);
+
+//
+// Specify an "extension" added to the filename specified via
+// SetLogDestination. This applies to all severity levels. It's
+// often used to append the port we're listening on to the logfile
+// name. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
+ const char* filename_extension);
+
+//
+// Make it so that all log messages of at least a particular severity
+// are logged to stderr (in addition to logging to the usual log
+// file(s)). Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity);
+
+//
+// Make it so that all log messages go only to stderr. Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void LogToStderr();
+
+//
+// Make it so that all log messages of at least a particular severity are
+// logged via email to a list of addresses (in addition to logging to the
+// usual log file(s)). The list of addresses is just a string containing
+// the email addresses to send to (separated by spaces, say). Thread-safe.
+//
+GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
+ const char* addresses);
+
+// A simple function that sends email. dest is a commma-separated
+// list of addressess. Thread-safe.
+GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
+ const char *subject, const char *body);
+
+GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories();
+
+// For tests only: Clear the internal [cached] list of logging directories to
+// force a refresh the next time GetLoggingDirectories is called.
+// Thread-hostile.
+void TestOnly_ClearLoggingDirectoriesList();
+
+// Returns a set of existing temporary directories, which will be a
+// subset of the directories returned by GetLogginDirectories().
+// Thread-safe.
+GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
+ std::vector<std::string>* list);
+
+// Print any fatal message again -- useful to call from signal handler
+// so that the last thing in the output is the fatal message.
+// Thread-hostile, but a race is unlikely.
+GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage();
+
+// Truncate a log file that may be the append-only output of multiple
+// processes and hence can't simply be renamed/reopened (typically a
+// stdout/stderr). If the file "path" is > "limit" bytes, copy the
+// last "keep" bytes to offset 0 and truncate the rest. Since we could
+// be racing with other writers, this approach has the potential to
+// lose very small amounts of data. For security, only follow symlinks
+// if the path is /proc/self/fd/*
+GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
+ int64 limit, int64 keep);
+
+// Truncate stdout and stderr if they are over the value specified by
+// --max_log_size; keep the final 1MB. This function has the same
+// race condition as TruncateLogFile.
+GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr();
+
+// Return the string representation of the provided LogSeverity level.
+// Thread-safe.
+GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
+
+// ---------------------------------------------------------------------
+// Implementation details that are not useful to most clients
+// ---------------------------------------------------------------------
+
+// A Logger is the interface used by logging modules to emit entries
+// to a log. A typical implementation will dump formatted data to a
+// sequence of files. We also provide interfaces that will forward
+// the data to another thread so that the invoker never blocks.
+// Implementations should be thread-safe since the logging system
+// will write to them from multiple threads.
+
+namespace base {
+
+class GOOGLE_GLOG_DLL_DECL Logger {
+ public:
+ virtual ~Logger();
+
+ // Writes "message[0,message_len-1]" corresponding to an event that
+ // occurred at "timestamp". If "force_flush" is true, the log file
+ // is flushed immediately.
+ //
+ // The input message has already been formatted as deemed
+ // appropriate by the higher level logging facility. For example,
+ // textual log messages already contain timestamps, and the
+ // file:linenumber header.
+ virtual void Write(bool force_flush,
+ time_t timestamp,
+ const char* message,
+ int message_len) = 0;
+
+ // Flush any buffered messages
+ virtual void Flush() = 0;
+
+ // Get the current LOG file size.
+ // The returned value is approximate since some
+ // logged data may not have been flushed to disk yet.
+ virtual uint32 LogSize() = 0;
+};
+
+// Get the logger for the specified severity level. The logger
+// remains the property of the logging module and should not be
+// deleted by the caller. Thread-safe.
+extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level);
+
+// Set the logger for the specified severity level. The logger
+// becomes the property of the logging module and should not
+// be deleted by the caller. Thread-safe.
+extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
+
+}
+
+// glibc has traditionally implemented two incompatible versions of
+// strerror_r(). There is a poorly defined convention for picking the
+// version that we want, but it is not clear whether it even works with
+// all versions of glibc.
+// So, instead, we provide this wrapper that automatically detects the
+// version that is in use, and then implements POSIX semantics.
+// N.B. In addition to what POSIX says, we also guarantee that "buf" will
+// be set to an empty string, if this function failed. This means, in most
+// cases, you do not need to check the error code and you can directly
+// use the value of "buf". It will never have an undefined value.
+// DEPRECATED: Use StrError(int) instead.
+GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
+
+// A thread-safe replacement for strerror(). Returns a string describing the
+// given POSIX error code.
+GOOGLE_GLOG_DLL_DECL std::string StrError(int err);
+
+// A class for which we define operator<<, which does nothing.
+class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
+ public:
+ // Initialize the LogStream so the messages can be written somewhere
+ // (they'll never be actually displayed). This will be needed if a
+ // NullStream& is implicitly converted to LogStream&, in which case
+ // the overloaded NullStream::operator<< will not be invoked.
+ NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
+ NullStream(const char* /*file*/, int /*line*/,
+ const CheckOpString& /*result*/) :
+ LogMessage::LogStream(message_buffer_, 1, 0) { }
+ NullStream &stream() { return *this; }
+ private:
+ // A very short buffer for messages (which we discard anyway). This
+ // will be needed if NullStream& converted to LogStream& (e.g. as a
+ // result of a conditional expression).
+ char message_buffer_[2];
+};
+
+// Do nothing. This operator is inline, allowing the message to be
+// compiled away. The message will not be compiled away if we do
+// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when
+// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly
+// converted to LogStream and the message will be computed and then
+// quietly discarded.
+template<class T>
+inline NullStream& operator<<(NullStream &str, const T &) { return str; }
+
+// Similar to NullStream, but aborts the program (without stack
+// trace), like LogMessageFatal.
+class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream {
+ public:
+ NullStreamFatal() { }
+ NullStreamFatal(const char* file, int line, const CheckOpString& result) :
+ NullStream(file, line, result) { }
+ ~NullStreamFatal() { _exit(1); }
+};
+
+// Install a signal handler that will dump signal information and a stack
+// trace when the program crashes on certain signals. We'll install the
+// signal handler for the following signals.
+//
+// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
+//
+// By default, the signal handler will write the failure dump to the
+// standard error. You can customize the destination by installing your
+// own writer function by InstallFailureWriter() below.
+//
+// Note on threading:
+//
+// The function should be called before threads are created, if you want
+// to use the failure signal handler for all threads. The stack trace
+// will be shown only for the thread that receives the signal. In other
+// words, stack traces of other threads won't be shown.
+GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler();
+
+// Installs a function that is used for writing the failure dump. "data"
+// is the pointer to the beginning of a message to be written, and "size"
+// is the size of the message. You should not expect the data is
+// terminated with '\0'.
+GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
+ void (*writer)(const char* data, int size));
+
+}
+
+#endif // _LOGGING_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/glog/raw_logging.h b/thirdparty/glog/glog-0.3.4/src/windows/glog/raw_logging.h
new file mode 100644
index 0000000..4757a71
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/glog/raw_logging.h
@@ -0,0 +1,189 @@
+// This file is automatically generated from src/glog/raw_logging.h.in
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Maxim Lifantsev
+//
+// Thread-safe logging routines that do not allocate any memory or
+// acquire any locks, and can therefore be used by low-level memory
+// allocation and synchronization code.
+
+#ifndef BASE_RAW_LOGGING_H_
+#define BASE_RAW_LOGGING_H_
+
+#include <time.h>
+
+namespace google {
+
+#include "glog/log_severity.h"
+#include "glog/vlog_is_on.h"
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+// This is similar to LOG(severity) << format... and VLOG(level) << format..,
+// but
+// * it is to be used ONLY by low-level modules that can't use normal LOG()
+// * it is desiged to be a low-level logger that does not allocate any
+// memory and does not need any locks, hence:
+// * it logs straight and ONLY to STDERR w/o buffering
+// * it uses an explicit format and arguments list
+// * it will silently chop off really long message strings
+// Usage example:
+// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
+// RAW_VLOG(3, "status is %i", status);
+// These will print an almost standard log lines like this to stderr only:
+// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+// I0821 211317 file.cc:142] RAW: status is 20
+#define RAW_LOG(severity, ...) \
+ do { \
+ switch (google::GLOG_ ## severity) { \
+ case 0: \
+ RAW_LOG_INFO(__VA_ARGS__); \
+ break; \
+ case 1: \
+ RAW_LOG_WARNING(__VA_ARGS__); \
+ break; \
+ case 2: \
+ RAW_LOG_ERROR(__VA_ARGS__); \
+ break; \
+ case 3: \
+ RAW_LOG_FATAL(__VA_ARGS__); \
+ break; \
+ default: \
+ break; \
+ } \
+ } while (0)
+
+// The following STRIP_LOG testing is performed in the header file so that it's
+// possible to completely compile out the logging code and the log messages.
+#if STRIP_LOG == 0
+#define RAW_VLOG(verboselevel, ...) \
+ do { \
+ if (VLOG_IS_ON(verboselevel)) { \
+ RAW_LOG_INFO(__VA_ARGS__); \
+ } \
+ } while (0)
+#else
+#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG == 0
+
+#if STRIP_LOG == 0
+#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG == 0
+
+#if STRIP_LOG <= 1
+#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG <= 1
+
+#if STRIP_LOG <= 2
+#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
+#endif // STRIP_LOG <= 2
+
+#if STRIP_LOG <= 3
+#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL, \
+ __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define RAW_LOG_FATAL(...) \
+ do { \
+ google::RawLogStub__(0, __VA_ARGS__); \
+ exit(1); \
+ } while (0)
+#endif // STRIP_LOG <= 3
+
+// Similar to CHECK(condition) << message,
+// but for low-level modules: we use only RAW_LOG that does not allocate memory.
+// We do not want to provide args list here to encourage this usage:
+// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
+// so that the args are not computed when not needed.
+#define RAW_CHECK(condition, message) \
+ do { \
+ if (!(condition)) { \
+ RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
+ } \
+ } while (0)
+
+// Debug versions of RAW_LOG and RAW_CHECK
+#ifndef NDEBUG
+
+#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
+#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
+
+#else // NDEBUG
+
+#define RAW_DLOG(severity, ...) \
+ while (false) \
+ RAW_LOG(severity, __VA_ARGS__)
+#define RAW_DCHECK(condition, message) \
+ while (false) \
+ RAW_CHECK(condition, message)
+
+#endif // NDEBUG
+
+// Stub log function used to work around for unused variable warnings when
+// building with STRIP_LOG > 0.
+static inline void RawLogStub__(int /* ignored */, ...) {
+}
+
+// Helper function to implement RAW_LOG and RAW_VLOG
+// Logs format... at "severity" level, reporting it
+// as called from file:line.
+// This does not allocate memory or acquire locks.
+GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
+ const char* file,
+ int line,
+ const char* format, ...)
+ ;
+
+// Hack to propagate time information into this module so that
+// this module does not have to directly call localtime_r(),
+// which could allocate memory.
+GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
+
+}
+
+#endif // BASE_RAW_LOGGING_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/glog/stl_logging.h b/thirdparty/glog/glog-0.3.4/src/windows/glog/stl_logging.h
new file mode 100644
index 0000000..a97a908
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/glog/stl_logging.h
@@ -0,0 +1,224 @@
+// This file is automatically generated from src/glog/stl_logging.h.in
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+
+// Copyright (c) 2003, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Stream output operators for STL containers; to be used for logging *only*.
+// Inclusion of this file lets you do:
+//
+// list<string> x;
+// LOG(INFO) << "data: " << x;
+// vector<int> v1, v2;
+// CHECK_EQ(v1, v2);
+//
+// If you want to use this header file with hash_compare maps or slist, you
+// need to define macros before including this file:
+//
+// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
+// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
+// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
+// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
+//
+
+#ifndef UTIL_GTL_STL_LOGGING_INL_H_
+#define UTIL_GTL_STL_LOGGING_INL_H_
+
+#if !1
+# error We do not support stl_logging for this compiler
+#endif
+
+#include <deque>
+#include <list>
+#include <map>
+#include <ostream>
+#include <set>
+#include <utility>
+#include <vector>
+
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+# include <unordered_map>
+# include <unordered_set>
+#endif
+
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+# include <tr1/unordered_map>
+# include <tr1/unordered_set>
+#endif
+
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+# include <ext/hash_set>
+# include <ext/hash_map>
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
+# include <ext/slist>
+#endif
+
+// Forward declare these two, and define them after all the container streams
+// operators so that we can recurse from pair -> container -> container -> pair
+// properly.
+template<class First, class Second>
+std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
+
+namespace google {
+
+template<class Iter>
+void PrintSequence(std::ostream& out, Iter begin, Iter end);
+
+}
+
+#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
+template<class T1, class T2> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2>& seq) { \
+ google::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_TWO_ARG_CONTAINER(std::vector)
+OUTPUT_TWO_ARG_CONTAINER(std::deque)
+OUTPUT_TWO_ARG_CONTAINER(std::list)
+#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
+OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
+#endif
+
+#undef OUTPUT_TWO_ARG_CONTAINER
+
+#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3>& seq) { \
+ google::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_THREE_ARG_CONTAINER(std::set)
+OUTPUT_THREE_ARG_CONTAINER(std::multiset)
+
+#undef OUTPUT_THREE_ARG_CONTAINER
+
+#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3, class T4> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3, T4>& seq) { \
+ google::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+OUTPUT_FOUR_ARG_CONTAINER(std::map)
+OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
+OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
+OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
+OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
+#endif
+
+#undef OUTPUT_FOUR_ARG_CONTAINER
+
+#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
+template<class T1, class T2, class T3, class T4, class T5> \
+inline std::ostream& operator<<(std::ostream& out, \
+ const Sequence<T1, T2, T3, T4, T5>& seq) { \
+ google::PrintSequence(out, seq.begin(), seq.end()); \
+ return out; \
+}
+
+#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
+OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
+OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
+OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
+#endif
+#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
+OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
+OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
+#endif
+
+#undef OUTPUT_FIVE_ARG_CONTAINER
+
+template<class First, class Second>
+inline std::ostream& operator<<(std::ostream& out,
+ const std::pair<First, Second>& p) {
+ out << '(' << p.first << ", " << p.second << ')';
+ return out;
+}
+
+namespace google {
+
+template<class Iter>
+inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
+ // Output at most 100 elements -- appropriate if used for logging.
+ for (int i = 0; begin != end && i < 100; ++i, ++begin) {
+ if (i > 0) out << ' ';
+ out << *begin;
+ }
+ if (begin != end) {
+ out << " ...";
+ }
+}
+
+}
+
+// Note that this is technically undefined behavior! We are adding things into
+// the std namespace for a reason though -- we are providing new operations on
+// types which are themselves defined with this namespace. Without this, these
+// operator overloads cannot be found via ADL. If these definitions are not
+// found via ADL, they must be #included before they're used, which requires
+// this header to be included before apparently independent other headers.
+//
+// For example, base/logging.h defines various template functions to implement
+// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
+// It does so via the function template MakeCheckOpValueString:
+// template<class T>
+// void MakeCheckOpValueString(strstream* ss, const T& v) {
+// (*ss) << v;
+// }
+// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
+// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
+// find these operator definitions via ADL.
+//
+// Even this solution has problems -- it may pull unintended operators into the
+// namespace as well, allowing them to also be found via ADL, and creating code
+// that only works with a particular order of includes. Long term, we need to
+// move all of the *definitions* into namespace std, bet we need to ensure no
+// one references them first. This lets us take that step. We cannot define them
+// in both because that would create ambiguous overloads when both are found.
+namespace std { using ::operator<<; }
+
+#endif // UTIL_GTL_STL_LOGGING_INL_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/glog/vlog_is_on.h b/thirdparty/glog/glog-0.3.4/src/windows/glog/vlog_is_on.h
new file mode 100644
index 0000000..409a401
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/glog/vlog_is_on.h
@@ -0,0 +1,133 @@
+// This file is automatically generated from src/glog/vlog_is_on.h.in
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+
+// Copyright (c) 1999, 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney and many others
+//
+// Defines the VLOG_IS_ON macro that controls the variable-verbosity
+// conditional logging.
+//
+// It's used by VLOG and VLOG_IF in logging.h
+// and by RAW_VLOG in raw_logging.h to trigger the logging.
+//
+// It can also be used directly e.g. like this:
+// if (VLOG_IS_ON(2)) {
+// // do some logging preparation and logging
+// // that can't be accomplished e.g. via just VLOG(2) << ...;
+// }
+//
+// The truth value that VLOG_IS_ON(level) returns is determined by
+// the three verbosity level flags:
+// --v=<n> Gives the default maximal active V-logging level;
+// 0 is the default.
+// Normally positive values are used for V-logging levels.
+// --vmodule=<str> Gives the per-module maximal V-logging levels to override
+// the value given by --v.
+// E.g. "my_module=2,foo*=3" would change the logging level
+// for all code in source files "my_module.*" and "foo*.*"
+// ("-inl" suffixes are also disregarded for this matching).
+//
+// SetVLOGLevel helper function is provided to do limited dynamic control over
+// V-logging by overriding the per-module settings given via --vmodule flag.
+//
+// CAVEAT: --vmodule functionality is not available in non gcc compilers.
+//
+
+#ifndef BASE_VLOG_IS_ON_H_
+#define BASE_VLOG_IS_ON_H_
+
+#include "glog/log_severity.h"
+
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef GOOGLE_GLOG_DLL_DECL
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
+# else
+# define GOOGLE_GLOG_DLL_DECL
+# endif
+#endif
+
+#if defined(__GNUC__)
+// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
+// (Normally) the first time every VLOG_IS_ON(n) site is hit,
+// we determine what variable will dynamically control logging at this site:
+// it's either FLAGS_v or an appropriate internal variable
+// matching the current source file that represents results of
+// parsing of --vmodule flag and/or SetVLOGLevel calls.
+#define VLOG_IS_ON(verboselevel) \
+ __extension__ \
+ ({ static google::int32* vlocal__ = &google::kLogSiteUninitialized; \
+ google::int32 verbose_level__ = (verboselevel); \
+ (*vlocal__ >= verbose_level__) && \
+ ((vlocal__ != &google::kLogSiteUninitialized) || \
+ (google::InitVLOG3__(&vlocal__, &FLAGS_v, \
+ __FILE__, verbose_level__))); })
+#else
+// GNU extensions not available, so we do not support --vmodule.
+// Dynamic value of FLAGS_v always controls the logging level.
+#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
+#endif
+
+// Set VLOG(_IS_ON) level for module_pattern to log_level.
+// This lets us dynamically control what is normally set by the --vmodule flag.
+// Returns the level that previously applied to module_pattern.
+// NOTE: To change the log level for VLOG(_IS_ON) sites
+// that have already executed after/during InitGoogleLogging,
+// one needs to supply the exact --vmodule pattern that applied to them.
+// (If no --vmodule pattern applied to them
+// the value of FLAGS_v will continue to control them.)
+extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
+ int log_level);
+
+// Various declarations needed for VLOG_IS_ON above: =========================
+
+// Special value used to indicate that a VLOG_IS_ON site has not been
+// initialized. We make this a large value, so the common-case check
+// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
+// passes in such cases and InitVLOG3__ is then triggered.
+extern google::int32 kLogSiteUninitialized;
+
+// Helper routine which determines the logging info for a particalur VLOG site.
+// site_flag is the address of the site-local pointer to the controlling
+// verbosity level
+// site_default is the default to use for *site_flag
+// fname is the current source file name
+// verbose_level is the argument to VLOG_IS_ON
+// We will return the return value for VLOG_IS_ON
+// and if possible set *site_flag appropriately.
+extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
+ google::int32** site_flag,
+ google::int32* site_default,
+ const char* fname,
+ google::int32 verbose_level);
+
+#endif // BASE_VLOG_IS_ON_H_
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/port.cc b/thirdparty/glog/glog-0.3.4/src/windows/port.cc
new file mode 100644
index 0000000..bfa6e70
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/port.cc
@@ -0,0 +1,64 @@
+/* Copyright (c) 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ * Copied from google-perftools and modified by Shinichiro Hamaji
+ */
+
+#ifndef _WIN32
+# error You should only be including windows/port.cc in a windows environment!
+#endif
+
+#include "config.h"
+#include <stdarg.h> // for va_list, va_start, va_end
+#include <string.h> // for strstr()
+#include <assert.h>
+#include <string>
+#include <vector>
+#include "port.h"
+
+using std::string;
+using std::vector;
+
+// These call the windows _vsnprintf, but always NUL-terminate.
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (size == 0) // not even room for a \0?
+ return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+
+int snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ const int r = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/port.h b/thirdparty/glog/glog-0.3.4/src/windows/port.h
new file mode 100644
index 0000000..24d7677
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/port.h
@@ -0,0 +1,159 @@
+/* Copyright (c) 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ * Copied from google-perftools and modified by Shinichiro Hamaji
+ *
+ * These are some portability typedefs and defines to make it a bit
+ * easier to compile this code under VC++.
+ *
+ * Several of these are taken from glib:
+ * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
+ */
+
+#ifndef CTEMPLATE_WINDOWS_PORT_H_
+#define CTEMPLATE_WINDOWS_PORT_H_
+
+#include "config.h"
+
+#ifdef _WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
+#endif
+
+#include <windows.h>
+#include <winsock.h> /* for gethostname */
+#include <io.h> /* because we so often use open/close/etc */
+#include <direct.h> /* for _getcwd() */
+#include <process.h> /* for _getpid() */
+#include <stdio.h> /* read in vsnprintf decl. before redifining it */
+#include <stdarg.h> /* template_dictionary.cc uses va_copy */
+#include <string.h> /* for _strnicmp(), strerror_s() */
+#include <time.h> /* for localtime_s() */
+/* Note: the C++ #includes are all together at the bottom. This file is
+ * used by both C and C++ code, so we put all the C++ together.
+ */
+
+#ifdef _MSC_VER
+
+/* 4244: otherwise we get problems when substracting two size_t's to an int
+ * 4251: it's complaining about a private struct I've chosen not to dllexport
+ * 4355: we use this in a constructor, but we do it safely
+ * 4715: for some reason VC++ stopped realizing you can't return after abort()
+ * 4800: we know we're casting ints/char*'s to bools, and we're ok with that
+ * 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
+ */
+#pragma warning(disable:4244 4251 4355 4715 4800 4996)
+
+/* file I/O */
+#define PATH_MAX 1024
+#define access _access
+#define getcwd _getcwd
+#define open _open
+#define read _read
+#define write _write
+#define lseek _lseek
+#define close _close
+#define popen _popen
+#define pclose _pclose
+#define R_OK 04 /* read-only (for access()) */
+#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+#ifndef __MINGW32__
+enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
+#endif
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+
+/* Not quite as lightweight as a hard-link, but more than good enough for us. */
+#define link(oldpath, newpath) CopyFileA(oldpath, newpath, false)
+
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+
+/* In windows-land, hash<> is called hash_compare<> (from xhash.h) */
+/* VC11 provides std::hash */
+#if defined(_MSC_VER) && (_MSC_VER < 1700)
+#define hash hash_compare
+#endif
+
+/* Sleep is in ms, on windows */
+#define sleep(secs) Sleep((secs) * 1000)
+
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-( We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+extern int snprintf(char *str, size_t size,
+ const char *format, ...);
+extern int safe_vsnprintf(char *str, size_t size,
+ const char *format, va_list ap);
+#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
+#define va_copy(dst, src) (dst) = (src)
+
+/* Windows doesn't support specifying the number of buckets as a
+ * hash_map constructor arg, so we leave this blank.
+ */
+#define CTEMPLATE_SMALL_HASHTABLE
+
+#define DEFAULT_TEMPLATE_ROOTDIR ".."
+
+// ----------------------------------- SYSTEM/PROCESS
+typedef int pid_t;
+#define getpid _getpid
+
+#endif // _MSC_VER
+
+// ----------------------------------- THREADS
+typedef DWORD pthread_t;
+typedef DWORD pthread_key_t;
+typedef LONG pthread_once_t;
+enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
+#define pthread_self GetCurrentThreadId
+#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
+
+inline struct tm* localtime_r(const time_t* timep, struct tm* result) {
+ localtime_s(result, timep);
+ return result;
+}
+
+inline char* strerror_r(int errnum, char* buf, size_t buflen) {
+ strerror_s(buf, buflen, errnum);
+ return buf;
+}
+
+#ifndef __cplusplus
+/* I don't see how to get inlining for C code in MSVC. Ah well. */
+#define inline
+#endif
+
+#endif /* _WIN32 */
+
+#endif /* CTEMPLATE_WINDOWS_PORT_H_ */
diff --git a/thirdparty/glog/glog-0.3.4/src/windows/preprocess.sh b/thirdparty/glog/glog-0.3.4/src/windows/preprocess.sh
new file mode 100644
index 0000000..5398988
--- /dev/null
+++ b/thirdparty/glog/glog-0.3.4/src/windows/preprocess.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+# Copyright (c) 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# ---
+# Author: Craig Silverstein
+# Copied from google-perftools and modified by Shinichiro Hamaji
+#
+# This script is meant to be run at distribution-generation time, for
+# instance by autogen.sh. It does some of the work configure would
+# normally do, for windows systems. In particular, it expands all the
+# @...@ variables found in .in files, and puts them here, in the windows
+# directory.
+#
+# This script should be run before any new release.
+
+if [ -z "$1" ]; then
+ echo "USAGE: $0 <src/ directory>"
+ exit 1
+fi
+
+DLLDEF_MACRO_NAME="GLOG_DLL_DECL"
+
+# The text we put in every .h files we create. As a courtesy, we'll
+# include a helpful comment for windows users as to how to use
+# GLOG_DLL_DECL. Apparently sed expands \n into a newline. Good!
+DLLDEF_DEFINES="\
+// NOTE: if you are statically linking the template library into your binary\n\
+// (rather than using the template .dll), set '/D $DLLDEF_MACRO_NAME='\n\
+// as a compiler flag in your project file to turn off the dllimports.\n\
+#ifndef $DLLDEF_MACRO_NAME\n\
+# define $DLLDEF_MACRO_NAME __declspec(dllimport)\n\
+#endif"
+
+# Read all the windows config info into variables
+# In order for the 'set' to take, this requires putting all in a subshell.
+(
+ while read define varname value; do
+ [ "$define" != "#define" ] && continue
+ eval "$varname='$value'"
+ done
+
+ # Process all the .in files in the "glog" subdirectory
+ mkdir -p "$1/windows/glog"
+ for file in `echo "$1"/glog/*.in`; do
+ echo "Processing $file"
+ outfile="$1/windows/glog/`basename $file .in`"
+
+ echo "\
+// This file is automatically generated from $file
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+" > "$outfile"
+ # Besides replacing @...@, we also need to turn on dllimport
+ # We also need to replace hash by hash_compare (annoying we hard-code :-( )
+ sed -e "s!@ac_windows_dllexport@!$DLLDEF_MACRO_NAME!g" \
+ -e "s!@ac_windows_dllexport_defines@!$DLLDEF_DEFINES!g" \
+ -e "s!@ac_cv_cxx_hash_map@!$HASH_MAP_H!g" \
+ -e "s!@ac_cv_cxx_hash_namespace@!$HASH_NAMESPACE!g" \
+ -e "s!@ac_cv_cxx_hash_set@!$HASH_SET_H!g" \
+ -e "s!@ac_cv_have_stdint_h@!0!g" \
+ -e "s!@ac_cv_have_systypes_h@!0!g" \
+ -e "s!@ac_cv_have_inttypes_h@!0!g" \
+ -e "s!@ac_cv_have_unistd_h@!0!g" \
+ -e "s!@ac_cv_have_uint16_t@!0!g" \
+ -e "s!@ac_cv_have_u_int16_t@!0!g" \
+ -e "s!@ac_cv_have___uint16@!1!g" \
+ -e "s!@ac_cv_have_libgflags@!0!g" \
+ -e "s!@ac_cv_have___builtin_expect@!0!g" \
+ -e "s!@ac_cv_cxx_using_operator@!1!g" \
+ -e "s!@ac_cv___attribute___noreturn@!!g" \
+ -e "s!@ac_cv___attribute___noinline@!!g" \
+ -e "s!@ac_cv___attribute___printf_4_5@!!g" \
+ -e "s!@ac_google_attribute@!${HAVE___ATTRIBUTE__:-0}!g" \
+ -e "s!@ac_google_end_namespace@!$_END_GOOGLE_NAMESPACE_!g" \
+ -e "s!@ac_google_namespace@!$GOOGLE_NAMESPACE!g" \
+ -e "s!@ac_google_start_namespace@!$_START_GOOGLE_NAMESPACE_!g" \
+ -e "s!@ac_htmlparser_namespace@!$HTMLPARSER_NAMESPACE!g" \
+ -e "s!\\bhash\\b!hash_compare!g" \
+ "$file" >> "$outfile"
+ done
+) < "$1/windows/config.h"
+
+# log_severity.h isn't a .in file.
+echo "\
+// This file is automatically generated from $1/glog/log_severity.h
+// using src/windows/preprocess.sh.
+// DO NOT EDIT!
+" > "$1/windows/glog/log_severity.h"
+cat "$1/glog/log_severity.h" >> "$1/windows/glog/log_severity.h"
+
+echo "DONE"