Update Libmv to latest upstream
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 20 Mar 2014 17:03:11 +0000 (23:03 +0600)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 20 Mar 2014 17:26:25 +0000 (23:26 +0600)
This is mainly a maintaince commit which syncs changes
between Blender and Libmv upstream also bringing new
GLog version.

This GLog version is presumably have better support of
MinGW from "the box".

This commit is also aimed to make further 3d part libs
update easier.

28 files changed:
extern/libmv/CMakeLists.txt
extern/libmv/ChangeLog
extern/libmv/SConscript
extern/libmv/bundle.sh
extern/libmv/third_party/gflags/gflags/gflags_declare.h
extern/libmv/third_party/glog/ChangeLog
extern/libmv/third_party/glog/README.libmv
extern/libmv/third_party/glog/src/base/commandlineflags.h
extern/libmv/third_party/glog/src/base/mutex.h
extern/libmv/third_party/glog/src/config_freebsd.h
extern/libmv/third_party/glog/src/config_hurd.h
extern/libmv/third_party/glog/src/config_linux.h
extern/libmv/third_party/glog/src/config_mac.h
extern/libmv/third_party/glog/src/glog/logging.h
extern/libmv/third_party/glog/src/glog/raw_logging.h
extern/libmv/third_party/glog/src/logging.cc
extern/libmv/third_party/glog/src/raw_logging.cc
extern/libmv/third_party/glog/src/signalhandler.cc
extern/libmv/third_party/glog/src/stacktrace_libunwind-inl.h
extern/libmv/third_party/glog/src/symbolize.cc
extern/libmv/third_party/glog/src/symbolize.h
extern/libmv/third_party/glog/src/utilities.cc
extern/libmv/third_party/glog/src/utilities.h
extern/libmv/third_party/glog/src/vlog_is_on.cc
extern/libmv/third_party/glog/src/windows/config.h
extern/libmv/third_party/glog/src/windows/glog/logging.h
extern/libmv/third_party/glog/src/windows/port.cc
extern/libmv/third_party/glog/src/windows/port.h

index 6c716b5752c46f065ecf63e49de7bbf767c035f0..f7173c3b1e14590cc2349d43d10a094bad48652f 100644 (file)
@@ -44,6 +44,8 @@ if(WITH_LIBMV)
        )
 
        list(APPEND INC
+               third_party/gflags
+               third_party/glog/src
                third_party/ceres/include
                ../../intern/guardedalloc
        )
@@ -218,10 +220,6 @@ if(WITH_LIBMV)
                        third_party/glog/src/symbolize.h
                        third_party/glog/src/utilities.h
                )
-
-               list(APPEND INC
-                       third_party/glog/src
-               )
        endif()
 else()
        list(APPEND SRC
index 641d2518fb85e5ea5c01367f2f5d37605ebcf673..c9df808e1b4febc273f9da16d77bd3efcfda20bb 100644 (file)
@@ -1,3 +1,135 @@
+commit a4f387680dbc1f8818fe3cd79174a9983127d89e
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Mar 20 23:07:34 2014 +0600
+
+    Compilation fixes for MinGW
+    
+    Many thanks to Antony Riakiotakis for the patch!
+
+commit f1aefcbf58fe04ea2967434f39f703bb486777c8
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Feb 27 16:21:19 2014 +0600
+
+    Implement separate BA step for tracks which have constant zero weight
+    
+    This is needed to minimize their reprojection error over the footage.
+    Without this extra step positions of such tracks were calculated by
+    algebraic intersection code only, which doesn't give best precision.
+
+commit bcf7f9470b2ea33cf89a31a72037ec03be631637
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Feb 27 14:16:42 2014 +0600
+
+    Avoid zero-sized problem when doing euclidean intersection
+    
+    Zero-sized problem might occur when intersecting track with
+    constant zero weight. For such tracks we'll just use result
+    of algebraic intersection.
+    
+    TODO: We probably need to have a separate BA step to adjust
+    positions of tracks with constant zero weight.
+
+commit f884bb20a93189b8210639f3de939c64177d66b3
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Wed Feb 26 18:00:40 2014 +0600
+
+    Ignore zero weighted markers in keyframe selection
+    
+    It doesn't make sense to use zero-weighted tracks as a correspondences
+    in keyframe selection.
+    
+    Such tracks are not guaranteed to be tracked accurately because their
+    purpose is to add reference points in 3D space without affecting the
+    solution.
+
+commit 74db5175cdbcabe673b82eef59c88fb7f342c43f
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Wed Feb 26 13:23:02 2014 +0600
+
+    Tweaks to make bundling into Blender warning-less
+    
+    Mainly issue i caused by conflicts in include directories,
+    so glog used to include config.h from gflags. It might be
+    fixed by splitting gflags/glog from Libmv in Blender build
+    system but that's not something fun to work on. Fixed by
+    making include directories  bit more explicit.
+    
+    Also solved no-previous-prototype warnings.
+
+commit bc4bc66af0115069562b79e837ccf4fd95c8f97e
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Fri Feb 21 14:55:13 2014 +0600
+
+    Raise epsilon used for model solver test
+    
+    It was too much small leading to false failure triggering
+    caused simply by precision issues.
+
+commit bf750590a6af4af3622c01fd1004c44da60484a7
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Tue Feb 18 23:35:52 2014 +0600
+
+    Made it possible to link against Ceres installed on the system
+    
+    Main purpose of this is to get away from bundled Ceres library
+    which is not so trivial to re-bundle and takes some to do this
+    (not talking about CMake options conflicts and pollution).
+    
+    Enabled by setting WITH_SYSTEM_CERES=ON. Default paths to search
+    Ceres library:
+    
+    - /usr/local
+    - /sw
+    - /opt/local
+    - /opt/csw
+    - /opt/lib/ceres
+    
+    You might also specify Ceres root directory using CERES_ROOT_DIR
+    variable (both CMake and environment variables are supported).
+    
+    If your Ceres is build statically, you're to control all additional
+    libraries needed to link against using CMAKE_EXE_LINKER_FLAGS.
+
+commit c9156fbf80c86853806844b754b1e48f45c5ec11
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Tue Feb 18 19:38:22 2014 +0600
+
+    Remove .orig file which was added by accident
+
+commit 62597e3cf0f266a2fefec415c89759e502793e06
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Jan 2 16:02:08 2014 +0600
+
+    Upgrade glog to latest svn r139
+    
+    The intention of this upgrade is to get rid of custom patches
+    we've been having to support compilation on different platforms
+    and compilers.
+
+commit 2452d5d42b390c7ab853e6fe60e58bdd7a01a004
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Tue Feb 18 18:46:08 2014 +0600
+
+    Tweak Ceres CMake to detect uninstall target properly on Windows
+
+commit 98a281d58ce2301f3dd239a97a448e53f48d0258
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Fri Feb 14 00:36:44 2014 +0600
+
+    Fix order of third party libs compilation and options used by them
+    
+    WITH_FAST_DETECTOR was defined too late and third_party folder
+    didn't see this option.
+
+commit 4962bccd643ec0f2aed3035170d5f20e8f6efc85
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Feb 13 23:55:03 2014 +0600
+
+    Disable Ceres unit tests and examples by default
+    
+    Actually we're to switch to external Ceres rather than
+    bundled one, would make life much easier actually.
+
 commit b1381540305d69c702eb2f051bd543fb5c1c3e2c
 Author: Sergey Sharybin <sergey.vfx@gmail.com>
 Date:   Thu Feb 6 18:01:58 2014 +0600
@@ -538,156 +670,3 @@ Author: Sergey Sharybin <sergey.vfx@gmail.com>
 Date:   Fri May 10 13:27:21 2013 +0600
 
     Left extra debugging print in reconstruction scale by accident.
-
-commit 7971967d24e3d8d505bd6e54523161ab5dd5b728
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Fri May 10 12:23:03 2013 +0600
-
-    Add check for points behind camera in euclidan BA cost functor
-    
-    In cases keyframes are no so good, algebraic two frames construction
-    could produce result, for which more aggressive Ceres-based BA code
-    will fall to a solution for which points goes behind the camera,
-    which is not so nice.
-    
-    Seems in newer Ceres returning false from cost functor wouldn't
-    abort solution, but will restrict solver from moving points behind
-    the camera.
-    
-    Works fine in own tests, but requires more tests.
-
-commit f34e73f6bd0041a31f779a78e1c2324f9799a4a2
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Wed Apr 24 22:06:38 2013 +0600
-
-    Forgot to add reconstruction scale to CMakeLists
-
-commit de08cbaebe1b95673c4bc8f639aa0228414cf4a2
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Wed Apr 24 19:40:39 2013 +0600
-
-    Reconstructed scene scale ambiguity improvement
-    
-    Added a function EuclideanScaleToUnity() which is
-    aimed to solve scale ambiguity by scaling solution
-    in a way cameras centers variance in unity.
-    
-    Currently only available for euclidean pipeline,
-    projective one is not finished anyway.
-
-commit 30ecb7dd075527c0e49220744bae65ec208dbdf5
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Tue Apr 23 01:41:29 2013 +0600
-
-    Use epsilon in modal solver test
-    
-    Default epsilon for isApprox was too small,
-    leading to some false test failures.
-
-commit d03b303c171b0b0a33ed0b31c9a744c9676492a9
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Tue Apr 23 01:35:56 2013 +0600
-
-    Update Ceres to current HEAD
-    
-    Brings optimization for DENSE_NORMAL_CHOLESKY and
-    also fixes threading issues with BLAS.
-
-commit 0a352686de0e87d59a2e37dbd0fddb351cbea2b7
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 15 05:35:33 2013 +0600
-
-    Fix for bundle adjusting with motion restricted
-    
-    Was a bug introduced in previous commit, which
-    was trying to set parameterization for non-existing
-    camera->t parameter block.
-    
-    Replaced with subset parameterization.
-    
-    Also added basic synthetic unit test for modal solver.
-
-commit 1742515b89ad5da53be95bfc574cbeffc51dc0e2
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 8 23:33:20 2013 +0600
-
-     Bundle adjustment improvements
-    
-    - Get rid of rotation matrix parameterization,
-      use angle-axis instead.
-    
-      Also Joined rotation and translation into
-      a single parameter block.
-    
-      This made minimization go significantly faster,
-      like 1.3x times in average.
-    
-    - Fix first camera when bundling. This is to
-      address orientation ambiguity.
-    
-      Reconstruction result could still vary in
-      size, but that's another issue to be addressed
-      later.
-    
-    Additional change:
-    
-    Split EuclideanBundleCommonIntrinsics into
-    smaller functions, so it's now a bit easier
-    to follow.
-
-commit 74bbeabf1c4570bfe04f3034afcde95134b3e161
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 8 23:31:57 2013 +0600
-
-    Update Ceres to current HEAD
-    
-    Brings up some noticeable speed improvements. In particular
-    the automatic differentiation and bundle adjustment solvers.
-
-commit e47519b0442527533ee046dd9881212d169561da
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 8 02:21:26 2013 +0600
-
-    Corrected path to gflags
-    
-    Currently tools/track.cc is not used, but let's
-    keep things a bit more up-to-date :)
-
-commit f617741b1f2a0ac7981dd71144eba187521d9ac4
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 8 02:17:16 2013 +0600
-
-    Re-enable tests for multiview and image
-    
-    For as long code is in repo and used by some tools
-    better to have it covered by tests.
-    
-    Some of them are failing tho, but that's completely
-    different story to be addressed later.
-
-commit 7dbb5a37333fb6c5a729b8bafb317ea210735cbc
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Mon Apr 8 02:10:07 2013 +0600
-
-    Do not modify cache's CMAKE_CXX_FLAGS_RELEASE when configuring Ceres
-    
-    Otherwise you'll have infinite appending of Ceres-specific flags
-    on every saving of any CmakeLists.txt.
-
-commit b413d22280de2481a2e2acdcda8431f601d65448
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date:   Sun Apr 7 21:53:23 2013 +0600
-
-    Fixed compilation with BUILD_TOOLS enabled
-    
-    This commit mainly reverts parts of following commits:
-        0eebc21db831211738acc938566bbc29d68d45db
-        d8109b7a4fede1660e0dbd73735f1a9e3fd79eec
-        e59595806c045916ab4ef15ef7047c1a728b2da9
-        2d6cd58ee1cd7c5073980f358c71b2898ad16b4c
-    
-    They declared  lots of stuff deprecated, but in
-    fact it's not deprecated just a bit different
-    usage pipeline. Anyway, deprecation shall not
-    happen spontaneously as a part of other changes.
-    And for sure shall not break anything.
index 544e5fda3812ab8714303e0950ec220375b335a4..796819faa5512c2f68d08295b6744311036c07db 100644 (file)
@@ -26,7 +26,7 @@ if env['WITH_BF_LIBMV']:
     src += env.Glob('libmv/tracking/*.cc')
     src += env.Glob('third_party/gflags/*.cc')
 
-    incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
+    incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include ../../intern/guardedalloc'
     incs += ' ' + env['BF_PNG_INC']
     incs += ' ' + env['BF_ZLIB_INC']
 
index 48d68435ef79be08140dbd443482632a66daee81..c98f8a310456eb903cbdb4de2fcd33aeb5c59968 100755 (executable)
@@ -132,6 +132,8 @@ if(WITH_LIBMV)
        )
 
        list(APPEND INC
+               third_party/gflags
+               third_party/glog/src
                third_party/ceres/include
                ../../intern/guardedalloc
        )
@@ -195,10 +197,6 @@ ${third_glog_sources}
 
 ${third_glog_headers}
                )
-
-               list(APPEND INC
-                       third_party/glog/src
-               )
        endif()
 else()
        list(APPEND SRC
@@ -237,7 +235,7 @@ if env['WITH_BF_LIBMV']:
     src = env.Glob("libmv-capi.cc")
 $src
 
-    incs += ' ../Eigen3 third_party/ceres/include ../../intern/guardedalloc'
+    incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include ../../intern/guardedalloc'
     incs += ' ' + env['BF_PNG_INC']
     incs += ' ' + env['BF_ZLIB_INC']
 
index e3013826d5323f81cb9a6eefdda2a743e75a27c8..503b686657ffd0559977f7e790a9698803b3cb45 100644 (file)
 #endif
 
 namespace google {
-#if 1      // the C99 format
+#if defined(__GNUC__) || defined(__MINGW32__)      // the C99 format
 typedef int32_t int32;
 typedef uint32_t uint32;
 typedef int64_t int64;
 typedef uint64_t uint64;
-#elif 1   // the BSD format
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)   // the BSD format
 typedef int32_t int32;
 typedef u_int32_t uint32;
 typedef int64_t int64;
 typedef u_int64_t uint64;
-#elif 0     // the windows (vc7) format
+#elif defined(_MSC_VER)     // the windows (vc7) format
 typedef __int32 int32;
 typedef unsigned __int32 uint32;
 typedef __int64 int64;
index 6ac0b0f0575fcad85457a48a5103d637617c1733..d1b4248441628e8f16ca0699e45f43d00e049780 100644 (file)
@@ -1,3 +1,18 @@
+2013-02-01  Google Inc. <opensource@google.com>
+
+       * google-glog: version 0.3.3
+       * Add --disable-rtti option for configure.
+       * Visual Studio build and test fix.
+       * QNX build fix (thanks vanuan).
+       * Reduce warnings.
+       * Fixed LOG_SYSRESULT (thanks ukai).
+       * FreeBSD build fix (thanks yyanagisawa).
+       * Clang build fix.
+       * Now users can re-initialize glog after ShutdownGoogleLogging.
+       * Color output support by GLOG_colorlogtostderr (thanks alexs).
+       * Now glog's ABI around flags are compatible with gflags.
+       * Document mentions how to modify flags from user programs.
+
 2012-01-12  Google Inc. <opensource@google.com>
 
        * google-glog: version 0.3.2
index 345bc9f5969cc4f0db89efe62330bc800deca064..eb4b2ea337989a901fde12a12979a07a67852f00 100644 (file)
@@ -1,25 +1,9 @@
 Project: Google Logging
 URL: http://code.google.com/p/google-glog/
 License: New BSD
-Upstream version: 0.3.2
+Upstream version: 0.3.3, r139
 Local modifications:
-
-Upgrading Notes
-* Replace <gflags/gflags.h> with "third_party/gflags/gflags/gflags.h" which is easier
-  to setup things in libmv and also helps with setting up building libmv into
-  external applications.
-* Replace "glog/logging.h" and  "glog/logging.h" with <glog/logging.h> and  <glog/logging.h>
-  which is needed on Windows platform because otherwise files like logging.cc will be using
-  relative path which points to headers used by linux instead of headers need to be used
-  on Windows.
-* Replace _asm int 3 with __debugbreak(). Such assembler code is obsolete and doesn't work
-  with 64bit versions of MSVC compilers.
-* Do not use stacktrace for MinGW and FreeBSD because it leads into issues accessing
-  some specific data on this platforms.
-* Define HAVE_LIB_GFLAGS for Windows builds.
-* Do not define __declspec(dllimport) for MinGW platforms.
-* Setup proper includes and datatypes for int32, uint32, int64 and uint64 for MinGW
-* Do not define va_copy for MinGW platforms (it's already defined there).
-* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
-  of lack of needed functions.
-* Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
+* Added per-platform config.h files so no configuration-time
+  checks for functions and so are needed.
+* See glog_tweaks.patch to see other tweaks which are done
+  against glog upstream.
index 483a96ee80bf841b41a41db85a4e24e38fdbecf6..529540ea461b0cca36d3a559e87a9b08b743cc7f 100644 (file)
 #ifndef BASE_COMMANDLINEFLAGS_H__
 #define BASE_COMMANDLINEFLAGS_H__
 
-#include "config.h"
+#include "../config.h"
 #include <string>
 #include <string.h>               // for memchr
 #include <stdlib.h>               // for getenv
 
 #ifdef HAVE_LIB_GFLAGS
 
-#include "third_party/gflags/gflags/gflags.h"
+#include <gflags/gflags.h>
 
 #else
 
-#include <glog/logging.h>
+#include "glog/logging.h"
 
-#define DECLARE_VARIABLE(type, name, tn)                                      \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name;                              \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
-#define DEFINE_VARIABLE(type, name, value, meaning, tn) \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead {  \
-  GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value);                              \
-  char FLAGS_no##name;                                                        \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
+#define DECLARE_VARIABLE(type, shorttype, name, tn)                     \
+  namespace fL##shorttype {                                             \
+    extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name;                      \
+  }                                                                     \
+  using fL##shorttype::FLAGS_##name
+#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn)      \
+  namespace fL##shorttype {                                             \
+    GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value);                      \
+    char FLAGS_no##name;                                                \
+  }                                                                     \
+  using fL##shorttype::FLAGS_##name
 
 // bool specialization
 #define DECLARE_bool(name) \
-  DECLARE_VARIABLE(bool, name, bool)
+  DECLARE_VARIABLE(bool, B, name, bool)
 #define DEFINE_bool(name, value, meaning) \
-  DEFINE_VARIABLE(bool, name, value, meaning, bool)
+  DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
 
 // int32 specialization
 #define DECLARE_int32(name) \
-  DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, name, int32)
+  DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, int32)
 #define DEFINE_int32(name, value, meaning) \
-  DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, name, value, meaning, int32)
+  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 FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name;                       \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
-#define DEFINE_string(name, value, meaning)                                   \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
-  GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name(value);                       \
-  char FLAGS_no##name;                                                        \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
+#define DECLARE_string(name)                                            \
+  namespace fLS {                                                       \
+    extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name;              \
+  }                                                                     \
+  using fLS::FLAGS_##name
+#define DEFINE_string(name, value, meaning)                             \
+  namespace fLS {                                                       \
+    std::string FLAGS_##name##_buf(value);                              \
+    GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name = FLAGS_##name##_buf; \
+    char FLAGS_no##name;                                                \
+  }                                                                     \
+  using fLS::FLAGS_##name
 
 #endif  // HAVE_LIB_GFLAGS
 
index 7ba88cb5a6326cdf71e541677c37e0bba83cdcd4..36fc55c4dcb15e8e0485b207815d80bd9aee8f75 100644 (file)
 #ifndef GOOGLE_MUTEX_H_
 #define GOOGLE_MUTEX_H_
 
-#include "config.h"           // to figure out pthreads support
+#include "../config.h"           // to figure out pthreads support
 
 #if defined(NO_THREADS)
   typedef int MutexType;      // to keep a lock-count
 #elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
-# define WIN32_LEAN_AND_MEAN  // We only need minimal includes
+# 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
 #   endif
 # endif
 // To avoid macro definition of ERROR.
-# define NOGDI
+# ifndef NOGDI
+#  define NOGDI
+# endif
 // To avoid macro definition of min/max.
-# define NOMINMAX
+# ifndef NOMINMAX
+#  define NOMINMAX
+# endif
 # include <windows.h>
   typedef CRITICAL_SECTION MutexType;
 #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
index a671a0080b39d2891d69492961a955a1196a4a1b..a1fe76fe8068704732b39f8f41bf8266a942d2a8 100644 (file)
 /* define if the compiler implements namespaces */
 #define HAVE_NAMESPACES 1
 
+/* Define if you have the 'pread' function */
+#define HAVE_PREAD 1
+
 /* Define if you have POSIX threads libraries and header files. */
 #define HAVE_PTHREAD 1
 
 /* Define to 1 if you have the <pwd.h> header file. */
 #define HAVE_PWD_H 1
 
+/* Define if you have the 'pwrite' function */
+#define HAVE_PWRITE 1
+
 /* define if the compiler implements pthread_rwlock_* */
 #define HAVE_RWLOCK 1
 
index 47aefa423d6214e93ffc44c4aa24a15496fc90d6..81e8ed7bac3c035a9c7b2e1f581ba2ed8905ef05 100644 (file)
 /* define if the compiler implements namespaces */
 #define HAVE_NAMESPACES 1
 
+/* Define if you have the 'pread' function */
+#define HAVE_PREAD 1
+
 /* Define if you have POSIX threads libraries and header files. */
 #define HAVE_PTHREAD 1
 
 /* Define to 1 if you have the <pwd.h> header file. */
 #define HAVE_PWD_H 1
 
+/* Define if you have the 'pwrite' function */
+#define HAVE_PWRITE 1
+
 /* define if the compiler implements pthread_rwlock_* */
 #define HAVE_RWLOCK 1
 
index 5877029882a4f3eaad6b70f7f6d9f5643e097ef3..7741ddebb63109ae3cb5ef0938c43397cb2b8481 100644 (file)
 /* define if the compiler implements namespaces */
 #define HAVE_NAMESPACES 1
 
+/* Define if you have the 'pread' function */
+#define HAVE_PREAD 1
+
 /* Define if you have POSIX threads libraries and header files. */
 #define HAVE_PTHREAD 1
 
 /* Define to 1 if you have the <pwd.h> header file. */
 #define HAVE_PWD_H 1
 
+/* Define if you have the 'pwrite' function */
+#define HAVE_PWRITE 1
+
 /* define if the compiler implements pthread_rwlock_* */
 #define HAVE_RWLOCK 1
 
index 9756fde22f36eb08373e28b46d68f2def177307b..1695472f031a4ddf3fa85702133af5e718cb230c 100644 (file)
 /* define if the compiler implements namespaces */
 #define HAVE_NAMESPACES 1
 
+/* Define if you have the 'pread' function */
+#define HAVE_PREAD 1
+
 /* Define if you have POSIX threads libraries and header files. */
 #define HAVE_PTHREAD 1
 
 /* Define to 1 if you have the <pwd.h> header file. */
 #define HAVE_PWD_H 1
 
+/* Define if you have the 'pwrite' function */
+#define HAVE_PWRITE 1
+
 /* define if the compiler implements pthread_rwlock_* */
 #define HAVE_RWLOCK 1
 
index 005649c17c23e049bb39af155d253c3688fb9baf..247c0467b6acd7eb0fac2a9354f4e07f27a51dea 100644 (file)
 // Pretty much everybody needs to #include this file so that they can
 // log various happenings.
 //
+#ifdef WIN32
+#  include "windows/glog/logging.h"
+#else  // WIN32
+
 #ifndef _LOGGING_H_
 #define _LOGGING_H_
 
 #include <errno.h>
 #include <string.h>
 #include <time.h>
+#include <iosfwd>
+#include <ostream>
+#include <sstream>
 #include <string>
 #if 1
 # include <unistd.h>
 #endif
-#ifdef __DEPRECATED
-// Make GCC quiet.
-# undef __DEPRECATED
-# include <strstream>
-# define __DEPRECATED
-#else
-# include <strstream>
-#endif
 #include <vector>
 
 // Annoying stuff for windows -- makes sure clients can import these functions
 #   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.
@@ -79,7 +86,7 @@
 #endif
 
 #if 1
-#include "third_party/gflags/gflags/gflags.h"
+#include <gflags/gflags.h>
 #endif
 
 namespace google {
@@ -126,8 +133,12 @@ typedef unsigned __int64 uint64;
 #ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
 #if 1
 #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
 
@@ -286,27 +297,27 @@ typedef unsigned __int64 uint64;
 
 #ifndef DECLARE_VARIABLE
 #define MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#define DECLARE_VARIABLE(type, name, tn)                                      \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name;                              \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
+#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, name, bool)
+  DECLARE_VARIABLE(bool, B, name, bool)
 
 // int32 specialization
 #define DECLARE_int32(name) \
-  DECLARE_VARIABLE(google::int32, name, int32)
+  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 FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name;                       \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
+#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
@@ -315,6 +326,9 @@ 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);
@@ -447,15 +461,16 @@ DECLARE_bool(stop_logging_if_full_disk);
 #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(result)) { \
-    LPTSTR message = NULL; \
-    LPTSTR msg = reinterpret_cast<LPTSTR>(&message); \
-    DWORD message_length = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
+  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() << message; \
+          &google::LogMessage::SendToLog).stream() \
+          << reinterpret_cast<const char*>(message); \
       LocalFree(message); \
     } \
   }
@@ -597,18 +612,68 @@ inline std::ostream& operator<<(
 
 namespace google {
 
-// Build the error message string.
-template<class t1, class t2>
-std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
-  // It means that we cannot use stl_logging if compiler doesn't
-  // support using expression for operator.
-  // TODO(hamaji): Figure out a way to fix.
-#if 1
-  using ::operator<<;
-#endif
-  std::strstream ss;
-  ss << names << " (" << v1 << " vs. " << v2 << ")";
-  return new std::string(ss.str(), ss.pcount());
+// 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)
+    __attribute__ ((noinline));
+
+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.
@@ -616,26 +681,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
 // 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 <class t1, class t2> \
-  inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
-                                        const char* names) { \
-    if (v1 op v2) return NULL; \
-    else return MakeCheckOpString(v1, v2, names); \
+  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* Check##name##Impl(int v1, int v2, const char* names) { \
-    return Check##name##Impl<int, int>(v1, v2, names); \
+  inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
+    return name##Impl<int, int>(v1, v2, exprtext); \
   }
 
-// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h
-// provides its own #defines for the simpler names EQ, NE, LE, etc.
+// 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(_EQ, ==)
-DEFINE_CHECK_OP_IMPL(_NE, !=)
-DEFINE_CHECK_OP_IMPL(_LE, <=)
-DEFINE_CHECK_OP_IMPL(_LT, < )
-DEFINE_CHECK_OP_IMPL(_GE, >=)
-DEFINE_CHECK_OP_IMPL(_GT, > )
+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.
@@ -940,52 +1005,65 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
 #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) \
-    CHECK(condition)
+    GLOG_MSVC_POP_WARNING() CHECK(condition)
 
 #define DCHECK_EQ(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_EQ(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
 
 #define DCHECK_NE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_NE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
 
 #define DCHECK_LE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_LE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
 
 #define DCHECK_LT(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_LT(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
 
 #define DCHECK_GE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_GE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
 
 #define DCHECK_GT(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_GT(val1, val2)
+    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) \
-    CHECK_STREQ(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
 
 #define DCHECK_STRCASEEQ(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRCASEEQ(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
 
 #define DCHECK_STRNE(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRNE(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
 
 #define DCHECK_STRCASENE(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRCASENE(str1, str2)
-
+    GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
 
 #endif  // NDEBUG
 
@@ -1002,6 +1080,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
 #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.
@@ -1031,22 +1132,30 @@ public:
 #ifdef _MSC_VER
 # pragma warning(disable: 4275)
 #endif
-  class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream {
+  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_in)
-      : ostrstream(buf, len),
-        ctr_(ctr_in) {
-      self_ = this;
+    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_in) { ctr_ = ctr_in; }
+    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
   };
@@ -1115,13 +1224,15 @@ public:
   // Call abort() or similar to perform LOG(FATAL) crash.
   static void Fail() __attribute__ ((noreturn));
 
-  std::ostream& stream() { return *(data_->stream_); }
+  std::ostream& stream();
 
-  int preserved_errno() const { return data_->preserved_errno_; }
+  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
@@ -1143,41 +1254,6 @@ private:
 
   // We keep the data in a separate struct so that each instance of
   // LogMessage uses less stack space.
-  struct GOOGLE_GLOG_DLL_DECL LogMessageData {
-    LogMessageData() {};
-
-    int preserved_errno_;      // preserved errno
-    char* buf_;
-    char* message_text_;  // Complete message text (points to selected buffer)
-    LogStream* stream_alloc_;
-    LogStream* stream_;
-    char severity_;      // What level is this LogMessage logged at?
-    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
-
-    ~LogMessageData();
-   private:
-    LogMessageData(const LogMessageData&);
-    void operator=(const LogMessageData&);
-  };
-
-  static LogMessageData fatal_msg_data_exclusive_;
-  static LogMessageData fatal_msg_data_shared_;
-
   LogMessageData* allocated_;
   LogMessageData* data_;
 
@@ -1456,8 +1532,12 @@ extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
 // 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 {
@@ -1525,3 +1605,5 @@ GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
 }
 
 #endif // _LOGGING_H_
+
+#endif  // WIN32
index 65278f62803f4782c3c7c7cc286fcc9d6389b670..b030f7f736d78d9f7c8d78c0c50397e6ed4cb06f 100644 (file)
 // acquire any locks, and can therefore be used by low-level memory
 // allocation and synchronization code.
 
+#ifdef WIN32
+#  include "windows/glog/raw_logging.h"
+#else  // WIN32
+
 #ifndef BASE_RAW_LOGGING_H_
 #define BASE_RAW_LOGGING_H_
 
@@ -183,3 +187,5 @@ GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
 }
 
 #endif  // BASE_RAW_LOGGING_H_
+
+#endif  // WIN32
index 57d5e24122ccf73748261d665d2c2b7090ee9f2b..03c427d8dc1b3e009941efbf9eb7db258417c0fc 100644 (file)
@@ -34,7 +34,6 @@
 #include <assert.h>
 #include <iomanip>
 #include <string>
-#include <algorithm>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>  // For _exit.
 #endif
@@ -59,8 +58,8 @@
 #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 "glog/logging.h"
+#include "glog/raw_logging.h"
 #include "base/googleinit.h"
 
 #ifdef HAVE_STACKTRACE
@@ -69,7 +68,6 @@
 
 using std::string;
 using std::vector;
-using std::ostrstream;
 using std::setw;
 using std::setfill;
 using std::hex;
@@ -77,7 +75,17 @@ using std::dec;
 using std::min;
 using std::ostream;
 using std::ostringstream;
-using std::strstream;
+
+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)
@@ -94,6 +102,8 @@ 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 "
@@ -169,6 +179,38 @@ GLOG_DEFINE_string(log_backtrace_at, "",
 // TODO(hamaji): consider windows
 #define PATH_SEPARATOR '/'
 
+#ifndef HAVE_PREAD
+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;
@@ -191,13 +233,125 @@ static void GetHostName(string* hostname) {
 #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.
+static 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 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
@@ -279,7 +433,7 @@ class LogFileObject : public base::Logger {
   // Actually create a logfile using the value of base_filename_ and the
   // supplied argument time_pid_string
   // REQUIRES: lock_ is held
-  bool CreateLogfile(const char* time_pid_string);
+  bool CreateLogfile(const string& time_pid_string);
 };
 
 }  // namespace
@@ -312,6 +466,9 @@ class LogDestination {
   static const int kNetworkBytes = 1400;
 
   static const string& hostname();
+  static const bool& terminal_supports_color() {
+    return terminal_supports_color_;
+  }
 
   static void DeleteLogDestinations();
 
@@ -362,6 +519,7 @@ class LogDestination {
   static LogSeverity email_logging_severity_;
   static string addresses_;
   static string hostname_;
+  static bool terminal_supports_color_;
 
   // arbitrary global logging destinations.
   static vector<LogSink*>* sinks_;
@@ -383,6 +541,7 @@ string LogDestination::hostname_;
 
 vector<LogSink*>* LogDestination::sinks_ = NULL;
 Mutex LogDestination::sink_mutex_;
+bool LogDestination::terminal_supports_color_ = TerminalSupportsColor();
 
 /* static */
 const string& LogDestination::hostname() {
@@ -503,6 +662,43 @@ inline void LogDestination::SetEmailLogging(LogSeverity 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, stderr);
+    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(stderr);
+  SetConsoleTextAttribute(stderr_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  fwrite(message, len, 1, stderr);
+  fflush(stderr);
+  // Restores the text color.
+  SetConsoleTextAttribute(stderr_handle, old_color_attrs);
+#else
+  fprintf(stderr, "\033[0;3%sm", GetAnsiColorCode(color));
+  fwrite(message, len, 1, stderr);
+  fprintf(stderr, "\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.
@@ -512,7 +708,7 @@ static void WriteToStderr(const char* message, size_t len) {
 inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
                                             const char* message, size_t len) {
   if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
-    WriteToStderr(message, len);
+    ColoredWriteToStderr(severity, message, len);
 #ifdef OS_WINDOWS
     // On Windows, also output to the debugger
     ::OutputDebugStringA(string(message,len).c_str());
@@ -561,12 +757,12 @@ inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
                                              const char* message,
                                              size_t len) {
 
-  if ( FLAGS_logtostderr )            // global flag: never log to file
-    WriteToStderr(message, len);
-  else
+  if ( FLAGS_logtostderr ) {           // global flag: never log to file
+    ColoredWriteToStderr(severity, message, len);
+  } else {
     for (int i = severity; i >= 0; --i)
       LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
-
+  }
 }
 
 inline void LogDestination::LogToSinks(LogSeverity severity,
@@ -691,7 +887,7 @@ void LogFileObject::FlushUnlocked(){
   next_flush_time_ = CycleClock_Now() + UsecToCycles(next);
 }
 
-bool LogFileObject::CreateLogfile(const char* time_pid_string) {
+bool LogFileObject::CreateLogfile(const string& time_pid_string) {
   string string_filename = base_filename_+filename_extension_+
                            time_pid_string;
   const char* filename = string_filename.c_str();
@@ -724,8 +920,10 @@ bool LogFileObject::CreateLogfile(const char* time_pid_string) {
     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.
-#ifdef 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;
@@ -779,24 +977,24 @@ void LogFileObject::Write(bool force_flush,
     localtime_r(&timestamp, &tm_time);
 
     // The logfile's filename will have the date/time & pid in it
-    char time_pid_string[256];  // More than enough chars for time, pid, \0
-    ostrstream time_pid_stream(time_pid_string, sizeof(time_pid_string));
+    ostringstream time_pid_stream;
     time_pid_stream.fill('0');
     time_pid_stream << 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
-                   << '.'
-                   << GetMainThreadPid()
-                   << '\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
+                    << '.'
+                    << GetMainThreadPid();
+    const string& time_pid_string = time_pid_stream.str();
 
     if (base_filename_selected_) {
       if (!CreateLogfile(time_pid_string)) {
         perror("Could not create log file");
-        fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n", time_pid_string);
+        fprintf(stderr, "COULD NOT CREATE LOGFILE '%s'!\n",
+                time_pid_string.c_str());
         return;
       }
     } else {
@@ -844,15 +1042,14 @@ void LogFileObject::Write(bool force_flush,
       // 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 %s!", time_pid_string);
+        fprintf(stderr, "COULD NOT CREATE A LOGGINGFILE %s!",
+                time_pid_string.c_str());
         return;
       }
     }
 
     // Write a header message into the log file
-    char file_header_string[512];  // Enough chars for time and binary info
-    ostrstream file_header_stream(file_header_string,
-                                  sizeof(file_header_string));
+    ostringstream file_header_stream;
     file_header_stream.fill('0');
     file_header_stream << "Log file created at: "
                        << 1900+tm_time.tm_year << '/'
@@ -865,10 +1062,11 @@ void LogFileObject::Write(bool force_flush,
                        << "Running on machine: "
                        << LogDestination::hostname() << '\n'
                        << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
-                       << "threadid file:line] msg" << '\n'
-                       << '\0';
-    int header_len = strlen(file_header_string);
-    fwrite(file_header_string, 1, header_len, file_);
+                       << "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;
   }
@@ -916,9 +1114,6 @@ void LogFileObject::Write(bool force_flush,
 
 }  // namespace
 
-// 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;
 
 // Static log data space to avoid alloc failures in a LOG(FATAL)
 //
@@ -929,55 +1124,55 @@ const size_t LogMessage::kMaxLogMessageLen = 30000;
 static Mutex fatal_msg_lock;
 static CrashReason crash_reason;
 static bool fatal_msg_exclusive = true;
-static char fatal_msg_buf_exclusive[LogMessage::kMaxLogMessageLen+1];
-static char fatal_msg_buf_shared[LogMessage::kMaxLogMessageLen+1];
-static LogMessage::LogStream fatal_msg_stream_exclusive(
-    fatal_msg_buf_exclusive, LogMessage::kMaxLogMessageLen, 0);
-static LogMessage::LogStream fatal_msg_stream_shared(
-    fatal_msg_buf_shared, LogMessage::kMaxLogMessageLen, 0);
-LogMessage::LogMessageData LogMessage::fatal_msg_data_exclusive_;
-LogMessage::LogMessageData LogMessage::fatal_msg_data_shared_;
+static LogMessage::LogMessageData fatal_msg_data_exclusive;
+static LogMessage::LogMessageData fatal_msg_data_shared;
 
-LogMessage::LogMessageData::~LogMessageData() {
-  delete[] buf_;
-  delete stream_alloc_;
+LogMessage::LogMessageData::LogMessageData()
+  : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
 }
 
 LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
-                      int ctr, void (LogMessage::*send_method)()) {
+                       int ctr, void (LogMessage::*send_method)())
+    : allocated_(NULL) {
   Init(file, line, severity, send_method);
-  data_->stream_->set_ctr(ctr);
+  data_->stream_.set_ctr(ctr);
 }
 
 LogMessage::LogMessage(const char* file, int line,
-                       const CheckOpString& result) {
+                       const CheckOpString& result)
+    : allocated_(NULL) {
   Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
   stream() << "Check failed: " << (*result.str_) << " ";
 }
 
-LogMessage::LogMessage(const char* file, int line) {
+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) {
+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,
-                       LogSink* sink, bool also_send_to_log) {
+                       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) {
+                       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) {
+                       string *message)
+    : allocated_(NULL) {
   Init(file, line, severity, &LogMessage::WriteToStringAndLog);
   data_->message_ = message;  // override Init()'s setting to NULL
 }
@@ -990,27 +1185,17 @@ void LogMessage::Init(const char* file,
   if (severity != GLOG_FATAL || !exit_on_dfatal) {
     allocated_ = new LogMessageData();
     data_ = allocated_;
-    data_->buf_ = new char[kMaxLogMessageLen+1];
-    data_->message_text_ = data_->buf_;
-    data_->stream_alloc_ =
-        new LogStream(data_->message_text_, kMaxLogMessageLen, 0);
-    data_->stream_ = data_->stream_alloc_;
     data_->first_fatal_ = false;
   } else {
     MutexLock l(&fatal_msg_lock);
     if (fatal_msg_exclusive) {
       fatal_msg_exclusive = false;
-      data_ = &fatal_msg_data_exclusive_;
-      data_->message_text_ = fatal_msg_buf_exclusive;
-      data_->stream_ = &fatal_msg_stream_exclusive;
+      data_ = &fatal_msg_data_exclusive;
       data_->first_fatal_ = true;
     } else {
-      data_ = &fatal_msg_data_shared_;
-      data_->message_text_ = fatal_msg_buf_shared;
-      data_->stream_ = &fatal_msg_stream_shared;
+      data_ = &fatal_msg_data_shared;
       data_->first_fatal_ = false;
     }
-    data_->stream_alloc_ = NULL;
   }
 
   stream().fill('0');
@@ -1051,7 +1236,7 @@ void LogMessage::Init(const char* file,
              << ' '
              << data_->basename_ << ':' << data_->line_ << "] ";
   }
-  data_->num_prefix_chars_ = data_->stream_->pcount();
+  data_->num_prefix_chars_ = data_->stream_.pcount();
 
   if (!FLAGS_log_backtrace_at.empty()) {
     char fileline[128];
@@ -1071,13 +1256,21 @@ LogMessage::~LogMessage() {
   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_log_ = data_->stream_.pcount();
   data_->num_chars_to_syslog_ =
     data_->num_chars_to_log_ - data_->num_prefix_chars_;
 
@@ -1127,7 +1320,7 @@ void LogMessage::Flush() {
 
 // 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_buf_exclusive.
+// use fatal_msg_data_exclusive.
 static time_t fatal_time;
 static char fatal_message[256];
 
@@ -1135,7 +1328,7 @@ void ReprintFatalMessage() {
   if (fatal_message[0]) {
     const int n = strlen(fatal_message);
     if (!FLAGS_logtostderr) {
-      // Also write to stderr
+      // Also write to stderr (don't color to avoid terminal checks)
       WriteToStderr(fatal_message, n);
     }
     LogDestination::LogToAllLogfiles(GLOG_ERROR, fatal_time, fatal_message, n);
@@ -1164,7 +1357,8 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
   // file if we haven't parsed the command line flags to get the
   // program name.
   if (FLAGS_logtostderr || !IsGoogleLoggingInitialized()) {
-    WriteToStderr(data_->message_text_, data_->num_chars_to_log_);
+    ColoredWriteToStderr(data_->severity_,
+                         data_->message_text_, data_->num_chars_to_log_);
 
     // this could be protected by a flag if necessary.
     LogDestination::LogToSinks(data_->severity_,
@@ -1236,10 +1430,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
 
 void LogMessage::RecordCrashReason(
     glog_internal_namespace_::CrashReason* reason) {
-  reason->filename = fatal_msg_data_exclusive_.fullname_;
-  reason->line_number = fatal_msg_data_exclusive_.line_;
-  reason->message = fatal_msg_buf_exclusive +
-                    fatal_msg_data_exclusive_.num_prefix_chars_;
+  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);
@@ -1366,8 +1560,13 @@ int64 LogMessage::num_messages(int 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);
-  CHECK(log == log->self());
+#endif
+  CHECK(log && log == log->self())
+      << "You must not use COUNTER with non-glog ostream";
   os << log->ctr();
   return os;
 }
@@ -1381,9 +1580,8 @@ ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
 ErrnoLogMessage::~ErrnoLogMessage() {
   // Don't access errno directly because it may have been altered
   // while streaming the message.
-  char buf[100];
-  posix_strerror_r(preserved_errno(), buf, sizeof(buf));
-  stream() << ": " << buf << " [" << preserved_errno() << "]";
+  stream() << ": " << StrError(preserved_errno()) << " ["
+           << preserved_errno() << "]";
 }
 
 void FlushLogFiles(LogSeverity min_severity) {
@@ -1465,9 +1663,7 @@ void LogToStderr() {
 namespace base {
 namespace internal {
 
-/* Put prototypes here to suppress strict compiler warnings */
-bool GetExitOnDFatal();
-void SetExitOnDFatal(bool value);
+namespace {
 
 bool GetExitOnDFatal() {
   MutexLock l(&log_mutex);
@@ -1489,6 +1685,8 @@ void SetExitOnDFatal(bool value) {
   exit_on_dfatal = value;
 }
 
+}  // namespace
+
 }  // namespace internal
 }  // namespace base
 
@@ -1516,13 +1714,11 @@ static bool SendEmailInternal(const char*dest, const char *subject,
       bool ok = pclose(pipe) != -1;
       if ( !ok ) {
         if ( use_logging ) {
-          char buf[100];
-          posix_strerror_r(errno, buf, sizeof(buf));
-          LOG(ERROR) << "Problems sending mail to " << dest << ": " << buf;
+          LOG(ERROR) << "Problems sending mail to " << dest << ": "
+                     << StrError(errno);
         } else {
-          char buf[100];
-          posix_strerror_r(errno, buf, sizeof(buf));
-          fprintf(stderr, "Problems sending mail to %s: %s\n", dest, buf);
+          fprintf(stderr, "Problems sending mail to %s: %s\n",
+                  dest, StrError(errno).c_str());
         }
       }
       return ok;
@@ -1644,8 +1840,11 @@ void TruncateLogFile(const char *path, int64 limit, int64 keep) {
   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) {
@@ -1730,11 +1929,11 @@ void TruncateStdoutStderr() {
     bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2));               \
     if (equal == expected) return NULL;                                 \
     else {                                                              \
-      strstream ss;                                                     \
+      ostringstream ss;                                                 \
       if (!s1) s1 = "";                                                 \
       if (!s2) s2 = "";                                                 \
       ss << #name " failed: " << names << " (" << s1 << " vs. " << s2 << ")"; \
-      return new string(ss.str(), ss.pcount());                         \
+      return new string(ss.str());                                      \
     }                                                                   \
   }
 DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
@@ -1793,6 +1992,15 @@ int posix_strerror_r(int err, char *buf, size_t len) {
   }
 }
 
+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) {}
 
@@ -1805,6 +2013,56 @@ LogMessageFatal::~LogMessageFatal() {
     LogMessage::Fail();
 }
 
+namespace base {
+
+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
+
+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) {
   glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
 }
index 42676cba5deedeb356d82e5acf08efb12ce59d70..7a7409bbf34b0bb3103fd33df76de0bf211ccc91 100644 (file)
@@ -42,8 +42,8 @@
 #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 "glog/logging.h"          // To pick up flag settings etc.
+#include "glog/raw_logging.h"
 #include "base/commandlineflags.h"
 
 #ifdef HAVE_STACKTRACE
index e95e9e97274dd3c3f0f8071857fa079ac7034ba9..cccd800d7696ea113ae320c6fed8415d12c24b8f 100644 (file)
@@ -34,7 +34,7 @@
 #include "utilities.h"
 #include "stacktrace.h"
 #include "symbolize.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 #include <signal.h>
 #include <time.h>
@@ -48,6 +48,9 @@
 
 _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
@@ -330,7 +333,10 @@ void FailureSignalHandler(int 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));
@@ -341,10 +347,13 @@ void InstallFailureSignalHandler() {
   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_
index 46002c1b01973b879f8795c60747b2e169e492e5..0dc14c6506e954754b04beb563eb069511bf347a 100644 (file)
@@ -37,7 +37,7 @@ extern "C" {
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 }
-#include <glog/raw_logging.h>
+#include "glog/raw_logging.h"
 #include "stacktrace.h"
 
 _START_GOOGLE_NAMESPACE_
index d1831e4ea79722a6a0bdc2f8ee69e580924c3e38..18bbccf307213d5257c51205e08ff37095608259 100644 (file)
@@ -111,7 +111,7 @@ _END_GOOGLE_NAMESPACE_
 
 #include "symbolize.h"
 #include "config.h"
-#include <glog/raw_logging.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)
@@ -232,7 +232,7 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
     }
     char header_name[kMaxSectionNameLen];
     if (sizeof(header_name) < name_len) {
-      RAW_LOG(WARNING, "Section name '%s' is too long (%"PRIuS"); "
+      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;
index 04e482bc315c03da546088c11685f9038e123169..1ebe4dd94a2540d5658de31345e340d86910e917 100644 (file)
@@ -56,7 +56,7 @@
 
 #include "utilities.h"
 #include "config.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 #ifdef HAVE_SYMBOLIZE
 
index 159b094c170fc64d3ab74b19de22ceca8f509e90..1e8836d243fa88c75d98f7f640c9f985a34d79d2 100644 (file)
@@ -136,6 +136,8 @@ static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) {
 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;
@@ -143,6 +145,7 @@ static void DumpStackTraceAndExit() {
   sigemptyset(&sig_action.sa_mask);
   sig_action.sa_handler = SIG_DFL;
   sigaction(SIGABRT, &sig_action, NULL);
+#endif  // HAVE_SIGACTION
 
   abort();
 }
@@ -233,7 +236,7 @@ bool PidHasChanged() {
 }
 
 pid_t GetTID() {
-  // On Linux and MACOSX , we try to use gettid().
+  // On Linux and MacOSX, we try to use gettid().
 #if defined OS_LINUX || defined OS_MACOSX
 #ifndef __NR_gettid
 #ifdef OS_MACOSX
@@ -331,6 +334,7 @@ void InitGoogleLoggingUtilities(const char* argv0) {
 void ShutdownGoogleLoggingUtilities() {
   CHECK(IsGoogleLoggingInitialized())
       << "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
+  g_program_invocation_short_name = NULL;
 #ifdef HAVE_SYSLOG_H
   closelog();
 #endif
index c8215b73f3301045566c66863c4e4062032e3bf5..4f41c92e434393895574663db946a7eaadf140e9 100644 (file)
@@ -79,7 +79,7 @@
 #endif
 
 #include "config.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 // There are three different ways we can try to get the stack trace:
 //
 #elif !defined(NO_FRAME_POINTER)
 # if defined(__i386__) && __GNUC__ >= 2
 #  define STACKTRACE_H "stacktrace_x86-inl.h"
-# elif defined(__x86_64__) && __GNUC__ >= 2
+# 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"
index 4396aa8d0664305cf76d6cd91f7df1fb9845be9e..cd7fc19bca89aa8e11c22b70a11fdcb794b7d405 100644 (file)
@@ -40,8 +40,8 @@
 #include <cstdio>
 #include <string>
 #include "base/commandlineflags.h"
-#include <glog/logging.h>
-#include <glog/raw_logging.h>
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
 #include "base/googleinit.h"
 
 // glog doesn't have annotation
@@ -62,11 +62,7 @@ _START_GOOGLE_NAMESPACE_
 
 namespace glog_internal_namespace_ {
 
-// Put protytype here to suppress strict compiler flags
-GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
-                                       size_t patt_len,
-                                       const char* str,
-                                       size_t str_len);
+namespace {
 
 // Implementation of fnmatch that does not need 0-termination
 // of arguments and does not allocate any memory,
@@ -101,6 +97,8 @@ GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
   }
 }
 
+}  // namespace
+
 }  // namespace glog_internal_namespace_
 
 using glog_internal_namespace_::SafeFNMatch_;
index 682a1b9309d79b076744d759916dd201777e3a5b..9fb3cc564d52a72e1d9a7d4b4e756e05c5438a0a 100644 (file)
 /* src/config.h.in.  Generated from configure.ac by autoheader.  */
 
-/* Namespace for Google classes */
-#define GOOGLE_NAMESPACE google
-
-/* Define if you have the `dladdr' function */
-#undef HAVE_DLADDR
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <libunwind.h> header file. */
-#undef HAVE_LIBUNWIND_H
-
 /* define if you have google gflags library */
 #define HAVE_LIB_GFLAGS 1
 
-/* define if you have libunwind */
-#undef HAVE_LIB_UNWIND
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* define if the compiler implements namespaces */
-#undef HAVE_NAMESPACES
-
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
-/* define if the compiler implements pthread_rwlock_* */
-#undef HAVE_RWLOCK
-
-/* Define if you have the `sigaltstack' function */
-#undef HAVE_SIGALTSTACK
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <syscall.h> header file. */
-#undef HAVE_SYSCALL_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#undef HAVE_SYS_SYSCALL_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-#undef HAVE_UCONTEXT_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* define if the compiler supports using expression for operator */
-#undef HAVE_USING_OPERATOR
-
-/* define if your compiler has __attribute__ */
-#undef HAVE___ATTRIBUTE__
-
-/* define if your compiler has __builtin_expect */
-#undef HAVE___BUILTIN_EXPECT
-
-/* define if your compiler has __sync_val_compare_and_swap */
-#undef HAVE___SYNC_VAL_COMPARE_AND_SWAP
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* How to access the PC from a struct ucontext */
-#undef PC_FROM_UCONTEXT
-
-/* Define to necessary symbol if this constant uses a non-standard name on
-   your system. */
-#undef PTHREAD_CREATE_JOINABLE
-
-/* The size of `void *', as computed by sizeof. */
-#undef SIZEOF_VOID_P
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* the namespace where STL code like vector<> is defined */
-#undef STL_NAMESPACE
-
-/* Version number of package */
-#undef VERSION
+/* Namespace for Google classes */
+#define GOOGLE_NAMESPACE google
 
 /* Stops putting the code inside the Google namespace */
 #define _END_GOOGLE_NAMESPACE_ }
index f623cd9e7938891caf6b1c52d7de636d70ee9563..6e9c9224f928c4f884261473514e08dd11d84df6 100644 (file)
 #include <errno.h>
 #include <string.h>
 #include <time.h>
+#include <iosfwd>
+#include <ostream>
+#include <sstream>
 #include <string>
 #if 0
 # include <unistd.h>
 #endif
-#ifdef __DEPRECATED
-// Make GCC quiet.
-# undef __DEPRECATED
-# include <strstream>
-# define __DEPRECATED
-#else
-# include <strstream>
-#endif
 #include <vector>
 
 // Annoying stuff for windows -- makes sure clients can import these functions
 #   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.
@@ -83,7 +86,7 @@
 #endif
 
 #if 1
-#include "third_party/gflags/gflags/gflags.h"
+#include <gflags/gflags.h>
 #endif
 
 #ifdef __MINGW32__
 
 namespace google {
 
-#if 0      // the C99 format
+#if defined(__MINGW32__)      // the C99 format
 typedef int32_t int32;
 typedef uint32_t uint32;
 typedef int64_t int64;
@@ -107,16 +110,11 @@ typedef int32_t int32;
 typedef u_int32_t uint32;
 typedef int64_t int64;
 typedef u_int64_t uint64;
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER)    // the windows (vc7) format
 typedef __int32 int32;
 typedef unsigned __int32 uint32;
 typedef __int64 int64;
 typedef unsigned __int64 uint64;
-#elif defined(__MINGW32__)
-typedef int32_t int32;
-typedef uint32_t uint32;
-typedef int64_t int64;
-typedef uint64_t uint64;
 #else
 #error Do not know how to define a 32-bit integer quantity on your system
 #endif
@@ -144,8 +142,12 @@ typedef uint64_t uint64;
 #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
 
@@ -304,27 +306,27 @@ typedef uint64_t uint64;
 
 #ifndef DECLARE_VARIABLE
 #define MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#define DECLARE_VARIABLE(type, name, tn)                                      \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name;                              \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name
+#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, name, bool)
+  DECLARE_VARIABLE(bool, B, name, bool)
 
 // int32 specialization
 #define DECLARE_int32(name) \
-  DECLARE_VARIABLE(google::int32, name, int32)
+  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 FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead {  \
-  extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name;                       \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name
+#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
@@ -333,6 +335,9 @@ 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);
@@ -465,15 +470,16 @@ DECLARE_bool(stop_logging_if_full_disk);
 #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(result)) { \
-    LPTSTR message = NULL; \
-    LPTSTR msg = reinterpret_cast<LPTSTR>(&message); \
-    DWORD message_length = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
+  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() << message; \
+          &google::LogMessage::SendToLog).stream() \
+          << reinterpret_cast<const char*>(message); \
       LocalFree(message); \
     } \
   }
@@ -615,18 +621,68 @@ inline std::ostream& operator<<(
 
 namespace google {
 
-// Build the error message string.
-template<class t1, class t2>
-std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
-  // It means that we cannot use stl_logging if compiler doesn't
-  // support using expression for operator.
-  // TODO(hamaji): Figure out a way to fix.
-#if 1
-  using ::operator<<;
-#endif
-  std::strstream ss;
-  ss << names << " (" << v1 << " vs. " << v2 << ")";
-  return new std::string(ss.str(), ss.pcount());
+// 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.
@@ -634,26 +690,26 @@ std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
 // 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 <class t1, class t2> \
-  inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
-                                        const char* names) { \
-    if (v1 op v2) return NULL; \
-    else return MakeCheckOpString(v1, v2, names); \
+  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* Check##name##Impl(int v1, int v2, const char* names) { \
-    return Check##name##Impl<int, int>(v1, v2, names); \
+  inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
+    return name##Impl<int, int>(v1, v2, exprtext); \
   }
 
-// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h
-// provides its own #defines for the simpler names EQ, NE, LE, etc.
+// 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(_EQ, ==)
-DEFINE_CHECK_OP_IMPL(_NE, !=)
-DEFINE_CHECK_OP_IMPL(_LE, <=)
-DEFINE_CHECK_OP_IMPL(_LT, < )
-DEFINE_CHECK_OP_IMPL(_GE, >=)
-DEFINE_CHECK_OP_IMPL(_GT, > )
+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.
@@ -958,52 +1014,65 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
 #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) \
-    CHECK(condition)
+    GLOG_MSVC_POP_WARNING() CHECK(condition)
 
 #define DCHECK_EQ(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_EQ(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
 
 #define DCHECK_NE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_NE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
 
 #define DCHECK_LE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_LE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
 
 #define DCHECK_LT(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_LT(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
 
 #define DCHECK_GE(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_GE(val1, val2)
+    GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
 
 #define DCHECK_GT(val1, val2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_GT(val1, val2)
+    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) \
-    CHECK_STREQ(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
 
 #define DCHECK_STRCASEEQ(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRCASEEQ(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
 
 #define DCHECK_STRNE(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRNE(str1, str2)
+    GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
 
 #define DCHECK_STRCASENE(str1, str2) \
+  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
   while (false) \
-    CHECK_STRCASENE(str1, str2)
-
+    GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
 
 #endif  // NDEBUG
 
@@ -1020,6 +1089,29 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
 #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.
@@ -1049,22 +1141,30 @@ public:
 #ifdef _MSC_VER
 # pragma warning(disable: 4275)
 #endif
-  class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream {
+  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_in)
-      : ostrstream(buf, len),
-        ctr_(ctr_in) {
-      self_ = this;
+    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_in) { ctr_ = ctr_in; }
+    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
   };
@@ -1133,13 +1233,15 @@ public:
   // Call abort() or similar to perform LOG(FATAL) crash.
   static void Fail() ;
 
-  std::ostream& stream() { return *(data_->stream_); }
+  std::ostream& stream();
 
-  int preserved_errno() const { return data_->preserved_errno_; }
+  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
@@ -1161,41 +1263,6 @@ private:
 
   // We keep the data in a separate struct so that each instance of
   // LogMessage uses less stack space.
-  struct GOOGLE_GLOG_DLL_DECL LogMessageData {
-    LogMessageData() {};
-
-    int preserved_errno_;      // preserved errno
-    char* buf_;
-    char* message_text_;  // Complete message text (points to selected buffer)
-    LogStream* stream_alloc_;
-    LogStream* stream_;
-    char severity_;      // What level is this LogMessage logged at?
-    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
-
-    ~LogMessageData();
-   private:
-    LogMessageData(const LogMessageData&);
-    void operator=(const LogMessageData&);
-  };
-
-  static LogMessageData fatal_msg_data_exclusive_;
-  static LogMessageData fatal_msg_data_shared_;
-
   LogMessageData* allocated_;
   LogMessageData* data_;
 
@@ -1474,8 +1541,12 @@ extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
 // 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 {
index 58e28b026c0d482072346808f587a595dfab120e..c16111a4b6dfb2b26904c53b0ac87456cd15a153 100644 (file)
@@ -55,7 +55,6 @@ int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
   return _vsnprintf(str, size-1, format, ap);
 }
 
-// MinGW64 defines
 #ifndef __MINGW64__
 int snprintf(char *str, size_t size, const char *format, ...) {
   va_list ap;
index e3e76ec29e0f0191040d5c9f7f82aed2f1f0572c..4879cbf5f92ce6b7fa7a9dc4b70cb7941888e062 100644 (file)
 
 #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 */
@@ -59,6 +62,8 @@
  * 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
@@ -111,9 +116,7 @@ extern int snprintf(char *str, size_t size,
 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)
-#if !defined(__MINGW32__)
 #define va_copy(dst, src)  (dst) = (src)
-#endif
 
 /* Windows doesn't support specifying the number of buckets as a
  * hash_map constructor arg, so we leave this blank.
@@ -123,11 +126,14 @@ extern int safe_vsnprintf(char *str, size_t size,
 #define DEFAULT_TEMPLATE_ROOTDIR  ".."
 
 // ----------------------------------- SYSTEM/PROCESS
-#ifndef __MINGW64__
 typedef int pid_t;
-#endif
 #define getpid  _getpid
 
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+
+#endif  // _MSC_VER
+
 // ----------------------------------- THREADS
 typedef DWORD pthread_t;
 typedef DWORD pthread_key_t;