Squashed 'third_party/google-glog/' changes from 5d46e1bcf..a1b6164ef
a1b6164ef windows: call to FormatMessage() should _IGNORE_INSERTS (#849)
278ed9689 simplify DLOG macro definition in NDEBUG mode (#830)
6ed0c9e58 added emscripten support (#846)
a34226ca9 support ndk r25 (#844)
c515e1ae2 remove unused STDC_HEADERS definition (#835)
79d692c64 Strip only the first leading @
086ce224d bazel: Use glog 0.6.0 in README.
b33e3bad4 Merge pull request #812 from google/release-0.6
54b8bcbbf release 0.6
864ef6492 Merge pull request #801 from skeptic-monkey/master
c640c2f7c Fix namespace resolution issue in LOG_EVERY_T
5addeedc0 Fix "'GLOG_EXPORT' macro redefined" on clang-cl
d153e294b Avoid "GLOG_EXPORT macro redefined" in clang-cl CI
c4ca519a8 Add CI job for clang-cl on Windows
a8e0007e9 Merge pull request #790 from git-hulk/feature/logs-to-stdout
553ddaea8 Merge pull request #794 from Arfrever/tests-TMPDIR
6d3f70a40 Pass EXIT_SUCCESS or EXIT_FAILURE to exit() and _exit()
612a7d28c Tests: Respect TEST_TMPDIR, TMPDIR, TMP environmental variables
180b700dd Add logtostdout and colorlogtostdout flags for logging to stdout
b38ed9d08 cmake_package_config_generate: Fix CMake warnings with CMake 3.23
9f0b7d3bf renamed GOOGLE_GLOG_DLL_DECL to GLOG_EXPORT
aa94e6b9a simplify flags export
17269d649 cmake: enable custom prefix by default
bc1fada1c libglog.pc: Set Libs.private for static linking
18836106d LogCleaner: avoid scanning logs too frequently
b0174b3dd On Solaris, uname() returns non-negative value
696941218 Changed my Email ID
643441014 cmake: require at least gflags 2.2.2
a8cfbe0c0 stdcxx: eliminate excessive use of std::string::c_str()
b3abfaa12 use uint32 for --max-log-size
43fc3bf91 Add log_year_in_prefix flag
42d509b1c revert to int atomics
224f66bb6 cmake: do not search for platform specific unwind
4ffa98388 ensure _Unwind_Backtrace to actually be available
087ad5bf3 eliminated clang warnings
9dc1107f8 run clang-tidy
dfb9ffc32 provide backward compatible send overload
c57511605 ci: removed deprecated msvc runner
d09b999f3 LogCleaner: make overdue_days_ unsigned int
baa7006e6 ci: enable warnings as errors
660352f02 cmake: require at least version 3.16 (fixes #705)
52354b2ad eliminate msvc warnings
ccbda2dfd LogCleaner: Fix relative paths and add a new test
ef36f800e Added an API to get GMT offset from LogMessageTime * Added API to get GMT offset * Made LogMessageTime as a memeber of LogMessage * Refactored LogSink::send() method
ee6faf13b ci: use codecov token
6e9b2f16f cmake: set CMP0074 policy
f4dd77ae6 ci: reworked windows builds
503e3dec8 Add Zhuoran Shen to AUTHORS and CONTRIBUTORS
531659984 Fix log filename format
cd8fbd5fb ci: prefix artifact directories
c8a7f5abe ci: added checkout action
f47582361 ci: install lcov
f773eb9b6 ci: unzip artifacts into separate directories
f42fd3b15 ci: fixed unzipping multiple archives
cb7c19d36 ci: removed non standard --zero option
cf4c4699b ci: unzip artifacts individually
5a3bd74cf ci: replaced forEach by a loop
1da31df93 ci: name unpack step and fix indent
6bd5acfb6 ci: download workflow artifacts
8121c0755 ci: aggregate coverage in separate workflow
8b872216e ci: simplify coveralls job id
11f08e7bb Merge pull request #742 from google/protect-vlog
65199ed0b protect VLOG by use_logging
b79e18b78 ci: updated coveralls job id
4399e5664 ci: explicitly identify coveralls builds
9206460cd Merge pull request #739 from google/cmake-glog-modules-install
64b4e327f cmake: fixed glog-modules.cmake installation
4df5ae746 ci: added cmake package config test
ab5e10929 Revert "cmake: fix incorrect relative path concatenation (#733)"
32522a5f6 ci: notify coveralls on finished parallel builds
d581807e3 ci: run coveralls on completed workflow
6c9f5b2ec ci: added jobs to coveralls workflow
0798a37bb ci: added coveralls workflow
33696664c restore the stream format after writing the log prefix (#731)
68964b8db cmake: fix incorrect relative path concatenation (#733)
17e7679fd Merge pull request #654 from aesophor/fix-path
c27c3a803 make LogCleaner support relative paths
e8e40f76d Merge pull request #732 from google/log-cleaner-tests
3362cc6c7 added log cleaner tests and fixed paths
9cf0eb7c9 Merge pull request #724 from google/mock-log
1398762db added mock log test
ce3533613 Merge pull request #723 from google/coverage-use-templates
06e665108 ci: replace generated headers by templates
56d3facee Merge pull request #722 from google/linux-github-action
4a55b1158 ci: added linux github workflow
396558472 support stack unwind on Android
acda90348 Merge pull request #720 from google/gmock-support
8474b7854 added gmock support
831a6f823 Add -Werror to Bazel presubmits
c34dbe987 Fix `syscall` warning in Bazel Build
56523194b Merge pull request #716 from google/export-os-defines
f7407d4d2 export OS_* defines (fixes #715)
2412db315 `raw_logging.h` depends on type definition in `logging.h`. Resolve https://github.com/google/glog/issues/712
3b6b05d70 Use __EMSCRIPTEN__ instead of __USE_POSIX2
de81bb0aa Fix link error for Emscripten
9733727be Merge pull request #706 from dfreese/tsan_annotation
ffb40018a Change size type in AnnotateBenignRaceSized to size_t from long
6f9e32a79 Merge pull request #700 from Starsss/master
df95749e8 Fix: not implement virtual class when WITH_CUSTOM_PREFIX on
35983c895 Merge pull request #696 from Fettpet/signed_compare
9fce37c46 Add a static cast to compare unsigned with unsigned
a063a04ec Merge pull request #694 from google/more-warnings
92cb3c449 fixed additional warnings
f8c8e99fd Merge pull request #688 from google/eliminate-warnings
98e0e8c65 cmake: bump .so version
0b83bb203 eliminate warnings
370cb741b Merge pull request #674 from StephLin/readme-fix-header-id
3ce6090d0 override header language
36bcd28c6 Merge pull request #687 from google/exception-spec
dfe573088 bump version
717f56983 fixed exception specification mismatch
eca3ddef8 Merge pull request #685 from z-aki/master
4a4331f2f Fix syscall deprecation warning on macOS >= 10.12
a01d739ea Merge pull request #684 from sergiud/cmake-namespaced-gflags
8d3ce1c29 Merge pull request #686 from google/ci-more-targets
c39fcf6e8 ci: added more targets
47ad26d5c readme: fixed inconsistent formatting
5bf7fdea1 cmake: prefer linking against gflags::gflags (fixes #683)
42ce901f2 Merge pull request #669 from darbitman/log-every-time-period
a1374c420 Implement LOG_EVERY_T. Use <chrono> and <atomic> for C++11 or greater. For non-Windows pre-C++11 systems, use <time.h> and built-in atomic operations. For Windows pre-C++11, use the Windows implementations for time and atomic operations.
6e46c125e bazel: add GLOG_CUSTOM_PREFIX_SUPPORT
a41555685 Remove ubuntu1604 from presubmit.yml
a1fa841f3 readme: fix wrong header id
a4a725d54 Merge pull request #671 from sergiud/cmake-define-have-cxx11-atomic
44331dc24 Merge pull request #672 from sergiud/cmake-allow-to-override-fpic
f0bac8852 cmake: allow to override `-fPIC`
764162569 Merge pull request #670 from sergiud/cmake-msvc-snprintf
d25a1b7bc cmake: export `<atomic>` availability (fixes #667)
9c1a25b93 cmake: fixed msvc snprintf detection (fixes #668)
c1499f64a Export COPYING
03f2b3861 Merge pull request #650 from romange/Prod
86fea1ab2 Allow updating vmodule levels after vmodule was parsed, invalidate already cached site flags vmodule flag is relevant for GNUC environments only.
fef48c17e Merge pull request #656 from romange/cygwin
d2fed749a Fix cmake configuration for cygwin environment
0b3d4cb47 Merge pull request #651 from xkszltl/initapi
81e0d616e Expose `IsGoogleLoggingInitialized()` in public API. Usually library does not have control of the process lifespan. Without this function, it is impossible to init/shutdown reliably. It has been one of the major pain points for years when using glog in libraries.
d5c04eec9 bazel: Use glog 0.5.0 in README
8f9ccfe77 Merge pull request #646 from sergiud/release-0.5
36fee386f release 0.5
8d40d7564 Merge pull request #642 from husskade/patch-1
a23e96f04 readme: update CMake source directory option
0efaa59a7 Merge pull request #641 from sergiud/nullptr
230da316c Merge pull request #637 from xiaobfly/master
bda40ec00 Merge pull request #640 from sergiud/gflags-windows-linker-warnings
762a2a7ee eliminated gflags related linker warnings (#569)
7d4eeb14f Merge pull request #554 from santigl/santigl/custom-prefixer
0cbc23529 Add support for setting a custom prefix format
c7656c3ec CHECK support for nullptr (fixes #341)
663bb2696 Merge pull request #620 from sergiud/cmake-allow-to-disable-symbolize
7ec73b509 Merge pull request #639 from sergiud/fix-windows-builds
efc341d76 fixed windows builds
a79416bab Merge pull request #638 from NeroBurner/github_actions
63ec71b58 Add windows builds with GitHub Actions
39e83581d cmake: allow to disable symbolize
635a07818 fix LogCleaner::IsLogFromCurrentProject for filename_extension
e51790bf3 Merge pull request #625 from sergiud/remove-windows-headers
36e6ed910 Merge pull request #635 from google/win-headers
7d60d6e04 removed windows specific headers
1041a221b Use generated config.h for Windows.
82320a8a8 Merge pull request #631 from xiaobfly/master
bf183f44f Merge pull request #632 from sergiud/cmake-default-shared-libs
9ee010d85 cmake: build shared libs by default
4fca1b967 fixed filename extension
30bb9086d bazel: use expand_template instead of genrules
d66e59318 Merge pull request #618 from sergiud/ac_cv___attribute___printf_4_5
d5fdcfefc Merge pull request #623 from sergiud/language-version
7f8a48b3b Merge pull request #595 from r-barnes/richard/ctr_type_fix
5abed00e3 Merge pull request #626 from sergiud/use-c++-headers
bf3e5a80a Change counter type to uint64
01f3e543e use C++ headers
2f7d608a9 Merge pull request #627 from sergiud/cmake-no-c-compiler
3f4df6aee cmake: do not require a C compiler
7a6e743eb Merge pull request #624 from sergiud/qualify-std-string
e27f14119 Merge pull request #622 from sergiud/max_log_size-overflow
0b3c27d04 fully qualify std::string
5c57edfbc readme: document C++ version
20984f973 Merge pull request #621 from sergiud/cmake-use-gtest
3533c22d2 handle --max_log_size overflow
be25d94c2 cmake: optionally use gtest
45fdc922d Merge pull request #619 from sergiud/cmake-proper-symbol-export
c30896d3d cmake: export symbols selectively
b442ef807 build: set ac_cv___attribute___printf_4_5
d4e8ebab7 Add layering_check to Bazel CI.
0863ad797 bazel: declare headers in top-level rule
ce50c57b9 Rename BUILD to BUILD.bazel.
d824eae3c Merge pull request #613 from sergiud/cmake-unwind-patch-match
df3ce126d cmake: fixed unwind patch component match check
246e49ac4 Merge pull request #610 from sergiud/readme-cleanup
9881ea596 Fix race conditions in LOG_EVERY_N (#492)
4cef72332 Merge pull request #611 from sergiud/incorrect-cygwin64-define
544b4a4f5 Merge pull request #609 from sergiud/cmake-unwind-empty-patch-component
b9be6bb5d consolidate readme
6d14ac3ef Fix the symlink creation bug if using bazel
795384957 replaced __CYGWIN32__ and __CYGWIN64__ by __CYGWIN__
e370cd516 bump version
3b21da69e cmake: handle empty unwind version patch component
4fa737b62 Merge pull request #400 from guoyuhong/fixWebmailer
4f09bed0b Merge pull request #263 from kennyyu/tsan_benign_race
7bba6030c Merge pull request #592 from aesophor/fix-logcleaner-file-ext
7a8b66aa1 Merge pull request #593 from aesophor/fix-typo
6d5da2154 Merge pull request #608 from mahiuchun/stl
15d51a17c Make stl_logging_unittest more robust.
fe1287dd5 src/logging.cc: Fix a typo in comment
431d74c80 src/logging.cc: Make LogCleaner aware of filename extension (#589)
c8f8135a5 Merge pull request #502 from aesophor/encapsulate-log-cleaner
d82641f70 Merge branch 'master' into encapsulate-log-cleaner
cec37e1cf Merge pull request #542 from xulongwu4/master
b55437ac1 Fix logmailer problem for dynamic lib.
c5dcae830 Merge pull request #467 from sukill/master
b30a009fa Merge pull request #585 from sergiud/remove-drop-autoconf-support
b539557b3 removed autoconf support
d516278b1 Merge pull request #540 from pwnall/fix-uv-warn
6c0a5fcb5 Fix unused parameter warning on gcc.
f28ae960c Merge pull request #573 from msamoila/msamoila-use-utc-time
fa0d50f9f Merge pull request #570 from jiuqiant/patch-1
fcc9da24a Merge pull request #545 from julianaito/master
40ab82281 Merge pull request #438 from d-uspenskiy/master
4c5a60c3c Merge pull request #551 from aesophor/replace-sprintf
8ee2bb5b3 Merge pull request #553 from huangqinjin/android
024b095d7 Merge pull request #552 from huangqinjin/master
d44246069 Merge pull request #579 from arj-fb/safety_check_at_SymbolizeAndDemangle
5bc1e1177 Merge pull request #580 from Yicong-Huang/patch-1
af4df08e5 Merge pull request #576 from santigl/santigl/streambuf-overflow-override
725818984 Add `override` to `LogStreamBuf::overflow()`
c652590d8 Update CMakeLists.txt
e5ef2728b Added check for if info.dli_sname is NULL
909069ea8 Add FLAGS_log_utc_time; when 'true' the time will be written in log in UTC
64650ef2e Connect glog to Andorid logging API
0a2e5931b Fix build for Emscripten (#546)
0a12a96ce Output to logcat on Android
d8998fe4f Make message text null-terminated
2e87f98fe Replace sprintf() with snprintf() (#536)
7001ab9ec OpenBSD/powerpc: clang does not define _CALL_* use proper ifdef
4a82a856d Use NULL to indicate uninitialized VLOG_IS_ON site.
3ba897659 fix bazel build for freebsd
ceb716388 Add extra information in log file header (application build/version, actual duration time)
28321d895 Merge pull request #503 from alexsmac/fix-custom-logger-deletion
5b4fb63d2 Prepend the year to each glog line (#516) (#530)
7da49d48a Merge pull request #515 from segfaulthunter/doc
940335d82 Add vcpkg installation instructions (#517)
dfc0e441c Merge pull request #523 from edbaunton/cmake-have-symbolize
eb13e4f67 Allow CMake user to disable Symbolize functionality
195d416e3 Add target existence checks to Unwind find module (#518)
74076bebc Explain log levels.
130a3e10d Use file offsets in traces if object has no symbols (#513)
445af7ef7 Merge pull request #508 from xiaosuo/close
a35e612c5 Don't call close(2) more than once
36fa99ba2 src/logging.cc: check the entire filename format
0a6704b43 Fix missing deletion of custom Logger
7764e4a8b src/logging.cc: match logfile with base_filename
3b5f2807f src/logging.cc: encapsulate log cleaner
1b7d54143 Add note about `namespace` on Win32.
95a365579 Remove unnecessary `defines`
c0d2ceade Avoid leaking config.h
925858d99 add windows target to bazel CI
20919b325 add windows support for bazel bazed build
7f732529d apply buildifier on glog.bzl
1863b4228 Merge pull request #368 from UVV-gh/cmake-sdk-fix
c0463b17b added cmake package config unit test
9a43cfb8d install unwind find module alongside glog
19570c69c renamed and cleaned up the unwind find module
58d7f873d Added fixed log name support, take 2 (#489)
0bf00f95a Merge pull request #491 from aesophor/update-doc
0f4975a68 doc: add information about log cleaner
5ef521d4a Merge pull request #487 from Telunsu/fix_wrong_assignment
e58e596f1 src/logging.cc: fix wrong assignment
f811ae9ed Merge pull request #485 from ffontaine/master
3ee89c86d src/symbolize.cc: do not check for HAVE_DLFCN_H for macOS
4d6aff418 Merge pull request #477 from ffontaine/master
742fe94f2 Use libunwind as an imported target
9630e0e84 src/utilities: fix build without pthread
fd3dc2c63 Merge pull request #484 from sergiud/remove-executable-flag
eec1435d5 removed executable flag from .cmake file
e227697b0 Merge pull request #483 from loop0day/enhance
82d0860b7 Support pkg-config
e0a2521e3 Merge pull request #482 from google/revert-19-master
a6f7be14c Add support for automatic removal of old logs (#432)
15fb5ca5b Revert "Added fixed log name support"
5792d60d6 Merge pull request #441 from asekretenko/useconds
44f6079fa Merge pull request #19 from ezegomez/master
242130d30 Merge pull request #350 from TheModMaker/fixIosSim
1a4c47a74 Merge pull request #88 from kekstee/master
f17d11aa8 Merge pull request #161 from mpercy/thread-local-libunwind-2
1227cf4da Merge pull request #312 from ruslo/pr.api21
0f83e53c4 Merge pull request #443 from ammubhave/fix_musl_build
e558d50b0 Merge pull request #370 from hemantbits/patch-1
30f7f3ee9 Merge pull request #479 from neheb/patch-2
6f5699a23 Merge pull request #460 from neheb/patch-1
e24276a35 logging: Fix compilation with uClibc++
1d762fa5b googletest: Switch to nanosleep
1655f4f91 Merge pull request #475 from ffontaine/master
10498b485 src/symbolize.cc: fix build without dlfcn.h
1e6b9f329 declare FLAGS_vmodule
4cc89c9e2 Merge pull request #465 from durswd/support_clang-cl
a8fad525e Changed the order of conditions
00cb9f4e6 I supported clang-cl with BUILD_SHARED_LIBS
ba8a9f695 fix typo: TOOD -> TODO (#448)
0d0c25431 Don't test on Ubuntu 14.04 (#446)
6ca3d3cf5 Fix stacktrace on bazel build. (#347)
834dd780b Fix symbolize_unittest for musl builds
94a54120d Extended the LogSink interface to be able to pass microseconds.
96a2f23dc Merge pull request #419 from shinh/release-0-4-0
5c576f78c Merge pull request #431 from romkatv/disallow_prefix
29dd5da60 Add Roman Perepelitsa to AUTHORS and CONTRIBUTORS
4db063134 Protect macros from user code to the left of them
460ec1f56 Merge branch 'master' into release-0-4-0
41f4bf9cb Merge pull request #425 from plmuon/remove-time-from-raw-logging
64041397b Use `static` to define CheckStackTrace on non-GNU (#429)
7f91846ca Stop using auto_ptr (#428)
e5588de96 remove time from raw logging
7ffca211f fix appveyor link (#424)
ed1ef7c4d Apply #397 to glog/logging.h.in
1431a17f3 Merge pull request #420 from kwaegel/patch-1
1d98d00c7 Update ChangeLog to record release dates at least
342fa2674 Use push/pop macro when supressing warning
406b0e702 glog: release 0.4.0
6d6d31872 Run src/windows/preprocess.sh
41a6a7880 Fix warnings
a606c3187 Allow getpwuid_r to return missing entry.
d064ab8d0 Fix build for Android API < 21
4764ca65f Annotate LOG_EVERY_N macros as a benign race for TSAN
f581614a7 Use thread local for libunwind GetStackTrace()
47af307fa Added fixed log name support
d68736bc1 Respect configured docdir
git-subtree-dir: third_party/google-glog
git-subtree-split: a1b6164ef15cf4be3b1914f2df7125fc7ffc7ca8
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
Change-Id: I2286351db32cb46aa8743a28e191dfc9c62783da
diff --git a/src/base/commandlineflags.h b/src/base/commandlineflags.h
index c8d5089..bcb12de 100644
--- a/src/base/commandlineflags.h
+++ b/src/base/commandlineflags.h
@@ -1,10 +1,10 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
-//
+//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -49,9 +49,9 @@
#define BASE_COMMANDLINEFLAGS_H__
#include "config.h"
+#include <cstdlib> // for getenv
+#include <cstring> // for memchr
#include <string>
-#include <string.h> // for memchr
-#include <stdlib.h> // for getenv
#ifdef HAVE_LIB_GFLAGS
@@ -59,18 +59,18 @@
#else
-#include "glog/logging.h"
+#include <glog/logging.h>
-#define DECLARE_VARIABLE(type, shorttype, name, tn) \
- namespace fL##shorttype { \
- extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
- } \
+#define DECLARE_VARIABLE(type, shorttype, name, tn) \
+ namespace fL##shorttype { \
+ extern GLOG_EXPORT 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; \
- } \
+#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
+ namespace fL##shorttype { \
+ GLOG_EXPORT type FLAGS_##name(value); \
+ char FLAGS_no##name; \
+ } \
using fL##shorttype::FLAGS_##name
// bool specialization
@@ -85,19 +85,27 @@
#define DEFINE_int32(name, value, meaning) \
DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, value, meaning, int32)
+// uint32 specialization
+#ifndef DECLARE_uint32
+#define DECLARE_uint32(name) \
+ DECLARE_VARIABLE(GOOGLE_NAMESPACE::uint32, U, name, uint32)
+#endif // DECLARE_uint64
+#define DEFINE_uint32(name, value, meaning) \
+ DEFINE_VARIABLE(GOOGLE_NAMESPACE::uint32, U, name, value, meaning, uint32)
+
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
-#define DECLARE_string(name) \
- namespace fLS { \
- extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
- } \
+#define DECLARE_string(name) \
+ namespace fLS { \
+ extern GLOG_EXPORT 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; \
- } \
+#define DEFINE_string(name, value, meaning) \
+ namespace fLS { \
+ std::string FLAGS_##name##_buf(value); \
+ GLOG_EXPORT std::string& FLAGS_##name = FLAGS_##name##_buf; \
+ char FLAGS_no##name; \
+ } \
using fLS::FLAGS_##name
#endif // HAVE_LIB_GFLAGS
@@ -115,6 +123,9 @@
#define GLOG_DEFINE_int32(name, value, meaning) \
DEFINE_int32(name, EnvToInt("GLOG_" #name, value), meaning)
+#define GLOG_DEFINE_uint32(name, value, meaning) \
+ DEFINE_uint32(name, EnvToUInt("GLOG_" #name, value), meaning)
+
#define GLOG_DEFINE_string(name, value, meaning) \
DEFINE_string(name, EnvToString("GLOG_" #name, value), meaning)
@@ -130,4 +141,7 @@
#define EnvToInt(envname, dflt) \
(!getenv(envname) ? (dflt) : strtol(getenv(envname), NULL, 10))
+#define EnvToUInt(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtoul(getenv(envname), NULL, 10))
+
#endif // BASE_COMMANDLINEFLAGS_H__
diff --git a/src/base/mutex.h b/src/base/mutex.h
index ced2b99..e82c597 100644
--- a/src/base/mutex.h
+++ b/src/base/mutex.h
@@ -1,10 +1,10 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
-//
+//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -26,7 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// ---
// Author: Craig Silverstein.
//
@@ -106,7 +106,7 @@
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+#elif defined(_WIN32) || defined(__CYGWIN__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
@@ -149,8 +149,8 @@
// We need to include these header files after defining _XOPEN_SOURCE
// as they may define the _XOPEN_SOURCE macro.
-#include <assert.h>
-#include <stdlib.h> // for abort()
+#include <cassert>
+#include <cstdlib> // for abort()
#define MUTEX_NAMESPACE glog_internal_namespace_
@@ -223,7 +223,7 @@
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
-#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
+#elif defined(_WIN32) || defined(__CYGWIN__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
diff --git a/src/cleanup_immediately_unittest.cc b/src/cleanup_immediately_unittest.cc
new file mode 100644
index 0000000..89d008e
--- /dev/null
+++ b/src/cleanup_immediately_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2021, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
+
+#include "base/commandlineflags.h"
+#include "googletest.h"
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
+using testing::_;
+using testing::AllOf;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::InitGoogleMock;
+using testing::StrictMock;
+using testing::StrNe;
+#endif
+
+using namespace GOOGLE_NAMESPACE;
+
+TEST(CleanImmediately, logging) {
+ google::SetLogFilenameExtension(".foobar");
+ google::EnableLogCleaner(0);
+
+ for (unsigned i = 0; i < 1000; ++i) {
+ LOG(INFO) << "cleanup test";
+ }
+
+ google::DisableLogCleaner();
+}
+
+int main(int argc, char **argv) {
+ FLAGS_colorlogtostderr = false;
+ FLAGS_timestamp_in_logfile_name = true;
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ // Make sure stderr is not buffered as stderr seems to be buffered
+ // on recent windows.
+ setbuf(stderr, NULL);
+
+ // Test some basics before InitGoogleLogging:
+ CaptureTestStderr();
+ const string early_stderr = GetCapturedTestStderr();
+
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+
+ InitGoogleLogging(argv[0]);
+
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+ InitGoogleMock(&argc, argv);
+#endif
+
+ // so that death tests run before we use threads
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+}
diff --git a/src/cleanup_with_absolute_prefix_unittest.cc b/src/cleanup_with_absolute_prefix_unittest.cc
new file mode 100644
index 0000000..d4bb47e
--- /dev/null
+++ b/src/cleanup_with_absolute_prefix_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2021, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
+
+#include "base/commandlineflags.h"
+#include "googletest.h"
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
+using testing::_;
+using testing::AllOf;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::InitGoogleMock;
+using testing::StrictMock;
+using testing::StrNe;
+#endif
+
+using namespace GOOGLE_NAMESPACE;
+
+TEST(CleanImmediatelyWithAbsolutePrefix, logging) {
+ google::EnableLogCleaner(0);
+ google::SetLogFilenameExtension(".barfoo");
+ google::SetLogDestination(GLOG_INFO, "test_cleanup_");
+
+ for (unsigned i = 0; i < 1000; ++i) {
+ LOG(INFO) << "cleanup test";
+ }
+
+ for (unsigned i = 0; i < 10; ++i) {
+ LOG(ERROR) << "cleanup test";
+ }
+
+ google::DisableLogCleaner();
+}
+
+int main(int argc, char **argv) {
+ FLAGS_colorlogtostderr = false;
+ FLAGS_timestamp_in_logfile_name = true;
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ // Make sure stderr is not buffered as stderr seems to be buffered
+ // on recent windows.
+ setbuf(stderr, NULL);
+
+ // Test some basics before InitGoogleLogging:
+ CaptureTestStderr();
+ const string early_stderr = GetCapturedTestStderr();
+
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+
+ InitGoogleLogging(argv[0]);
+
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+ InitGoogleMock(&argc, argv);
+#endif
+
+ // so that death tests run before we use threads
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+}
diff --git a/src/cleanup_with_relative_prefix_unittest.cc b/src/cleanup_with_relative_prefix_unittest.cc
new file mode 100644
index 0000000..330f465
--- /dev/null
+++ b/src/cleanup_with_relative_prefix_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2021, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
+
+#include "base/commandlineflags.h"
+#include "googletest.h"
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
+using testing::_;
+using testing::AllOf;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::InitGoogleMock;
+using testing::StrictMock;
+using testing::StrNe;
+#endif
+
+using namespace GOOGLE_NAMESPACE;
+
+TEST(CleanImmediatelyWithRelativePrefix, logging) {
+ google::EnableLogCleaner(0);
+ google::SetLogFilenameExtension(".relativefoo");
+ google::SetLogDestination(GLOG_INFO, "test_subdir/test_cleanup_");
+
+ for (unsigned i = 0; i < 1000; ++i) {
+ LOG(INFO) << "cleanup test";
+ }
+
+ google::DisableLogCleaner();
+}
+
+int main(int argc, char **argv) {
+ FLAGS_colorlogtostderr = false;
+ FLAGS_timestamp_in_logfile_name = true;
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+ // Make sure stderr is not buffered as stderr seems to be buffered
+ // on recent windows.
+ setbuf(stderr, NULL);
+
+ // Test some basics before InitGoogleLogging:
+ CaptureTestStderr();
+ const string early_stderr = GetCapturedTestStderr();
+
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+
+ InitGoogleLogging(argv[0]);
+
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+ InitGoogleMock(&argc, argv);
+#endif
+
+ // so that death tests run before we use threads
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+}
diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in
index ee8cdfe..20b5f1c 100644
--- a/src/config.h.cmake.in
+++ b/src/config.h.cmake.in
@@ -16,8 +16,11 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H
-/* Define to 1 if you have the <execinfo.h> header file. */
-#cmakedefine HAVE_EXECINFO_H
+/* Define if you have the `backtrace' function in <execinfo.h> */
+#cmakedefine HAVE_EXECINFO_BACKTRACE
+
+/* Define if you have the `backtrace_symbols' function in <execinfo.h> */
+#cmakedefine HAVE_EXECINFO_BACKTRACE_SYMBOLS
/* Define if you have the `fcntl' function */
#cmakedefine HAVE_FCNTL
@@ -31,9 +34,6 @@
/* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_LIBPTHREAD
-/* Define to 1 if you have the <libunwind.h> header file. */
-#cmakedefine HAVE_LIBUNWIND_H
-
/* define if you have google gflags library */
#cmakedefine HAVE_LIB_GFLAGS
@@ -43,6 +43,9 @@
/* define if you have google gtest library */
#cmakedefine HAVE_LIB_GTEST
+/* define if you have dbghelp library */
+#cmakedefine HAVE_DBGHELP
+
/* define if you have libunwind */
#cmakedefine HAVE_LIB_UNWIND
@@ -79,15 +82,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
-/* Define to 1 if you have the <stdlib.h> header file. */
-#cmakedefine HAVE_STDLIB_H
-
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H
-/* Define to 1 if you have the <string.h> header file. */
-#cmakedefine HAVE_STRING_H
-
/* Define to 1 if you have the <syscall.h> header file. */
#cmakedefine HAVE_SYSCALL_H
@@ -112,14 +109,20 @@
/* Define to 1 if you have the <sys/utsname.h> header file. */
#cmakedefine HAVE_SYS_UTSNAME_H
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#cmakedefine HAVE_SYS_WAIT_H
+
/* Define to 1 if you have the <ucontext.h> header file. */
#cmakedefine HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
-/* Define to 1 if you have the <unwind.h> header file. */
-#cmakedefine HAVE_UNWIND_H ${HAVE_UNWIND_H}
+/* Define if you linking to _Unwind_Backtrace is possible. */
+#cmakedefine HAVE__UNWIND_BACKTRACE
+
+/* Define if you linking to _Unwind_GetIP is possible. */
+#cmakedefine HAVE__UNWIND_GETIP
/* define if the compiler supports using expression for operator */
#cmakedefine HAVE_USING_OPERATOR
@@ -139,6 +142,9 @@
/* define if localtime_r is available in time.h */
#cmakedefine HAVE_LOCALTIME_R
+/* define if gmtime_r is available in time.h */
+#cmakedefine HAVE_GMTIME_R
+
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#cmakedefine LT_OBJDIR
@@ -167,7 +173,7 @@
/* How to access the PC from a struct ucontext */
#cmakedefine PC_FROM_UCONTEXT
-/* define if we should print raw pc values on symbolization failure. */
+/* define if we should print file offsets in traces instead of symbolizing. */
#cmakedefine PRINT_UNSYMBOLIZED_STACK_TRACES
/* Define to necessary symbol if this constant uses a non-standard name on
@@ -177,9 +183,6 @@
/* The size of `void *', as computed by sizeof. */
#cmakedefine SIZEOF_VOID_P ${SIZEOF_VOID_P}
-/* Define to 1 if you have the ANSI C header files. */
-#cmakedefine STDC_HEADERS
-
/* the namespace where STL code like vector<> is defined */
#cmakedefine STL_NAMESPACE ${STL_NAMESPACE}
@@ -192,6 +195,15 @@
/* Check whether aligned_storage and alignof present */
#cmakedefine HAVE_ALIGNED_STORAGE ${HAVE_ALIGNED_STORAGE}
+/* Check whether C++11 atomic is available */
+#cmakedefine HAVE_CXX11_ATOMIC ${HAVE_CXX11_ATOMIC}
+
+/* Check whether C++11 chrono is available */
+#cmakedefine HAVE_CXX11_CHRONO ${HAVE_CXX11_CHRONO}
+
+/* Check whether C++11 nullptr_t is available */
+#cmakedefine HAVE_CXX11_NULLPTR_T ${HAVE_CXX11_NULLPTR_T}
+
/* Version number of package */
#cmakedefine VERSION
@@ -213,4 +225,7 @@
#endif
+/* Replacement for deprecated syscall(SYS_gettid) on macOS. */
+#cmakedefine HAVE_PTHREAD_THREADID_NP ${HAVE_PTHREAD_THREADID_NP}
+
#endif // GLOG_CONFIG_H
diff --git a/src/config_for_unittests.h b/src/config_for_unittests.h
deleted file mode 100644
index 13ea8ea..0000000
--- a/src/config_for_unittests.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// All Rights Reserved.
-//
-// Author: Craig Silverstein
-// Copied from google-perftools and modified by Shinichiro Hamaji
-//
-// This file is needed for windows -- unittests are not part of the
-// glog dll, but still want to include config.h just like the
-// dll does, so they can use internal tools and APIs for testing.
-//
-// The problem is that config.h declares GOOGLE_GLOG_DLL_DECL to be
-// for exporting symbols, but the unittest needs to *import* symbols
-// (since it's not the dll).
-//
-// The solution is to have this file, which is just like config.h but
-// sets GOOGLE_GLOG_DLL_DECL to do a dllimport instead of a dllexport.
-//
-// The reason we need this extra GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
-// variable is in case people want to set GOOGLE_GLOG_DLL_DECL explicitly
-// to something other than __declspec(dllexport). In that case, they
-// may want to use something other than __declspec(dllimport) for the
-// unittest case. For that, we allow folks to define both
-// GOOGLE_GLOG_DLL_DECL and GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS explicitly.
-//
-// NOTE: This file is equivalent to config.h on non-windows systems,
-// which never defined GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS and always
-// define GOOGLE_GLOG_DLL_DECL to the empty string.
-
-#include "config.h"
-
-#undef GOOGLE_GLOG_DLL_DECL
-#ifdef GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
-# define GOOGLE_GLOG_DLL_DECL GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
-#else
-// if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
-# define GOOGLE_GLOG_DLL_DECL
-#endif
diff --git a/src/demangle.cc b/src/demangle.cc
index 9369f9a..9276c5b 100644
--- a/src/demangle.cc
+++ b/src/demangle.cc
@@ -34,18 +34,18 @@
//
// Note that we only have partial C++0x support yet.
-#include <stdio.h> // for NULL
-#include "utilities.h"
-#include "demangle.h"
+#include <cstdio> // for NULL
-#if defined(OS_WINDOWS)
+#include "demangle.h"
+#include "utilities.h"
+
+#if defined(GLOG_OS_WINDOWS)
#include <dbghelp.h>
-#pragma comment(lib, "dbghelp")
#endif
_START_GOOGLE_NAMESPACE_
-#if !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_WINDOWS)
typedef struct {
const char *abbrev;
const char *real_name;
@@ -149,15 +149,15 @@
// State needed for demangling.
typedef struct {
- const char *mangled_cur; // Cursor of mangled name.
- char *out_cur; // Cursor of output string.
- const char *out_begin; // Beginning of output string.
- const char *out_end; // End of output string.
- const char *prev_name; // For constructors/destructors.
- int prev_name_length; // For constructors/destructors.
- short nest_level; // For nested names.
- bool append; // Append flag.
- bool overflowed; // True if output gets overflowed.
+ const char *mangled_cur; // Cursor of mangled name.
+ char *out_cur; // Cursor of output string.
+ const char *out_begin; // Beginning of output string.
+ const char *out_end; // End of output string.
+ const char *prev_name; // For constructors/destructors.
+ ssize_t prev_name_length; // For constructors/destructors.
+ short nest_level; // For nested names.
+ bool append; // Append flag.
+ bool overflowed; // True if output gets overflowed.
} State;
// We don't use strlen() in libc since it's not guaranteed to be async
@@ -172,8 +172,8 @@
}
// Returns true if "str" has at least "n" characters remaining.
-static bool AtLeastNumCharsRemaining(const char *str, int n) {
- for (int i = 0; i < n; ++i) {
+static bool AtLeastNumCharsRemaining(const char *str, ssize_t n) {
+ for (ssize_t i = 0; i < n; ++i) {
if (str[i] == '\0') {
return false;
}
@@ -192,7 +192,7 @@
}
static void InitState(State *state, const char *mangled,
- char *out, int out_size) {
+ char *out, size_t out_size) {
state->mangled_cur = mangled;
state->out_cur = out;
state->out_begin = out;
@@ -269,9 +269,8 @@
// Append "str" at "out_cur". If there is an overflow, "overflowed"
// is set to true for later use. The output string is ensured to
// always terminate with '\0' as long as there is no overflow.
-static void Append(State *state, const char * const str, const int length) {
- int i;
- for (i = 0; i < length; ++i) {
+static void Append(State *state, const char * const str, ssize_t length) {
+ for (ssize_t i = 0; i < length; ++i) {
if (state->out_cur + 1 < state->out_end) { // +1 for '\0'
*state->out_cur = str[i];
++state->out_cur;
@@ -327,7 +326,7 @@
// Append "str" with some tweaks, iff "append" state is true.
// Returns true so that it can be placed in "if" conditions.
static void MaybeAppendWithLength(State *state, const char * const str,
- const int length) {
+ ssize_t length) {
if (state->append && length > 0) {
// Append a space if the output buffer ends with '<' and "str"
// starts with '<' to avoid <<<.
@@ -347,8 +346,8 @@
// A convenient wrapper arount MaybeAppendWithLength().
static bool MaybeAppend(State *state, const char * const str) {
if (state->append) {
- int length = StrLen(str);
- MaybeAppendWithLength(state, str, length);
+ size_t length = StrLen(str);
+ MaybeAppendWithLength(state, str, static_cast<ssize_t>(length));
}
return true;
}
@@ -402,9 +401,10 @@
// Returns true if the identifier of the given length pointed to by
// "mangled_cur" is anonymous namespace.
-static bool IdentifierIsAnonymousNamespace(State *state, int length) {
+static bool IdentifierIsAnonymousNamespace(State *state, ssize_t length) {
static const char anon_prefix[] = "_GLOBAL__N_";
- return (length > (int)sizeof(anon_prefix) - 1 && // Should be longer.
+ return (length > static_cast<ssize_t>(sizeof(anon_prefix)) -
+ 1 && // Should be longer.
StrPrefix(state->mangled_cur, anon_prefix));
}
@@ -422,7 +422,7 @@
static bool ParseNumber(State *state, int *number_out);
static bool ParseFloatNumber(State *state);
static bool ParseSeqId(State *state);
-static bool ParseIdentifier(State *state, int length);
+static bool ParseIdentifier(State *state, ssize_t length);
static bool ParseAbiTags(State *state);
static bool ParseAbiTag(State *state);
static bool ParseOperatorName(State *state);
@@ -691,7 +691,7 @@
}
// <identifier> ::= <unqualified source code identifier> (of given length)
-static bool ParseIdentifier(State *state, int length) {
+static bool ParseIdentifier(State *state, ssize_t length) {
if (length == -1 ||
!AtLeastNumCharsRemaining(state->mangled_cur, length)) {
return false;
@@ -891,7 +891,7 @@
if (ParseOneCharToken(state, 'C') &&
ParseCharClass(state, "123")) {
const char * const prev_name = state->prev_name;
- const int prev_name_length = state->prev_name_length;
+ const ssize_t prev_name_length = state->prev_name_length;
MaybeAppendWithLength(state, prev_name, prev_name_length);
return true;
}
@@ -900,7 +900,7 @@
if (ParseOneCharToken(state, 'D') &&
ParseCharClass(state, "012")) {
const char * const prev_name = state->prev_name;
- const int prev_name_length = state->prev_name_length;
+ const ssize_t prev_name_length = state->prev_name_length;
MaybeAppend(state, "~");
MaybeAppendWithLength(state, prev_name, prev_name_length);
return true;
@@ -1323,8 +1323,9 @@
#endif
// The demangler entry point.
-bool Demangle(const char *mangled, char *out, int out_size) {
-#if defined(OS_WINDOWS)
+bool Demangle(const char *mangled, char *out, size_t out_size) {
+#if defined(GLOG_OS_WINDOWS)
+#if defined(HAVE_DBGHELP)
// When built with incremental linking, the Windows debugger
// library provides a more complicated `Symbol->Name` with the
// Incremental Linking Table offset, which looks like
@@ -1339,7 +1340,7 @@
if (lparen) {
// Extract the string `(?...)`
const char *rparen = strchr(lparen, ')');
- size_t length = rparen - lparen - 1;
+ size_t length = static_cast<size_t>(rparen - lparen) - 1;
strncpy(buffer, lparen + 1, length);
buffer[length] = '\0';
mangled = buffer;
@@ -1347,6 +1348,12 @@
// We use the ANSI version to ensure the string type is always `char *`.
return UnDecorateSymbolName(mangled, out, out_size, UNDNAME_COMPLETE);
#else
+ (void)mangled;
+ (void)out;
+ (void)out_size;
+ return false;
+#endif
+#else
State state;
InitState(&state, mangled, out, out_size);
return ParseTopLevelMangledName(&state) && !state.overflowed;
diff --git a/src/demangle.h b/src/demangle.h
index 991b6ff..f347b98 100644
--- a/src/demangle.h
+++ b/src/demangle.h
@@ -71,14 +71,14 @@
#define BASE_DEMANGLE_H_
#include "config.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
_START_GOOGLE_NAMESPACE_
// Demangle "mangled". On success, return true and write the
// demangled symbol name to "out". Otherwise, return false.
// "out" is modified even if demangling is unsuccessful.
-bool GOOGLE_GLOG_DLL_DECL Demangle(const char *mangled, char *out, int out_size);
+bool GLOG_EXPORT Demangle(const char *mangled, char *out, size_t out_size);
_END_GOOGLE_NAMESPACE_
diff --git a/src/demangle_unittest.cc b/src/demangle_unittest.cc
index be48341..ddc90b0 100644
--- a/src/demangle_unittest.cc
+++ b/src/demangle_unittest.cc
@@ -36,7 +36,7 @@
#include <iostream>
#include <fstream>
#include <string>
-#include "glog/logging.h"
+#include <glog/logging.h>
#include "demangle.h"
#include "googletest.h"
#include "config.h"
@@ -62,8 +62,9 @@
}
}
-#if defined(OS_WINDOWS)
+#if defined(GLOG_OS_WINDOWS)
+#if defined(HAVE_DBGHELP) && !defined(NDEBUG)
TEST(Demangle, Windows) {
EXPECT_STREQ(
"public: static void __cdecl Foo::func(int)",
@@ -75,6 +76,7 @@
"int __cdecl foobarArray(int * const)",
DemangleIt("?foobarArray@@YAHQAH@Z"));
}
+#endif
#else
diff --git a/src/glog/log_severity.h b/src/glog/log_severity.h
index 99945a4..aa48f53 100644
--- a/src/glog/log_severity.h
+++ b/src/glog/log_severity.h
@@ -30,14 +30,20 @@
#ifndef BASE_LOG_SEVERITY_H__
#define BASE_LOG_SEVERITY_H__
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
+// The recommended semantics of the log levels are as follows:
+//
+// INFO:
+// Use for state changes or other major events, or to aid debugging.
+// WARNING:
+// Use for undesired but relatively expected events, which may indicate a
+// problem
+// ERROR:
+// Use for undesired and unexpected events that the program can recover from.
+// All ERRORs should be actionable - it should be appropriate to file a bug
+// whenever an ERROR occurs in production.
+// FATAL:
+// Use for undesired and unexpected events that the program cannot recover
+// from.
// Variables of type LogSeverity are widely taken to lie in the range
// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
@@ -61,7 +67,7 @@
#define DFATAL_LEVEL FATAL
#endif
-extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
+extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES];
// NDEBUG usage helpers related to (RAW_)DCHECK:
//
diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in
index 448253f..8a26cbc 100644
--- a/src/glog/logging.h.in
+++ b/src/glog/logging.h.in
@@ -1,4 +1,4 @@
-// Copyright (c) 1999, Google Inc.
+// Copyright (c) 2022, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,18 @@
// Pretty much everybody needs to #include this file so that they can
// log various happenings.
//
-#ifndef _LOGGING_H_
-#define _LOGGING_H_
+#ifndef GLOG_LOGGING_H
+#define GLOG_LOGGING_H
-#include <errno.h>
-#include <string.h>
-#include <time.h>
+#if @ac_cv_cxx11_chrono@ && __cplusplus >= 201103L
+#include <chrono>
+#endif
+
+#include <cerrno>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
#include <iosfwd>
#include <ostream>
#include <sstream>
@@ -57,13 +63,10 @@
#define GLOG_MSVC_POP_WARNING()
#endif
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
+#include <glog/platform.h>
+
+#if @ac_cv_have_glog_export@
+#include <glog/export.h>
#endif
// We care a lot about number of bits things take up. Unfortunately,
@@ -86,9 +89,15 @@
#include <gflags/gflags.h>
#endif
+#if @ac_cv_cxx11_atomic@ && __cplusplus >= 201103L
+#include <atomic>
+#elif defined(GLOG_OS_WINDOWS)
+#include <Windows.h>
+#endif
+
@ac_google_start_namespace@
-#if @ac_cv_have_uint16_t@ // the C99 format
+#if @ac_cv_have_stdint_h@ // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
@@ -107,8 +116,70 @@
#error Do not know how to define a 32-bit integer quantity on your system
#endif
+#if !(@ac_cv_have_ssize_t@)
+typedef ptrdiff_t ssize_t;
+#endif
+
+#if !(@ac_cv_have_mode_t@)
+typedef int mode_t;
+#endif
+
+typedef double WallTime;
+
+struct GLOG_EXPORT LogMessageTime {
+ LogMessageTime();
+ LogMessageTime(std::tm t);
+ LogMessageTime(std::time_t timestamp, WallTime now);
+
+ const time_t& timestamp() const { return timestamp_; }
+ const int& sec() const { return time_struct_.tm_sec; }
+ const int32_t& usec() const { return usecs_; }
+ const int&(min)() const { return time_struct_.tm_min; }
+ const int& hour() const { return time_struct_.tm_hour; }
+ const int& day() const { return time_struct_.tm_mday; }
+ const int& month() const { return time_struct_.tm_mon; }
+ const int& year() const { return time_struct_.tm_year; }
+ const int& dayOfWeek() const { return time_struct_.tm_wday; }
+ const int& dayInYear() const { return time_struct_.tm_yday; }
+ const int& dst() const { return time_struct_.tm_isdst; }
+ const long int& gmtoff() const { return gmtoffset_; }
+ const std::tm& tm() const { return time_struct_; }
+
+ private:
+ void init(const std::tm& t, std::time_t timestamp, WallTime now);
+ std::tm time_struct_; // Time of creation of LogMessage
+ time_t timestamp_; // Time of creation of LogMessage in seconds
+ int32_t usecs_; // Time of creation of LogMessage - microseconds part
+ long int gmtoffset_;
+
+ void CalcGmtOffset();
+};
+
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+struct LogMessageInfo {
+ explicit LogMessageInfo(const char* const severity_,
+ const char* const filename_,
+ const int& line_number_,
+ const int& thread_id_,
+ const LogMessageTime& time_):
+ severity(severity_), filename(filename_), line_number(line_number_),
+ thread_id(thread_id_), time(time_)
+ {}
+
+ const char* const severity;
+ const char* const filename;
+ const int &line_number;
+ const int &thread_id;
+ const LogMessageTime& time;
+};
+
+typedef void(*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l, void* data);
+
+#endif
+
@ac_google_end_namespace@
+
// The global value of GOOGLE_STRIP_LOG. All the messages logged to
// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
// If it can be determined at compile time that the message will not be
@@ -280,12 +351,13 @@
//
// Log lines have this form:
//
-// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
+// Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg...
//
// where the fields are defined as follows:
//
// L A single character, representing the log level
// (eg 'I' for INFO)
+// yyyy The year
// mm The month (zero padded; ie May is '05')
// dd The day (zero padded)
// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
@@ -305,11 +377,36 @@
// synchronized. Hence, use caution when comparing the low bits of
// timestamps from different machines.
+#pragma push_macro("DECLARE_VARIABLE")
+#pragma push_macro("DECLARE_bool")
+#pragma push_macro("DECLARE_string")
+#pragma push_macro("DECLARE_int32")
+#pragma push_macro("DECLARE_uint32")
+
+#ifdef DECLARE_VARIABLE
+#undef DECLARE_VARIABLE
+#endif
+
+#ifdef DECLARE_bool
+#undef DECLARE_bool
+#endif
+
+#ifdef DECLARE_string
+#undef DECLARE_string
+#endif
+
+#ifdef DECLARE_int32
+#undef DECLARE_int32
+#endif
+
+#ifdef DECLARE_uint32
+#undef DECLARE_uint32
+#endif
+
#ifndef DECLARE_VARIABLE
-#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
- extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
+ extern GLOG_EXPORT type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
@@ -321,15 +418,30 @@
#define DECLARE_int32(name) \
DECLARE_VARIABLE(@ac_google_namespace@::int32, I, name, int32)
+#if !defined(DECLARE_uint32)
+// uint32 specialization
+#define DECLARE_uint32(name) \
+ DECLARE_VARIABLE(@ac_google_namespace@::uint32, U, name, uint32)
+#endif // !defined(DECLARE_uint32) && !(@ac_cv_have_libgflags@)
+
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace fLS { \
- extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
+ extern GLOG_EXPORT std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif
+// Set whether appending a timestamp to the log file name
+DECLARE_bool(timestamp_in_logfile_name);
+
+// Set whether log messages go to stdout instead of logfiles
+DECLARE_bool(logtostdout);
+
+// Set color messages logged to stdout (if supported by terminal).
+DECLARE_bool(colorlogtostdout);
+
// Set whether log messages go to stderr instead of logfiles
DECLARE_bool(logtostderr);
@@ -346,6 +458,9 @@
// Set whether the log prefix should be prepended to each line of output.
DECLARE_bool(log_prefix);
+// Set whether the year should be included in the log prefix.
+DECLARE_bool(log_year_in_prefix);
+
// Log messages at a level <= this flag are buffered.
// Log messages at a higher level are flushed immediately.
DECLARE_int32(logbuflevel);
@@ -370,19 +485,16 @@
DECLARE_int32(v); // in vlog_is_on.cc
+DECLARE_string(vmodule); // also in vlog_is_on.cc
+
// Sets the maximum log file size (in MB).
-DECLARE_int32(max_log_size);
+DECLARE_uint32(max_log_size);
// Sets whether to avoid logging to the disk if the disk is full.
DECLARE_bool(stop_logging_if_full_disk);
-#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#undef DECLARE_VARIABLE
-#undef DECLARE_bool
-#undef DECLARE_int32
-#undef DECLARE_string
-#endif
+// Use UTC time for logging
+DECLARE_bool(log_utc_time);
// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
// security reasons. See LOG(severtiy) below.
@@ -484,7 +596,8 @@
LPSTR message = NULL; \
LPSTR msg = reinterpret_cast<LPSTR>(&message); \
DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
- FORMAT_MESSAGE_FROM_SYSTEM, \
+ FORMAT_MESSAGE_FROM_SYSTEM | \
+ FORMAT_MESSAGE_IGNORE_INSERTS, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
@ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_ERROR, 0, \
@@ -509,18 +622,38 @@
@ac_google_start_namespace@
// They need the definitions of integer types.
-#include "glog/log_severity.h"
-#include "glog/vlog_is_on.h"
+#include <glog/log_severity.h>
+#include <glog/vlog_is_on.h>
// Initialize google's logging library. You will see the program name
// specified by argv0 in log outputs.
-GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
+GLOG_EXPORT void InitGoogleLogging(const char* argv0);
+
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+GLOG_EXPORT void InitGoogleLogging(const char* argv0,
+ CustomPrefixCallback prefix_callback,
+ void* prefix_callback_data = NULL);
+#endif
+
+// Check if google's logging library has been initialized.
+GLOG_EXPORT bool IsGoogleLoggingInitialized();
// Shutdown google's logging library.
-GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
+GLOG_EXPORT void ShutdownGoogleLogging();
+
+#if defined(__GNUC__)
+typedef void (*logging_fail_func_t)() __attribute__((noreturn));
+#else
+typedef void (*logging_fail_func_t)();
+#endif
// Install a function which will be called after LOG(FATAL).
-GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)());
+GLOG_EXPORT void InstallFailureFunction(logging_fail_func_t fail_func);
+
+// Enable/Disable old log cleaner.
+GLOG_EXPORT void EnableLogCleaner(unsigned int overdue_days);
+GLOG_EXPORT void DisableLogCleaner();
+GLOG_EXPORT void SetApplicationFingerprint(const std::string& fingerprint);
class LogSink; // defined below
@@ -554,7 +687,7 @@
// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
// severity.
#define LOG_TO_STRING(severity, message) \
- LOG_TO_STRING_##severity(static_cast<string*>(message)).stream()
+ LOG_TO_STRING_##severity(static_cast<std::string*>(message)).stream()
// If a non-NULL pointer is given, we push the message onto the end
// of a vector of strings; otherwise, we report it with LOG(severity).
@@ -567,10 +700,8 @@
#define LOG_STRING(severity, outvec) \
LOG_TO_STRING_##severity(static_cast<std::vector<std::string>*>(outvec)).stream()
-#define LOG_IF(severity, condition) \
- !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
-#define SYSLOG_IF(severity, condition) \
- !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & SYSLOG(severity)
+#define LOG_IF(severity, condition) if(condition) LOG(severity)
+#define SYSLOG_IF(severity, condition) if(condition) SYSLOG(severity)
#define LOG_ASSERT(condition) \
LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
@@ -611,10 +742,12 @@
inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
inline long GetReferenceableValue(long t) { return t; }
inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
+#if __cplusplus >= 201103L
inline long long GetReferenceableValue(long long t) { return t; }
inline unsigned long long GetReferenceableValue(unsigned long long t) {
return t;
}
+#endif
// This is a dummy class to define the following operator.
struct DummyClassToDefineOperator {};
@@ -640,13 +773,20 @@
// Overrides for char types provide readable values for unprintable
// characters.
-template <> GOOGLE_GLOG_DLL_DECL
+template <> GLOG_EXPORT
void MakeCheckOpValueString(std::ostream* os, const char& v);
-template <> GOOGLE_GLOG_DLL_DECL
+template <> GLOG_EXPORT
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
-template <> GOOGLE_GLOG_DLL_DECL
+template <> GLOG_EXPORT
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
+// This is required because nullptr is only present in c++ 11 and later.
+#if @ac_cv_cxx11_nullptr_t@ && __cplusplus >= 201103L
+// Provide printable value for nullptr_t
+template <> GLOG_EXPORT
+void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& v);
+#endif
+
// 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)
@@ -668,7 +808,7 @@
// 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 {
+class GLOG_EXPORT CheckOpMessageBuilder {
public:
// Inserts "exprtext" and " (" to the stream.
explicit CheckOpMessageBuilder(const char *exprtext);
@@ -801,7 +941,7 @@
// Helper functions for string comparisons.
// To avoid bloat, the definitions are in logging.cc.
#define DECLARE_CHECK_STROP_IMPL(func, expected) \
- GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \
+ GLOG_EXPORT std::string* Check##func##expected##Impl( \
const char* s1, const char* s2, const char* names);
DECLARE_CHECK_STROP_IMPL(strcmp, true)
DECLARE_CHECK_STROP_IMPL(strcmp, false)
@@ -858,8 +998,7 @@
__FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, counter, \
&@ac_google_namespace@::LogMessage::SendToLog)
-#define PLOG_IF(severity, condition) \
- !(condition) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & PLOG(severity)
+#define PLOG_IF(severity, condition) if(condition) PLOG(severity)
// A CHECK() macro that postpends errno if the condition is false. E.g.
//
@@ -888,8 +1027,101 @@
#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
+#if @ac_cv_cxx11_constexpr@ && __cplusplus >= 201103L
+#define GLOG_CONSTEXPR constexpr
+#else
+#define GLOG_CONSTEXPR const
+#endif
+
+#define LOG_TIME_PERIOD LOG_EVERY_N_VARNAME(timePeriod_, __LINE__)
+#define LOG_PREVIOUS_TIME_RAW LOG_EVERY_N_VARNAME(previousTimeRaw_, __LINE__)
+#define LOG_TIME_DELTA LOG_EVERY_N_VARNAME(deltaTime_, __LINE__)
+#define LOG_CURRENT_TIME LOG_EVERY_N_VARNAME(currentTime_, __LINE__)
+#define LOG_PREVIOUS_TIME LOG_EVERY_N_VARNAME(previousTime_, __LINE__)
+
+#if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+# define GLOG_SANITIZE_THREAD 1
+# endif
+#endif
+
+#if !defined(GLOG_SANITIZE_THREAD) && defined(__SANITIZE_THREAD__) && __SANITIZE_THREAD__
+# define GLOG_SANITIZE_THREAD 1
+#endif
+
+#if defined(GLOG_SANITIZE_THREAD)
+#define GLOG_IFDEF_THREAD_SANITIZER(X) X
+#else
+#define GLOG_IFDEF_THREAD_SANITIZER(X)
+#endif
+
+#if defined(GLOG_SANITIZE_THREAD)
+} // namespace google
+
+// We need to identify the static variables as "benign" races
+// to avoid noisy reports from TSAN.
+extern "C" void AnnotateBenignRaceSized(
+ const char *file,
+ int line,
+ const volatile void *mem,
+ size_t size,
+ const char *description);
+
+namespace google {
+#endif
+
+#if __cplusplus >= 201103L && @ac_cv_cxx11_chrono@ && @ac_cv_cxx11_atomic@ // Have <chrono> and <atomic>
+#define SOME_KIND_OF_LOG_EVERY_T(severity, seconds) \
+ GLOG_CONSTEXPR std::chrono::nanoseconds LOG_TIME_PERIOD = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(seconds)); \
+ static std::atomic<@ac_google_namespace@::int64> LOG_PREVIOUS_TIME_RAW; \
+ GLOG_IFDEF_THREAD_SANITIZER( \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_TIME_PERIOD, sizeof(@ac_google_namespace@::int64), "")); \
+ GLOG_IFDEF_THREAD_SANITIZER( \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_PREVIOUS_TIME_RAW, sizeof(@ac_google_namespace@::int64), "")); \
+ const auto LOG_CURRENT_TIME = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()); \
+ const auto LOG_PREVIOUS_TIME = LOG_PREVIOUS_TIME_RAW.load(std::memory_order_relaxed); \
+ const auto LOG_TIME_DELTA = LOG_CURRENT_TIME - std::chrono::nanoseconds(LOG_PREVIOUS_TIME); \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) \
+ LOG_PREVIOUS_TIME_RAW.store(std::chrono::duration_cast<std::chrono::nanoseconds>(LOG_CURRENT_TIME).count(), std::memory_order_relaxed); \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity).stream()
+#elif defined(GLOG_OS_WINDOWS)
+#define SOME_KIND_OF_LOG_EVERY_T(severity, seconds) \
+ GLOG_CONSTEXPR LONGLONG LOG_TIME_PERIOD = (seconds) * LONGLONG(1000000000); \
+ static LARGE_INTEGER LOG_PREVIOUS_TIME; \
+ LONGLONG LOG_TIME_DELTA; \
+ { \
+ LARGE_INTEGER currTime; \
+ LARGE_INTEGER freq; \
+ QueryPerformanceCounter(&currTime); \
+ QueryPerformanceFrequency(&freq); \
+ InterlockedCompareExchange64(&LOG_PREVIOUS_TIME.QuadPart, currTime.QuadPart, 0); \
+ LOG_TIME_DELTA = (currTime.QuadPart - LOG_PREVIOUS_TIME.QuadPart) * LONGLONG(1000000000) / freq.QuadPart; \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) InterlockedExchange64(&LOG_PREVIOUS_TIME.QuadPart, currTime.QuadPart); \
+ } \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity).stream()
+#else
+#define SOME_KIND_OF_LOG_EVERY_T(severity, seconds) \
+ GLOG_CONSTEXPR @ac_google_namespace@::int64 LOG_TIME_PERIOD(seconds * 1000000000); \
+ static @ac_google_namespace@::int64 LOG_PREVIOUS_TIME; \
+ @ac_google_namespace@::int64 LOG_TIME_DELTA = 0; \
+ { \
+ timespec currentTime = {}; \
+ clock_gettime(CLOCK_MONOTONIC, ¤tTime); \
+ LOG_TIME_DELTA = (currentTime.tv_sec * 1000000000 + currentTime.tv_nsec) - LOG_PREVIOUS_TIME; \
+ } \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) __sync_add_and_fetch(&LOG_PREVIOUS_TIME, LOG_TIME_DELTA); \
+ if (LOG_TIME_DELTA > LOG_TIME_PERIOD) @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity).stream()
+#endif
+
+#if @ac_cv_cxx11_atomic@ && __cplusplus >= 201103L
#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
++LOG_OCCURRENCES; \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
@@ -898,16 +1130,20 @@
&what_to_do).stream()
#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
++LOG_OCCURRENCES; \
- if (condition && \
+ if ((condition) && \
((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
@ac_google_namespace@::LogMessage( \
__FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
++LOG_OCCURRENCES; \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
@@ -916,7 +1152,8 @@
&what_to_do).stream()
#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0; \
+ static std::atomic<int> LOG_OCCURRENCES(0); \
+ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
if (LOG_OCCURRENCES <= n) \
++LOG_OCCURRENCES; \
if (LOG_OCCURRENCES <= n) \
@@ -924,6 +1161,94 @@
__FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
+#elif defined(GLOG_OS_WINDOWS)
+
+#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
+ static volatile unsigned LOG_OCCURRENCES = 0; \
+ static volatile unsigned LOG_OCCURRENCES_MOD_N = 0; \
+ InterlockedIncrement(&LOG_OCCURRENCES); \
+ if (InterlockedIncrement(&LOG_OCCURRENCES_MOD_N) > n) \
+ InterlockedExchangeSubtract(&LOG_OCCURRENCES_MOD_N, n); \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
+ static volatile unsigned LOG_OCCURRENCES = 0; \
+ static volatile unsigned LOG_OCCURRENCES_MOD_N = 0; \
+ InterlockedIncrement(&LOG_OCCURRENCES); \
+ if ((condition) && \
+ ((InterlockedIncrement(&LOG_OCCURRENCES_MOD_N), \
+ (LOG_OCCURRENCES_MOD_N > n && InterlockedExchangeSubtract(&LOG_OCCURRENCES_MOD_N, n))), \
+ LOG_OCCURRENCES_MOD_N == 1)) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
+ static volatile unsigned LOG_OCCURRENCES = 0; \
+ static volatile unsigned LOG_OCCURRENCES_MOD_N = 0; \
+ InterlockedIncrement(&LOG_OCCURRENCES); \
+ if (InterlockedIncrement(&LOG_OCCURRENCES_MOD_N) > n) \
+ InterlockedExchangeSubtract(&LOG_OCCURRENCES_MOD_N, n); \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::ErrnoLogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
+ static volatile unsigned LOG_OCCURRENCES = 0; \
+ if (LOG_OCCURRENCES <= n) \
+ InterlockedIncrement(&LOG_OCCURRENCES); \
+ if (LOG_OCCURRENCES <= n) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#else
+
+#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ __sync_add_and_fetch(&LOG_OCCURRENCES, 1); \
+ if (__sync_add_and_fetch(&LOG_OCCURRENCES_MOD_N, 1) > n) \
+ __sync_sub_and_fetch(&LOG_OCCURRENCES_MOD_N, n); \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ __sync_add_and_fetch(&LOG_OCCURRENCES, 1); \
+ if ((condition) && \
+ (__sync_add_and_fetch(&LOG_OCCURRENCES_MOD_N, 1) || true) && \
+ ((LOG_OCCURRENCES_MOD_N >= n && __sync_sub_and_fetch(&LOG_OCCURRENCES_MOD_N, n)) || true) && \
+ LOG_OCCURRENCES_MOD_N == (1 % n)) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
+ __sync_add_and_fetch(&LOG_OCCURRENCES, 1); \
+ if (__sync_add_and_fetch(&LOG_OCCURRENCES_MOD_N, 1) > n) \
+ __sync_sub_and_fetch(&LOG_OCCURRENCES_MOD_N, n); \
+ if (LOG_OCCURRENCES_MOD_N == 1) \
+ @ac_google_namespace@::ErrnoLogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+
+#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
+ static int LOG_OCCURRENCES = 0; \
+ if (LOG_OCCURRENCES <= n) \
+ __sync_add_and_fetch(&LOG_OCCURRENCES, 1); \
+ if (LOG_OCCURRENCES <= n) \
+ @ac_google_namespace@::LogMessage( \
+ __FILE__, __LINE__, @ac_google_namespace@::GLOG_ ## severity, LOG_OCCURRENCES, \
+ &what_to_do).stream()
+#endif
+
namespace glog_internal_namespace_ {
template <bool>
struct CompileAssert {
@@ -932,12 +1257,14 @@
// Returns true if FailureSignalHandler is installed.
// Needs to be exported since it's used by the signalhandler_unittest.
-GOOGLE_GLOG_DLL_DECL bool IsFailureSignalHandlerInstalled();
+GLOG_EXPORT bool IsFailureSignalHandlerInstalled();
} // namespace glog_internal_namespace_
#define LOG_EVERY_N(severity, n) \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), @ac_google_namespace@::LogMessage::SendToLog)
+#define LOG_EVERY_T(severity, T) SOME_KIND_OF_LOG_EVERY_T(severity, (T))
+
#define SYSLOG_EVERY_N(severity, n) \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), @ac_google_namespace@::LogMessage::SendToSyslogAndLog)
@@ -1003,24 +1330,17 @@
#else // !DCHECK_IS_ON()
-#define DLOG(severity) \
- true ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+#define DLOG(severity) if((false)) LOG(severity)
-#define DVLOG(verboselevel) \
- (true || !VLOG_IS_ON(verboselevel)) ?\
- (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(INFO)
+#define DVLOG(verboselevel) if((false) && VLOG_IS_ON(verboselevel)) LOG(INFO)
-#define DLOG_IF(severity, condition) \
- (true || !(condition)) ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+#define DLOG_IF(severity, condition) if((false) && (condition)) LOG(severity)
-#define DLOG_EVERY_N(severity, n) \
- true ? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+#define DLOG_EVERY_N(severity, n) if((false)) LOG(severity)
-#define DLOG_IF_EVERY_N(severity, condition, n) \
- (true || !(condition))? (void) 0 : @ac_google_namespace@::LogMessageVoidify() & LOG(severity)
+#define DLOG_IF_EVERY_N(severity, condition, n) if((false) && (condition)) LOG(severity)
-#define DLOG_ASSERT(condition) \
- true ? (void) 0 : LOG_ASSERT(condition)
+#define DLOG_ASSERT(condition) if((false)) LOG_ASSERT(condition)
// MSVC warning C4127: conditional expression is constant
#define DCHECK(condition) \
@@ -1102,7 +1422,7 @@
// 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 {
+class GLOG_EXPORT LogStreamBuf : public std::streambuf {
public:
// REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'.
LogStreamBuf(char *buf, int len) {
@@ -1110,12 +1430,12 @@
}
// This effectively ignores overflow.
- virtual int_type overflow(int_type ch) {
+ int_type overflow(int_type ch) {
return ch;
}
// Legacy public ostrstream method.
- size_t pcount() const { return pptr() - pbase(); }
+ size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); }
char* pbase() const { return std::streambuf::pbase(); }
};
@@ -1130,7 +1450,7 @@
// You shouldn't actually use LogMessage's constructor to log things,
// though. You should use the LOG() macro (and variants thereof)
// above.
-class GOOGLE_GLOG_DLL_DECL LogMessage {
+class GLOG_EXPORT LogMessage {
public:
enum {
// Passing kNoLogPrefix for the line number disables the
@@ -1147,16 +1467,11 @@
// 2005 if you are deriving from a type in the Standard C++ Library"
// http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
// Let's just ignore the warning.
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable: 4275)
-#endif
- class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
+GLOG_MSVC_PUSH_DISABLE_WARNING(4275)
+ class GLOG_EXPORT LogStream : public std::ostream {
+GLOG_MSVC_POP_WARNING()
public:
- LogStream(char *buf, int len, int ctr)
+ LogStream(char *buf, int len, int64 ctr)
: std::ostream(NULL),
streambuf_(buf, len),
ctr_(ctr),
@@ -1164,8 +1479,8 @@
rdbuf(&streambuf_);
}
- int ctr() const { return ctr_; }
- void set_ctr(int ctr) { ctr_ = ctr; }
+ int64 ctr() const { return ctr_; }
+ void set_ctr(int64 ctr) { ctr_ = ctr; }
LogStream* self() const { return self_; }
// Legacy std::streambuf methods.
@@ -1177,7 +1492,7 @@
LogStream(const LogStream&);
LogStream& operator=(const LogStream&);
base_logging::LogStreamBuf streambuf_;
- int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
+ int64 ctr_; // Counter hack (for the LOG_EVERY_X() macro)
LogStream *self_; // Consistency check hack
};
@@ -1185,7 +1500,7 @@
// icc 8 requires this typedef to avoid an internal compiler error.
typedef void (LogMessage::*SendMethod)();
- LogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ LogMessage(const char* file, int line, LogSeverity severity, int64 ctr,
SendMethod send_method);
// Two special constructors that generate reduced amounts of code at
@@ -1252,6 +1567,8 @@
// Must be called without the log_mutex held. (L < log_mutex)
static int64 num_messages(int severity);
+ const LogMessageTime& getLogMessageTime() const;
+
struct LogMessageData;
private:
@@ -1277,6 +1594,7 @@
// LogMessage uses less stack space.
LogMessageData* allocated_;
LogMessageData* data_;
+ LogMessageTime logmsgtime_;
friend class LogDestination;
@@ -1287,7 +1605,7 @@
// This class happens to be thread-hostile because all instances share
// a single data buffer, but since it can only be created just before
// the process dies, we don't worry so much.
-class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage {
+class GLOG_EXPORT LogMessageFatal : public LogMessage {
public:
LogMessageFatal(const char* file, int line);
LogMessageFatal(const char* file, int line, const CheckOpString& result);
@@ -1316,7 +1634,7 @@
// reasonably good C++11 support, so we set LANG_CXX for it and
// newer versions (_MSC_VER >= 1900).
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
- (defined(_MSC_VER) && _MSC_VER >= 1900))
+ (defined(_MSC_VER) && _MSC_VER >= 1900)) && !defined(__UCLIBCXX_MAJOR__)
// Helper for CHECK_NOTNULL().
//
// In C++11, all cases can be handled by a single function. Since the value
@@ -1348,15 +1666,14 @@
// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
// only works if ostream is a LogStream. If the ostream is not a
// LogStream you'll get an assert saying as much at runtime.
-GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os,
+GLOG_EXPORT std::ostream& operator<<(std::ostream &os,
const PRIVATE_Counter&);
// Derived class for PLOG*() above.
-class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage {
+class GLOG_EXPORT ErrnoLogMessage : public LogMessage {
public:
-
- ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr,
+ ErrnoLogMessage(const char* file, int line, LogSeverity severity, int64 ctr,
void (LogMessage::*send_method)());
// Postpends ": strerror(errno) [errno]".
@@ -1368,34 +1685,21 @@
};
-// This class is used to explicitly ignore values in the conditional
-// logging macros. This avoids compiler warnings like "value computed
-// is not used" and "statement has no effect".
-
-class GOOGLE_GLOG_DLL_DECL LogMessageVoidify {
- public:
- LogMessageVoidify() { }
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(std::ostream&) { }
-};
-
-
// Flushes all log files that contains messages that are at least of
// the specified severity level. Thread-safe.
-GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity);
+GLOG_EXPORT void FlushLogFiles(LogSeverity min_severity);
// Flushes all log files that contains messages that are at least of
// the specified severity level. Thread-hostile because it ignores
// locking -- used for catastrophic failures.
-GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity);
+GLOG_EXPORT void FlushLogFilesUnsafe(LogSeverity min_severity);
//
// Set the destination to which a particular severity level of log
// messages is sent. If base_filename is "", it means "don't log this
// severity". Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity,
+GLOG_EXPORT void SetLogDestination(LogSeverity severity,
const char* base_filename);
//
@@ -1404,7 +1708,7 @@
// you don't call this function, the symlink basename is the
// invocation name of the program. Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity,
+GLOG_EXPORT void SetLogSymlink(LogSeverity severity,
const char* symlink_basename);
//
@@ -1412,7 +1716,7 @@
// Users should subclass LogSink and override send to do whatever they want.
// Implementations must be thread-safe because a shared instance will
// be called from whichever thread ran the LOG(XXX) line.
-class GOOGLE_GLOG_DLL_DECL LogSink {
+class GLOG_EXPORT LogSink {
public:
virtual ~LogSink();
@@ -1421,8 +1725,13 @@
// during this call.
virtual void send(LogSeverity severity, const char* full_filename,
const char* base_filename, int line,
- const struct ::tm* tm_time,
- const char* message, size_t message_len) = 0;
+ const LogMessageTime& logmsgtime, const char* message,
+ size_t message_len);
+ // Provide an overload for compatibility purposes
+ GLOG_DEPRECATED
+ virtual void send(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line, const std::tm* t,
+ const char* message, size_t message_len);
// Redefine this to implement waiting for
// the sink's logging logic to complete.
@@ -1442,13 +1751,13 @@
// Returns the normal text output of the log message.
// Can be useful to implement send().
static std::string ToString(LogSeverity severity, const char* file, int line,
- const struct ::tm* tm_time,
+ const LogMessageTime &logmsgtime,
const char* message, size_t message_len);
};
// Add or remove a LogSink as a consumer of logging data. Thread-safe.
-GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
-GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination);
+GLOG_EXPORT void AddLogSink(LogSink *destination);
+GLOG_EXPORT void RemoveLogSink(LogSink *destination);
//
// Specify an "extension" added to the filename specified via
@@ -1456,7 +1765,7 @@
// often used to append the port we're listening on to the logfile
// name. Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
+GLOG_EXPORT void SetLogFilenameExtension(
const char* filename_extension);
//
@@ -1464,12 +1773,12 @@
// are logged to stderr (in addition to logging to the usual log
// file(s)). Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity);
+GLOG_EXPORT void SetStderrLogging(LogSeverity min_severity);
//
// Make it so that all log messages go only to stderr. Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void LogToStderr();
+GLOG_EXPORT void LogToStderr();
//
// Make it so that all log messages of at least a particular severity are
@@ -1477,15 +1786,15 @@
// usual log file(s)). The list of addresses is just a string containing
// the email addresses to send to (separated by spaces, say). Thread-safe.
//
-GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
+GLOG_EXPORT void SetEmailLogging(LogSeverity min_severity,
const char* addresses);
// A simple function that sends email. dest is a commma-separated
// list of addressess. Thread-safe.
-GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
- const char *subject, const char *body);
+GLOG_EXPORT bool SendEmail(const char* dest, const char* subject,
+ const char* body);
-GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories();
+GLOG_EXPORT const std::vector<std::string>& GetLoggingDirectories();
// For tests only: Clear the internal [cached] list of logging directories to
// force a refresh the next time GetLoggingDirectories is called.
@@ -1493,15 +1802,15 @@
void TestOnly_ClearLoggingDirectoriesList();
// Returns a set of existing temporary directories, which will be a
-// subset of the directories returned by GetLogginDirectories().
+// subset of the directories returned by GetLoggingDirectories().
// Thread-safe.
-GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
+GLOG_EXPORT void GetExistingTempDirectories(
std::vector<std::string>* list);
// Print any fatal message again -- useful to call from signal handler
// so that the last thing in the output is the fatal message.
// Thread-hostile, but a race is unlikely.
-GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage();
+GLOG_EXPORT void ReprintFatalMessage();
// Truncate a log file that may be the append-only output of multiple
// processes and hence can't simply be renamed/reopened (typically a
@@ -1510,17 +1819,16 @@
// be racing with other writers, this approach has the potential to
// lose very small amounts of data. For security, only follow symlinks
// if the path is /proc/self/fd/*
-GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
- int64 limit, int64 keep);
+GLOG_EXPORT void TruncateLogFile(const char* path, uint64 limit, uint64 keep);
// Truncate stdout and stderr if they are over the value specified by
// --max_log_size; keep the final 1MB. This function has the same
// race condition as TruncateLogFile.
-GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr();
+GLOG_EXPORT void TruncateStdoutStderr();
// Return the string representation of the provided LogSeverity level.
// Thread-safe.
-GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
+GLOG_EXPORT const char* GetLogSeverityName(LogSeverity severity);
// ---------------------------------------------------------------------
// Implementation details that are not useful to most clients
@@ -1535,7 +1843,7 @@
namespace base {
-class GOOGLE_GLOG_DLL_DECL Logger {
+class GLOG_EXPORT Logger {
public:
virtual ~Logger();
@@ -1550,7 +1858,7 @@
virtual void Write(bool force_flush,
time_t timestamp,
const char* message,
- int message_len) = 0;
+ size_t message_len) = 0;
// Flush any buffered messages
virtual void Flush() = 0;
@@ -1564,12 +1872,12 @@
// Get the logger for the specified severity level. The logger
// remains the property of the logging module and should not be
// deleted by the caller. Thread-safe.
-extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level);
+extern GLOG_EXPORT Logger* GetLogger(LogSeverity level);
// Set the logger for the specified severity level. The logger
// becomes the property of the logging module and should not
// be deleted by the caller. Thread-safe.
-extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
+extern GLOG_EXPORT void SetLogger(LogSeverity level, Logger* logger);
}
@@ -1584,14 +1892,14 @@
// 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);
+GLOG_EXPORT 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);
+GLOG_EXPORT std::string StrError(int err);
// A class for which we define operator<<, which does nothing.
-class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
+class GLOG_EXPORT NullStream : public LogMessage::LogStream {
public:
// Initialize the LogStream so the messages can be written somewhere
// (they'll never be actually displayed). This will be needed if a
@@ -1620,12 +1928,19 @@
// Similar to NullStream, but aborts the program (without stack
// trace), like LogMessageFatal.
-class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream {
+class GLOG_EXPORT NullStreamFatal : public NullStream {
public:
NullStreamFatal() { }
NullStreamFatal(const char* file, int line, const CheckOpString& result) :
NullStream(file, line, result) { }
- @ac_cv___attribute___noreturn@ ~NullStreamFatal() throw () { _exit(1); }
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif // _MSC_VER
+ @ac_cv___attribute___noreturn@ ~NullStreamFatal() throw () { _exit(EXIT_FAILURE); }
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif // _MSC_VER
};
// Install a signal handler that will dump signal information and a stack
@@ -1644,15 +1959,21 @@
// to use the failure signal handler for all threads. The stack trace
// will be shown only for the thread that receives the signal. In other
// words, stack traces of other threads won't be shown.
-GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler();
+GLOG_EXPORT void InstallFailureSignalHandler();
// Installs a function that is used for writing the failure dump. "data"
// is the pointer to the beginning of a message to be written, and "size"
// is the size of the message. You should not expect the data is
// terminated with '\0'.
-GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
- void (*writer)(const char* data, int size));
+GLOG_EXPORT void InstallFailureWriter(
+ void (*writer)(const char* data, size_t size));
@ac_google_end_namespace@
-#endif // _LOGGING_H_
+#pragma pop_macro("DECLARE_VARIABLE")
+#pragma pop_macro("DECLARE_bool")
+#pragma pop_macro("DECLARE_string")
+#pragma pop_macro("DECLARE_int32")
+#pragma pop_macro("DECLARE_uint32")
+
+#endif // GLOG_LOGGING_H
diff --git a/src/glog/platform.h b/src/glog/platform.h
new file mode 100644
index 0000000..7893c45
--- /dev/null
+++ b/src/glog/platform.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Shinichiro Hamaji
+//
+// Detect supported platforms.
+
+#ifndef GLOG_PLATFORM_H
+#define GLOG_PLATFORM_H
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#define GLOG_OS_WINDOWS
+#elif defined(__CYGWIN__) || defined(__CYGWIN32__)
+#define GLOG_OS_CYGWIN
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+#ifndef GLOG_OS_LINUX
+#define GLOG_OS_LINUX
+#endif
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+#define GLOG_OS_MACOSX
+#elif defined(__FreeBSD__)
+#define GLOG_OS_FREEBSD
+#elif defined(__NetBSD__)
+#define GLOG_OS_NETBSD
+#elif defined(__OpenBSD__)
+#define GLOG_OS_OPENBSD
+#elif defined(__EMSCRIPTEN__)
+#define GLOG_OS_EMSCRIPTEN
+#else
+// TODO(hamaji): Add other platforms.
+#error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github.
+#endif
+
+#endif // GLOG_PLATFORM_H
diff --git a/src/glog/raw_logging.h.in b/src/glog/raw_logging.h.in
index fa17057..66fec91 100644
--- a/src/glog/raw_logging.h.in
+++ b/src/glog/raw_logging.h.in
@@ -33,23 +33,20 @@
// acquire any locks, and can therefore be used by low-level memory
// allocation and synchronization code.
-#ifndef BASE_RAW_LOGGING_H_
-#define BASE_RAW_LOGGING_H_
+#ifndef GLOG_RAW_LOGGING_H
+#define GLOG_RAW_LOGGING_H
-#include <time.h>
+#include <ctime>
@ac_google_start_namespace@
-#include "glog/log_severity.h"
-#include "glog/vlog_is_on.h"
+#include <glog/log_severity.h>
+#include <glog/logging.h>
+#include <glog/vlog_is_on.h>
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvariadic-macros"
#endif
// This is similar to LOG(severity) << format... and VLOG(level) << format..,
@@ -64,8 +61,8 @@
// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// RAW_VLOG(3, "status is %i", status);
// These will print an almost standard log lines like this to stderr only:
-// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
-// I0821 211317 file.cc:142] RAW: status is 20
+// E20200821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+// I20200821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (@ac_google_namespace@::GLOG_ ## severity) { \
@@ -88,7 +85,7 @@
// The following STRIP_LOG testing is performed in the header file so that it's
// possible to completely compile out the logging code and the log messages.
-#if STRIP_LOG == 0
+#if !defined(STRIP_LOG) || STRIP_LOG == 0
#define RAW_VLOG(verboselevel, ...) \
do { \
if (VLOG_IS_ON(verboselevel)) { \
@@ -99,35 +96,35 @@
#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
-#if STRIP_LOG == 0
+#if !defined(STRIP_LOG) || STRIP_LOG == 0
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
-#if STRIP_LOG <= 1
+#if !defined(STRIP_LOG) || STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
-#if STRIP_LOG <= 2
+#if !defined(STRIP_LOG) || STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
-#if STRIP_LOG <= 3
+#if !defined(STRIP_LOG) || STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
do { \
@ac_google_namespace@::RawLogStub__(0, __VA_ARGS__); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} while (0)
#endif // STRIP_LOG <= 3
@@ -160,6 +157,10 @@
#endif // NDEBUG
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int /* ignored */, ...) {
@@ -169,17 +170,10 @@
// Logs format... at "severity" level, reporting it
// as called from file:line.
// This does not allocate memory or acquire locks.
-GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
- const char* file,
- int line,
- const char* format, ...)
- @ac_cv___attribute___printf_4_5@;
-
-// Hack to propagate time information into this module so that
-// this module does not have to directly call localtime_r(),
-// which could allocate memory.
-GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
+GLOG_EXPORT void RawLog__(LogSeverity severity, const char* file, int line,
+ const char* format, ...)
+ @ac_cv___attribute___printf_4_5@;
@ac_google_end_namespace@
-#endif // BASE_RAW_LOGGING_H_
+#endif // GLOG_RAW_LOGGING_H
diff --git a/src/glog/stl_logging.h.in b/src/glog/stl_logging.h.in
index 600945d..bdfdc8b 100644
--- a/src/glog/stl_logging.h.in
+++ b/src/glog/stl_logging.h.in
@@ -59,7 +59,7 @@
#include <utility>
#include <vector>
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+#if defined(GLOG_STL_LOGGING_FOR_UNORDERED) && __cplusplus >= 201103L
# include <unordered_map>
# include <unordered_set>
#endif
@@ -130,7 +130,7 @@
OUTPUT_FOUR_ARG_CONTAINER(std::map)
OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+#if defined(GLOG_STL_LOGGING_FOR_UNORDERED) && __cplusplus >= 201103L
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
#endif
@@ -153,7 +153,7 @@
return out; \
}
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
+#if defined(GLOG_STL_LOGGING_FOR_UNORDERED) && __cplusplus >= 201103L
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
#endif
diff --git a/src/glog/vlog_is_on.h.in b/src/glog/vlog_is_on.h.in
index 3f4c4a3..7526fc3 100644
--- a/src/glog/vlog_is_on.h.in
+++ b/src/glog/vlog_is_on.h.in
@@ -41,7 +41,7 @@
// // that can't be accomplished e.g. via just VLOG(2) << ...;
// }
//
-// The truth value that VLOG_IS_ON(level) returns is determined by
+// The truth value that VLOG_IS_ON(level) returns is determined by
// the three verbosity level flags:
// --v=<n> Gives the default maximal active V-logging level;
// 0 is the default.
@@ -61,16 +61,7 @@
#ifndef BASE_VLOG_IS_ON_H_
#define BASE_VLOG_IS_ON_H_
-#include "glog/log_severity.h"
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
+#include <glog/log_severity.h>
#if defined(__GNUC__)
// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
@@ -81,12 +72,11 @@
// parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \
__extension__ \
- ({ static @ac_google_namespace@::int32* vlocal__ = &@ac_google_namespace@::kLogSiteUninitialized; \
+ ({ static @ac_google_namespace@::SiteFlag vlocal__ = {NULL, NULL, 0, NULL}; \
@ac_google_namespace@::int32 verbose_level__ = (verboselevel); \
- (*vlocal__ >= verbose_level__) && \
- ((vlocal__ != &@ac_google_namespace@::kLogSiteUninitialized) || \
- (@ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
- __FILE__, verbose_level__))); })
+ (vlocal__.level == NULL ? @ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
+ __FILE__, verbose_level__) : *vlocal__.level >= verbose_level__); \
+ })
#else
// GNU extensions not available, so we do not support --vmodule.
// Dynamic value of FLAGS_v always controls the logging level.
@@ -101,16 +91,16 @@
// one needs to supply the exact --vmodule pattern that applied to them.
// (If no --vmodule pattern applied to them
// the value of FLAGS_v will continue to control them.)
-extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
- int log_level);
+extern GLOG_EXPORT int SetVLOGLevel(const char* module_pattern, int log_level);
// Various declarations needed for VLOG_IS_ON above: =========================
-// Special value used to indicate that a VLOG_IS_ON site has not been
-// initialized. We make this a large value, so the common-case check
-// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
-// passes in such cases and InitVLOG3__ is then triggered.
-extern @ac_google_namespace@::int32 kLogSiteUninitialized;
+struct SiteFlag {
+ @ac_google_namespace@::int32* level;
+ const char* base_name;
+ size_t base_len;
+ SiteFlag* next;
+};
// Helper routine which determines the logging info for a particalur VLOG site.
// site_flag is the address of the site-local pointer to the controlling
@@ -120,10 +110,9 @@
// verbose_level is the argument to VLOG_IS_ON
// We will return the return value for VLOG_IS_ON
// and if possible set *site_flag appropriately.
-extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
- @ac_google_namespace@::int32** site_flag,
- @ac_google_namespace@::int32* site_default,
- const char* fname,
+extern GLOG_EXPORT bool InitVLOG3__(
+ @ac_google_namespace@::SiteFlag* site_flag,
+ @ac_google_namespace@::int32* site_default, const char* fname,
@ac_google_namespace@::int32 verbose_level);
#endif // BASE_VLOG_IS_ON_H_
diff --git a/src/googletest.h b/src/googletest.h
index 49ddbc0..5761361 100644
--- a/src/googletest.h
+++ b/src/googletest.h
@@ -37,18 +37,16 @@
#include "utilities.h"
-#include <ctype.h>
-#include <setjmp.h>
-#include <time.h>
-
+#include <cctype>
+#include <csetjmp>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
#include <map>
#include <sstream>
#include <string>
#include <vector>
-#include <stdio.h>
-#include <stdlib.h>
-
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -58,30 +56,39 @@
#include "base/commandlineflags.h"
+#if __cplusplus < 201103L && !defined(_MSC_VER)
+#define GOOGLE_GLOG_THROW_BAD_ALLOC throw (std::bad_alloc)
+#else
+#define GOOGLE_GLOG_THROW_BAD_ALLOC
+#endif
+
using std::map;
using std::string;
using std::vector;
_START_GOOGLE_NAMESPACE_
-extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
+extern GLOG_EXPORT void (*g_logging_fail_func)();
_END_GOOGLE_NAMESPACE_
-#undef GOOGLE_GLOG_DLL_DECL
-#define GOOGLE_GLOG_DLL_DECL
+#undef GLOG_EXPORT
+#define GLOG_EXPORT
static inline string GetTempDir() {
-#ifndef OS_WINDOWS
- return "/tmp";
-#else
- char tmp[MAX_PATH];
- GetTempPathA(MAX_PATH, tmp);
- return tmp;
-#endif
+ vector<string> temp_directories_list;
+ google::GetExistingTempDirectories(&temp_directories_list);
+
+ if (temp_directories_list.empty()) {
+ fprintf(stderr, "No temporary directory found\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Use first directory from list of existing temporary directories.
+ return temp_directories_list.front();
}
-#if defined(OS_WINDOWS) && defined(_MSC_VER) && !defined(TEST_SRC_DIR)
+#if defined(GLOG_OS_WINDOWS) && defined(_MSC_VER) && !defined(TEST_SRC_DIR)
// The test will run in glog/vsproject/<project name>
// (e.g., glog/vsproject/logging_unittest).
static const char TEST_SRC_DIR[] = "../..";
@@ -118,11 +125,20 @@
// The following is some bare-bones testing infrastructure
+#define EXPECT_NEAR(val1, val2, abs_error) \
+ do { \
+ if (abs(val1 - val2) > abs_error) { \
+ fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, #abs_error, \
+ #val2); \
+ exit(EXIT_FAILURE); \
+ } \
+ } while (0)
+
#define EXPECT_TRUE(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -132,7 +148,7 @@
do { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -145,7 +161,7 @@
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -153,7 +169,7 @@
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -161,7 +177,7 @@
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -169,7 +185,7 @@
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
@@ -190,7 +206,8 @@
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
}
- fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
+ fprintf(stderr, "Passed %d tests\n\nPASS\n",
+ static_cast<int>(g_testlist.size()));
return 0;
}
@@ -207,7 +224,7 @@
longjmp(g_jmp_buf, 1);
}
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
// TODO(hamaji): Death test somehow doesn't work in Windows.
#define ASSERT_DEATH(fn, msg)
#else
@@ -222,7 +239,7 @@
g_logging_fail_func = original_logging_fail_func; \
if (!g_called_abort) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
- exit(1); \
+ exit(EXIT_FAILURE); \
} \
} while (0)
#endif
@@ -258,10 +275,17 @@
++iter) {
clock_t start = clock();
iter->second(iter_cnt);
- double elapsed_ns =
- ((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
+ double elapsed_ns = (static_cast<double>(clock()) - start) /
+ CLOCKS_PER_SEC * 1000 * 1000 * 1000;
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat="
+#endif
printf("%s\t%8.2lf\t%10d\n",
iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
}
puts("");
}
@@ -329,6 +353,9 @@
CHECK(s_captured_streams[fd] == NULL);
s_captured_streams[fd] = new CapturedStream(fd, filename);
}
+static inline void CaptureTestStdout() {
+ CaptureTestOutput(STDOUT_FILENO, FLAGS_test_tmpdir + "/captured.out");
+}
static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
}
@@ -385,12 +412,16 @@
return GetCapturedTestOutput(STDERR_FILENO);
}
-// Check if the string is [IWEF](\d{4}|DATE)
+static const std::size_t kLoggingPrefixLength = 9;
+
+// Check if the string is [IWEF](\d{8}|YEARDATE)
static inline bool IsLoggingPrefix(const string& s) {
- if (s.size() != 5) return false;
+ if (s.size() != kLoggingPrefixLength) {
+ return false;
+ }
if (!strchr("IWEF", s[0])) return false;
- for (int i = 1; i <= 4; ++i) {
- if (!isdigit(s[i]) && s[i] != "DATE"[i-1]) return false;
+ for (size_t i = 1; i <= 8; ++i) {
+ if (!isdigit(s[i]) && s[i] != "YEARDATE"[i-1]) return false;
}
return true;
}
@@ -398,20 +429,25 @@
// Convert log output into normalized form.
//
// Example:
-// I0102 030405 logging_unittest.cc:345] RAW: vlog -1
-// => IDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
+// I20200102 030405 logging_unittest.cc:345] RAW: vlog -1
+// => IYEARDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
static inline string MungeLine(const string& line) {
- std::istringstream iss(line);
string before, logcode_date, time, thread_lineinfo;
- iss >> logcode_date;
- while (!IsLoggingPrefix(logcode_date)) {
- before += " " + logcode_date;
- if (!(iss >> logcode_date)) {
- // We cannot find the header of log output.
- return before;
+ std::size_t begin_of_logging_prefix = 0;
+ for (; begin_of_logging_prefix + kLoggingPrefixLength < line.size();
+ ++begin_of_logging_prefix) {
+ if (IsLoggingPrefix(
+ line.substr(begin_of_logging_prefix, kLoggingPrefixLength))) {
+ break;
}
}
- if (!before.empty()) before += " ";
+ if (begin_of_logging_prefix + kLoggingPrefixLength >= line.size()) {
+ return line;
+ } else if (begin_of_logging_prefix > 0) {
+ before = line.substr(0, begin_of_logging_prefix - 1);
+ }
+ std::istringstream iss(line.substr(begin_of_logging_prefix));
+ iss >> logcode_date;
iss >> time;
iss >> thread_lineinfo;
CHECK(!thread_lineinfo.empty());
@@ -428,7 +464,7 @@
thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
string rest;
std::getline(iss, rest);
- return (before + logcode_date[0] + "DATE TIME__ " + thread_lineinfo +
+ return (before + logcode_date[0] + "YEARDATE TIME__ " + thread_lineinfo +
MungeLine(rest));
}
@@ -437,7 +473,7 @@
const string& newsub) {
size_t pos = str->find(oldsub);
if (pos != string::npos) {
- str->replace(pos, oldsub.size(), newsub.c_str());
+ str->replace(pos, oldsub.size(), newsub);
}
}
@@ -448,10 +484,11 @@
string result;
while (fgets(buf, 4095, fp)) {
string line = MungeLine(buf);
- char null_str[256];
- char ptr_str[256];
- sprintf(null_str, "%p", static_cast<void*>(NULL));
- sprintf(ptr_str, "%p", reinterpret_cast<void*>(PTR_TEST_VALUE));
+ const size_t str_size = 256;
+ char null_str[str_size];
+ char ptr_str[str_size];
+ snprintf(null_str, str_size, "%p", static_cast<void*>(NULL));
+ snprintf(ptr_str, str_size, "%p", reinterpret_cast<void*>(PTR_TEST_VALUE));
StringReplace(&line, "__NULLP__", null_str);
StringReplace(&line, "__PTRTEST__", ptr_str);
@@ -473,9 +510,13 @@
fclose(fp);
}
-static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
- CapturedStream* cap = s_captured_streams[STDERR_FILENO];
- CHECK(cap) << ": did you forget CaptureTestStderr()?";
+static inline bool MungeAndDiffTest(const string& golden_filename,
+ CapturedStream* cap) {
+ if (cap == s_captured_streams[STDOUT_FILENO]) {
+ CHECK(cap) << ": did you forget CaptureTestStdout()?";
+ } else {
+ CHECK(cap) << ": did you forget CaptureTestStderr()?";
+ }
cap->StopCapture();
@@ -489,7 +530,7 @@
WriteToFile(golden, munged_golden);
string munged_captured = cap->filename() + ".munged";
WriteToFile(captured, munged_captured);
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
string diffcmd("fc " + munged_golden + " " + munged_captured);
#else
string diffcmd("diff -u " + munged_golden + " " + munged_captured);
@@ -505,6 +546,14 @@
return true;
}
+static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
+ return MungeAndDiffTest(golden_filename, s_captured_streams[STDERR_FILENO]);
+}
+
+static inline bool MungeAndDiffTestStdout(const string& golden_filename) {
+ return MungeAndDiffTest(golden_filename, s_captured_streams[STDOUT_FILENO]);
+}
+
// Save flags used from logging_unittest.cc.
#ifndef HAVE_LIB_GFLAGS
struct FlagSaver {
@@ -531,12 +580,12 @@
virtual ~Thread() {}
void SetJoinable(bool) {}
-#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
+#if defined(GLOG_OS_WINDOWS) && !defined(GLOG_OS_CYGWIN)
void Start() {
handle_ = CreateThread(NULL,
0,
- (LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
- (LPVOID)this,
+ &Thread::InvokeThreadW,
+ this,
0,
&th_);
CHECK(handle_) << "CreateThread";
@@ -560,11 +609,15 @@
private:
static void* InvokeThread(void* self) {
- ((Thread*)self)->Run();
+ (static_cast<Thread*>(self))->Run();
return NULL;
}
-#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
+#if defined(GLOG_OS_WINDOWS) && !defined(GLOG_OS_CYGWIN)
+ static DWORD __stdcall InvokeThreadW(LPVOID self) {
+ InvokeThread(self);
+ return 0;
+ }
HANDLE handle_;
DWORD th_;
#else
@@ -572,9 +625,14 @@
#endif
};
-static inline void SleepForMilliseconds(int t) {
-#ifndef OS_WINDOWS
+static inline void SleepForMilliseconds(unsigned t) {
+#ifndef GLOG_OS_WINDOWS
+# if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L
+ const struct timespec req = {0, t * 1000 * 1000};
+ nanosleep(&req, NULL);
+# else
usleep(t * 1000);
+# endif
#else
Sleep(t);
#endif
@@ -586,21 +644,29 @@
_END_GOOGLE_NAMESPACE_
-void* operator new(size_t size) {
+void* operator new(size_t size) GOOGLE_GLOG_THROW_BAD_ALLOC {
if (GOOGLE_NAMESPACE::g_new_hook) {
GOOGLE_NAMESPACE::g_new_hook();
}
return malloc(size);
}
-void* operator new[](size_t size) {
+void* operator new[](size_t size) GOOGLE_GLOG_THROW_BAD_ALLOC {
return ::operator new(size);
}
-void operator delete(void* p) {
+void operator delete(void* p) throw() {
free(p);
}
-void operator delete[](void* p) {
+void operator delete(void* p, size_t) throw() {
+ ::operator delete(p);
+}
+
+void operator delete[](void* p) throw() {
+ ::operator delete(p);
+}
+
+void operator delete[](void* p, size_t) throw() {
::operator delete(p);
}
diff --git a/src/logging.cc b/src/logging.cc
index 18a8ec6..1df1034 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -32,7 +32,7 @@
#include "utilities.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
#include <iomanip>
#include <string>
#ifdef HAVE_UNISTD_H
@@ -44,11 +44,12 @@
#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h> // For uname.
#endif
+#include <ctime>
#include <fcntl.h>
#include <cstdio>
#include <iostream>
-#include <stdarg.h>
-#include <stdlib.h>
+#include <cstdarg>
+#include <cstdlib>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
@@ -56,17 +57,26 @@
# include <syslog.h>
#endif
#include <vector>
-#include <errno.h> // for errno
+#include <cerrno> // for errno
#include <sstream>
+#ifdef GLOG_OS_WINDOWS
+#include "windows/dirent.h"
+#else
+#include <dirent.h> // for automatic removal of old logs
+#endif
#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
# include "stacktrace.h"
#endif
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
using std::string;
using std::vector;
using std::setw;
@@ -103,13 +113,20 @@
return memchr("tTyY1\0", valstr[0], 6) != NULL;
}
+GLOG_DEFINE_bool(timestamp_in_logfile_name,
+ BoolFromEnv("GOOGLE_TIMESTAMP_IN_LOGFILE_NAME", true),
+ "put a timestamp at the end of the log file name");
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(colorlogtostdout, false,
+ "color messages logged to stdout (if supported by terminal)");
+GLOG_DEFINE_bool(logtostdout, BoolFromEnv("GOOGLE_LOGTOSTDOUT", false),
+ "log messages go to stdout instead of logfiles");
+#ifdef GLOG_OS_LINUX
GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "
"Logs can grow very quickly and they are rarely read before they "
"need to be evicted from memory. Instead, drop them from memory "
@@ -131,6 +148,8 @@
"in addition to logfiles");
GLOG_DEFINE_bool(log_prefix, true,
"Prepend the log prefix to the start of each log line");
+GLOG_DEFINE_bool(log_year_in_prefix, true,
+ "Include the year in the log prefix");
GLOG_DEFINE_int32(minloglevel, 0, "Messages logged at a lower level than this don't "
"actually get logged anywhere");
GLOG_DEFINE_int32(logbuflevel, 0,
@@ -139,11 +158,15 @@
" ...)");
GLOG_DEFINE_int32(logbufsecs, 30,
"Buffer log messages for at most this many seconds");
+
+GLOG_DEFINE_int32(logcleansecs, 60 * 5, // every 5 minutes
+ "Clean overdue logs every this many seconds");
+
GLOG_DEFINE_int32(logemaillevel, 999,
"Email log messages logged at this level or higher"
" (0 means email all; 3 means email FATAL only;"
" ...)");
-GLOG_DEFINE_string(logmailer, "/bin/mail",
+GLOG_DEFINE_string(logmailer, "",
"Mailer used to send logging email");
// Compute the default value for --log_dir
@@ -168,9 +191,9 @@
GLOG_DEFINE_string(log_link, "", "Put additional links to the log "
"files in this directory");
-GLOG_DEFINE_int32(max_log_size, 1800,
- "approx. maximum log file size (in MB). A value of 0 will "
- "be silently overridden to 1.");
+GLOG_DEFINE_uint32(max_log_size, 1800,
+ "approx. maximum log file size (in MB). A value of 0 will "
+ "be silently overridden to 1.");
GLOG_DEFINE_bool(stop_logging_if_full_disk, false,
"Stop attempting to log to disk if the disk is full.");
@@ -178,11 +201,14 @@
GLOG_DEFINE_string(log_backtrace_at, "",
"Emit a backtrace when logging at file:linenum.");
+GLOG_DEFINE_bool(log_utc_time, false,
+ "Use UTC time for logging.");
+
// TODO(hamaji): consider windows
#define PATH_SEPARATOR '/'
#ifndef HAVE_PREAD
-#if defined(OS_WINDOWS)
+#if defined(GLOG_OS_WINDOWS)
#include <basetsd.h>
#define ssize_t SSIZE_T
#endif
@@ -220,12 +246,12 @@
static void GetHostName(string* hostname) {
#if defined(HAVE_SYS_UTSNAME_H)
struct utsname buf;
- if (0 != uname(&buf)) {
+ if (uname(&buf) < 0) {
// ensure null termination on failure
*buf.nodename = '\0';
}
*hostname = buf.nodename;
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
char buf[MAX_COMPUTERNAME_LENGTH + 1];
DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerNameA(buf, &len)) {
@@ -242,7 +268,7 @@
// Returns true iff terminal supports using colors in output.
static bool TerminalSupportsColor() {
bool term_supports_color = false;
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
// on Windows TERM variable is usually not set, but the console does
// support colors.
term_supports_color = true;
@@ -296,7 +322,7 @@
return color;
}
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
// Returns the character attribute for the given color.
static WORD GetColorAttribute(GLogColor color) {
@@ -321,11 +347,13 @@
return NULL; // stop warning about return type.
}
-#endif // OS_WINDOWS
+#endif // GLOG_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);
+static uint32 MaxLogSize() {
+ return (FLAGS_max_log_size > 0 && FLAGS_max_log_size < 4096
+ ? FLAGS_max_log_size
+ : 1);
}
// An arbitrary limit on the length of a single log message. This
@@ -347,8 +375,6 @@
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
@@ -392,6 +418,15 @@
base::Logger::~Logger() {
}
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+namespace {
+ // Optional user-configured callback to print custom prefixes.
+ CustomPrefixCallback custom_prefix_callback = NULL;
+ // User-provided data to pass to the callback:
+ void* custom_prefix_callback_data = NULL;
+}
+#endif
+
namespace {
// Encapsulates all file-system related state
@@ -403,7 +438,7 @@
virtual void Write(bool force_flush, // Should we force a flush here?
time_t timestamp, // Timestamp for this entry
const char* message,
- int message_len);
+ size_t message_len);
// Configuration options
void SetBasename(const char* basename);
@@ -440,13 +475,50 @@
uint32 file_length_;
unsigned int rollover_attempt_;
int64 next_flush_time_; // cycle count at which to flush log
+ WallTime start_time_;
// Actually create a logfile using the value of base_filename_ and the
- // supplied argument time_pid_string
+ // optional argument time_pid_string
// REQUIRES: lock_ is held
bool CreateLogfile(const string& time_pid_string);
};
+// Encapsulate all log cleaner related states
+class LogCleaner {
+ public:
+ LogCleaner();
+
+ // Setting overdue_days to 0 days will delete all logs.
+ void Enable(unsigned int overdue_days);
+ void Disable();
+
+ // update next_cleanup_time_
+ void UpdateCleanUpTime();
+
+ void Run(bool base_filename_selected,
+ const string& base_filename,
+ const string& filename_extension);
+
+ bool enabled() const { return enabled_; }
+
+ private:
+ vector<string> GetOverdueLogNames(string log_directory, unsigned int days,
+ const string& base_filename,
+ const string& filename_extension) const;
+
+ bool IsLogFromCurrentProject(const string& filepath,
+ const string& base_filename,
+ const string& filename_extension) const;
+
+ bool IsLogLastModifiedOver(const string& filepath, unsigned int days) const;
+
+ bool enabled_;
+ unsigned int overdue_days_;
+ int64 next_cleanup_time_; // cycle count at which to clean overdue log
+};
+
+LogCleaner log_cleaner;
+
} // namespace
class LogDestination {
@@ -485,12 +557,12 @@
private:
LogDestination(LogSeverity severity, const char* base_filename);
- ~LogDestination() { }
+ ~LogDestination();
// Take a log message of a particular severity and log it to stderr
// iff it's of a high enough severity to deserve it.
static void MaybeLogToStderr(LogSeverity severity, const char* message,
- size_t len);
+ size_t message_len, size_t prefix_len);
// Take a log message of a particular severity and log it to email
// iff it's of a high enough severity to deserve it.
@@ -509,12 +581,9 @@
const char* message, size_t len);
// Send logging info to all registered sinks.
- static void LogToSinks(LogSeverity severity,
- const char *full_filename,
- const char *base_filename,
- int line,
- const struct ::tm* tm_time,
- const char* message,
+ static void LogToSinks(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line,
+ const LogMessageTime& logmsgtime, const char* message,
size_t message_len);
// Wait for all registered sinks via WaitTillSent
@@ -571,6 +640,13 @@
logger_(&fileobject_) {
}
+LogDestination::~LogDestination() {
+ if (logger_ && logger_ != &fileobject_) {
+ // Delete user-specified logger set via SetLogger().
+ delete logger_;
+ }
+}
+
inline void LogDestination::FlushLogFilesUnsafe(int min_severity) {
// assume we have the log_mutex or we simply don't care
// about it
@@ -627,13 +703,7 @@
MutexLock l(&sink_mutex_);
// This doesn't keep the sinks in order, but who cares?
if (sinks_) {
- for (int i = sinks_->size() - 1; i >= 0; i--) {
- if ((*sinks_)[i] == destination) {
- (*sinks_)[i] = (*sinks_)[sinks_->size() - 1];
- sinks_->pop_back();
- break;
- }
- }
+ sinks_->erase(std::remove(sinks_->begin(), sinks_->end(), destination), sinks_->end());
}
}
@@ -673,41 +743,61 @@
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;
+static void ColoredWriteToStderrOrStdout(FILE* output, LogSeverity severity,
+ const char* message, size_t len) {
+ bool is_stdout = (output == stdout);
+ const GLogColor color = (LogDestination::terminal_supports_color() &&
+ ((!is_stdout && FLAGS_colorlogtostderr) ||
+ (is_stdout && FLAGS_colorlogtostdout)))
+ ? 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);
+ fwrite(message, len, 1, output);
return;
}
-#ifdef OS_WINDOWS
- const HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+#ifdef GLOG_OS_WINDOWS
+ const HANDLE output_handle =
+ GetStdHandle(is_stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
// Gets the current text color.
CONSOLE_SCREEN_BUFFER_INFO buffer_info;
- GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);
+ GetConsoleScreenBufferInfo(output_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,
+ fflush(output);
+ SetConsoleTextAttribute(output_handle,
GetColorAttribute(color) | FOREGROUND_INTENSITY);
- fwrite(message, len, 1, stderr);
- fflush(stderr);
+ fwrite(message, len, 1, output);
+ fflush(output);
// Restores the text color.
- SetConsoleTextAttribute(stderr_handle, old_color_attrs);
+ SetConsoleTextAttribute(output_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
+ fprintf(output, "\033[0;3%sm", GetAnsiColorCode(color));
+ fwrite(message, len, 1, output);
+ fprintf(output, "\033[m"); // Resets the terminal to default.
+#endif // GLOG_OS_WINDOWS
+}
+
+static void ColoredWriteToStdout(LogSeverity severity, const char* message,
+ size_t len) {
+ FILE* output = stdout;
+ // We also need to send logs to the stderr when the severity is
+ // higher or equal to the stderr threshold.
+ if (severity >= FLAGS_stderrthreshold) {
+ output = stderr;
+ }
+ ColoredWriteToStderrOrStdout(output, severity, message, len);
+}
+
+static void ColoredWriteToStderr(LogSeverity severity, const char* message,
+ size_t len) {
+ ColoredWriteToStderrOrStdout(stderr, severity, message, len);
}
static void WriteToStderr(const char* message, size_t len) {
@@ -717,12 +807,26 @@
}
inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
- const char* message, size_t len) {
+ const char* message, size_t message_len, size_t prefix_len) {
if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
- ColoredWriteToStderr(severity, message, len);
-#ifdef OS_WINDOWS
+ ColoredWriteToStderr(severity, message, message_len);
+#ifdef GLOG_OS_WINDOWS
+ (void) prefix_len;
// On Windows, also output to the debugger
- ::OutputDebugStringA(string(message,len).c_str());
+ ::OutputDebugStringA(message);
+#elif defined(__ANDROID__)
+ // On Android, also output to logcat
+ const int android_log_levels[NUM_SEVERITIES] = {
+ ANDROID_LOG_INFO,
+ ANDROID_LOG_WARN,
+ ANDROID_LOG_ERROR,
+ ANDROID_LOG_FATAL,
+ };
+ __android_log_write(android_log_levels[severity],
+ glog_internal_namespace_::ProgramInvocationShortName(),
+ message + prefix_len);
+#else
+ (void) prefix_len;
#endif
}
}
@@ -767,27 +871,28 @@
time_t timestamp,
const char* message,
size_t len) {
-
- if ( FLAGS_logtostderr ) { // global flag: never log to file
+ if (FLAGS_logtostdout) { // global flag: never log to file
+ ColoredWriteToStdout(severity, message, len);
+ } else if (FLAGS_logtostderr) { // global flag: never log to file
ColoredWriteToStderr(severity, message, len);
} else {
- for (int i = severity; i >= 0; --i)
+ for (int i = severity; i >= 0; --i) {
LogDestination::MaybeLogToLogfile(i, timestamp, message, len);
+ }
}
}
inline void LogDestination::LogToSinks(LogSeverity severity,
- const char *full_filename,
- const char *base_filename,
- int line,
- const struct ::tm* tm_time,
+ const char* full_filename,
+ const char* base_filename, int line,
+ const LogMessageTime& logmsgtime,
const char* message,
size_t message_len) {
ReaderMutexLock l(&sink_mutex_);
if (sinks_) {
- for (int i = sinks_->size() - 1; i >= 0; i--) {
+ for (size_t i = sinks_->size(); i-- > 0; ) {
(*sinks_)[i]->send(severity, full_filename, base_filename,
- line, tm_time, message, message_len);
+ line, logmsgtime, message, message_len);
}
}
}
@@ -795,7 +900,7 @@
inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) {
ReaderMutexLock l(&sink_mutex_);
if (sinks_) {
- for (int i = sinks_->size() - 1; i >= 0; i--) {
+ for (size_t i = sinks_->size(); i-- > 0; ) {
(*sinks_)[i]->WaitTillSent();
}
}
@@ -829,6 +934,35 @@
namespace {
+std::string g_application_fingerprint;
+
+} // namespace
+
+void SetApplicationFingerprint(const std::string& fingerprint) {
+ g_application_fingerprint = fingerprint;
+}
+
+namespace {
+
+// Directory delimiter; Windows supports both forward slashes and backslashes
+#ifdef GLOG_OS_WINDOWS
+const char possible_dir_delim[] = {'\\', '/'};
+#else
+const char possible_dir_delim[] = {'/'};
+#endif
+
+string PrettyDuration(int secs) {
+ std::stringstream result;
+ int mins = secs / 60;
+ int hours = mins / 60;
+ mins = mins % 60;
+ secs = secs % 60;
+ result.fill('0');
+ result << hours << ':' << setw(2) << mins << ':' << setw(2) << secs;
+ return result.str();
+}
+
+
LogFileObject::LogFileObject(LogSeverity severity,
const char* base_filename)
: base_filename_selected_(base_filename != NULL),
@@ -841,7 +975,8 @@
dropped_mem_length_(0),
file_length_(0),
rollover_attempt_(kRolloverAttemptFrequency-1),
- next_flush_time_(0) {
+ next_flush_time_(0),
+ start_time_(WallTime_Now()) {
assert(severity >= 0);
assert(severity < NUM_SEVERITIES);
}
@@ -903,23 +1038,65 @@
}
bool LogFileObject::CreateLogfile(const string& time_pid_string) {
- string string_filename = base_filename_+filename_extension_+
- time_pid_string;
+ string string_filename = base_filename_;
+ if (FLAGS_timestamp_in_logfile_name) {
+ string_filename += time_pid_string;
+ }
+ string_filename += filename_extension_;
const char* filename = string_filename.c_str();
- int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, FLAGS_logfile_mode);
+ //only write to files, create if non-existant.
+ int flags = O_WRONLY | O_CREAT;
+ if (FLAGS_timestamp_in_logfile_name) {
+ //demand that the file is unique for our timestamp (fail if it exists).
+ flags = flags | O_EXCL;
+ }
+ int fd = open(filename, flags, static_cast<mode_t>(FLAGS_logfile_mode));
if (fd == -1) return false;
#ifdef HAVE_FCNTL
// Mark the file close-on-exec. We don't really care if this fails
fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ // Mark the file as exclusive write access to avoid two clients logging to the
+ // same file. This applies particularly when !FLAGS_timestamp_in_logfile_name
+ // (otherwise open would fail because the O_EXCL flag on similar filename).
+ // locks are released on unlock or close() automatically, only after log is
+ // released.
+ // This will work after a fork as it is not inherited (not stored in the fd).
+ // Lock will not be lost because the file is opened with exclusive lock (write)
+ // and we will never read from it inside the process.
+ // TODO windows implementation of this (as flock is not available on mingw).
+ static struct flock w_lock;
+
+ w_lock.l_type = F_WRLCK;
+ w_lock.l_start = 0;
+ w_lock.l_whence = SEEK_SET;
+ w_lock.l_len = 0;
+
+ int wlock_ret = fcntl(fd, F_SETLK, &w_lock);
+ if (wlock_ret == -1) {
+ close(fd); //as we are failing already, do not check errors here
+ return false;
+ }
#endif
+ //fdopen in append mode so if the file exists it will fseek to the end
file_ = fdopen(fd, "a"); // Make a FILE*.
if (file_ == NULL) { // Man, we're screwed!
close(fd);
- unlink(filename); // Erase the half-baked evidence: an unusable log file
+ if (FLAGS_timestamp_in_logfile_name) {
+ unlink(filename); // Erase the half-baked evidence: an unusable log file, only if we just created it.
+ }
return false;
}
-
+#ifdef GLOG_OS_WINDOWS
+ // https://github.com/golang/go/issues/27638 - make sure we seek to the end to append
+ // empirically replicated with wine over mingw build
+ if (!FLAGS_timestamp_in_logfile_name) {
+ if (fseek(file_, 0, SEEK_END) != 0) {
+ return false;
+ }
+ }
+#endif
// We try to create a symlink called <program_name>.<severity>,
// which is easier to use. (Every time we create a new logfile,
// we destroy the old symlink and create a new one, so it always
@@ -931,11 +1108,11 @@
const string linkname =
symlink_basename_ + '.' + LogSeverityNames[severity_];
string linkpath;
- if ( slash ) linkpath = string(filename, slash-filename+1); // get dirname
+ if ( slash ) linkpath = string(filename, static_cast<size_t>(slash-filename+1)); // get dirname
linkpath += linkname;
unlink(linkpath.c_str()); // delete old one if it exists
-#if defined(OS_WINDOWS)
+#if defined(GLOG_OS_WINDOWS)
// TODO(hamaji): Create lnk file on Windows?
#elif defined(HAVE_UNISTD_H)
// We must have unistd.h.
@@ -964,7 +1141,7 @@
void LogFileObject::Write(bool force_flush,
time_t timestamp,
const char* message,
- int message_len) {
+ size_t message_len) {
MutexLock l(&lock_);
// We don't log if the base_name_ is "" (which means "don't write")
@@ -972,12 +1149,11 @@
return;
}
- if (static_cast<int>(file_length_ >> 20) >= MaxLogSize() ||
- PidHasChanged()) {
+ if (file_length_ >> 20U >= MaxLogSize() || PidHasChanged()) {
if (file_ != NULL) fclose(file_);
file_ = NULL;
file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0;
- rollover_attempt_ = kRolloverAttemptFrequency-1;
+ rollover_attempt_ = kRolloverAttemptFrequency - 1;
}
// If there's no destination file, make one before outputting
@@ -989,7 +1165,11 @@
rollover_attempt_ = 0;
struct ::tm tm_time;
- localtime_r(×tamp, &tm_time);
+ if (FLAGS_log_utc_time) {
+ gmtime_r(×tamp, &tm_time);
+ } else {
+ localtime_r(×tamp, &tm_time);
+ }
// The logfile's filename will have the date/time & pid in it
ostringstream time_pid_stream;
@@ -1073,14 +1253,23 @@
<< ' '
<< setw(2) << tm_time.tm_hour << ':'
<< setw(2) << tm_time.tm_min << ':'
- << setw(2) << tm_time.tm_sec << '\n'
+ << setw(2) << tm_time.tm_sec << (FLAGS_log_utc_time ? " UTC\n" : "\n")
<< "Running on machine: "
- << LogDestination::hostname() << '\n'
- << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu "
+ << LogDestination::hostname() << '\n';
+
+ if(!g_application_fingerprint.empty()) {
+ file_header_stream << "Application fingerprint: " << g_application_fingerprint << '\n';
+ }
+ const char* const date_time_format = FLAGS_log_year_in_prefix
+ ? "yyyymmdd hh:mm:ss.uuuuuu"
+ : "mmdd hh:mm:ss.uuuuuu";
+ file_header_stream << "Running duration (h:mm:ss): "
+ << PrettyDuration(static_cast<int>(WallTime_Now() - start_time_)) << '\n'
+ << "Log line format: [IWEF]" << date_time_format << " "
<< "threadid file:line] msg" << '\n';
const string& file_header_string = file_header_stream.str();
- const int header_len = file_header_string.size();
+ const size_t header_len = file_header_string.size();
fwrite(file_header_string.data(), 1, header_len, file_);
file_length_ += header_len;
bytes_since_flush_ += header_len;
@@ -1104,8 +1293,9 @@
bytes_since_flush_ += message_len;
}
} else {
- if ( CycleClock_Now() >= next_flush_time_ )
+ if (CycleClock_Now() >= next_flush_time_) {
stop_writing = false; // check to see if disk has free space.
+ }
return; // no need to flush
}
@@ -1115,26 +1305,226 @@
(bytes_since_flush_ >= 1000000) ||
(CycleClock_Now() >= next_flush_time_) ) {
FlushUnlocked();
-#ifdef OS_LINUX
+#ifdef GLOG_OS_LINUX
// Only consider files >= 3MiB
- if (FLAGS_drop_log_memory && file_length_ >= (3 << 20)) {
+ if (FLAGS_drop_log_memory && file_length_ >= (3U << 20U)) {
// Don't evict the most recent 1-2MiB so as not to impact a tailer
// of the log file and to avoid page rounding issue on linux < 4.7
- uint32 total_drop_length = (file_length_ & ~((1 << 20) - 1)) - (1 << 20);
+ uint32 total_drop_length =
+ (file_length_ & ~((1U << 20U) - 1U)) - (1U << 20U);
uint32 this_drop_length = total_drop_length - dropped_mem_length_;
- if (this_drop_length >= (2 << 20)) {
+ if (this_drop_length >= (2U << 20U)) {
// Only advise when >= 2MiB to drop
- posix_fadvise(fileno(file_), dropped_mem_length_, this_drop_length,
+# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
+ // 'posix_fadvise' introduced in API 21:
+ // * https://android.googlesource.com/platform/bionic/+/6880f936173081297be0dc12f687d341b86a4cfa/libc/libc.map.txt#732
+# else
+ posix_fadvise(fileno(file_), static_cast<off_t>(dropped_mem_length_),
+ static_cast<off_t>(this_drop_length),
POSIX_FADV_DONTNEED);
+# endif
dropped_mem_length_ = total_drop_length;
}
}
#endif
+
+ // Remove old logs
+ if (log_cleaner.enabled()) {
+ log_cleaner.Run(base_filename_selected_,
+ base_filename_,
+ filename_extension_);
+ }
}
}
-} // namespace
+LogCleaner::LogCleaner() : enabled_(false), overdue_days_(7), next_cleanup_time_(0) {}
+void LogCleaner::Enable(unsigned int overdue_days) {
+ enabled_ = true;
+ overdue_days_ = overdue_days;
+}
+
+void LogCleaner::Disable() {
+ enabled_ = false;
+}
+
+void LogCleaner::UpdateCleanUpTime() {
+ const int64 next = (FLAGS_logcleansecs
+ * 1000000); // in usec
+ next_cleanup_time_ = CycleClock_Now() + UsecToCycles(next);
+}
+
+void LogCleaner::Run(bool base_filename_selected,
+ const string& base_filename,
+ const string& filename_extension) {
+ assert(enabled_);
+ assert(!base_filename_selected || !base_filename.empty());
+
+ // avoid scanning logs too frequently
+ if (CycleClock_Now() < next_cleanup_time_) {
+ return;
+ }
+ UpdateCleanUpTime();
+
+ vector<string> dirs;
+
+ if (!base_filename_selected) {
+ dirs = GetLoggingDirectories();
+ } else {
+ size_t pos = base_filename.find_last_of(possible_dir_delim, string::npos,
+ sizeof(possible_dir_delim));
+ if (pos != string::npos) {
+ string dir = base_filename.substr(0, pos + 1);
+ dirs.push_back(dir);
+ } else {
+ dirs.push_back(".");
+ }
+ }
+
+ for (size_t i = 0; i < dirs.size(); i++) {
+ vector<string> logs = GetOverdueLogNames(dirs[i],
+ overdue_days_,
+ base_filename,
+ filename_extension);
+ for (size_t j = 0; j < logs.size(); j++) {
+ static_cast<void>(unlink(logs[j].c_str()));
+ }
+ }
+}
+
+vector<string> LogCleaner::GetOverdueLogNames(
+ string log_directory, unsigned int days, const string& base_filename,
+ const string& filename_extension) const {
+ // The names of overdue logs.
+ vector<string> overdue_log_names;
+
+ // Try to get all files within log_directory.
+ DIR *dir;
+ struct dirent *ent;
+
+ if ((dir = opendir(log_directory.c_str()))) {
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
+ continue;
+ }
+
+ string filepath = ent->d_name;
+ const char* const dir_delim_end =
+ possible_dir_delim + sizeof(possible_dir_delim);
+
+ if (!log_directory.empty() &&
+ std::find(possible_dir_delim, dir_delim_end,
+ log_directory[log_directory.size() - 1]) != dir_delim_end) {
+ filepath = log_directory + filepath;
+ }
+
+ if (IsLogFromCurrentProject(filepath, base_filename, filename_extension) &&
+ IsLogLastModifiedOver(filepath, days)) {
+ overdue_log_names.push_back(filepath);
+ }
+ }
+ closedir(dir);
+ }
+
+ return overdue_log_names;
+}
+
+bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
+ const string& base_filename,
+ const string& filename_extension) const {
+ // We should remove duplicated delimiters from `base_filename`, e.g.,
+ // before: "/tmp//<base_filename>.<create_time>.<pid>"
+ // after: "/tmp/<base_filename>.<create_time>.<pid>"
+ string cleaned_base_filename;
+
+ const char* const dir_delim_end =
+ possible_dir_delim + sizeof(possible_dir_delim);
+
+ size_t real_filepath_size = filepath.size();
+ for (size_t i = 0; i < base_filename.size(); ++i) {
+ const char& c = base_filename[i];
+
+ if (cleaned_base_filename.empty()) {
+ cleaned_base_filename += c;
+ } else if (std::find(possible_dir_delim, dir_delim_end, c) ==
+ dir_delim_end ||
+ (!cleaned_base_filename.empty() &&
+ c != cleaned_base_filename[cleaned_base_filename.size() - 1])) {
+ cleaned_base_filename += c;
+ }
+ }
+
+ // Return early if the filename doesn't start with `cleaned_base_filename`.
+ if (filepath.find(cleaned_base_filename) != 0) {
+ return false;
+ }
+
+ // Check if in the string `filename_extension` is right next to
+ // `cleaned_base_filename` in `filepath` if the user
+ // has set a custom filename extension.
+ if (!filename_extension.empty()) {
+ if (cleaned_base_filename.size() >= real_filepath_size) {
+ return false;
+ }
+ // for origin version, `filename_extension` is middle of the `filepath`.
+ string ext = filepath.substr(cleaned_base_filename.size(), filename_extension.size());
+ if (ext == filename_extension) {
+ cleaned_base_filename += filename_extension;
+ }
+ else {
+ // for new version, `filename_extension` is right of the `filepath`.
+ if (filename_extension.size() >= real_filepath_size) {
+ return false;
+ }
+ real_filepath_size = filepath.size() - filename_extension.size();
+ if (filepath.substr(real_filepath_size) != filename_extension) {
+ return false;
+ }
+ }
+ }
+
+ // The characters after `cleaned_base_filename` should match the format:
+ // YYYYMMDD-HHMMSS.pid
+ for (size_t i = cleaned_base_filename.size(); i < real_filepath_size; i++) {
+ const char& c = filepath[i];
+
+ if (i <= cleaned_base_filename.size() + 7) { // 0 ~ 7 : YYYYMMDD
+ if (c < '0' || c > '9') { return false; }
+
+ } else if (i == cleaned_base_filename.size() + 8) { // 8: -
+ if (c != '-') { return false; }
+
+ } else if (i <= cleaned_base_filename.size() + 14) { // 9 ~ 14: HHMMSS
+ if (c < '0' || c > '9') { return false; }
+
+ } else if (i == cleaned_base_filename.size() + 15) { // 15: .
+ if (c != '.') { return false; }
+
+ } else if (i >= cleaned_base_filename.size() + 16) { // 16+: pid
+ if (c < '0' || c > '9') { return false; }
+ }
+ }
+
+ return true;
+}
+
+bool LogCleaner::IsLogLastModifiedOver(const string& filepath,
+ unsigned int days) const {
+ // Try to get the last modified time of this file.
+ struct stat file_stat;
+
+ if (stat(filepath.c_str(), &file_stat) == 0) {
+ const time_t seconds_in_a_day = 60 * 60 * 24;
+ time_t last_modified_time = file_stat.st_mtime;
+ time_t current_time = time(NULL);
+ return difftime(current_time, last_modified_time) > days * seconds_in_a_day;
+ }
+
+ // If failed to get file stat, don't return true!
+ return false;
+}
+
+} // namespace
// Static log data space to avoid alloc failures in a LOG(FATAL)
//
@@ -1154,7 +1544,7 @@
// allocations).
static GLOG_THREAD_LOCAL_STORAGE bool thread_data_available = true;
-#ifdef HAVE_ALIGNED_STORAGE
+#if defined(HAVE_ALIGNED_STORAGE) && __cplusplus >= 201103L
static GLOG_THREAD_LOCAL_STORAGE
std::aligned_storage<sizeof(LogMessage::LogMessageData),
alignof(LogMessage::LogMessageData)>::type thread_msg_data;
@@ -1169,7 +1559,7 @@
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
- int ctr, void (LogMessage::*send_method)())
+ int64 ctr, void (LogMessage::*send_method)())
: allocated_(NULL) {
Init(file, line, severity, send_method);
data_->stream_.set_ctr(ctr);
@@ -1255,7 +1645,6 @@
}
}
- stream().fill('0');
data_->preserved_errno_ = errno;
data_->severity_ = severity;
data_->line_ = line;
@@ -1263,10 +1652,8 @@
data_->sink_ = NULL;
data_->outvec_ = NULL;
WallTime now = WallTime_Now();
- data_->timestamp_ = static_cast<time_t>(now);
- localtime_r(&data_->timestamp_, &data_->tm_time_);
- int usecs = static_cast<int>((now - data_->timestamp_) * 1000000);
- RawLog__SetLastTime(data_->tm_time_, usecs);
+ time_t timestamp_now = static_cast<time_t>(now);
+ logmsgtime_ = LogMessageTime(timestamp_now, now);
data_->num_chars_to_log_ = 0;
data_->num_chars_to_syslog_ = 0;
@@ -1275,23 +1662,45 @@
data_->has_been_flushed_ = false;
// If specified, prepend a prefix to each line. For example:
- // I1018 160715 f5d4fbb0 logging.cc:1153]
- // (log level, GMT month, date, time, thread_id, file basename, line)
+ // I20201018 160715 f5d4fbb0 logging.cc:1153]
+ // (log level, GMT year, month, date, time, thread_id, file basename, line)
// We exclude the thread_id for the default thread.
if (FLAGS_log_prefix && (line != kNoLogPrefix)) {
- stream() << LogSeverityNames[severity][0]
- << setw(2) << 1+data_->tm_time_.tm_mon
- << setw(2) << data_->tm_time_.tm_mday
- << ' '
- << setw(2) << data_->tm_time_.tm_hour << ':'
- << setw(2) << data_->tm_time_.tm_min << ':'
- << setw(2) << data_->tm_time_.tm_sec << "."
- << setw(6) << usecs
- << ' '
- << setfill(' ') << setw(5)
- << static_cast<unsigned int>(GetTID()) << setfill('0')
- << ' '
- << data_->basename_ << ':' << data_->line_ << "] ";
+ std::ios saved_fmt(NULL);
+ saved_fmt.copyfmt(stream());
+ stream().fill('0');
+ #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+ if (custom_prefix_callback == NULL) {
+ #endif
+ stream() << LogSeverityNames[severity][0];
+ if (FLAGS_log_year_in_prefix) {
+ stream() << setw(4) << 1900 + logmsgtime_.year();
+ }
+ stream() << setw(2) << 1 + logmsgtime_.month()
+ << setw(2) << logmsgtime_.day()
+ << ' '
+ << setw(2) << logmsgtime_.hour() << ':'
+ << setw(2) << logmsgtime_.min() << ':'
+ << setw(2) << logmsgtime_.sec() << "."
+ << setw(6) << logmsgtime_.usec()
+ << ' '
+ << setfill(' ') << setw(5)
+ << static_cast<unsigned int>(GetTID()) << setfill('0')
+ << ' '
+ << data_->basename_ << ':' << data_->line_ << "] ";
+ #ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+ } else {
+ custom_prefix_callback(
+ stream(),
+ LogMessageInfo(LogSeverityNames[severity],
+ data_->basename_, data_->line_, GetTID(),
+ logmsgtime_),
+ custom_prefix_callback_data
+ );
+ stream() << " ";
+ }
+ #endif
+ stream().copyfmt(saved_fmt);
}
data_->num_prefix_chars_ = data_->stream_.pcount();
@@ -1299,7 +1708,7 @@
char fileline[128];
snprintf(fileline, sizeof(fileline), "%s:%d", data_->basename_, line);
#ifdef HAVE_STACKTRACE
- if (!strcmp(FLAGS_log_backtrace_at.c_str(), fileline)) {
+ if (FLAGS_log_backtrace_at == fileline) {
string stacktrace;
DumpStackTraceToString(&stacktrace);
stream() << " (stacktrace:\n" << stacktrace << ") ";
@@ -1308,6 +1717,10 @@
}
}
+const LogMessageTime& LogMessage::getLogMessageTime() const {
+ return logmsgtime_;
+}
+
LogMessage::~LogMessage() {
Flush();
#ifdef GLOG_THREAD_LOCAL_STORAGE
@@ -1334,8 +1747,9 @@
// 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)
+ if (data_->has_been_flushed_ || data_->severity_ < FLAGS_minloglevel) {
return;
+ }
data_->num_chars_to_log_ = data_->stream_.pcount();
data_->num_chars_to_syslog_ =
@@ -1355,6 +1769,7 @@
original_final_char = data_->message_text_[data_->num_chars_to_log_];
data_->message_text_[data_->num_chars_to_log_++] = '\n';
}
+ data_->message_text_[data_->num_chars_to_log_] = '\0';
// Prevent any subtle race conditions by wrapping a mutex lock around
// the actual logging action per se.
@@ -1393,7 +1808,7 @@
void ReprintFatalMessage() {
if (fatal_message[0]) {
- const int n = strlen(fatal_message);
+ const size_t n = strlen(fatal_message);
if (!FLAGS_logtostderr) {
// Also write to stderr (don't color to avoid terminal checks)
WriteToStderr(fatal_message, n);
@@ -1423,34 +1838,39 @@
// global flag: never log to file if set. Also -- don't log to a
// file if we haven't parsed the command line flags to get the
// program name.
- if (FLAGS_logtostderr || !IsGoogleLoggingInitialized()) {
- ColoredWriteToStderr(data_->severity_,
- data_->message_text_, data_->num_chars_to_log_);
+ if (FLAGS_logtostderr || FLAGS_logtostdout || !IsGoogleLoggingInitialized()) {
+ if (FLAGS_logtostdout) {
+ ColoredWriteToStdout(data_->severity_, data_->message_text_,
+ data_->num_chars_to_log_);
+ } else {
+ ColoredWriteToStderr(data_->severity_, data_->message_text_,
+ data_->num_chars_to_log_);
+ }
// this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
- data_->line_, &data_->tm_time_,
+ data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
- data_->num_prefix_chars_ - 1));
+ data_->num_prefix_chars_ - 1) );
} else {
-
// log this message to all log files of severity <= severity_
- LogDestination::LogToAllLogfiles(data_->severity_, data_->timestamp_,
+ LogDestination::LogToAllLogfiles(data_->severity_, logmsgtime_.timestamp(),
data_->message_text_,
data_->num_chars_to_log_);
LogDestination::MaybeLogToStderr(data_->severity_, data_->message_text_,
- data_->num_chars_to_log_);
+ data_->num_chars_to_log_,
+ data_->num_prefix_chars_);
LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_,
data_->num_chars_to_log_);
LogDestination::LogToSinks(data_->severity_,
data_->fullname_, data_->basename_,
- data_->line_, &data_->tm_time_,
+ data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_
- - data_->num_prefix_chars_ - 1));
+ - data_->num_prefix_chars_ - 1) );
// NOTE: -1 removes trailing \n
}
@@ -1465,17 +1885,18 @@
SetCrashReason(&crash_reason);
// Store shortened fatal message for other logs and GWQ status
- const int copy = min<int>(data_->num_chars_to_log_,
+ const size_t copy = min(data_->num_chars_to_log_,
sizeof(fatal_message)-1);
memcpy(fatal_message, data_->message_text_, copy);
fatal_message[copy] = '\0';
- fatal_time = data_->timestamp_;
+ fatal_time = logmsgtime_.timestamp();
}
- if (!FLAGS_logtostderr) {
+ if (!FLAGS_logtostderr && !FLAGS_logtostdout) {
for (int i = 0; i < NUM_SEVERITIES; ++i) {
- if ( LogDestination::log_destinations_[i] )
+ if (LogDestination::log_destinations_[i]) {
LogDestination::log_destinations_[i]->logger_->Write(true, 0, "", 0);
+ }
}
}
@@ -1491,6 +1912,12 @@
if (write(STDERR_FILENO, message, strlen(message)) < 0) {
// Ignore errors.
}
+#if defined(__ANDROID__)
+ // ANDROID_LOG_FATAL as this message is of FATAL severity.
+ __android_log_write(ANDROID_LOG_FATAL,
+ glog_internal_namespace_::ProgramInvocationShortName(),
+ message);
+#endif
Fail();
}
}
@@ -1509,28 +1936,11 @@
#endif
}
-#ifdef HAVE___ATTRIBUTE__
-# define ATTRIBUTE_NORETURN __attribute__((noreturn))
-#else
-# define ATTRIBUTE_NORETURN
-#endif
+GLOG_EXPORT logging_fail_func_t g_logging_fail_func =
+ reinterpret_cast<logging_fail_func_t>(&abort);
-#if defined(OS_WINDOWS)
-__declspec(noreturn)
-#endif
-static void logging_fail() ATTRIBUTE_NORETURN;
-
-static void logging_fail() {
- abort();
-}
-
-typedef void (*logging_fail_func_t)() ATTRIBUTE_NORETURN;
-
-GOOGLE_GLOG_DLL_DECL
-logging_fail_func_t g_logging_fail_func = &logging_fail;
-
-void InstallFailureFunction(void (*fail_func)()) {
- g_logging_fail_func = (logging_fail_func_t)fail_func;
+void InstallFailureFunction(logging_fail_func_t fail_func) {
+ g_logging_fail_func = fail_func;
}
void LogMessage::Fail() {
@@ -1543,10 +1953,10 @@
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_,
- data_->line_, &data_->tm_time_,
+ data_->line_, logmsgtime_,
data_->message_text_ + data_->num_prefix_chars_,
(data_->num_chars_to_log_ -
- data_->num_prefix_chars_ - 1));
+ data_->num_prefix_chars_ - 1) );
}
}
@@ -1563,7 +1973,7 @@
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
// Omit prefix of message and trailing newline when recording in outvec_.
const char *start = data_->message_text_ + data_->num_prefix_chars_;
- int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
+ size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
data_->outvec_->push_back(string(start, len));
} else {
SendToLog();
@@ -1576,7 +1986,7 @@
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
// Omit prefix of message and trailing newline when writing to message_.
const char *start = data_->message_text_ + data_->num_prefix_chars_;
- int len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
+ size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
data_->message_->assign(start, len);
}
SendToLog();
@@ -1636,10 +2046,9 @@
}
ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
- LogSeverity severity, int ctr,
+ LogSeverity severity, int64 ctr,
void (LogMessage::*send_method)())
- : LogMessage(file, line, severity, ctr, send_method) {
-}
+ : LogMessage(file, line, severity, ctr, send_method) {}
ErrnoLogMessage::~ErrnoLogMessage() {
// Don't access errno directly because it may have been altered
@@ -1667,30 +2076,57 @@
LogSink::~LogSink() {
}
+void LogSink::send(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line,
+ const LogMessageTime& time, const char* message,
+ size_t message_len) {
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996)
+#endif // __GNUC__
+ send(severity, full_filename, base_filename, line, &time.tm(), message,
+ message_len);
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+#pragma warning(pop)
+#endif // __GNUC__
+}
+
+void LogSink::send(LogSeverity severity, const char* full_filename,
+ const char* base_filename, int line, const std::tm* t,
+ const char* message, size_t message_len) {
+ (void)severity;
+ (void)full_filename;
+ (void)base_filename;
+ (void)line;
+ (void)t;
+ (void)message;
+ (void)message_len;
+}
+
void LogSink::WaitTillSent() {
// noop default
}
string LogSink::ToString(LogSeverity severity, const char* file, int line,
- const struct ::tm* tm_time,
- const char* message, size_t message_len) {
+ const LogMessageTime& logmsgtime, const char* message,
+ size_t message_len) {
ostringstream stream(string(message, message_len));
stream.fill('0');
- // FIXME(jrvb): Updating this to use the correct value for usecs
- // requires changing the signature for both this method and
- // LogSink::send(). This change needs to be done in a separate CL
- // so subclasses of LogSink can be updated at the same time.
- int usecs = 0;
-
stream << LogSeverityNames[severity][0]
- << setw(2) << 1+tm_time->tm_mon
- << setw(2) << tm_time->tm_mday
+ << setw(4) << 1900 + logmsgtime.year()
+ << setw(2) << 1 + logmsgtime.month()
+ << setw(2) << logmsgtime.day()
<< ' '
- << setw(2) << tm_time->tm_hour << ':'
- << setw(2) << tm_time->tm_min << ':'
- << setw(2) << tm_time->tm_sec << '.'
- << setw(6) << usecs
+ << setw(2) << logmsgtime.hour() << ':'
+ << setw(2) << logmsgtime.min() << ':'
+ << setw(2) << logmsgtime.sec() << '.'
+ << setw(6) << logmsgtime.usec()
<< ' '
<< setfill(' ') << setw(5) << GetTID() << setfill('0')
<< ' '
@@ -1752,6 +2188,7 @@
} // namespace internal
} // namespace base
+#ifndef GLOG_OS_EMSCRIPTEN
// Shell-escaping as we need to shell out ot /bin/mail.
static const char kDontNeedShellEscapeChars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -1786,13 +2223,14 @@
}
return result;
}
-
+#endif
// use_logging controls whether the logging functions LOG/VLOG are used
// to log errors. It should be set to false when the caller holds the
// log_mutex.
static bool SendEmailInternal(const char*dest, const char *subject,
const char*body, bool use_logging) {
+#ifndef GLOG_OS_EMSCRIPTEN
if (dest && *dest) {
if ( use_logging ) {
VLOG(1) << "Trying to send TITLE:" << subject
@@ -1802,16 +2240,23 @@
subject, body, dest);
}
+ string logmailer = FLAGS_logmailer;
+ if (logmailer.empty()) {
+ logmailer = "/bin/mail";
+ }
string cmd =
- FLAGS_logmailer + " -s" +
+ logmailer + " -s" +
ShellEscape(subject) + " " + ShellEscape(dest);
- VLOG(4) << "Mailing command: " << cmd;
+ if (use_logging) {
+ VLOG(4) << "Mailing command: " << cmd;
+ }
FILE* pipe = popen(cmd.c_str(), "w");
if (pipe != NULL) {
// Add the body if we have one
- if (body)
+ if (body) {
fwrite(body, sizeof(char), strlen(body), pipe);
+ }
bool ok = pclose(pipe) != -1;
if ( !ok ) {
if ( use_logging ) {
@@ -1831,6 +2276,13 @@
}
}
}
+#else
+ (void)dest;
+ (void)subject;
+ (void)body;
+ (void)use_logging;
+ LOG(WARNING) << "Email support not available; not sending message";
+#endif
return false;
}
@@ -1840,7 +2292,7 @@
static void GetTempDirectories(vector<string>* list) {
list->clear();
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
// On windows we'll try to find a directory in this order:
// C:/Documents & Settings/whomever/TEMP (or whatever GetTempPath() is)
// C:/TMP/
@@ -1896,10 +2348,10 @@
if ( !FLAGS_log_dir.empty() ) {
// A dir was specified, we should use it
- logging_directories_list->push_back(FLAGS_log_dir.c_str());
+ logging_directories_list->push_back(FLAGS_log_dir);
} else {
GetTempDirectories(logging_directories_list);
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
char tmp[MAX_PATH];
if (GetWindowsDirectoryA(tmp, MAX_PATH))
logging_directories_list->push_back(tmp);
@@ -1933,16 +2385,16 @@
}
}
-void TruncateLogFile(const char *path, int64 limit, int64 keep) {
+void TruncateLogFile(const char *path, uint64 limit, uint64 keep) {
#ifdef HAVE_UNISTD_H
struct stat statbuf;
const int kCopyBlockSize = 8 << 10;
char copybuf[kCopyBlockSize];
- int64 read_offset, write_offset;
+ off_t 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
+#ifdef GLOG_OS_LINUX
const char *procfd_prefix = "/proc/self/fd/";
if (strncmp(procfd_prefix, path, strlen(procfd_prefix))) flags |= O_NOFOLLOW;
#endif
@@ -1974,18 +2426,18 @@
// See if the path refers to a regular file bigger than the
// specified limit
if (!S_ISREG(statbuf.st_mode)) goto out_close_fd;
- if (statbuf.st_size <= limit) goto out_close_fd;
- if (statbuf.st_size <= keep) goto out_close_fd;
+ if (statbuf.st_size <= static_cast<off_t>(limit)) goto out_close_fd;
+ if (statbuf.st_size <= static_cast<off_t>(keep)) goto out_close_fd;
// This log file is too large - we need to truncate it
LOG(INFO) << "Truncating " << path << " to " << keep << " bytes";
// Copy the last "keep" bytes of the file to the beginning of the file
- read_offset = statbuf.st_size - keep;
+ read_offset = statbuf.st_size - static_cast<off_t>(keep);
write_offset = 0;
- int bytesin, bytesout;
+ ssize_t bytesin, bytesout;
while ((bytesin = pread(fd, copybuf, sizeof(copybuf), read_offset)) > 0) {
- bytesout = pwrite(fd, copybuf, bytesin, write_offset);
+ bytesout = pwrite(fd, copybuf, static_cast<size_t>(bytesin), write_offset);
if (bytesout == -1) {
PLOG(ERROR) << "Unable to write to " << path;
break;
@@ -2009,12 +2461,12 @@
#else
LOG(ERROR) << "No log truncation support.";
#endif
-}
+ }
void TruncateStdoutStderr() {
#ifdef HAVE_UNISTD_H
- int64 limit = MaxLogSize() << 20;
- int64 keep = 1 << 20;
+ uint64 limit = MaxLogSize() << 20U;
+ uint64 keep = 1U << 20U;
TruncateLogFile("/proc/self/fd/1", limit, keep);
TruncateLogFile("/proc/self/fd/2", limit, keep);
#else
@@ -2081,7 +2533,7 @@
return 0;
} else {
buf[0] = '\000';
-#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD)
if (reinterpret_cast<intptr_t>(rc) < sys_nerr) {
// This means an error on MacOSX or FreeBSD.
return -1;
@@ -2142,7 +2594,7 @@
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
- (*os) << "char value " << (short)v;
+ (*os) << "char value " << static_cast<short>(v);
}
}
@@ -2151,7 +2603,7 @@
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
- (*os) << "signed char value " << (short)v;
+ (*os) << "signed char value " << static_cast<short>(v);
}
}
@@ -2160,14 +2612,31 @@
if (v >= 32 && v <= 126) {
(*os) << "'" << v << "'";
} else {
- (*os) << "unsigned char value " << (unsigned short)v;
+ (*os) << "unsigned char value " << static_cast<unsigned short>(v);
}
}
+#if defined(HAVE_CXX11_NULLPTR_T) && __cplusplus >= 201103L
+template <>
+void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& /*v*/) {
+ (*os) << "nullptr";
+}
+#endif // defined(HAVE_CXX11_NULLPTR_T)
+
void InitGoogleLogging(const char* argv0) {
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
}
+#ifdef GLOG_CUSTOM_PREFIX_SUPPORT
+void InitGoogleLogging(const char* argv0,
+ CustomPrefixCallback prefix_callback,
+ void* prefix_callback_data) {
+ custom_prefix_callback = prefix_callback;
+ custom_prefix_callback_data = prefix_callback_data;
+ InitGoogleLogging(argv0);
+}
+#endif
+
void ShutdownGoogleLogging() {
glog_internal_namespace_::ShutdownGoogleLoggingUtilities();
LogDestination::DeleteLogDestinations();
@@ -2175,4 +2644,56 @@
logging_directories_list = NULL;
}
+void EnableLogCleaner(unsigned int overdue_days) {
+ log_cleaner.Enable(overdue_days);
+}
+
+void DisableLogCleaner() {
+ log_cleaner.Disable();
+}
+
+LogMessageTime::LogMessageTime()
+ : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
+
+LogMessageTime::LogMessageTime(std::tm t) {
+ std::time_t timestamp = std::mktime(&t);
+ init(t, timestamp, 0);
+}
+
+LogMessageTime::LogMessageTime(std::time_t timestamp, WallTime now) {
+ std::tm t;
+ if (FLAGS_log_utc_time)
+ gmtime_r(×tamp, &t);
+ else
+ localtime_r(×tamp, &t);
+ init(t, timestamp, now);
+}
+
+void LogMessageTime::init(const std::tm& t, std::time_t timestamp,
+ WallTime now) {
+ time_struct_ = t;
+ timestamp_ = timestamp;
+ usecs_ = static_cast<int32>((now - timestamp) * 1000000);
+
+ CalcGmtOffset();
+}
+
+void LogMessageTime::CalcGmtOffset() {
+ std::tm gmt_struct;
+ int isDst = 0;
+ if ( FLAGS_log_utc_time ) {
+ localtime_r(×tamp_, &gmt_struct);
+ isDst = gmt_struct.tm_isdst;
+ gmt_struct = time_struct_;
+ } else {
+ isDst = time_struct_.tm_isdst;
+ gmtime_r(×tamp_, &gmt_struct);
+ }
+
+ time_t gmt_sec = mktime(&gmt_struct);
+ const long hour_secs = 3600;
+ // If the Daylight Saving Time(isDst) is active subtract an hour from the current timestamp.
+ gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0) ) ;
+}
+
_END_GOOGLE_NAMESPACE_
diff --git a/src/logging_custom_prefix_unittest.cc b/src/logging_custom_prefix_unittest.cc
new file mode 100644
index 0000000..615dce7
--- /dev/null
+++ b/src/logging_custom_prefix_unittest.cc
@@ -0,0 +1,1384 @@
+// Copyright (c) 2002, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: Ray Sidney
+
+#include "utilities.h"
+
+#include <fcntl.h>
+#ifdef HAVE_GLOB_H
+# include <glob.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/commandlineflags.h"
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
+#include "googletest.h"
+
+DECLARE_string(log_backtrace_at); // logging.cc
+
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
+#ifdef HAVE_LIB_GMOCK
+#include <gmock/gmock.h>
+#include "mock-log.h"
+// Introduce several symbols from gmock.
+using testing::_;
+using testing::AnyNumber;
+using testing::HasSubstr;
+using testing::AllOf;
+using testing::StrNe;
+using testing::StrictMock;
+using testing::InitGoogleMock;
+using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
+#endif
+
+using namespace std;
+using namespace GOOGLE_NAMESPACE;
+
+// Some non-advertised functions that we want to test or use.
+_START_GOOGLE_NAMESPACE_
+namespace base {
+namespace internal {
+bool GetExitOnDFatal();
+void SetExitOnDFatal(bool value);
+} // namespace internal
+} // namespace base
+_END_GOOGLE_NAMESPACE_
+
+static void TestLogging(bool check_counts);
+static void TestRawLogging();
+static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
+static void TestLoggingLevels();
+static void TestLogString();
+static void TestLogSink();
+static void TestLogToString();
+static void TestLogSinkWaitTillSent();
+static void TestCHECK();
+static void TestDCHECK();
+static void TestSTREQ();
+static void TestBasename();
+static void TestBasenameAppendWhenNoTimestamp();
+static void TestTwoProcessesWrite();
+static void TestSymlink();
+static void TestExtension();
+static void TestWrapper();
+static void TestErrno();
+static void TestTruncate();
+static void TestCustomLoggerDeletionOnShutdown();
+
+static int x = -1;
+static void BM_Check1(int n) {
+ while (n-- > 0) {
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ CHECK_GE(n, x);
+ }
+}
+BENCHMARK(BM_Check1)
+
+static void CheckFailure(int a, int b, const char* file, int line, const char* msg);
+static void BM_Check3(int n) {
+ while (n-- > 0) {
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
+ }
+}
+BENCHMARK(BM_Check3)
+
+static void BM_Check2(int n) {
+ if (n == 17) {
+ x = 5;
+ }
+ while (n-- > 0) {
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ CHECK(n >= x);
+ }
+}
+BENCHMARK(BM_Check2)
+
+static void CheckFailure(int, int, const char* /* file */, int /* line */,
+ const char* /* msg */) {
+}
+
+static void BM_logspeed(int n) {
+ while (n-- > 0) {
+ LOG(INFO) << "test message";
+ }
+}
+BENCHMARK(BM_logspeed)
+
+static void BM_vlog(int n) {
+ while (n-- > 0) {
+ VLOG(1) << "test message";
+ }
+}
+BENCHMARK(BM_vlog)
+
+// Dynamically generate a prefix using the default format and write it to the stream.
+void PrefixAttacher(std::ostream &s, const LogMessageInfo &l, void* data) {
+ // Assert that `data` contains the expected contents before producing the
+ // prefix (otherwise causing the tests to fail):
+ if (data == NULL || *static_cast<string*>(data) != "good data") {
+ return;
+ }
+
+ s << l.severity[0]
+ << setw(4) << 1900 + l.time.year()
+ << setw(2) << 1 + l.time.month()
+ << setw(2) << l.time.day()
+ << ' '
+ << setw(2) << l.time.hour() << ':'
+ << setw(2) << l.time.min() << ':'
+ << setw(2) << l.time.sec() << "."
+ << setw(6) << l.time.usec()
+ << ' '
+ << setfill(' ') << setw(5)
+ << l.thread_id << setfill('0')
+ << ' '
+ << l.filename << ':' << l.line_number << "]";
+}
+
+int main(int argc, char **argv) {
+ FLAGS_colorlogtostderr = false;
+ FLAGS_timestamp_in_logfile_name = true;
+
+ // Make sure stderr is not buffered as stderr seems to be buffered
+ // on recent windows.
+ setbuf(stderr, NULL);
+
+ // Test some basics before InitGoogleLogging:
+ CaptureTestStderr();
+ LogWithLevels(FLAGS_v, FLAGS_stderrthreshold,
+ FLAGS_logtostderr, FLAGS_alsologtostderr);
+ LogWithLevels(0, 0, 0, 0); // simulate "before global c-tors"
+ const string early_stderr = GetCapturedTestStderr();
+
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+
+ // Setting a custom prefix generator (it will use the default format so that
+ // the golden outputs can be reused):
+ string prefix_attacher_data = "good data";
+ InitGoogleLogging(argv[0], &PrefixAttacher, static_cast<void*>(&prefix_attacher_data));
+
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+
+ RunSpecifiedBenchmarks();
+
+ FLAGS_logtostderr = true;
+
+ InitGoogleTest(&argc, argv);
+#ifdef HAVE_LIB_GMOCK
+ InitGoogleMock(&argc, argv);
+#endif
+
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+
+ // so that death tests run before we use threads
+ CHECK_EQ(RUN_ALL_TESTS(), 0);
+
+ CaptureTestStderr();
+
+ // re-emit early_stderr
+ LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr;
+
+ TestLogging(true);
+ TestRawLogging();
+ TestLoggingLevels();
+ TestLogString();
+ TestLogSink();
+ TestLogToString();
+ TestLogSinkWaitTillSent();
+ TestCHECK();
+ TestDCHECK();
+ TestSTREQ();
+
+ // TODO: The golden test portion of this test is very flakey.
+ EXPECT_TRUE(
+ MungeAndDiffTestStderr(FLAGS_test_srcdir + "/src/logging_custom_prefix_unittest.err"));
+
+ FLAGS_logtostderr = false;
+
+ TestBasename();
+ TestBasenameAppendWhenNoTimestamp();
+ TestTwoProcessesWrite();
+ TestSymlink();
+ TestExtension();
+ TestWrapper();
+ TestErrno();
+ TestTruncate();
+ TestCustomLoggerDeletionOnShutdown();
+
+ fprintf(stdout, "PASS\n");
+ return 0;
+}
+
+void TestLogging(bool check_counts) {
+ int64 base_num_infos = LogMessage::num_messages(GLOG_INFO);
+ int64 base_num_warning = LogMessage::num_messages(GLOG_WARNING);
+ int64 base_num_errors = LogMessage::num_messages(GLOG_ERROR);
+
+ LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4;
+ for ( int i = 0; i < 10; ++i ) {
+ int old_errno = errno;
+ errno = i;
+ PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER;
+ errno = old_errno;
+
+ LOG_EVERY_N(ERROR, 3) << "Log every 3, iteration " << COUNTER << endl;
+ LOG_EVERY_N(ERROR, 4) << "Log every 4, iteration " << COUNTER << endl;
+
+ LOG_IF_EVERY_N(WARNING, true, 5) << "Log if every 5, iteration " << COUNTER;
+ LOG_IF_EVERY_N(WARNING, false, 3)
+ << "Log if every 3, iteration " << COUNTER;
+ LOG_IF_EVERY_N(INFO, true, 1) << "Log if every 1, iteration " << COUNTER;
+ LOG_IF_EVERY_N(ERROR, (i < 3), 2)
+ << "Log if less than 3 every 2, iteration " << COUNTER;
+ }
+ LOG_IF(WARNING, true) << "log_if this";
+ LOG_IF(WARNING, false) << "don't log_if this";
+
+ char s[] = "array";
+ LOG(INFO) << s;
+ const char const_s[] = "const array";
+ LOG(INFO) << const_s;
+ int j = 1000;
+ LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
+ << setw(1) << hex << j;
+ LOG(INFO) << "foo " << std::setw(10) << 1.0;
+
+ {
+ google::LogMessage outer(__FILE__, __LINE__, GLOG_ERROR);
+ outer.stream() << "outer";
+
+ LOG(ERROR) << "inner";
+ }
+
+ LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
+
+ if (check_counts) {
+ CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO));
+ CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING));
+ CHECK_EQ(base_num_errors + 17, LogMessage::num_messages(GLOG_ERROR));
+ }
+}
+
+static void NoAllocNewHook() {
+ LOG(FATAL) << "unexpected new";
+}
+
+struct NewHook {
+ NewHook() {
+ g_new_hook = &NoAllocNewHook;
+ }
+ ~NewHook() {
+ g_new_hook = NULL;
+ }
+};
+
+TEST(DeathNoAllocNewHook, logging) {
+ // tests that NewHook used below works
+ NewHook new_hook;
+ ASSERT_DEATH({
+ new int;
+ }, "unexpected new");
+}
+
+void TestRawLogging() {
+ string* foo = new string("foo ");
+ string huge_str(50000, 'a');
+
+ FlagSaver saver;
+
+ // Check that RAW loggging does not use mallocs.
+ NewHook new_hook;
+
+ RAW_LOG(INFO, "%s%s%d%c%f", foo->c_str(), "bar ", 10, ' ', 3.4);
+ char s[] = "array";
+ RAW_LOG(WARNING, "%s", s);
+ const char const_s[] = "const array";
+ RAW_LOG(INFO, "%s", const_s);
+ void* p = reinterpret_cast<void*>(PTR_TEST_VALUE);
+ RAW_LOG(INFO, "ptr %p", p);
+ p = NULL;
+ RAW_LOG(INFO, "ptr %p", p);
+ int j = 1000;
+ RAW_LOG(ERROR, "%s%d%c%010d%s%1x", foo->c_str(), j, ' ', j, " ", j);
+ RAW_VLOG(0, "foo %d", j);
+
+#if defined(NDEBUG)
+ RAW_LOG(INFO, "foo %d", j); // so that have same stderr to compare
+#else
+ RAW_DLOG(INFO, "foo %d", j); // test RAW_DLOG in debug mode
+#endif
+
+ // test how long messages are chopped:
+ RAW_LOG(WARNING, "Huge string: %s", huge_str.c_str());
+ RAW_VLOG(0, "Huge string: %s", huge_str.c_str());
+
+ FLAGS_v = 0;
+ RAW_LOG(INFO, "log");
+ RAW_VLOG(0, "vlog 0 on");
+ RAW_VLOG(1, "vlog 1 off");
+ RAW_VLOG(2, "vlog 2 off");
+ RAW_VLOG(3, "vlog 3 off");
+ FLAGS_v = 2;
+ RAW_LOG(INFO, "log");
+ RAW_VLOG(1, "vlog 1 on");
+ RAW_VLOG(2, "vlog 2 on");
+ RAW_VLOG(3, "vlog 3 off");
+
+#if defined(NDEBUG)
+ RAW_DCHECK(1 == 2, " RAW_DCHECK's shouldn't be compiled in normal mode");
+#endif
+
+ RAW_CHECK(1 == 1, "should be ok");
+ RAW_DCHECK(true, "should be ok");
+
+ delete foo;
+}
+
+void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
+ RAW_LOG(INFO,
+ "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d",
+ v, severity, err, alsoerr);
+
+ FlagSaver saver;
+
+ FLAGS_v = v;
+ FLAGS_stderrthreshold = severity;
+ FLAGS_logtostderr = err;
+ FLAGS_alsologtostderr = alsoerr;
+
+ RAW_VLOG(-1, "vlog -1");
+ RAW_VLOG(0, "vlog 0");
+ RAW_VLOG(1, "vlog 1");
+ RAW_LOG(INFO, "log info");
+ RAW_LOG(WARNING, "log warning");
+ RAW_LOG(ERROR, "log error");
+
+ VLOG(-1) << "vlog -1";
+ VLOG(0) << "vlog 0";
+ VLOG(1) << "vlog 1";
+ LOG(INFO) << "log info";
+ LOG(WARNING) << "log warning";
+ LOG(ERROR) << "log error";
+
+ VLOG_IF(-1, true) << "vlog_if -1";
+ VLOG_IF(-1, false) << "don't vlog_if -1";
+ VLOG_IF(0, true) << "vlog_if 0";
+ VLOG_IF(0, false) << "don't vlog_if 0";
+ VLOG_IF(1, true) << "vlog_if 1";
+ VLOG_IF(1, false) << "don't vlog_if 1";
+ LOG_IF(INFO, true) << "log_if info";
+ LOG_IF(INFO, false) << "don't log_if info";
+ LOG_IF(WARNING, true) << "log_if warning";
+ LOG_IF(WARNING, false) << "don't log_if warning";
+ LOG_IF(ERROR, true) << "log_if error";
+ LOG_IF(ERROR, false) << "don't log_if error";
+
+ int c;
+ c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1);
+ c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1);
+ c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1);
+ c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1);
+ c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0);
+ c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0);
+
+ c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
+ EXPECT_EQ(c, -1);
+ c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
+ EXPECT_EQ(c, -1);
+ c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
+ EXPECT_EQ(c, 0);
+ c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
+ EXPECT_EQ(c, 0);
+ c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
+ EXPECT_EQ(c, 1);
+ c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
+ EXPECT_EQ(c, 1);
+ c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
+ EXPECT_EQ(c, 0);
+ c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
+ EXPECT_EQ(c, 0);
+}
+
+void TestLoggingLevels() {
+ LogWithLevels(0, GLOG_INFO, false, false);
+ LogWithLevels(1, GLOG_INFO, false, false);
+ LogWithLevels(-1, GLOG_INFO, false, false);
+ LogWithLevels(0, GLOG_WARNING, false, false);
+ LogWithLevels(0, GLOG_ERROR, false, false);
+ LogWithLevels(0, GLOG_FATAL, false, false);
+ LogWithLevels(0, GLOG_FATAL, true, false);
+ LogWithLevels(0, GLOG_FATAL, false, true);
+ LogWithLevels(1, GLOG_WARNING, false, false);
+ LogWithLevels(1, GLOG_FATAL, false, true);
+}
+
+TEST(DeathRawCHECK, logging) {
+ ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
+ "RAW: Check false failed: failure 1");
+ ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"),
+ "RAW: Check 1 == 2 failed: failure 2");
+}
+
+void TestLogString() {
+ vector<string> errors;
+ vector<string> *no_errors = NULL;
+
+ LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info";
+ LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning";
+ LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error";
+
+ LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info";
+ LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning";
+ LOG_STRING(ERROR, NULL) << "LOG_STRING: " << "reported error";
+
+ for (size_t i = 0; i < errors.size(); ++i) {
+ LOG(INFO) << "Captured by LOG_STRING: " << errors[i];
+ }
+}
+
+void TestLogToString() {
+ string error;
+ string* no_error = NULL;
+
+ LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+ LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+ LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error";
+ LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
+
+ LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info";
+ LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning";
+ LOG_TO_STRING(ERROR, NULL) << "LOG_TO_STRING: " << "reported error";
+}
+
+class TestLogSinkImpl : public LogSink {
+ public:
+ vector<string> errors;
+ virtual void send(LogSeverity severity, const char* /* full_filename */,
+ const char* base_filename, int line,
+ const LogMessageTime &logmsgtime,
+ const char* message, size_t message_len) {
+ errors.push_back(
+ ToString(severity, base_filename, line, logmsgtime, message, message_len));
+ }
+};
+
+void TestLogSink() {
+ TestLogSinkImpl sink;
+ LogSink *no_sink = NULL;
+
+ LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info";
+ LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning";
+ LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error";
+
+ LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info";
+ LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning";
+ LOG_TO_SINK(NULL, ERROR) << "LOG_TO_SINK: " << "reported error";
+
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error";
+
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning";
+ LOG_TO_SINK_BUT_NOT_TO_LOGFILE(NULL, ERROR)
+ << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed error";
+
+ LOG(INFO) << "Captured by LOG_TO_SINK:";
+ for (size_t i = 0; i < sink.errors.size(); ++i) {
+ LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
+ << sink.errors[i];
+ }
+}
+
+// For testing using CHECK*() on anonymous enums.
+enum {
+ CASE_A,
+ CASE_B
+};
+
+void TestCHECK() {
+ // Tests using CHECK*() on int values.
+ CHECK(1 == 1);
+ CHECK_EQ(1, 1);
+ CHECK_NE(1, 2);
+ CHECK_GE(1, 1);
+ CHECK_GE(2, 1);
+ CHECK_LE(1, 1);
+ CHECK_LE(1, 2);
+ CHECK_GT(2, 1);
+ CHECK_LT(1, 2);
+
+ // Tests using CHECK*() on anonymous enums.
+ // Apple's GCC doesn't like this.
+#if !defined(GLOG_OS_MACOSX)
+ CHECK_EQ(CASE_A, CASE_A);
+ CHECK_NE(CASE_A, CASE_B);
+ CHECK_GE(CASE_A, CASE_A);
+ CHECK_GE(CASE_B, CASE_A);
+ CHECK_LE(CASE_A, CASE_A);
+ CHECK_LE(CASE_A, CASE_B);
+ CHECK_GT(CASE_B, CASE_A);
+ CHECK_LT(CASE_A, CASE_B);
+#endif
+}
+
+void TestDCHECK() {
+#if defined(NDEBUG)
+ DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode";
+#endif
+ DCHECK( 1 == 1 );
+ DCHECK_EQ(1, 1);
+ DCHECK_NE(1, 2);
+ DCHECK_GE(1, 1);
+ DCHECK_GE(2, 1);
+ DCHECK_LE(1, 1);
+ DCHECK_LE(1, 2);
+ DCHECK_GT(2, 1);
+ DCHECK_LT(1, 2);
+
+ int64* orig_ptr = new int64;
+ int64* ptr = DCHECK_NOTNULL(orig_ptr);
+ CHECK_EQ(ptr, orig_ptr);
+ delete orig_ptr;
+}
+
+void TestSTREQ() {
+ CHECK_STREQ("this", "this");
+ CHECK_STREQ(NULL, NULL);
+ CHECK_STRCASEEQ("this", "tHiS");
+ CHECK_STRCASEEQ(NULL, NULL);
+ CHECK_STRNE("this", "tHiS");
+ CHECK_STRNE("this", NULL);
+ CHECK_STRCASENE("this", "that");
+ CHECK_STRCASENE(NULL, "that");
+ CHECK_STREQ((string("a")+"b").c_str(), "ab");
+ CHECK_STREQ(string("test").c_str(),
+ (string("te") + string("st")).c_str());
+}
+
+TEST(DeathSTREQ, logging) {
+ ASSERT_DEATH(CHECK_STREQ(NULL, "this"), "");
+ ASSERT_DEATH(CHECK_STREQ("this", "siht"), "");
+ ASSERT_DEATH(CHECK_STRCASEEQ(NULL, "siht"), "");
+ ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), "");
+ ASSERT_DEATH(CHECK_STRNE(NULL, NULL), "");
+ ASSERT_DEATH(CHECK_STRNE("this", "this"), "");
+ ASSERT_DEATH(CHECK_STREQ((string("a")+"b").c_str(), "abc"), "");
+}
+
+TEST(CheckNOTNULL, Simple) {
+ int64 t;
+ void *ptr = static_cast<void *>(&t);
+ void *ref = CHECK_NOTNULL(ptr);
+ EXPECT_EQ(ptr, ref);
+ CHECK_NOTNULL(reinterpret_cast<char *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<unsigned char *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<int *>(ptr));
+ CHECK_NOTNULL(reinterpret_cast<int64 *>(ptr));
+}
+
+TEST(DeathCheckNN, Simple) {
+ ASSERT_DEATH(CHECK_NOTNULL(static_cast<void *>(NULL)), "");
+}
+
+// Get list of file names that match pattern
+static void GetFiles(const string& pattern, vector<string>* files) {
+ files->clear();
+#if defined(HAVE_GLOB_H)
+ glob_t g;
+ const int r = glob(pattern.c_str(), 0, NULL, &g);
+ CHECK((r == 0) || (r == GLOB_NOMATCH)) << ": error matching " << pattern;
+ for (size_t i = 0; i < g.gl_pathc; i++) {
+ files->push_back(string(g.gl_pathv[i]));
+ }
+ globfree(&g);
+#elif defined(GLOG_OS_WINDOWS)
+ WIN32_FIND_DATAA data;
+ HANDLE handle = FindFirstFileA(pattern.c_str(), &data);
+ size_t index = pattern.rfind('\\');
+ if (index == string::npos) {
+ LOG(FATAL) << "No directory separator.";
+ }
+ const string dirname = pattern.substr(0, index + 1);
+ if (handle == INVALID_HANDLE_VALUE) {
+ // Finding no files is OK.
+ return;
+ }
+ do {
+ files->push_back(dirname + data.cFileName);
+ } while (FindNextFileA(handle, &data));
+ BOOL result = FindClose(handle);
+ LOG_SYSRESULT(result != 0);
+#else
+# error There is no way to do glob.
+#endif
+}
+
+// Delete files patching pattern
+static void DeleteFiles(const string& pattern) {
+ vector<string> files;
+ GetFiles(pattern, &files);
+ for (size_t i = 0; i < files.size(); i++) {
+ CHECK(unlink(files[i].c_str()) == 0) << ": " << strerror(errno);
+ }
+}
+
+//check string is in file (or is *NOT*, depending on optional checkInFileOrNot)
+static void CheckFile(const string& name, const string& expected_string, const bool checkInFileOrNot = true) {
+ vector<string> files;
+ GetFiles(name + "*", &files);
+ CHECK_EQ(files.size(), 1UL);
+
+ FILE* file = fopen(files[0].c_str(), "r");
+ CHECK(file != NULL) << ": could not open " << files[0];
+ char buf[1000];
+ while (fgets(buf, sizeof(buf), file) != NULL) {
+ char* first = strstr(buf, expected_string.c_str());
+ //if first == NULL, not found.
+ //Terser than if (checkInFileOrNot && first != NULL || !check...
+ if (checkInFileOrNot != (first == NULL)) {
+ fclose(file);
+ return;
+ }
+ }
+ fclose(file);
+ LOG(FATAL) << "Did " << (checkInFileOrNot? "not " : "") << "find " << expected_string << " in " << files[0];
+}
+
+static void TestBasename() {
+ fprintf(stderr, "==== Test setting log file basename\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename";
+ DeleteFiles(dest + "*");
+
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base";
+ FlushLogFiles(GLOG_INFO);
+
+ CheckFile(dest, "message to new base");
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+static void TestBasenameAppendWhenNoTimestamp() {
+ fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
+ DeleteFiles(dest + "*");
+
+ ofstream out(dest.c_str());
+ out << "test preexisting content" << endl;
+ out.close();
+
+ CheckFile(dest, "test preexisting content");
+
+ FLAGS_timestamp_in_logfile_name=false;
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base, appending to preexisting file";
+ FlushLogFiles(GLOG_INFO);
+ FLAGS_timestamp_in_logfile_name=true;
+
+ //if the logging overwrites the file instead of appending it will fail.
+ CheckFile(dest, "test preexisting content");
+ CheckFile(dest, "message to new base, appending to preexisting file");
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+static void TestTwoProcessesWrite() {
+// test only implemented for platforms with fork & wait; the actual implementation relies on flock
+#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL)
+ fprintf(stderr, "==== Test setting log file basename and two processes writing - second should fail\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
+ DeleteFiles(dest + "*");
+
+ //make both processes write into the same file (easier test)
+ FLAGS_timestamp_in_logfile_name=false;
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base, parent";
+ FlushLogFiles(GLOG_INFO);
+
+ pid_t pid = fork();
+ CHECK_ERR(pid);
+ if (pid == 0) {
+ LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file";
+ ShutdownGoogleLogging(); //for children proc
+ exit(EXIT_SUCCESS);
+ } else if (pid > 0) {
+ wait(NULL);
+ }
+ FLAGS_timestamp_in_logfile_name=true;
+
+ CheckFile(dest, "message to new base, parent");
+ CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false);
+
+ // Release
+ LogToStderr();
+ DeleteFiles(dest + "*");
+#endif
+}
+
+static void TestSymlink() {
+#ifndef GLOG_OS_WINDOWS
+ fprintf(stderr, "==== Test setting log file symlink\n");
+ string dest = FLAGS_test_tmpdir + "/logging_test_symlink";
+ string sym = FLAGS_test_tmpdir + "/symlinkbase";
+ DeleteFiles(dest + "*");
+ DeleteFiles(sym + "*");
+
+ SetLogSymlink(GLOG_INFO, "symlinkbase");
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new symlink";
+ FlushLogFiles(GLOG_INFO);
+ CheckFile(sym, "message to new symlink");
+
+ DeleteFiles(dest + "*");
+ DeleteFiles(sym + "*");
+#endif
+}
+
+static void TestExtension() {
+ fprintf(stderr, "==== Test setting log file extension\n");
+ string dest = FLAGS_test_tmpdir + "/logging_test_extension";
+ DeleteFiles(dest + "*");
+
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ SetLogFilenameExtension("specialextension");
+ LOG(INFO) << "message to new extension";
+ FlushLogFiles(GLOG_INFO);
+ CheckFile(dest, "message to new extension");
+
+ // Check that file name ends with extension
+ vector<string> filenames;
+ GetFiles(dest + "*", &filenames);
+ CHECK_EQ(filenames.size(), 1UL);
+ CHECK(strstr(filenames[0].c_str(), "specialextension") != NULL);
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+struct MyLogger : public base::Logger {
+ string data;
+
+ virtual void Write(bool /* should_flush */,
+ time_t /* timestamp */,
+ const char* message,
+ size_t length) {
+ data.append(message, length);
+ }
+
+ virtual void Flush() { }
+
+ virtual uint32 LogSize() { return data.length(); }
+};
+
+static void TestWrapper() {
+ fprintf(stderr, "==== Test log wrapper\n");
+
+ MyLogger my_logger;
+ base::Logger* old_logger = base::GetLogger(GLOG_INFO);
+ base::SetLogger(GLOG_INFO, &my_logger);
+ LOG(INFO) << "Send to wrapped logger";
+ FlushLogFiles(GLOG_INFO);
+ base::SetLogger(GLOG_INFO, old_logger);
+
+ CHECK(strstr(my_logger.data.c_str(), "Send to wrapped logger") != NULL);
+}
+
+static void TestErrno() {
+ fprintf(stderr, "==== Test errno preservation\n");
+
+ errno = ENOENT;
+ TestLogging(false);
+ CHECK_EQ(errno, ENOENT);
+}
+
+static void TestOneTruncate(const char *path, uint64 limit, uint64 keep,
+ size_t dsize, size_t ksize, size_t expect) {
+ int fd;
+ CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
+
+ const char *discardstr = "DISCARDME!", *keepstr = "KEEPME!";
+ const size_t discard_size = strlen(discardstr), keep_size = strlen(keepstr);
+
+ // Fill the file with the requested data; first discard data, then kept data
+ size_t written = 0;
+ while (written < dsize) {
+ size_t bytes = min(dsize - written, discard_size);
+ CHECK_ERR(write(fd, discardstr, bytes));
+ written += bytes;
+ }
+ written = 0;
+ while (written < ksize) {
+ size_t bytes = min(ksize - written, keep_size);
+ CHECK_ERR(write(fd, keepstr, bytes));
+ written += bytes;
+ }
+
+ TruncateLogFile(path, limit, keep);
+
+ // File should now be shorter
+ struct stat statbuf;
+ CHECK_ERR(fstat(fd, &statbuf));
+ CHECK_EQ(static_cast<size_t>(statbuf.st_size), expect);
+ CHECK_ERR(lseek(fd, 0, SEEK_SET));
+
+ // File should contain the suffix of the original file
+ const size_t buf_size = static_cast<size_t>(statbuf.st_size) + 1;
+ char* buf = new char[buf_size];
+ memset(buf, 0, buf_size);
+ CHECK_ERR(read(fd, buf, buf_size));
+
+ const char* p = buf;
+ size_t checked = 0;
+ while (checked < expect) {
+ size_t bytes = min(expect - checked, keep_size);
+ CHECK(!memcmp(p, keepstr, bytes));
+ checked += bytes;
+ }
+ close(fd);
+ delete[] buf;
+}
+
+static void TestTruncate() {
+#ifdef HAVE_UNISTD_H
+ fprintf(stderr, "==== Test log truncation\n");
+ string path = FLAGS_test_tmpdir + "/truncatefilecustom";
+
+ // Test on a small file
+ TestOneTruncate(path.c_str(), 10, 10, 10, 10, 10);
+
+ // And a big file (multiple blocks to copy)
+ TestOneTruncate(path.c_str(), 2U << 20U, 4U << 10U, 3U << 20U, 4U << 10U,
+ 4U << 10U);
+
+ // Check edge-case limits
+ TestOneTruncate(path.c_str(), 10, 20, 0, 20, 20);
+ TestOneTruncate(path.c_str(), 10, 0, 0, 0, 0);
+ TestOneTruncate(path.c_str(), 10, 50, 0, 10, 10);
+ TestOneTruncate(path.c_str(), 50, 100, 0, 30, 30);
+
+ // MacOSX 10.4 doesn't fail in this case.
+ // Windows doesn't have symlink.
+ // Let's just ignore this test for these cases.
+#if !defined(GLOG_OS_MACOSX) && !defined(GLOG_OS_WINDOWS)
+ // Through a symlink should fail to truncate
+ string linkname = path + ".link";
+ unlink(linkname.c_str());
+ CHECK_ERR(symlink(path.c_str(), linkname.c_str()));
+ TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30);
+#endif
+
+ // The /proc/self path makes sense only for linux.
+#if defined(GLOG_OS_LINUX)
+ // Through an open fd symlink should work
+ int fd;
+ CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
+ char fdpath[64];
+ snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
+ TestOneTruncate(fdpath, 10, 10, 10, 10, 10);
+#endif
+
+#endif
+}
+
+struct RecordDeletionLogger : public base::Logger {
+ RecordDeletionLogger(bool* set_on_destruction,
+ base::Logger* wrapped_logger) :
+ set_on_destruction_(set_on_destruction),
+ wrapped_logger_(wrapped_logger)
+ {
+ *set_on_destruction_ = false;
+ }
+ virtual ~RecordDeletionLogger() {
+ *set_on_destruction_ = true;
+ }
+ virtual void Write(bool force_flush,
+ time_t timestamp,
+ const char* message,
+ size_t length) {
+ wrapped_logger_->Write(force_flush, timestamp, message, length);
+ }
+ virtual void Flush() { wrapped_logger_->Flush(); }
+ virtual uint32 LogSize() { return wrapped_logger_->LogSize(); }
+ private:
+ bool* set_on_destruction_;
+ base::Logger* wrapped_logger_;
+};
+
+static void TestCustomLoggerDeletionOnShutdown() {
+ bool custom_logger_deleted = false;
+ base::SetLogger(GLOG_INFO,
+ new RecordDeletionLogger(&custom_logger_deleted,
+ base::GetLogger(GLOG_INFO)));
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+ ShutdownGoogleLogging();
+ EXPECT_TRUE(custom_logger_deleted);
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+}
+
+_START_GOOGLE_NAMESPACE_
+namespace glog_internal_namespace_ {
+extern // in logging.cc
+bool SafeFNMatch_(const char* pattern, size_t patt_len,
+ const char* str, size_t str_len);
+} // namespace glog_internal_namespace_
+using glog_internal_namespace_::SafeFNMatch_;
+_END_GOOGLE_NAMESPACE_
+
+static bool WrapSafeFNMatch(string pattern, string str) {
+ pattern += "abc";
+ str += "defgh";
+ return SafeFNMatch_(pattern.data(), pattern.size() - 3,
+ str.data(), str.size() - 5);
+}
+
+TEST(SafeFNMatch, logging) {
+ CHECK(WrapSafeFNMatch("foo", "foo"));
+ CHECK(!WrapSafeFNMatch("foo", "bar"));
+ CHECK(!WrapSafeFNMatch("foo", "fo"));
+ CHECK(!WrapSafeFNMatch("foo", "foo2"));
+ CHECK(WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext"));
+ CHECK(WrapSafeFNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/baz.ext"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo"));
+ CHECK(!WrapSafeFNMatch("bar/foo.ext", "bar/foo.ext.zip"));
+ CHECK(WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext"));
+ CHECK(WrapSafeFNMatch("ba?/*.ext", "baZ/FOO.ext"));
+ CHECK(!WrapSafeFNMatch("ba?/*.ext", "barr/foo.ext"));
+ CHECK(!WrapSafeFNMatch("ba?/*.ext", "bar/foo.ext2"));
+ CHECK(WrapSafeFNMatch("ba?/*", "bar/foo.ext2"));
+ CHECK(WrapSafeFNMatch("ba?/*", "bar/"));
+ CHECK(!WrapSafeFNMatch("ba?/?", "bar/"));
+ CHECK(!WrapSafeFNMatch("ba?/*", "bar"));
+}
+
+// TestWaitingLogSink will save messages here
+// No lock: Accessed only by TestLogSinkWriter thread
+// and after its demise by its creator.
+static vector<string> global_messages;
+
+// helper for TestWaitingLogSink below.
+// Thread that does the logic of TestWaitingLogSink
+// It's free to use LOG() itself.
+class TestLogSinkWriter : public Thread {
+ public:
+
+ TestLogSinkWriter() : should_exit_(false) {
+ SetJoinable(true);
+ Start();
+ }
+
+ // Just buffer it (can't use LOG() here).
+ void Buffer(const string& message) {
+ mutex_.Lock();
+ RAW_LOG(INFO, "Buffering");
+ messages_.push(message);
+ mutex_.Unlock();
+ RAW_LOG(INFO, "Buffered");
+ }
+
+ // Wait for the buffer to clear (can't use LOG() here).
+ void Wait() {
+ RAW_LOG(INFO, "Waiting");
+ mutex_.Lock();
+ while (!NoWork()) {
+ mutex_.Unlock();
+ SleepForMilliseconds(1);
+ mutex_.Lock();
+ }
+ RAW_LOG(INFO, "Waited");
+ mutex_.Unlock();
+ }
+
+ // Trigger thread exit.
+ void Stop() {
+ MutexLock l(&mutex_);
+ should_exit_ = true;
+ }
+
+ private:
+
+ // helpers ---------------
+
+ // For creating a "Condition".
+ bool NoWork() { return messages_.empty(); }
+ bool HaveWork() { return !messages_.empty() || should_exit_; }
+
+ // Thread body; CAN use LOG() here!
+ virtual void Run() {
+ while (1) {
+ mutex_.Lock();
+ while (!HaveWork()) {
+ mutex_.Unlock();
+ SleepForMilliseconds(1);
+ mutex_.Lock();
+ }
+ if (should_exit_ && messages_.empty()) {
+ mutex_.Unlock();
+ break;
+ }
+ // Give the main thread time to log its message,
+ // so that we get a reliable log capture to compare to golden file.
+ // Same for the other sleep below.
+ SleepForMilliseconds(20);
+ RAW_LOG(INFO, "Sink got a messages"); // only RAW_LOG under mutex_ here
+ string message = messages_.front();
+ messages_.pop();
+ // Normally this would be some more real/involved logging logic
+ // where LOG() usage can't be eliminated,
+ // e.g. pushing the message over with an RPC:
+ size_t messages_left = messages_.size();
+ mutex_.Unlock();
+ SleepForMilliseconds(20);
+ // May not use LOG while holding mutex_, because Buffer()
+ // acquires mutex_, and Buffer is called from LOG(),
+ // which has its own internal mutex:
+ // LOG()->LogToSinks()->TestWaitingLogSink::send()->Buffer()
+ LOG(INFO) << "Sink is sending out a message: " << message;
+ LOG(INFO) << "Have " << messages_left << " left";
+ global_messages.push_back(message);
+ }
+ }
+
+ // data ---------------
+
+ Mutex mutex_;
+ bool should_exit_;
+ queue<string> messages_; // messages to be logged
+};
+
+// A log sink that exercises WaitTillSent:
+// it pushes data to a buffer and wakes up another thread to do the logging
+// (that other thread can than use LOG() itself),
+class TestWaitingLogSink : public LogSink {
+ public:
+
+ TestWaitingLogSink() {
+ tid_ = pthread_self(); // for thread-specific behavior
+ AddLogSink(this);
+ }
+ ~TestWaitingLogSink() {
+ RemoveLogSink(this);
+ writer_.Stop();
+ writer_.Join();
+ }
+
+ // (re)define LogSink interface
+
+ virtual void send(LogSeverity severity, const char* /* full_filename */,
+ const char* base_filename, int line,
+ const LogMessageTime &logmsgtime,
+ const char* message, size_t message_len) {
+ // Push it to Writer thread if we are the original logging thread.
+ // Note: Something like ThreadLocalLogSink is a better choice
+ // to do thread-specific LogSink logic for real.
+ if (pthread_equal(tid_, pthread_self())) {
+ writer_.Buffer(ToString(severity, base_filename, line,
+ logmsgtime, message, message_len));
+ }
+ }
+
+ virtual void WaitTillSent() {
+ // Wait for Writer thread if we are the original logging thread.
+ if (pthread_equal(tid_, pthread_self())) writer_.Wait();
+ }
+
+ private:
+
+ pthread_t tid_;
+ TestLogSinkWriter writer_;
+};
+
+// Check that LogSink::WaitTillSent can be used in the advertised way.
+// We also do golden-stderr comparison.
+static void TestLogSinkWaitTillSent() {
+ { TestWaitingLogSink sink;
+ // Sleeps give the sink threads time to do all their work,
+ // so that we get a reliable log capture to compare to the golden file.
+ LOG(INFO) << "Message 1";
+ SleepForMilliseconds(60);
+ LOG(ERROR) << "Message 2";
+ SleepForMilliseconds(60);
+ LOG(WARNING) << "Message 3";
+ SleepForMilliseconds(60);
+ }
+ for (size_t i = 0; i < global_messages.size(); ++i) {
+ LOG(INFO) << "Sink capture: " << global_messages[i];
+ }
+ CHECK_EQ(global_messages.size(), 3UL);
+}
+
+TEST(Strerror, logging) {
+ int errcode = EINTR;
+ char *msg = strdup(strerror(errcode));
+ const size_t buf_size = strlen(msg) + 1;
+ char *buf = new char[buf_size];
+ CHECK_EQ(posix_strerror_r(errcode, NULL, 0), -1);
+ buf[0] = 'A';
+ CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
+ CHECK_EQ(buf[0], 'A');
+ CHECK_EQ(posix_strerror_r(errcode, NULL, buf_size), -1);
+#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD)
+ // MacOSX or FreeBSD considers this case is an error since there is
+ // no enough space.
+ CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
+#else
+ CHECK_EQ(posix_strerror_r(errcode, buf, 1), 0);
+#endif
+ CHECK_STREQ(buf, "");
+ CHECK_EQ(posix_strerror_r(errcode, buf, buf_size), 0);
+ CHECK_STREQ(buf, msg);
+ delete[] buf;
+ CHECK_EQ(msg, StrError(errcode));
+ free(msg);
+}
+
+// Simple routines to look at the sizes of generated code for LOG(FATAL) and
+// CHECK(..) via objdump
+/*
+static void MyFatal() {
+ LOG(FATAL) << "Failed";
+}
+static void MyCheck(bool a, bool b) {
+ CHECK_EQ(a, b);
+}
+*/
+#ifdef HAVE_LIB_GMOCK
+
+TEST(DVLog, Basic) {
+ ScopedMockLog log;
+
+#if defined(NDEBUG)
+ // We are expecting that nothing is logged.
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+#else
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "debug log"));
+#endif
+
+ FLAGS_v = 1;
+ DVLOG(1) << "debug log";
+}
+
+TEST(DVLog, V0) {
+ ScopedMockLog log;
+
+ // We are expecting that nothing is logged.
+ EXPECT_CALL(log, Log(_, _, _)).Times(0);
+
+ FLAGS_v = 0;
+ DVLOG(1) << "debug log";
+}
+
+TEST(LogAtLevel, Basic) {
+ ScopedMockLog log;
+
+ // The function version outputs "logging.h" as a file name.
+ EXPECT_CALL(log, Log(GLOG_WARNING, StrNe(__FILE__), "function version"));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "macro version"));
+
+ int severity = GLOG_WARNING;
+ LogAtLevel(severity, "function version");
+
+ severity = GLOG_INFO;
+ // We can use the macro version as a C++ stream.
+ LOG_AT_LEVEL(severity) << "macro" << ' ' << "version";
+}
+
+TEST(TestExitOnDFatal, ToBeOrNotToBe) {
+ // Check the default setting...
+ EXPECT_TRUE(base::internal::GetExitOnDFatal());
+
+ // Turn off...
+ base::internal::SetExitOnDFatal(false);
+ EXPECT_FALSE(base::internal::GetExitOnDFatal());
+
+ // We don't die.
+ {
+ ScopedMockLog log;
+ //EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
+ // LOG(DFATAL) has severity FATAL if debugging, but is
+ // downgraded to ERROR if not debugging.
+ const LogSeverity severity =
+#if defined(NDEBUG)
+ GLOG_ERROR;
+#else
+ GLOG_FATAL;
+#endif
+ EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
+ LOG(DFATAL) << "This should not be fatal";
+ }
+
+ // Turn back on...
+ base::internal::SetExitOnDFatal(true);
+ EXPECT_TRUE(base::internal::GetExitOnDFatal());
+
+#ifdef GTEST_HAS_DEATH_TEST
+ // Death comes on little cats' feet.
+ EXPECT_DEBUG_DEATH({
+ LOG(DFATAL) << "This should be fatal in debug mode";
+ }, "This should be fatal in debug mode");
+#endif
+}
+
+#ifdef HAVE_STACKTRACE
+
+static void BacktraceAtHelper() {
+ LOG(INFO) << "Not me";
+
+// The vertical spacing of the next 3 lines is significant.
+ LOG(INFO) << "Backtrace me";
+}
+static int kBacktraceAtLine = __LINE__ - 2; // The line of the LOG(INFO) above
+
+TEST(LogBacktraceAt, DoesNotBacktraceWhenDisabled) {
+ StrictMock<ScopedMockLog> log;
+
+ FLAGS_log_backtrace_at = "";
+
+ EXPECT_CALL(log, Log(_, _, "Backtrace me"));
+ EXPECT_CALL(log, Log(_, _, "Not me"));
+
+ BacktraceAtHelper();
+}
+
+TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
+ StrictMock<ScopedMockLog> log;
+
+ char where[100];
+ snprintf(where, 100, "%s:%d", const_basename(__FILE__), kBacktraceAtLine);
+ FLAGS_log_backtrace_at = where;
+
+ // The LOG at the specified line should include a stacktrace which includes
+ // the name of the containing function, followed by the log message.
+ // We use HasSubstr()s instead of ContainsRegex() for environments
+ // which don't have regexp.
+ EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"),
+ HasSubstr("BacktraceAtHelper"),
+ HasSubstr("main"),
+ HasSubstr("Backtrace me"))));
+ // Other LOGs should not include a backtrace.
+ EXPECT_CALL(log, Log(_, _, "Not me"));
+
+ BacktraceAtHelper();
+}
+
+#endif // HAVE_STACKTRACE
+
+#endif // HAVE_LIB_GMOCK
+
+struct UserDefinedClass {
+ bool operator==(const UserDefinedClass&) const { return true; }
+};
+
+inline ostream& operator<<(ostream& out, const UserDefinedClass&) {
+ out << "OK";
+ return out;
+}
+
+TEST(UserDefinedClass, logging) {
+ UserDefinedClass u;
+ vector<string> buf;
+ LOG_STRING(INFO, &buf) << u;
+ CHECK_EQ(1UL, buf.size());
+ CHECK(buf[0].find("OK") != string::npos);
+
+ // We must be able to compile this.
+ CHECK_EQ(u, u);
+}
+
+TEST(LogMsgTime, gmtoff) {
+ /*
+ * Unit test for GMT offset API
+ * TODO: To properly test this API, we need a platform independent way to set time-zone.
+ * */
+ google::LogMessage log_obj(__FILE__, __LINE__);
+
+ long int nGmtOff = log_obj.getLogMessageTime().gmtoff();
+ // GMT offset ranges from UTC-12:00 to UTC+14:00
+ const long utc_min_offset = -43200;
+ const long utc_max_offset = 50400;
+ EXPECT_TRUE( (nGmtOff >= utc_min_offset) && (nGmtOff <= utc_max_offset) );
+}
diff --git a/src/logging_custom_prefix_unittest.err b/src/logging_custom_prefix_unittest.err
new file mode 100644
index 0000000..ccd5ba9
--- /dev/null
+++ b/src/logging_custom_prefix_unittest.err
@@ -0,0 +1,308 @@
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WARNING: Logging before InitGoogleLogging() is written to STDERR
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] foo bar 10 3.4
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 1
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 1
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 5, iteration 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 1
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 2
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 3
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 4
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 4
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 5
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 5
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 5, iteration 6
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 6
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 7
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 7
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 8
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 4, iteration 9
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 9
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log every 3, iteration 10
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Log if every 1, iteration 10
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if this
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] const array
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] foo 1000 1000 3e8
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] foo 1
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] inner
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] outer
+no prefix
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo bar 10 3.400000
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: const array
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: ptr __PTRTEST__
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: ptr __NULLP__
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: foo 1000
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 2 on
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_STRING: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_SINK:
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected info
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported info
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] LOG_TO_STRING: reported error
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Have 0 left
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_custom_prefix_unittest.cc:LINE] Message 3
diff --git a/src/logging_striptest_main.cc b/src/logging_striptest_main.cc
index 2fb9127..27e1254 100644
--- a/src/logging_striptest_main.cc
+++ b/src/logging_striptest_main.cc
@@ -31,10 +31,10 @@
// The common part of the striplog tests.
-#include <stdio.h>
+#include <cstdio>
#include <string>
#include <iosfwd>
-#include "glog/logging.h"
+#include <glog/logging.h>
#include "base/commandlineflags.h"
#include "config.h"
diff --git a/src/logging_unittest.cc b/src/logging_unittest.cc
index 8770d52..728b5fe 100644
--- a/src/logging_unittest.cc
+++ b/src/logging_unittest.cc
@@ -29,7 +29,7 @@
//
// Author: Ray Sidney
-#include "config_for_unittests.h"
+#include "config.h"
#include "utilities.h"
#include <fcntl.h>
@@ -40,7 +40,13 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
#include <iomanip>
#include <iostream>
#include <memory>
@@ -49,12 +55,9 @@
#include <string>
#include <vector>
-#include <stdio.h>
-#include <stdlib.h>
-
#include "base/commandlineflags.h"
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
#include "googletest.h"
DECLARE_string(log_backtrace_at); // logging.cc
@@ -95,6 +98,7 @@
static void TestRawLogging();
static void LogWithLevels(int v, int severity, bool err, bool alsoerr);
static void TestLoggingLevels();
+static void TestVLogModule();
static void TestLogString();
static void TestLogSink();
static void TestLogToString();
@@ -103,11 +107,15 @@
static void TestDCHECK();
static void TestSTREQ();
static void TestBasename();
+static void TestBasenameAppendWhenNoTimestamp();
+static void TestTwoProcessesWrite();
static void TestSymlink();
static void TestExtension();
static void TestWrapper();
static void TestErrno();
static void TestTruncate();
+static void TestCustomLoggerDeletionOnShutdown();
+static void TestLogPeriodically();
static int x = -1;
static void BM_Check1(int n) {
@@ -122,7 +130,7 @@
CHECK_GE(n, x);
}
}
-BENCHMARK(BM_Check1);
+BENCHMARK(BM_Check1)
static void CheckFailure(int a, int b, const char* file, int line, const char* msg);
static void BM_Check3(int n) {
@@ -137,7 +145,7 @@
if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
}
}
-BENCHMARK(BM_Check3);
+BENCHMARK(BM_Check3)
static void BM_Check2(int n) {
if (n == 17) {
@@ -154,7 +162,7 @@
CHECK(n >= x);
}
}
-BENCHMARK(BM_Check2);
+BENCHMARK(BM_Check2)
static void CheckFailure(int, int, const char* /* file */, int /* line */,
const char* /* msg */) {
@@ -165,20 +173,19 @@
LOG(INFO) << "test message";
}
}
-BENCHMARK(BM_logspeed);
+BENCHMARK(BM_logspeed)
static void BM_vlog(int n) {
while (n-- > 0) {
VLOG(1) << "test message";
}
}
-BENCHMARK(BM_vlog);
+BENCHMARK(BM_vlog)
int main(int argc, char **argv) {
FLAGS_colorlogtostderr = false;
-#ifdef HAVE_LIB_GFLAGS
- ParseCommandLineFlags(&argc, &argv, true);
-#endif
+ FLAGS_timestamp_in_logfile_name = true;
+
// Make sure stderr is not buffered as stderr seems to be buffered
// on recent windows.
setbuf(stderr, NULL);
@@ -190,8 +197,12 @@
LogWithLevels(0, 0, 0, 0); // simulate "before global c-tors"
const string early_stderr = GetCapturedTestStderr();
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+
InitGoogleLogging(argv[0]);
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+
RunSpecifiedBenchmarks();
FLAGS_logtostderr = true;
@@ -201,6 +212,10 @@
InitGoogleMock(&argc, argv);
#endif
+#ifdef HAVE_LIB_GFLAGS
+ ParseCommandLineFlags(&argc, &argv, true);
+#endif
+
// so that death tests run before we use threads
CHECK_EQ(RUN_ALL_TESTS(), 0);
@@ -212,6 +227,7 @@
TestLogging(true);
TestRawLogging();
TestLoggingLevels();
+ TestVLogModule();
TestLogString();
TestLogSink();
TestLogToString();
@@ -226,14 +242,32 @@
FLAGS_logtostderr = false;
+ FLAGS_logtostdout = true;
+ FLAGS_stderrthreshold = NUM_SEVERITIES;
+ CaptureTestStdout();
+ TestRawLogging();
+ TestLoggingLevels();
+ TestLogString();
+ TestLogSink();
+ TestLogToString();
+ TestLogSinkWaitTillSent();
+ TestCHECK();
+ TestDCHECK();
+ TestSTREQ();
+ EXPECT_TRUE(
+ MungeAndDiffTestStdout(FLAGS_test_srcdir + "/src/logging_unittest.out"));
+ FLAGS_logtostdout = false;
+
TestBasename();
+ TestBasenameAppendWhenNoTimestamp();
+ TestTwoProcessesWrite();
TestSymlink();
TestExtension();
TestWrapper();
TestErrno();
TestTruncate();
-
- ShutdownGoogleLogging();
+ TestCustomLoggerDeletionOnShutdown();
+ TestLogPeriodically();
fprintf(stdout, "PASS\n");
return 0;
@@ -271,6 +305,7 @@
int j = 1000;
LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
<< setw(1) << hex << j;
+ LOG(INFO) << "foo " << std::setw(10) << 1.0;
{
google::LogMessage outer(__FILE__, __LINE__, GLOG_ERROR);
@@ -282,7 +317,7 @@
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
if (check_counts) {
- CHECK_EQ(base_num_infos + 14, LogMessage::num_messages(GLOG_INFO));
+ CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO));
CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING));
CHECK_EQ(base_num_errors + 17, LogMessage::num_messages(GLOG_ERROR));
}
@@ -331,7 +366,7 @@
RAW_LOG(ERROR, "%s%d%c%010d%s%1x", foo->c_str(), j, ' ', j, " ", j);
RAW_VLOG(0, "foo %d", j);
-#ifdef NDEBUG
+#if defined(NDEBUG)
RAW_LOG(INFO, "foo %d", j); // so that have same stderr to compare
#else
RAW_DLOG(INFO, "foo %d", j); // test RAW_DLOG in debug mode
@@ -353,7 +388,7 @@
RAW_VLOG(2, "vlog 2 on");
RAW_VLOG(3, "vlog 3 off");
-#ifdef NDEBUG
+#if defined(NDEBUG)
RAW_DCHECK(1 == 2, " RAW_DCHECK's shouldn't be compiled in normal mode");
#endif
@@ -441,6 +476,24 @@
LogWithLevels(1, GLOG_FATAL, false, true);
}
+int TestVlogHelper() {
+ if (VLOG_IS_ON(1)) {
+ return 1;
+ }
+ return 0;
+}
+
+void TestVLogModule() {
+ int c = TestVlogHelper();
+ EXPECT_EQ(0, c);
+
+#if defined(__GNUC__)
+ EXPECT_EQ(0, SetVLOGLevel("logging_unittest", 1));
+ c = TestVlogHelper();
+ EXPECT_EQ(1, c);
+#endif
+}
+
TEST(DeathRawCHECK, logging) {
ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
"RAW: Check false failed: failure 1");
@@ -486,10 +539,10 @@
vector<string> errors;
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
- const struct tm* tm_time,
+ const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
errors.push_back(
- ToString(severity, base_filename, line, tm_time, message, message_len));
+ ToString(severity, base_filename, line, logmsgtime, message, message_len));
}
};
@@ -546,7 +599,7 @@
// Tests using CHECK*() on anonymous enums.
// Apple's GCC doesn't like this.
-#if !defined(OS_MACOSX)
+#if !defined(GLOG_OS_MACOSX)
CHECK_EQ(CASE_A, CASE_A);
CHECK_NE(CASE_A, CASE_B);
CHECK_GE(CASE_A, CASE_A);
@@ -559,7 +612,7 @@
}
void TestDCHECK() {
-#ifdef NDEBUG
+#if defined(NDEBUG)
DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode";
#endif
DCHECK( 1 == 1 );
@@ -572,9 +625,10 @@
DCHECK_GT(2, 1);
DCHECK_LT(1, 2);
- auto_ptr<int64> sptr(new int64);
- int64* ptr = DCHECK_NOTNULL(sptr.get());
- CHECK_EQ(ptr, sptr.get());
+ int64* orig_ptr = new int64;
+ int64* ptr = DCHECK_NOTNULL(orig_ptr);
+ CHECK_EQ(ptr, orig_ptr);
+ delete orig_ptr;
}
void TestSTREQ() {
@@ -627,7 +681,7 @@
files->push_back(string(g.gl_pathv[i]));
}
globfree(&g);
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
WIN32_FIND_DATAA data;
HANDLE handle = FindFirstFileA(pattern.c_str(), &data);
size_t index = pattern.rfind('\\');
@@ -643,7 +697,7 @@
files->push_back(dirname + data.cFileName);
} while (FindNextFileA(handle, &data));
BOOL result = FindClose(handle);
- LOG_SYSRESULT(result);
+ LOG_SYSRESULT(result != 0);
#else
# error There is no way to do glob.
#endif
@@ -658,7 +712,8 @@
}
}
-static void CheckFile(const string& name, const string& expected_string) {
+//check string is in file (or is *NOT*, depending on optional checkInFileOrNot)
+static void CheckFile(const string& name, const string& expected_string, const bool checkInFileOrNot = true) {
vector<string> files;
GetFiles(name + "*", &files);
CHECK_EQ(files.size(), 1UL);
@@ -667,13 +722,16 @@
CHECK(file != NULL) << ": could not open " << files[0];
char buf[1000];
while (fgets(buf, sizeof(buf), file) != NULL) {
- if (strstr(buf, expected_string.c_str()) != NULL) {
+ char* first = strstr(buf, expected_string.c_str());
+ //if first == NULL, not found.
+ //Terser than if (checkInFileOrNot && first != NULL || !check...
+ if (checkInFileOrNot != (first == NULL)) {
fclose(file);
return;
}
}
fclose(file);
- LOG(FATAL) << "Did not find " << expected_string << " in " << files[0];
+ LOG(FATAL) << "Did " << (checkInFileOrNot? "not " : "") << "find " << expected_string << " in " << files[0];
}
static void TestBasename() {
@@ -692,8 +750,67 @@
DeleteFiles(dest + "*");
}
+static void TestBasenameAppendWhenNoTimestamp() {
+ fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
+ DeleteFiles(dest + "*");
+
+ ofstream out(dest.c_str());
+ out << "test preexisting content" << endl;
+ out.close();
+
+ CheckFile(dest, "test preexisting content");
+
+ FLAGS_timestamp_in_logfile_name=false;
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base, appending to preexisting file";
+ FlushLogFiles(GLOG_INFO);
+ FLAGS_timestamp_in_logfile_name=true;
+
+ //if the logging overwrites the file instead of appending it will fail.
+ CheckFile(dest, "test preexisting content");
+ CheckFile(dest, "message to new base, appending to preexisting file");
+
+ // Release file handle for the destination file to unlock the file in Windows.
+ LogToStderr();
+ DeleteFiles(dest + "*");
+}
+
+static void TestTwoProcessesWrite() {
+// test only implemented for platforms with fork & wait; the actual implementation relies on flock
+#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL)
+ fprintf(stderr, "==== Test setting log file basename and two processes writing - second should fail\n");
+ const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
+ DeleteFiles(dest + "*");
+
+ //make both processes write into the same file (easier test)
+ FLAGS_timestamp_in_logfile_name=false;
+ SetLogDestination(GLOG_INFO, dest.c_str());
+ LOG(INFO) << "message to new base, parent";
+ FlushLogFiles(GLOG_INFO);
+
+ pid_t pid = fork();
+ CHECK_ERR(pid);
+ if (pid == 0) {
+ LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file";
+ ShutdownGoogleLogging(); //for children proc
+ exit(EXIT_SUCCESS);
+ } else if (pid > 0) {
+ wait(NULL);
+ }
+ FLAGS_timestamp_in_logfile_name=true;
+
+ CheckFile(dest, "message to new base, parent");
+ CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false);
+
+ // Release
+ LogToStderr();
+ DeleteFiles(dest + "*");
+#endif
+}
+
static void TestSymlink() {
-#ifndef OS_WINDOWS
+#ifndef GLOG_OS_WINDOWS
fprintf(stderr, "==== Test setting log file symlink\n");
string dest = FLAGS_test_tmpdir + "/logging_test_symlink";
string sym = FLAGS_test_tmpdir + "/symlinkbase";
@@ -739,7 +856,7 @@
virtual void Write(bool /* should_flush */,
time_t /* timestamp */,
const char* message,
- int length) {
+ size_t length) {
data.append(message, length);
}
@@ -769,8 +886,8 @@
CHECK_EQ(errno, ENOENT);
}
-static void TestOneTruncate(const char *path, int64 limit, int64 keep,
- int64 dsize, int64 ksize, int64 expect) {
+static void TestOneTruncate(const char *path, uint64 limit, uint64 keep,
+ size_t dsize, size_t ksize, size_t expect) {
int fd;
CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
@@ -778,15 +895,15 @@
const size_t discard_size = strlen(discardstr), keep_size = strlen(keepstr);
// Fill the file with the requested data; first discard data, then kept data
- int64 written = 0;
+ size_t written = 0;
while (written < dsize) {
- int bytes = min<int64>(dsize - written, discard_size);
+ size_t bytes = min(dsize - written, discard_size);
CHECK_ERR(write(fd, discardstr, bytes));
written += bytes;
}
written = 0;
while (written < ksize) {
- int bytes = min<int64>(ksize - written, keep_size);
+ size_t bytes = min(ksize - written, keep_size);
CHECK_ERR(write(fd, keepstr, bytes));
written += bytes;
}
@@ -796,19 +913,19 @@
// File should now be shorter
struct stat statbuf;
CHECK_ERR(fstat(fd, &statbuf));
- CHECK_EQ(statbuf.st_size, expect);
+ CHECK_EQ(static_cast<size_t>(statbuf.st_size), expect);
CHECK_ERR(lseek(fd, 0, SEEK_SET));
// File should contain the suffix of the original file
- const size_t buf_size = statbuf.st_size + 1;
+ const size_t buf_size = static_cast<size_t>(statbuf.st_size) + 1;
char* buf = new char[buf_size];
memset(buf, 0, buf_size);
CHECK_ERR(read(fd, buf, buf_size));
- const char *p = buf;
- int64 checked = 0;
+ const char* p = buf;
+ size_t checked = 0;
while (checked < expect) {
- int bytes = min<int64>(expect - checked, keep_size);
+ size_t bytes = min(expect - checked, keep_size);
CHECK(!memcmp(p, keepstr, bytes));
checked += bytes;
}
@@ -825,7 +942,8 @@
TestOneTruncate(path.c_str(), 10, 10, 10, 10, 10);
// And a big file (multiple blocks to copy)
- TestOneTruncate(path.c_str(), 2<<20, 4<<10, 3<<20, 4<<10, 4<<10);
+ TestOneTruncate(path.c_str(), 2U << 20U, 4U << 10U, 3U << 20U, 4U << 10U,
+ 4U << 10U);
// Check edge-case limits
TestOneTruncate(path.c_str(), 10, 20, 0, 20, 20);
@@ -836,7 +954,7 @@
// MacOSX 10.4 doesn't fail in this case.
// Windows doesn't have symlink.
// Let's just ignore this test for these cases.
-#if !defined(OS_MACOSX) && !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_MACOSX) && !defined(GLOG_OS_WINDOWS)
// Through a symlink should fail to truncate
string linkname = path + ".link";
unlink(linkname.c_str());
@@ -845,7 +963,7 @@
#endif
// The /proc/self path makes sense only for linux.
-#if defined(OS_LINUX)
+#if defined(GLOG_OS_LINUX)
// Through an open fd symlink should work
int fd;
CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
@@ -857,6 +975,134 @@
#endif
}
+struct RecordDeletionLogger : public base::Logger {
+ RecordDeletionLogger(bool* set_on_destruction,
+ base::Logger* wrapped_logger) :
+ set_on_destruction_(set_on_destruction),
+ wrapped_logger_(wrapped_logger)
+ {
+ *set_on_destruction_ = false;
+ }
+ virtual ~RecordDeletionLogger() {
+ *set_on_destruction_ = true;
+ }
+ virtual void Write(bool force_flush,
+ time_t timestamp,
+ const char* message,
+ size_t length) {
+ wrapped_logger_->Write(force_flush, timestamp, message, length);
+ }
+ virtual void Flush() { wrapped_logger_->Flush(); }
+ virtual uint32 LogSize() { return wrapped_logger_->LogSize(); }
+ private:
+ bool* set_on_destruction_;
+ base::Logger* wrapped_logger_;
+};
+
+static void TestCustomLoggerDeletionOnShutdown() {
+ bool custom_logger_deleted = false;
+ base::SetLogger(GLOG_INFO,
+ new RecordDeletionLogger(&custom_logger_deleted,
+ base::GetLogger(GLOG_INFO)));
+ EXPECT_TRUE(IsGoogleLoggingInitialized());
+ ShutdownGoogleLogging();
+ EXPECT_TRUE(custom_logger_deleted);
+ EXPECT_FALSE(IsGoogleLoggingInitialized());
+}
+
+namespace LogTimes {
+// Log a "message" every 10ms, 10 times. These numbers are nice compromise
+// between total running time of 100ms and the period of 10ms. The period is
+// large enough such that any CPU and OS scheduling variation shouldn't affect
+// the results from the ideal case by more than 5% (500us or 0.5ms)
+GLOG_CONSTEXPR int64_t LOG_PERIOD_NS = 10000000; // 10ms
+GLOG_CONSTEXPR int64_t LOG_PERIOD_TOL_NS = 500000; // 500us
+
+// Set an upper limit for the number of times the stream operator can be
+// called. Make sure not to exceed this number of times the stream operator is
+// called, since it is also the array size and will be indexed by the stream
+// operator.
+GLOG_CONSTEXPR size_t MAX_CALLS = 10;
+} // namespace LogTimes
+
+#if defined(HAVE_CXX11_CHRONO) && __cplusplus >= 201103L
+struct LogTimeRecorder {
+ LogTimeRecorder() : m_streamTimes(0) {}
+ size_t m_streamTimes;
+ std::chrono::steady_clock::time_point m_callTimes[LogTimes::MAX_CALLS];
+};
+// The stream operator is called by LOG_EVERY_T every time a logging event
+// occurs. Make sure to save the times for each call as they will be used later
+// to verify the time delta between each call.
+std::ostream& operator<<(std::ostream& stream, LogTimeRecorder& t) {
+ t.m_callTimes[t.m_streamTimes++] = std::chrono::steady_clock::now();
+ return stream;
+}
+// get elapsed time in nanoseconds
+int64 elapsedTime_ns(const std::chrono::steady_clock::time_point& begin,
+ const std::chrono::steady_clock::time_point& end) {
+ return std::chrono::duration_cast<std::chrono::nanoseconds>((end - begin))
+ .count();
+}
+#elif defined(GLOG_OS_WINDOWS)
+struct LogTimeRecorder {
+ LogTimeRecorder() : m_streamTimes(0) {}
+ size_t m_streamTimes;
+ LARGE_INTEGER m_callTimes[LogTimes::MAX_CALLS];
+};
+std::ostream& operator<<(std::ostream& stream, LogTimeRecorder& t) {
+ QueryPerformanceCounter(&t.m_callTimes[t.m_streamTimes++]);
+ return stream;
+}
+// get elapsed time in nanoseconds
+int64 elapsedTime_ns(const LARGE_INTEGER& begin, const LARGE_INTEGER& end) {
+ LARGE_INTEGER freq;
+ QueryPerformanceFrequency(&freq);
+ return (end.QuadPart - begin.QuadPart) * LONGLONG(1000000000) / freq.QuadPart;
+}
+#else
+struct LogTimeRecorder {
+ LogTimeRecorder() : m_streamTimes(0) {}
+ size_t m_streamTimes;
+ timespec m_callTimes[LogTimes::MAX_CALLS];
+};
+std::ostream& operator<<(std::ostream& stream, LogTimeRecorder& t) {
+ clock_gettime(CLOCK_MONOTONIC, &t.m_callTimes[t.m_streamTimes++]);
+ return stream;
+}
+// get elapsed time in nanoseconds
+int64 elapsedTime_ns(const timespec& begin, const timespec& end) {
+ return (end.tv_sec - begin.tv_sec) * 1000000000 +
+ (end.tv_nsec - begin.tv_nsec);
+}
+#endif
+
+static void TestLogPeriodically() {
+ fprintf(stderr, "==== Test log periodically\n");
+
+ LogTimeRecorder timeLogger;
+
+ GLOG_CONSTEXPR double LOG_PERIOD_SEC = LogTimes::LOG_PERIOD_NS * 1e-9;
+
+ while (timeLogger.m_streamTimes < LogTimes::MAX_CALLS) {
+ LOG_EVERY_T(INFO, LOG_PERIOD_SEC)
+ << timeLogger << "Timed Message #" << timeLogger.m_streamTimes;
+ }
+
+ // Calculate time between each call in nanoseconds for higher resolution to
+ // minimize error.
+ int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1];
+ for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) {
+ nsBetweenCalls[i - 1] = elapsedTime_ns(
+ timeLogger.m_callTimes[i - 1], timeLogger.m_callTimes[i]);
+ }
+
+ for (size_t idx = 0; idx < LogTimes::MAX_CALLS - 1; ++idx) {
+ int64 time_ns = nsBetweenCalls[idx];
+ EXPECT_NEAR(time_ns, LogTimes::LOG_PERIOD_NS, LogTimes::LOG_PERIOD_TOL_NS);
+ }
+}
+
_START_GOOGLE_NAMESPACE_
namespace glog_internal_namespace_ {
extern // in logging.cc
@@ -968,7 +1214,7 @@
// Normally this would be some more real/involved logging logic
// where LOG() usage can't be eliminated,
// e.g. pushing the message over with an RPC:
- int messages_left = messages_.size();
+ size_t messages_left = messages_.size();
mutex_.Unlock();
SleepForMilliseconds(20);
// May not use LOG while holding mutex_, because Buffer()
@@ -1008,16 +1254,17 @@
virtual void send(LogSeverity severity, const char* /* full_filename */,
const char* base_filename, int line,
- const struct tm* tm_time,
+ const LogMessageTime &logmsgtime,
const char* message, size_t message_len) {
// Push it to Writer thread if we are the original logging thread.
// Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line,
- tm_time, message, message_len));
+ logmsgtime, message, message_len));
}
}
+
virtual void WaitTillSent() {
// Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait();
@@ -1032,6 +1279,9 @@
// Check that LogSink::WaitTillSent can be used in the advertised way.
// We also do golden-stderr comparison.
static void TestLogSinkWaitTillSent() {
+ // Clear global_messages here to make sure that this test case can be
+ // reentered
+ global_messages.clear();
{ TestWaitingLogSink sink;
// Sleeps give the sink threads time to do all their work,
// so that we get a reliable log capture to compare to the golden file.
@@ -1058,7 +1308,7 @@
CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
CHECK_EQ(buf[0], 'A');
CHECK_EQ(posix_strerror_r(errcode, NULL, buf_size), -1);
-#if defined(OS_MACOSX) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD)
// MacOSX or FreeBSD considers this case is an error since there is
// no enough space.
CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
@@ -1075,23 +1325,24 @@
// Simple routines to look at the sizes of generated code for LOG(FATAL) and
// CHECK(..) via objdump
+/*
static void MyFatal() {
LOG(FATAL) << "Failed";
}
static void MyCheck(bool a, bool b) {
CHECK_EQ(a, b);
}
-
+*/
#ifdef HAVE_LIB_GMOCK
TEST(DVLog, Basic) {
ScopedMockLog log;
-#if NDEBUG
+#if defined(NDEBUG)
// We are expecting that nothing is logged.
EXPECT_CALL(log, Log(_, _, _)).Times(0);
#else
- EXPECT_CALL(log, Log(INFO, __FILE__, "debug log"));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "debug log"));
#endif
FLAGS_v = 1;
@@ -1112,13 +1363,13 @@
ScopedMockLog log;
// The function version outputs "logging.h" as a file name.
- EXPECT_CALL(log, Log(WARNING, StrNe(__FILE__), "function version"));
- EXPECT_CALL(log, Log(INFO, __FILE__, "macro version"));
+ EXPECT_CALL(log, Log(GLOG_WARNING, StrNe(__FILE__), "function version"));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "macro version"));
- int severity = WARNING;
+ int severity = GLOG_WARNING;
LogAtLevel(severity, "function version");
- severity = INFO;
+ severity = GLOG_INFO;
// We can use the macro version as a C++ stream.
LOG_AT_LEVEL(severity) << "macro" << ' ' << "version";
}
@@ -1138,10 +1389,10 @@
// LOG(DFATAL) has severity FATAL if debugging, but is
// downgraded to ERROR if not debugging.
const LogSeverity severity =
-#ifdef NDEBUG
- ERROR;
+#if defined(NDEBUG)
+ GLOG_ERROR;
#else
- FATAL;
+ GLOG_FATAL;
#endif
EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
LOG(DFATAL) << "This should not be fatal";
diff --git a/src/logging_unittest.err b/src/logging_unittest.err
index 2ecc1b0..21517cb 100644
--- a/src/logging_unittest.err
+++ b/src/logging_unittest.err
@@ -1,307 +1,308 @@
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WARNING: Logging before InitGoogleLogging() is written to STDERR
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] foo bar 10 3.4
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 1
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 1
-WDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 1
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 2
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 3
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 4
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 4
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 5
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 5
-WDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 6
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 6
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 7
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 7
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 8
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 9
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 9
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 10
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 10
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
-IDATE TIME__ THREADID logging_unittest.cc:LINE] array
-IDATE TIME__ THREADID logging_unittest.cc:LINE] const array
-EDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 0000001000 3e8
-EDATE TIME__ THREADID logging_unittest.cc:LINE] inner
-EDATE TIME__ THREADID logging_unittest.cc:LINE] outer
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo bar 10 3.4
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 1
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 1
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 1
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 2
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 3
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 4
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 4
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 5
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 5
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 6
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 6
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 7
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 7
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 8
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 9
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 9
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 10
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 10
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] array
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] const array
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 1000 3e8
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] inner
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] outer
no prefix
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: const array
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __PTRTEST__
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __NULLP__
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0 on
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1 on
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 2 on
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
-EDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
-WDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
-EDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
-EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
-WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
-IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
-IDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: const array
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __PTRTEST__
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __NULLP__
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0 on
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1 on
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 2 on
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
diff --git a/src/logging_unittest.out b/src/logging_unittest.out
new file mode 100644
index 0000000..18795e1
--- /dev/null
+++ b/src/logging_unittest.out
@@ -0,0 +1,150 @@
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
+IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
diff --git a/src/mock-log.h b/src/mock-log.h
index 30a0f74..bdfb3c5 100644
--- a/src/mock-log.h
+++ b/src/mock-log.h
@@ -42,7 +42,7 @@
#include <gmock/gmock.h>
-#include "glog/logging.h"
+#include <glog/logging.h>
_START_GOOGLE_NAMESPACE_
namespace glog_testing {
@@ -72,7 +72,7 @@
ScopedMockLog() { AddLogSink(this); }
// When the object is destructed, it stops intercepting logs.
- virtual ~ScopedMockLog() { RemoveLogSink(this); }
+ ~ScopedMockLog() { RemoveLogSink(this); }
// Implements the mock method:
//
@@ -116,7 +116,7 @@
virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
const char* full_filename,
const char* /*base_filename*/, int /*line*/,
- const tm* /*tm_time*/,
+ const LogMessageTime & /*logmsgtime*/,
const char* message, size_t message_len) {
// We are only interested in the log severity, full file name, and
// log message.
diff --git a/src/mock-log_test.cc b/src/mock-log_unittest.cc
similarity index 78%
rename from src/mock-log_test.cc
rename to src/mock-log_unittest.cc
index 7d58a30..b9bef4e 100644
--- a/src/mock-log_test.cc
+++ b/src/mock-log_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2007, Google Inc.
+// Copyright (c) 2022, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -40,13 +40,13 @@
namespace {
-using GOOGLE_NAMESPACE::INFO;
-using GOOGLE_NAMESPACE::WARNING;
-using GOOGLE_NAMESPACE::ERROR;
+using GOOGLE_NAMESPACE::GLOG_ERROR;
+using GOOGLE_NAMESPACE::GLOG_INFO;
+using GOOGLE_NAMESPACE::GLOG_WARNING;
using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
using std::string;
using testing::_;
-using testing::HasSubstr;
+using testing::EndsWith;
using testing::InSequence;
using testing::InvokeWithoutArgs;
@@ -55,10 +55,11 @@
ScopedMockLog log;
InSequence s;
- EXPECT_CALL(log, Log(WARNING, HasSubstr("/mock-log_test.cc"), "Fishy."));
- EXPECT_CALL(log, Log(INFO, _, "Working..."))
+ EXPECT_CALL(log,
+ Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy."));
+ EXPECT_CALL(log, Log(GLOG_INFO, _, "Working..."))
.Times(2);
- EXPECT_CALL(log, Log(ERROR, _, "Bad!!"));
+ EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!"));
LOG(WARNING) << "Fishy.";
LOG(INFO) << "Working...";
@@ -86,13 +87,13 @@
TEST(ScopedMockLogTest, LogDuringIntercept) {
ScopedMockLog log;
InSequence s;
- EXPECT_CALL(log, Log(INFO, __FILE__, "Logging a branch..."))
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "Logging a branch..."))
.WillOnce(InvokeWithoutArgs(LogTree));
- EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the whole tree..."))
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "Logging the whole tree..."))
.WillOnce(InvokeWithoutArgs(LogForest));
- EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest."));
- EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest.."));
- EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest..."));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "Logging the entire forest."));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "Logging the entire forest.."));
+ EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "Logging the entire forest..."));
LogBranch();
}
@@ -100,6 +101,7 @@
int main(int argc, char **argv) {
GOOGLE_NAMESPACE::InitGoogleLogging(argv[0]);
+ testing::InitGoogleTest(&argc, argv);
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/src/package_config_unittest/working_config/CMakeLists.txt b/src/package_config_unittest/working_config/CMakeLists.txt
new file mode 100644
index 0000000..5fcfe7f
--- /dev/null
+++ b/src/package_config_unittest/working_config/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required (VERSION 3.16)
+project (glog_package_config LANGUAGES CXX)
+
+find_package (glog REQUIRED NO_MODULE)
+
+add_executable (glog_package_config glog_package_config.cc)
+
+target_link_libraries (glog_package_config PRIVATE glog::glog)
diff --git a/src/package_config_unittest/working_config/glog_package_config.cc b/src/package_config_unittest/working_config/glog_package_config.cc
new file mode 100644
index 0000000..b7b5cf6
--- /dev/null
+++ b/src/package_config_unittest/working_config/glog_package_config.cc
@@ -0,0 +1,6 @@
+#include <glog/logging.h>
+
+int main(int /*argc*/, char** argv)
+{
+ google::InitGoogleLogging(argv[0]);
+}
diff --git a/src/raw_logging.cc b/src/raw_logging.cc
index 7a7409b..befeac8 100644
--- a/src/raw_logging.cc
+++ b/src/raw_logging.cc
@@ -34,16 +34,16 @@
#include "utilities.h"
#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
+#include <cstdio>
+#include <cerrno>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write()
#endif
#include <fcntl.h> // for open()
-#include <time.h>
+#include <ctime>
#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
@@ -59,25 +59,25 @@
# include <unistd.h>
#endif
-#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
-# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
+#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \
+ (!(defined(GLOG_OS_MACOSX))) && !defined(GLOG_OS_EMSCRIPTEN)
+#define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
- // Not so safe, but what can you do?
-# define safe_write(fd, s, len) write(fd, s, len)
+// Not so safe, but what can you do?
+#define safe_write(fd, s, len) write(fd, s, len)
#endif
_START_GOOGLE_NAMESPACE_
-// Data for RawLog__ below. We simply pick up the latest
-// time data created by a normal log message to avoid calling
-// localtime_r which can allocate memory.
-static struct ::tm last_tm_time_for_raw_log;
-static int last_usecs_for_raw_log;
-
-void RawLog__SetLastTime(const struct ::tm& t, int usecs) {
- memcpy(&last_tm_time_for_raw_log, &t, sizeof(last_tm_time_for_raw_log));
- last_usecs_for_raw_log = usecs;
-}
+#if defined(__GNUC__)
+#define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck) \
+ __attribute__((format(archetype, stringIndex, firstToCheck)))
+#define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex) \
+ __attribute__((format_arg(stringIndex)))
+#else
+#define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck)
+#define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex)
+#endif
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
@@ -87,23 +87,31 @@
// Helper for RawLog__ below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
-static bool DoRawLog(char** buf, int* size, const char* format, ...) {
+GLOG_ATTRIBUTE_FORMAT(printf, 3, 4)
+static bool DoRawLog(char** buf, size_t* size, const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vsnprintf(*buf, *size, format, ap);
va_end(ap);
- if (n < 0 || n > *size) return false;
- *size -= n;
+ if (n < 0 || static_cast<size_t>(n) > *size) return false;
+ *size -= static_cast<size_t>(n);
*buf += n;
return true;
}
// Helper for RawLog__ below.
-inline static bool VADoRawLog(char** buf, int* size,
+inline static bool VADoRawLog(char** buf, size_t* size,
const char* format, va_list ap) {
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
int n = vsnprintf(*buf, *size, format, ap);
- if (n < 0 || n > *size) return false;
- *size -= n;
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+ if (n < 0 || static_cast<size_t>(n) > *size) return false;
+ *size -= static_cast<size_t>(n);
*buf += n;
return true;
}
@@ -113,29 +121,28 @@
static CrashReason crash_reason;
static char crash_buf[kLogBufSize + 1] = { 0 }; // Will end in '\0'
+GLOG_ATTRIBUTE_FORMAT(printf, 4, 5)
void RawLog__(LogSeverity severity, const char* file, int line,
const char* format, ...) {
- if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
- FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
+ if (!(FLAGS_logtostdout || FLAGS_logtostderr ||
+ severity >= FLAGS_stderrthreshold || FLAGS_alsologtostderr ||
+ !IsGoogleLoggingInitialized())) {
return; // this stderr log message is suppressed
}
// can't call localtime_r here: it can allocate
- struct ::tm& t = last_tm_time_for_raw_log;
char buffer[kLogBufSize];
char* buf = buffer;
- int size = sizeof(buffer);
+ size_t size = sizeof(buffer);
// NOTE: this format should match the specification in base/logging.h
- DoRawLog(&buf, &size, "%c%02d%02d %02d:%02d:%02d.%06d %5u %s:%d] RAW: ",
+ DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
LogSeverityNames[severity][0],
- 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
- last_usecs_for_raw_log,
static_cast<unsigned int>(GetTID()),
const_basename(const_cast<char *>(file)), line);
// Record the position and size of the buffer after the prefix
const char* msg_start = buf;
- const int msg_size = size;
+ const size_t msg_size = size;
va_list ap;
va_start(ap, format);
diff --git a/src/signalhandler.cc b/src/signalhandler.cc
index 961ee96..68a549a 100644
--- a/src/signalhandler.cc
+++ b/src/signalhandler.cc
@@ -34,10 +34,10 @@
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
-#include <signal.h>
-#include <time.h>
+#include <csignal>
+#include <ctime>
#ifdef HAVE_UCONTEXT_H
# include <ucontext.h>
#endif
@@ -63,7 +63,7 @@
{ SIGILL, "SIGILL" },
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
-#if !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_WINDOWS)
{ SIGBUS, "SIGBUS" },
#endif
{ SIGTERM, "SIGTERM" },
@@ -71,6 +71,7 @@
static bool kFailureSignalHandlerInstalled = false;
+#if !defined(GLOG_OS_WINDOWS)
// Returns the program counter from signal context, NULL if unknown.
void* GetPC(void* ucontext_in_void) {
#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
@@ -78,26 +79,29 @@
ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
return (void*)context->PC_FROM_UCONTEXT;
}
+#else
+ (void)ucontext_in_void;
#endif
return NULL;
}
+#endif
// The class is used for formatting error messages. We don't use printf()
// as it's not async signal safe.
class MinimalFormatter {
public:
- MinimalFormatter(char *buffer, int size)
+ MinimalFormatter(char *buffer, size_t size)
: buffer_(buffer),
cursor_(buffer),
end_(buffer + size) {
}
// Returns the number of bytes written in the buffer.
- int num_bytes_written() const { return (int) (cursor_ - buffer_); }
+ std::size_t num_bytes_written() const { return static_cast<std::size_t>(cursor_ - buffer_); }
// Appends string from "str" and updates the internal cursor.
void AppendString(const char* str) {
- int i = 0;
+ ptrdiff_t i = 0;
while (str[i] != '\0' && cursor_ + i < end_) {
cursor_[i] = str[i];
++i;
@@ -107,12 +111,12 @@
// Formats "number" in "radix" and updates the internal cursor.
// Lowercase letters are used for 'a' - 'z'.
- void AppendUint64(uint64 number, int radix) {
- int i = 0;
+ void AppendUint64(uint64 number, unsigned radix) {
+ unsigned i = 0;
while (cursor_ + i < end_) {
- const int tmp = number % radix;
+ const uint64 tmp = number % radix;
number /= radix;
- cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
+ cursor_[i] = static_cast<char>(tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
++i;
if (number == 0) {
break;
@@ -145,14 +149,14 @@
};
// Writes the given data with the size to the standard error.
-void WriteToStderr(const char* data, int size) {
+void WriteToStderr(const char* data, size_t size) {
if (write(STDERR_FILENO, data, size) < 0) {
// Ignore errors.
}
}
// The writer function can be changed by InstallFailureWriter().
-void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
+void (*g_failure_writer)(const char* data, size_t size) = WriteToStderr;
// Dumps time information. We don't dump human-readable time information
// as localtime() is not guaranteed to be async signal safe.
@@ -161,16 +165,16 @@
char buf[256]; // Big enough for time info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString("*** Aborted at ");
- formatter.AppendUint64(time_in_sec, 10);
+ formatter.AppendUint64(static_cast<uint64>(time_in_sec), 10);
formatter.AppendString(" (unix time)");
formatter.AppendString(" try \"date -d @");
- formatter.AppendUint64(time_in_sec, 10);
+ formatter.AppendUint64(static_cast<uint64>(time_in_sec), 10);
formatter.AppendString("\" if you are using GNU date ***\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
-// TOOD(hamaji): Use signal instead of sigaction?
-#ifdef HAVE_SIGACTION
+// TODO(hamaji): Use signal instead of sigaction?
+#if defined(HAVE_STACKTRACE) && defined(HAVE_SIGACTION)
// Dumps information about the signal to STDERR.
void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
@@ -192,25 +196,26 @@
// Use the signal number if the name is unknown. The signal name
// should be known, but just in case.
formatter.AppendString("Signal ");
- formatter.AppendUint64(signal_number, 10);
+ formatter.AppendUint64(static_cast<uint64>(signal_number), 10);
}
formatter.AppendString(" (@0x");
formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
formatter.AppendString(")");
formatter.AppendString(" received by PID ");
- formatter.AppendUint64(getpid(), 10);
+ formatter.AppendUint64(static_cast<uint64>(getpid()), 10);
formatter.AppendString(" (TID 0x");
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
- // returns a pointer. Hence we use C-style cast here, rather than
- // reinterpret/static_cast, to support both types of environments.
- formatter.AppendUint64((uintptr_t)pthread_self(), 16);
+ // returns a pointer.
+ pthread_t id = pthread_self();
+ formatter.AppendUint64(
+ reinterpret_cast<uint64>(reinterpret_cast<const char*>(id)), 16);
formatter.AppendString(") ");
// Only linux has the PID of the signal sender in si_pid.
-#ifdef OS_LINUX
+#ifdef GLOG_OS_LINUX
formatter.AppendString("from PID ");
- formatter.AppendUint64(siginfo->si_pid, 10);
+ formatter.AppendUint64(static_cast<uint64>(siginfo->si_pid), 10);
formatter.AppendString("; ");
#endif
formatter.AppendString("stack trace: ***\n");
@@ -253,7 +258,7 @@
sig_action.sa_handler = SIG_DFL;
sigaction(signal_number, &sig_action, NULL);
kill(getpid(), signal_number);
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
signal(signal_number, SIG_DFL);
raise(signal_number);
#endif
@@ -267,7 +272,7 @@
// Dumps signal and stack frame information, and invokes the default
// signal handler once our job is done.
-#if defined(OS_WINDOWS)
+#if defined(GLOG_OS_WINDOWS)
void FailureSignalHandler(int signal_number)
#else
void FailureSignalHandler(int signal_number,
@@ -314,7 +319,7 @@
// First dump time info.
DumpTimeInfo();
-#if !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_WINDOWS)
// Get the program counter from ucontext.
void *pc = GetPC(ucontext);
DumpStackFrameInfo("PC: ", pc);
@@ -327,11 +332,15 @@
const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
# ifdef HAVE_SIGACTION
DumpSignalInfo(signal_number, signal_info);
+#elif !defined(GLOG_OS_WINDOWS)
+ (void)signal_info;
# endif
// Dump the stack traces.
for (int i = 0; i < depth; ++i) {
DumpStackFrameInfo(" ", stack[i]);
}
+#elif !defined(GLOG_OS_WINDOWS)
+ (void)signal_info;
#endif
// *** TRANSITION ***
@@ -362,9 +371,10 @@
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sigaction(SIGABRT, NULL, &sig_action);
- if (sig_action.sa_sigaction == &FailureSignalHandler)
+ if (sig_action.sa_sigaction == &FailureSignalHandler) {
return true;
-#elif defined(OS_WINDOWS)
+ }
+#elif defined(GLOG_OS_WINDOWS)
return kFailureSignalHandlerInstalled;
#endif // HAVE_SIGACTION
return false;
@@ -385,7 +395,7 @@
CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
}
kFailureSignalHandlerInstalled = true;
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler),
SIG_ERR);
@@ -394,8 +404,8 @@
#endif // HAVE_SIGACTION
}
-void InstallFailureWriter(void (*writer)(const char* data, int size)) {
-#if defined(HAVE_SIGACTION) || defined(OS_WINDOWS)
+void InstallFailureWriter(void (*writer)(const char* data, size_t size)) {
+#if defined(HAVE_SIGACTION) || defined(GLOG_OS_WINDOWS)
g_failure_writer = writer;
#endif // HAVE_SIGACTION
}
diff --git a/src/signalhandler_unittest.cc b/src/signalhandler_unittest.cc
index 36d957b..c4c99cc 100644
--- a/src/signalhandler_unittest.cc
+++ b/src/signalhandler_unittest.cc
@@ -37,11 +37,11 @@
#if defined(HAVE_PTHREAD)
# include <pthread.h>
#endif
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
#include <string>
-#include "glog/logging.h"
+#include <glog/logging.h>
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
@@ -54,9 +54,10 @@
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
- // returns a pointer. Hence we use C-style cast here, rather than
- // reinterpret/static_cast, to support both types of environments.
- fprintf(stderr, "0x%lx is dying\n", (long)pthread_self());
+ // returns a pointer.
+ fprintf(
+ stderr, "0x%px is dying\n",
+ static_cast<const void*>(reinterpret_cast<const char*>(pthread_self())));
// Use volatile to prevent from these to be optimized away.
volatile int a = 0;
volatile int b = 1 / a;
@@ -64,7 +65,7 @@
return NULL;
}
-static void WriteToStdout(const char* data, int size) {
+static void WriteToStdout(const char* data, size_t size) {
if (write(STDOUT_FILENO, data, size) < 0) {
// Ignore errors.
}
diff --git a/src/stacktrace.h b/src/stacktrace.h
index cb64b33..55b98b2 100644
--- a/src/stacktrace.h
+++ b/src/stacktrace.h
@@ -34,7 +34,7 @@
#define BASE_STACKTRACE_H_
#include "config.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
_START_GOOGLE_NAMESPACE_
@@ -54,7 +54,7 @@
// .... ...
//
// "result" must not be NULL.
-GOOGLE_GLOG_DLL_DECL int GetStackTrace(void** result, int max_depth, int skip_count);
+GLOG_EXPORT int GetStackTrace(void** result, int max_depth, int skip_count);
_END_GOOGLE_NAMESPACE_
diff --git a/src/stacktrace_generic-inl.h b/src/stacktrace_generic-inl.h
index fad81d3..96397d0 100644
--- a/src/stacktrace_generic-inl.h
+++ b/src/stacktrace_generic-inl.h
@@ -46,12 +46,15 @@
size = backtrace(stack, kStackLength);
skip_count++; // we want to skip the current frame as well
int result_count = size - skip_count;
- if (result_count < 0)
+ if (result_count < 0) {
result_count = 0;
- if (result_count > max_depth)
+ }
+ if (result_count > max_depth) {
result_count = max_depth;
- for (int i = 0; i < result_count; i++)
+ }
+ for (int i = 0; i < result_count; i++) {
result[i] = stack[i + skip_count];
+ }
return result_count;
}
diff --git a/src/stacktrace_libunwind-inl.h b/src/stacktrace_libunwind-inl.h
index 0dc14c6..0b20d23 100644
--- a/src/stacktrace_libunwind-inl.h
+++ b/src/stacktrace_libunwind-inl.h
@@ -37,7 +37,7 @@
#define UNW_LOCAL_ONLY
#include <libunwind.h>
}
-#include "glog/raw_logging.h"
+#include <glog/raw_logging.h>
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
@@ -49,7 +49,9 @@
// recursive request, we'd end up with infinite recursion or deadlock.
// Luckily, it's safe to ignore those subsequent traces. In such
// cases, we return 0 to indicate the situation.
-static bool g_now_entering = false;
+// We can use the GCC __thread syntax here since libunwind is not supported on
+// Windows.
+static __thread bool g_tl_entered; // Initialized to false.
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
@@ -58,29 +60,33 @@
unw_cursor_t cursor;
unw_context_t uc;
- if (sync_val_compare_and_swap(&g_now_entering, false, true)) {
+ if (g_tl_entered) {
return 0;
}
+ g_tl_entered = true;
unw_getcontext(&uc);
RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed");
skip_count++; // Do not include the "GetStackTrace" frame
while (n < max_depth) {
- int ret = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip);
- if (ret < 0)
+ int ret =
+ unw_get_reg(&cursor, UNW_REG_IP, reinterpret_cast<unw_word_t *>(&ip));
+ if (ret < 0) {
break;
+ }
if (skip_count > 0) {
skip_count--;
} else {
result[n++] = ip;
}
ret = unw_step(&cursor);
- if (ret <= 0)
+ if (ret <= 0) {
break;
+ }
}
- g_now_entering = false;
+ g_tl_entered = false;
return n;
}
diff --git a/src/stacktrace_powerpc-inl.h b/src/stacktrace_powerpc-inl.h
index 03b9108..911970c 100644
--- a/src/stacktrace_powerpc-inl.h
+++ b/src/stacktrace_powerpc-inl.h
@@ -35,7 +35,7 @@
// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
-#include <stdio.h>
+#include <cstdio>
#include <stdint.h> // for uintptr_t
#include "stacktrace.h"
@@ -47,7 +47,7 @@
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
- void **new_sp = (void **) *old_sp;
+ void **new_sp = static_cast<void **>(*old_sp);
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
@@ -114,7 +114,7 @@
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2);
-#elif defined(__linux)
+#elif defined(__linux) || defined(__OpenBSD__)
// This check is in case the compiler doesn't define _CALL_SYSV.
result[n++] = *(sp+1);
#else
diff --git a/src/stacktrace_unittest.cc b/src/stacktrace_unittest.cc
index c6ab638..7213284 100644
--- a/src/stacktrace_unittest.cc
+++ b/src/stacktrace_unittest.cc
@@ -29,14 +29,14 @@
#include "utilities.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
#include "config.h"
#include "base/commandlineflags.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
#include "stacktrace.h"
-#ifdef HAVE_EXECINFO_H
+#ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS
# include <execinfo.h>
#endif
@@ -111,6 +111,11 @@
//-----------------------------------------------------------------------//
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-label-as-value"
+#endif
+
void ATTRIBUTE_NOINLINE CheckStackTrace(int);
static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
const int STACK_LEN = 10;
@@ -126,12 +131,19 @@
CHECK_LE(size, STACK_LEN);
if (1) {
-#ifdef HAVE_EXECINFO_H
+#ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS
char **strings = backtrace_symbols(stack, size);
printf("Obtained %d stack frames.\n", size);
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < size; i++) {
printf("%s %p\n", strings[i], stack[i]);
- printf("CheckStackTrace() addr: %p\n", &CheckStackTrace);
+ }
+
+ union {
+ void (*p1)(int);
+ void* p2;
+ } p = {&CheckStackTrace};
+
+ printf("CheckStackTrace() addr: %p\n", p.p2);
free(strings);
#endif
}
@@ -152,42 +164,61 @@
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
DECLARE_ADDRESS_LABEL(start);
- for (int j = i; j >= 0; j--)
+ for (int j = i; j >= 0; j--) {
CheckStackTraceLeaf();
+ }
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
DECLARE_ADDRESS_LABEL(start);
- for (int j = i; j >= 0; j--)
+ for (int j = i; j >= 0; j--) {
CheckStackTrace4(j);
+ }
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
DECLARE_ADDRESS_LABEL(start);
- for (int j = i; j >= 0; j--)
+ for (int j = i; j >= 0; j--) {
CheckStackTrace3(j);
+ }
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
DECLARE_ADDRESS_LABEL(start);
- for (int j = i; j >= 0; j--)
+ for (int j = i; j >= 0; j--) {
CheckStackTrace2(j);
+ }
DECLARE_ADDRESS_LABEL(end);
}
+
+#ifndef __GNUC__
+// On non-GNU environment, we use the address of `CheckStackTrace` to
+// guess the address range of this function. This guess is wrong for
+// non-static function on Windows. This is probably because
+// `&CheckStackTrace` returns the address of a trampoline like PLT,
+// not the actual address of `CheckStackTrace`.
+// See https://github.com/google/glog/issues/421 for the detail.
+static
+#endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
DECLARE_ADDRESS_LABEL(start);
- for (int j = i; j >= 0; j--)
+ for (int j = i; j >= 0; j--) {
CheckStackTrace1(j);
+ }
DECLARE_ADDRESS_LABEL(end);
}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
//-----------------------------------------------------------------------//
int main(int, char ** argv) {
diff --git a/src/stacktrace_x86_64-inl.h b/src/stacktrace_unwind-inl.h
similarity index 91%
rename from src/stacktrace_x86_64-inl.h
rename to src/stacktrace_unwind-inl.h
index f7d1dca..dc1665b 100644
--- a/src/stacktrace_x86_64-inl.h
+++ b/src/stacktrace_unwind-inl.h
@@ -31,10 +31,9 @@
//
// Produce stack trace using libgcc
-extern "C" {
-#include <stdlib.h> // for NULL
+#include <cstdlib> // for NULL
#include <unwind.h> // ABI defined unwinder
-}
+
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
@@ -48,7 +47,7 @@
// Workaround for the malloc() in _Unwind_Backtrace() issue.
-static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context *uc, void *opq) {
+static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context */*uc*/, void */*opq*/) {
return _URC_NO_REASON;
}
@@ -69,24 +68,26 @@
static StackTraceInit module_initializer; // Force initialization
static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context *uc, void *opq) {
- trace_arg_t *targ = (trace_arg_t *) opq;
+ trace_arg_t *targ = static_cast<trace_arg_t *>(opq);
if (targ->skip_count > 0) {
targ->skip_count--;
} else {
- targ->result[targ->count++] = (void *) _Unwind_GetIP(uc);
+ targ->result[targ->count++] = reinterpret_cast<void *>(_Unwind_GetIP(uc));
}
- if (targ->count == targ->max_depth)
+ if (targ->count == targ->max_depth) {
return _URC_END_OF_STACK;
+ }
return _URC_NO_REASON;
}
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
- if (!ready_to_run)
+ if (!ready_to_run) {
return 0;
+ }
trace_arg_t targ;
diff --git a/src/stacktrace_windows-inl.h b/src/stacktrace_windows-inl.h
index 7263188..e6af561 100644
--- a/src/stacktrace_windows-inl.h
+++ b/src/stacktrace_windows-inl.h
@@ -34,7 +34,7 @@
#include "config.h"
#include "port.h"
#include "stacktrace.h"
-#include <DbgHelp.h>
+#include <dbghelp.h>
_START_GOOGLE_NAMESPACE_
@@ -44,7 +44,7 @@
}
skip_count++; // we want to skip the current frame as well
// This API is thread-safe (moreover it walks only the current thread).
- return CaptureStackBackTrace(skip_count, max_depth, result, NULL);
+ return CaptureStackBackTrace(static_cast<DWORD>(skip_count), static_cast<DWORD>(max_depth), result, NULL);
}
_END_GOOGLE_NAMESPACE_
diff --git a/src/stacktrace_x86-inl.h b/src/stacktrace_x86-inl.h
index 3b8d5a8..48e87f7 100644
--- a/src/stacktrace_x86-inl.h
+++ b/src/stacktrace_x86-inl.h
@@ -33,12 +33,12 @@
#include "utilities.h" // for OS_* macros
-#if !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_WINDOWS)
#include <unistd.h>
#include <sys/mman.h>
#endif
-#include <stdio.h> // for NULL
+#include <cstdio> // for NULL
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
@@ -49,7 +49,7 @@
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
- void **new_sp = (void **) *old_sp;
+ void **new_sp = static_cast<void **>(*old_sp);
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
@@ -58,23 +58,28 @@
// at a greater address that the current one.
if (new_sp <= old_sp) return NULL;
// Assume stack frames larger than 100,000 bytes are bogus.
- if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
+ if (reinterpret_cast<uintptr_t>(new_sp) -
+ reinterpret_cast<uintptr_t>(old_sp) >
+ 100000)
+ return NULL;
} else {
// In the non-strict mode, allow discontiguous stack frames.
// (alternate-signal-stacks for example).
if (new_sp == old_sp) return NULL;
// And allow frames upto about 1MB.
- if ((new_sp > old_sp)
- && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
+ if ((new_sp > old_sp) && (reinterpret_cast<uintptr_t>(new_sp) -
+ reinterpret_cast<uintptr_t>(old_sp) >
+ 1000000))
+ return NULL;
}
- if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
+ if (reinterpret_cast<uintptr_t>(new_sp) & (sizeof(void *) - 1)) return NULL;
#ifdef __i386__
// On 64-bit machines, the stack pointer can be very close to
// 0xffffffff, so we explicitly check for a pointer into the
// last two pages in the address space
if ((uintptr_t)new_sp >= 0xffffe000) return NULL;
#endif
-#if !defined(OS_WINDOWS)
+#if !defined(GLOG_OS_WINDOWS)
if (!STRICT_UNWINDING) {
// Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
// on AMD-based machines with VDSO-enabled kernels.
@@ -82,9 +87,12 @@
// Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here.
static int page_size = getpagesize();
- void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1));
- if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1)
+ void *new_sp_aligned =
+ reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(new_sp) &
+ static_cast<uintptr_t>(~(page_size - 1)));
+ if (msync(new_sp_aligned, static_cast<size_t>(page_size), MS_ASYNC) == -1) {
return NULL;
+ }
}
#endif
return new_sp;
@@ -127,7 +135,7 @@
int n = 0;
while (sp && n < max_depth) {
- if (*(sp+1) == (void *)0) {
+ if (*(sp + 1) == NULL) {
// In 64-bit code, we often see a frame that
// points to itself and has a return address of 0.
break;
diff --git a/src/stl_logging_unittest.cc b/src/stl_logging_unittest.cc
index 269094c..5ab2414 100644
--- a/src/stl_logging_unittest.cc
+++ b/src/stl_logging_unittest.cc
@@ -58,8 +58,8 @@
# endif
#endif
-#include "glog/logging.h"
-#include "glog/stl_logging.h"
+#include <glog/logging.h>
+#include <glog/stl_logging.h>
#include "googletest.h"
using namespace std;
@@ -68,7 +68,7 @@
#endif
struct user_hash {
- size_t operator()(int x) const { return x; }
+ size_t operator()(int x) const { return static_cast<size_t>(x); }
};
static void TestSTLLogging() {
@@ -107,7 +107,10 @@
hs.insert(30);
ostringstream ss;
ss << hs;
- EXPECT_EQ(ss.str(), "10 20 30");
+ EXPECT_EQ(ss.str().size(), 8);
+ EXPECT_TRUE(ss.str().find("10") != string::npos);
+ EXPECT_TRUE(ss.str().find("20") != string::npos);
+ EXPECT_TRUE(ss.str().find("30") != string::npos);
hash_set<int> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
@@ -122,7 +125,10 @@
hm[30] = "thirty";
ostringstream ss;
ss << hm;
- EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
+ EXPECT_EQ(ss.str().size(), 35);
+ EXPECT_TRUE(ss.str().find("(10, ten)") != string::npos);
+ EXPECT_TRUE(ss.str().find("(20, twenty)") != string::npos);
+ EXPECT_TRUE(ss.str().find("(30, thirty)") != string::npos);
hash_map<int, string> copied_hm(hm);
CHECK_EQ(hm, copied_hm); // this must compile
}
@@ -135,8 +141,9 @@
for (int i = 0; i < 100; i++) {
v.push_back(i);
if (i > 0) expected += ' ';
- char buf[256];
- sprintf(buf, "%d", i);
+ const size_t buf_size = 256;
+ char buf[buf_size];
+ snprintf(buf, buf_size, "%d", i);
expected += buf;
}
v.push_back(100);
@@ -170,7 +177,10 @@
hs.insert(30);
ostringstream ss;
ss << hs;
- EXPECT_EQ(ss.str(), "10 20 30");
+ EXPECT_EQ(ss.str().size(), 8);
+ EXPECT_TRUE(ss.str().find("10") != string::npos);
+ EXPECT_TRUE(ss.str().find("20") != string::npos);
+ EXPECT_TRUE(ss.str().find("30") != string::npos);
hash_set<int, user_hash> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
diff --git a/src/symbolize.cc b/src/symbolize.cc
index 1ffc607..f56e97c 100644
--- a/src/symbolize.cc
+++ b/src/symbolize.cc
@@ -46,7 +46,7 @@
// and memmove(). We assume they are async-signal-safe.
//
// Additional header can be specified by the GLOG_BUILD_CONFIG_INCLUDE
-// macro to add platform specific defines (e.g. OS_OPENBSD).
+// macro to add platform specific defines (e.g. GLOG_OS_OPENBSD).
#ifdef GLOG_BUILD_CONFIG_INCLUDE
#include GLOG_BUILD_CONFIG_INCLUDE
@@ -56,7 +56,7 @@
#if defined(HAVE_SYMBOLIZE)
-#include <string.h>
+#include <cstring>
#include <algorithm>
#include <limits>
@@ -94,12 +94,12 @@
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
// get inlined.
-static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size) {
+static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size) {
char demangled[256]; // Big enough for sane demangled symbols.
if (Demangle(out, demangled, sizeof(demangled))) {
// Demangling succeeded. Copy to out if the space allows.
size_t len = strlen(demangled);
- if (len + 1 <= (size_t)out_size) { // +1 for '\0'.
+ if (len + 1 <= out_size) { // +1 for '\0'.
SAFE_ASSERT(len < sizeof(demangled));
memmove(out, demangled, len + 1);
}
@@ -110,27 +110,29 @@
#if defined(__ELF__)
+#if defined(HAVE_DLFCN_H)
#include <dlfcn.h>
-#if defined(OS_OPENBSD)
+#endif
+#if defined(GLOG_OS_OPENBSD)
#include <sys/exec_elf.h>
#else
#include <elf.h>
#endif
-#include <errno.h>
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <fcntl.h>
-#include <limits.h>
#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "symbolize.h"
#include "config.h"
-#include "glog/raw_logging.h"
+#include <glog/raw_logging.h>
// Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
@@ -142,25 +144,25 @@
// and EINTR. On success, return the number of bytes read. Otherwise, return
// -1.
static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count,
- const off_t offset) {
+ const size_t offset) {
SAFE_ASSERT(fd >= 0);
- SAFE_ASSERT(count <= std::numeric_limits<ssize_t>::max());
+ SAFE_ASSERT(count <= static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
char *buf0 = reinterpret_cast<char *>(buf);
- ssize_t num_bytes = 0;
+ size_t num_bytes = 0;
while (num_bytes < count) {
ssize_t len;
NO_INTR(len = pread(fd, buf0 + num_bytes, count - num_bytes,
- offset + num_bytes));
+ static_cast<off_t>(offset + num_bytes)));
if (len < 0) { // There was an error other than EINTR.
return -1;
}
if (len == 0) { // Reached EOF.
break;
}
- num_bytes += len;
+ num_bytes += static_cast<size_t>(len);
}
SAFE_ASSERT(num_bytes <= count);
- return num_bytes;
+ return static_cast<ssize_t>(num_bytes);
}
// Try reading exactly "count" bytes from "offset" bytes in a file
@@ -168,9 +170,9 @@
// short reads and EINTR. On success, return true. Otherwise, return
// false.
static bool ReadFromOffsetExact(const int fd, void *buf,
- const size_t count, const off_t offset) {
+ const size_t count, const size_t offset) {
ssize_t len = ReadFromOffset(fd, buf, count, offset);
- return len == count;
+ return static_cast<size_t>(len) == count;
}
// Returns elf_header.e_type if the file pointed by fd is an ELF binary.
@@ -191,23 +193,23 @@
// To keep stack consumption low, we would like this function to not get
// inlined.
static ATTRIBUTE_NOINLINE bool
-GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const off_t sh_offset,
+GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const size_t sh_offset,
ElfW(Word) type, ElfW(Shdr) *out) {
// Read at most 16 section headers at a time to save read calls.
ElfW(Shdr) buf[16];
- for (int i = 0; i < sh_num;) {
- const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]);
- const ssize_t num_bytes_to_read =
+ for (size_t i = 0; i < sh_num;) {
+ const size_t num_bytes_left = (sh_num - i) * sizeof(buf[0]);
+ const size_t num_bytes_to_read =
(sizeof(buf) > num_bytes_left) ? num_bytes_left : sizeof(buf);
const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read,
sh_offset + i * sizeof(buf[0]));
if (len == -1) {
return false;
}
- SAFE_ASSERT(len % sizeof(buf[0]) == 0);
- const ssize_t num_headers_in_buf = len / sizeof(buf[0]);
+ SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
+ const size_t num_headers_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0]));
- for (int j = 0; j < num_headers_in_buf; ++j) {
+ for (size_t j = 0; j < num_headers_in_buf; ++j) {
if (buf[j].sh_type == type) {
*out = buf[j];
return true;
@@ -231,14 +233,15 @@
}
ElfW(Shdr) shstrtab;
- off_t shstrtab_offset = (elf_header.e_shoff +
- elf_header.e_shentsize * elf_header.e_shstrndx);
+ size_t shstrtab_offset =
+ (elf_header.e_shoff + static_cast<size_t>(elf_header.e_shentsize) *
+ static_cast<size_t>(elf_header.e_shstrndx));
if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) {
return false;
}
- for (int i = 0; i < elf_header.e_shnum; ++i) {
- off_t section_header_offset = (elf_header.e_shoff +
+ for (size_t i = 0; i < elf_header.e_shnum; ++i) {
+ size_t section_header_offset = (elf_header.e_shoff +
elf_header.e_shentsize * i);
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
return false;
@@ -250,11 +253,11 @@
// No point in even trying.
return false;
}
- off_t name_offset = shstrtab.sh_offset + out->sh_name;
+ size_t name_offset = shstrtab.sh_offset + out->sh_name;
ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset);
if (n_read == -1) {
return false;
- } else if (n_read != name_len) {
+ } else if (static_cast<size_t>(n_read) != name_len) {
// Short read -- name could be at end of file.
continue;
}
@@ -272,34 +275,34 @@
// To keep stack consumption low, we would like this function to not get
// inlined.
static ATTRIBUTE_NOINLINE bool
-FindSymbol(uint64_t pc, const int fd, char *out, int out_size,
+FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size,
uint64_t symbol_offset, const ElfW(Shdr) *strtab,
const ElfW(Shdr) *symtab) {
if (symtab == NULL) {
return false;
}
- const int num_symbols = symtab->sh_size / symtab->sh_entsize;
- for (int i = 0; i < num_symbols;) {
- off_t offset = symtab->sh_offset + i * symtab->sh_entsize;
+ const size_t num_symbols = symtab->sh_size / symtab->sh_entsize;
+ for (unsigned i = 0; i < num_symbols;) {
+ size_t offset = symtab->sh_offset + i * symtab->sh_entsize;
// If we are reading Elf64_Sym's, we want to limit this array to
// 32 elements (to keep stack consumption low), otherwise we can
// have a 64 element Elf32_Sym array.
-#if __WORDSIZE == 64
-#define NUM_SYMBOLS 32
+#if defined(__WORDSIZE) && __WORDSIZE == 64
+ const size_t NUM_SYMBOLS = 32U;
#else
-#define NUM_SYMBOLS 64
+ const size_t NUM_SYMBOLS = 64U;
#endif
// Read at most NUM_SYMBOLS symbols at once to save read() calls.
ElfW(Sym) buf[NUM_SYMBOLS];
- int num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i);
+ size_t num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i);
const ssize_t len =
ReadFromOffset(fd, &buf, sizeof(buf[0]) * num_symbols_to_read, offset);
- SAFE_ASSERT(len % sizeof(buf[0]) == 0);
- const ssize_t num_symbols_in_buf = len / sizeof(buf[0]);
+ SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
+ const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read);
- for (int j = 0; j < num_symbols_in_buf; ++j) {
+ for (unsigned j = 0; j < num_symbols_in_buf; ++j) {
const ElfW(Sym)& symbol = buf[j];
uint64_t start_address = symbol.st_value;
start_address += symbol_offset;
@@ -310,6 +313,7 @@
ssize_t len1 = ReadFromOffset(fd, out, out_size,
strtab->sh_offset + symbol.st_name);
if (len1 <= 0 || memchr(out, '\0', out_size) == NULL) {
+ memset(out, 0, out_size);
return false;
}
return true; // Obtained the symbol name.
@@ -327,7 +331,7 @@
static bool GetSymbolFromObjectFile(const int fd,
uint64_t pc,
char* out,
- int out_size,
+ size_t out_size,
uint64_t base_address) {
// Read the ELF header.
ElfW(Ehdr) elf_header;
@@ -372,13 +376,13 @@
explicit FileDescriptor(int fd) : fd_(fd) {}
~FileDescriptor() {
if (fd_ >= 0) {
- NO_INTR(close(fd_));
+ close(fd_);
}
}
int get() { return fd_; }
private:
- explicit FileDescriptor(const FileDescriptor&);
+ FileDescriptor(const FileDescriptor &);
void operator=(const FileDescriptor&);
};
@@ -389,7 +393,7 @@
// and snprintf().
class LineReader {
public:
- explicit LineReader(int fd, char *buf, int buf_len, off_t offset)
+ explicit LineReader(int fd, char *buf, size_t buf_len, size_t offset)
: fd_(fd),
buf_(buf),
buf_len_(buf_len),
@@ -409,25 +413,25 @@
if (num_bytes <= 0) { // EOF or error.
return false;
}
- offset_ += num_bytes;
+ offset_ += static_cast<size_t>(num_bytes);
eod_ = buf_ + num_bytes;
bol_ = buf_;
} else {
bol_ = eol_ + 1; // Advance to the next line in the buffer.
SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
if (!HasCompleteLine()) {
- const int incomplete_line_length = eod_ - bol_;
+ const size_t incomplete_line_length = static_cast<size_t>(eod_ - bol_);
// Move the trailing incomplete line to the beginning.
memmove(buf_, bol_, incomplete_line_length);
// Read text from file and append it.
char * const append_pos = buf_ + incomplete_line_length;
- const int capacity_left = buf_len_ - incomplete_line_length;
+ const size_t capacity_left = buf_len_ - incomplete_line_length;
const ssize_t num_bytes =
ReadFromOffset(fd_, append_pos, capacity_left, offset_);
if (num_bytes <= 0) { // EOF or error.
return false;
}
- offset_ += num_bytes;
+ offset_ += static_cast<size_t>(num_bytes);
eod_ = append_pos + num_bytes;
bol_ = buf_;
}
@@ -454,11 +458,11 @@
}
private:
- explicit LineReader(const LineReader&);
+ LineReader(const LineReader &);
void operator=(const LineReader&);
char *FindLineFeed() {
- return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_));
+ return reinterpret_cast<char *>(memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_)));
}
bool BufferIsEmpty() {
@@ -471,8 +475,8 @@
const int fd_;
char * const buf_;
- const int buf_len_;
- off_t offset_;
+ const size_t buf_len_;
+ size_t offset_;
char *bol_;
char *eol_;
const char *eod_; // End of data in "buf_".
@@ -488,7 +492,7 @@
int ch = *p;
if ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
- *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
+ *hex = (*hex << 4U) | (ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U);
} else { // Encountered the first non-hex character.
break;
}
@@ -510,7 +514,7 @@
uint64_t &start_address,
uint64_t &base_address,
char *out_file_name,
- int out_file_name_size) {
+ size_t out_file_name_size) {
int object_fd;
int maps_fd;
@@ -530,7 +534,7 @@
// Iterate over maps and look for the map containing the pc. Then
// look into the symbol tables inside.
char buf[1024]; // Big enough for line of sane /proc/self/maps
- int num_maps = 0;
+ unsigned num_maps = 0;
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf), 0);
while (true) {
num_maps++;
@@ -662,16 +666,17 @@
// POSIX doesn't define any async-signal safe function for converting
// an integer to ASCII. We'll have to define our own version.
-// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
+// itoa_r() converts an (unsigned) integer to ASCII. It returns "buf", if the
// conversion was successful or NULL otherwise. It never writes more than "sz"
// bytes. Output will be truncated as needed, and a NUL character is always
// appended.
// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
-static char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
+static char *itoa_r(uintptr_t i, char *buf, size_t sz, unsigned base, size_t padding) {
// Make sure we can write at least one NUL byte.
size_t n = 1;
- if (n > sz)
+ if (n > sz) {
return NULL;
+ }
if (base < 2 || base > 16) {
buf[0] = '\000';
@@ -680,21 +685,6 @@
char *start = buf;
- uintptr_t j = i;
-
- // Handle negative numbers (only for base 10).
- if (i < 0 && base == 10) {
- // This does "j = -i" while avoiding integer overflow.
- j = static_cast<uintptr_t>(-(i + 1)) + 1;
-
- // Make sure we can write the '-' character.
- if (++n > sz) {
- buf[0] = '\000';
- return NULL;
- }
- *start++ = '-';
- }
-
// Loop until we have converted the entire number. Output at least one
// character (i.e. '0').
char *ptr = start;
@@ -706,12 +696,13 @@
}
// Output the next digit.
- *ptr++ = "0123456789abcdef"[j % base];
- j /= base;
+ *ptr++ = "0123456789abcdef"[i % base];
+ i /= base;
- if (padding > 0)
+ if (padding > 0) {
padding--;
- } while (j > 0 || padding > 0);
+ }
+ } while (i > 0 || padding > 0);
// Terminate the output with a NUL character.
*ptr = '\000';
@@ -730,8 +721,8 @@
// Safely appends string |source| to string |dest|. Never writes past the
// buffer size |dest_size| and guarantees that |dest| is null-terminated.
-static void SafeAppendString(const char* source, char* dest, int dest_size) {
- int dest_string_length = strlen(dest);
+static void SafeAppendString(const char* source, char* dest, size_t dest_size) {
+ size_t dest_string_length = strlen(dest);
SAFE_ASSERT(dest_string_length < dest_size);
dest += dest_string_length;
dest_size -= dest_string_length;
@@ -743,7 +734,7 @@
// Converts a 64-bit value into a hex string, and safely appends it to |dest|.
// Never writes past the buffer size |dest_size| and guarantees that |dest| is
// null-terminated.
-static void SafeAppendHexNumber(uint64_t value, char* dest, int dest_size) {
+static void SafeAppendHexNumber(uint64_t value, char* dest, size_t dest_size) {
// 64-bit numbers in hex can have up to 16 digits.
char buf[17] = {'\0'};
SafeAppendString(itoa_r(value, buf, sizeof(buf), 16, 0), dest, dest_size);
@@ -758,7 +749,7 @@
// To keep stack consumption low, we would like this function to not
// get inlined.
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
- int out_size) {
+ size_t out_size) {
uint64_t pc0 = reinterpret_cast<uintptr_t>(pc);
uint64_t start_address = 0;
uint64_t base_address = 0;
@@ -781,9 +772,10 @@
out_size - 1);
}
+ FileDescriptor wrapped_object_fd(object_fd);
+
#if defined(PRINT_UNSYMBOLIZED_STACK_TRACES)
{
- FileDescriptor wrapped_object_fd(object_fd);
#else
// Check whether a file name was returned.
if (object_fd < 0) {
@@ -802,7 +794,6 @@
// Failed to determine the object file containing PC. Bail out.
return false;
}
- FileDescriptor wrapped_object_fd(object_fd);
int elf_type = FileGetElfType(wrapped_object_fd.get());
if (elf_type == -1) {
return false;
@@ -816,12 +807,23 @@
pc, out, out_size,
relocation);
if (num_bytes_written > 0) {
- out += num_bytes_written;
- out_size -= num_bytes_written;
+ out += static_cast<size_t>(num_bytes_written);
+ out_size -= static_cast<size_t>(num_bytes_written);
}
}
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0,
out, out_size, base_address)) {
+ if (out[1] && !g_symbolize_callback) {
+ // The object file containing PC was opened successfully however the
+ // symbol was not found. The object may have been stripped. This is still
+ // considered success because the object file name and offset are known
+ // and tools like asan_symbolize.py can be used for the symbolization.
+ out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
+ SafeAppendString("+0x", out, out_size);
+ SafeAppendHexNumber(pc0 - base_address, out, out_size);
+ SafeAppendString(")", out, out_size);
+ return true;
+ }
return false;
}
@@ -832,22 +834,24 @@
_END_GOOGLE_NAMESPACE_
-#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
+#elif (defined(GLOG_OS_MACOSX) || defined(GLOG_OS_EMSCRIPTEN)) && defined(HAVE_DLADDR)
#include <dlfcn.h>
-#include <string.h>
+#include <cstring>
_START_GOOGLE_NAMESPACE_
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
- int out_size) {
+ size_t out_size) {
Dl_info info;
if (dladdr(pc, &info)) {
- if ((int)strlen(info.dli_sname) < out_size) {
- strcpy(out, info.dli_sname);
- // Symbolization succeeded. Now we try to demangle the symbol.
- DemangleInplace(out, out_size);
- return true;
+ if (info.dli_sname) {
+ if (strlen(info.dli_sname) < out_size) {
+ strcpy(out, info.dli_sname);
+ // Symbolization succeeded. Now we try to demangle the symbol.
+ DemangleInplace(out, out_size);
+ return true;
+ }
}
}
return false;
@@ -855,7 +859,7 @@
_END_GOOGLE_NAMESPACE_
-#elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
+#elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
#include <windows.h>
#include <dbghelp.h>
@@ -892,7 +896,7 @@
};
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
- int out_size) {
+ size_t out_size) {
const static SymInitializer symInitializer;
if (!symInitializer.ready) {
return false;
@@ -907,7 +911,7 @@
// This could break if a symbol has Unicode in it.
BOOL ret = SymFromAddr(symInitializer.process,
reinterpret_cast<DWORD64>(pc), 0, symbol);
- if (ret == 1 && static_cast<int>(symbol->NameLen) < out_size) {
+ if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) {
// `NameLen` does not include the null terminating character.
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);
out[static_cast<size_t>(symbol->NameLen)] = '\0';
@@ -926,8 +930,7 @@
_START_GOOGLE_NAMESPACE_
-bool Symbolize(void *pc, char *out, int out_size) {
- SAFE_ASSERT(out_size >= 0);
+bool Symbolize(void *pc, char *out, size_t out_size) {
return SymbolizeAndDemangle(pc, out, out_size);
}
@@ -935,14 +938,14 @@
#else /* HAVE_SYMBOLIZE */
-#include <assert.h>
+#include <cassert>
#include "config.h"
_START_GOOGLE_NAMESPACE_
// TODO: Support other environments.
-bool Symbolize(void *pc, char *out, int out_size) {
+bool Symbolize(void* /*pc*/, char* /*out*/, size_t /*out_size*/) {
assert(0);
return false;
}
diff --git a/src/symbolize.h b/src/symbolize.h
index c6f9ec4..dcbb194 100644
--- a/src/symbolize.h
+++ b/src/symbolize.h
@@ -56,7 +56,7 @@
#include "utilities.h"
#include "config.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
#ifdef HAVE_SYMBOLIZE
@@ -121,6 +121,7 @@
char* out,
size_t out_size,
uint64_t relocation);
+GLOG_EXPORT
void InstallSymbolizeCallback(SymbolizeCallback callback);
// Installs a callback function, which will be called instead of
@@ -137,7 +138,7 @@
uint64_t& start_address,
uint64_t& base_address,
char* out_file_name,
- int out_file_name_size);
+ size_t out_file_name_size);
void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback);
@@ -151,7 +152,7 @@
// symbol name to "out". The symbol name is demangled if possible
// (supports symbols generated by GCC 3.x or newer). Otherwise,
// returns false.
-GOOGLE_GLOG_DLL_DECL bool Symbolize(void *pc, char *out, int out_size);
+GLOG_EXPORT bool Symbolize(void* pc, char* out, size_t out_size);
_END_GOOGLE_NAMESPACE_
diff --git a/src/symbolize_unittest.cc b/src/symbolize_unittest.cc
index 9a17e7b..2522e73 100644
--- a/src/symbolize_unittest.cc
+++ b/src/symbolize_unittest.cc
@@ -31,15 +31,16 @@
//
// Unit tests for functions in symbolize.cc.
-#include "utilities.h"
+#include "symbolize.h"
-#include <signal.h>
+#include <glog/logging.h>
+
+#include <csignal>
#include <iostream>
-#include "glog/logging.h"
-#include "symbolize.h"
-#include "googletest.h"
#include "config.h"
+#include "googletest.h"
+#include "utilities.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
@@ -49,10 +50,18 @@
using namespace std;
using namespace GOOGLE_NAMESPACE;
+// Avoid compile error due to "cast between pointer-to-function and
+// pointer-to-object is an extension" warnings.
+#if defined(__GNUG__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
#if defined(HAVE_STACKTRACE)
#define always_inline
+#if defined(__ELF__) || defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
// A wrapper function for Symbolize() to make the unit test simple.
static const char *TrySymbolize(void *pc) {
static char symbol[4096];
@@ -62,6 +71,7 @@
return NULL;
}
}
+#endif
# if defined(__ELF__)
@@ -70,7 +80,7 @@
#if defined(__GNUC__) && !defined(__OPENCC__)
# if __GNUC__ >= 4
# define TEST_WITH_MODERN_GCC
-# if __i386__ // always_inline isn't supported for x86_64 with GCC 4.1.0.
+# if defined(__i386__) && __i386__ // always_inline isn't supported for x86_64 with GCC 4.1.0.
# undef always_inline
# define always_inline __attribute__((always_inline))
# define HAVE_ALWAYS_INLINE
@@ -87,12 +97,16 @@
void nonstatic_func();
void nonstatic_func() {
volatile int a = 0;
- ++a;
+ // NOTE: In C++20, increment of object of volatile-qualified type is
+ // deprecated.
+ a = a + 1;
}
static void static_func() {
volatile int a = 0;
- ++a;
+ // NOTE: In C++20, increment of object of volatile-qualified type is
+ // deprecated.
+ a = a + 1;
}
}
@@ -105,10 +119,14 @@
// The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here.
- const char *static_func_symbol = TrySymbolize((void *)(&static_func));
+ const char *static_func_symbol =
+ TrySymbolize(reinterpret_cast<void *>(&static_func));
+
+#if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(NULL != static_func_symbol);
EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 ||
strcmp("static_func()", static_func_symbol) == 0);
+#endif
EXPECT_TRUE(NULL == TrySymbolize(NULL));
}
@@ -119,7 +137,9 @@
void ATTRIBUTE_NOINLINE Foo::func(int x) {
volatile int a = x;
- ++a;
+ // NOTE: In C++20, increment of object of volatile-qualified type is
+ // deprecated.
+ a = a + 1;
}
// With a modern GCC, Symbolize() should return demangled symbol
@@ -127,7 +147,9 @@
#ifdef TEST_WITH_MODERN_GCC
TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100);
+#if !defined(_MSC_VER) || !defined(NDEBUG)
EXPECT_STREQ("Foo::func()", TrySymbolize((void *)(&Foo::func)));
+#endif
}
#endif
@@ -152,9 +174,9 @@
static char g_symbolize_buffer[4096];
static char *g_symbolize_result;
-static void EmptySignalHandler(int signo) {}
+static void EmptySignalHandler(int /*signo*/) {}
-static void SymbolizeSignalHandler(int signo) {
+static void SymbolizeSignalHandler(int /*signo*/) {
if (Symbolize(g_pc_to_symbolize, g_symbolize_buffer,
sizeof(g_symbolize_buffer))) {
g_symbolize_result = g_symbolize_buffer;
@@ -275,7 +297,7 @@
int stack_consumed;
const char* symbol;
- symbol = SymbolizeStackConsumption((void *)(&nonstatic_func),
+ symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&nonstatic_func),
&stack_consumed);
EXPECT_STREQ("nonstatic_func", symbol);
EXPECT_GT(stack_consumed, 0);
@@ -283,7 +305,7 @@
// The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here.
- symbol = SymbolizeStackConsumption((void *)(&static_func),
+ symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&static_func),
&stack_consumed);
CHECK(NULL != symbol);
EXPECT_TRUE(strcmp("static_func", symbol) == 0 ||
@@ -298,7 +320,8 @@
int stack_consumed;
const char* symbol;
- symbol = SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed);
+ symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&Foo::func),
+ &stack_consumed);
EXPECT_STREQ("Foo::func()", symbol);
EXPECT_GT(stack_consumed, 0);
@@ -331,8 +354,11 @@
#if defined(TEST_X86_32_AND_64) && defined(HAVE_ATTRIBUTE_NOINLINE)
void *pc = non_inline_func();
const char *symbol = TrySymbolize(pc);
+
+#if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "non_inline_func");
+#endif
cout << "Test case TestWithPCInsideNonInlineFunction passed." << endl;
#endif
}
@@ -341,8 +367,11 @@
#if defined(TEST_X86_32_AND_64) && defined(HAVE_ALWAYS_INLINE)
void *pc = inline_func(); // Must be inlined.
const char *symbol = TrySymbolize(pc);
+
+#if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != NULL);
CHECK_STREQ(symbol, __FUNCTION__);
+#endif
cout << "Test case TestWithPCInsideInlineFunction passed." << endl;
#endif
}
@@ -353,13 +382,16 @@
#if defined(HAVE_ATTRIBUTE_NOINLINE)
void *return_address = __builtin_return_address(0);
const char *symbol = TrySymbolize(return_address);
+
+#if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "main");
+#endif
cout << "Test case TestWithReturnAddress passed." << endl;
#endif
}
-# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
+# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
#ifdef _MSC_VER
#include <intrin.h>
@@ -372,13 +404,18 @@
__declspec(noinline) void Foo::func(int x) {
volatile int a = x;
- ++a;
+ // NOTE: In C++20, increment of object of volatile-qualified type is
+ // deprecated.
+ a = a + 1;
}
TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100);
const char* ret = TrySymbolize((void *)(&Foo::func));
+
+#if defined(HAVE_DBGHELP) && !defined(NDEBUG)
EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret);
+#endif
}
__declspec(noinline) void TestWithReturnAddress() {
@@ -390,8 +427,10 @@
#endif
;
const char *symbol = TrySymbolize(return_address);
+#if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "main");
+#endif
cout << "Test case TestWithReturnAddress passed." << endl;
}
# endif // __ELF__
@@ -401,7 +440,7 @@
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv);
-#if defined(HAVE_SYMBOLIZE)
+#if defined(HAVE_SYMBOLIZE) && defined(HAVE_STACKTRACE)
# if defined(__ELF__)
// We don't want to get affected by the callback interface, that may be
// used to install some callback function at InitGoogle() time.
@@ -411,10 +450,10 @@
TestWithPCInsideNonInlineFunction();
TestWithReturnAddress();
return RUN_ALL_TESTS();
-# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
+# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
TestWithReturnAddress();
return RUN_ALL_TESTS();
-# else // OS_WINDOWS
+# else // GLOG_OS_WINDOWS
printf("PASS (no symbolize_unittest support)\n");
return 0;
# endif // __ELF__
@@ -423,3 +462,7 @@
return 0;
#endif // HAVE_SYMBOLIZE
}
+
+#if defined(__GNUG__)
+#pragma GCC diagnostic pop
+#endif
diff --git a/src/utilities.cc b/src/utilities.cc
index 25c4b76..a332f1a 100644
--- a/src/utilities.cc
+++ b/src/utilities.cc
@@ -29,16 +29,17 @@
//
// Author: Shinichiro Hamaji
+#include "config.h"
#include "utilities.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
-#include <signal.h>
+#include <csignal>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
-#include <time.h>
+#include <ctime>
#if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H)
@@ -53,6 +54,9 @@
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
#include "base/googleinit.h"
@@ -61,7 +65,10 @@
_START_GOOGLE_NAMESPACE_
static const char* g_program_invocation_short_name = NULL;
-static pthread_t g_main_thread_id;
+
+bool IsGoogleLoggingInitialized() {
+ return g_program_invocation_short_name != NULL;
+}
_END_GOOGLE_NAMESPACE_
@@ -88,6 +95,12 @@
if (write(STDERR_FILENO, data, strlen(data)) < 0) {
// Ignore errors.
}
+#if defined(__ANDROID__)
+ // ANDROID_LOG_FATAL as fatal error occurred and now is dumping call stack.
+ __android_log_write(ANDROID_LOG_FATAL,
+ glog_internal_namespace_::ProgramInvocationShortName(),
+ data);
+#endif
}
static void DebugWriteToString(const char* data, void *arg) {
@@ -139,10 +152,15 @@
}
}
+#if defined(__GNUC__)
+__attribute__((noreturn))
+#elif defined(_MSC_VER)
+__declspec(noreturn)
+#endif
static void DumpStackTraceAndExit() {
DumpStackTrace(1, DebugWriteToStderr, NULL);
- // TOOD(hamaji): Use signal instead of sigaction?
+ // TODO(hamaji): Use signal instead of sigaction?
if (IsFailureSignalHandlerInstalled()) {
// Set the default signal handler for SIGABRT, to avoid invoking our
// own signal handler installed by InstallFailureSignalHandler().
@@ -152,7 +170,7 @@
sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sig_action, NULL);
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
signal(SIGABRT, SIG_DFL);
#endif // HAVE_SIGACTION
}
@@ -177,31 +195,21 @@
}
}
-bool IsGoogleLoggingInitialized() {
- return g_program_invocation_short_name != NULL;
-}
-
-bool is_default_thread() {
- if (g_program_invocation_short_name == NULL) {
- // InitGoogleLogging() not yet called, so unlikely to be in a different
- // thread
- return true;
- } else {
- return pthread_equal(pthread_self(), g_main_thread_id);
- }
-}
-
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
struct timeval {
long tv_sec, tv_usec;
};
// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
// See COPYING for copyright information.
-static int gettimeofday(struct timeval *tv, void* tz) {
+static int gettimeofday(struct timeval *tv, void* /*tz*/) {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlong-long"
+#endif
#define EPOCHFILETIME (116444736000000000ULL)
FILETIME ft;
- LARGE_INTEGER li;
+ ULARGE_INTEGER li;
uint64 tt;
GetSystemTimeAsFileTime(&ft);
@@ -210,6 +218,9 @@
tt = (li.QuadPart - EPOCHFILETIME) / 10;
tv->tv_sec = tt / 1000000;
tv->tv_usec = tt % 1000000;
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
return 0;
}
@@ -247,9 +258,9 @@
pid_t GetTID() {
// On Linux and MacOSX, we try to use gettid().
-#if defined OS_LINUX || defined OS_MACOSX
+#if defined GLOG_OS_LINUX || defined GLOG_OS_MACOSX
#ifndef __NR_gettid
-#ifdef OS_MACOSX
+#ifdef GLOG_OS_MACOSX
#define __NR_gettid SYS_gettid
#elif ! defined __i386__
#error "Must define __NR_gettid for non-x86 platforms"
@@ -259,7 +270,13 @@
#endif
static bool lacks_gettid = false;
if (!lacks_gettid) {
- pid_t tid = syscall(__NR_gettid);
+#if (defined(GLOG_OS_MACOSX) && defined(HAVE_PTHREAD_THREADID_NP))
+ uint64_t tid64;
+ const int error = pthread_threadid_np(NULL, &tid64);
+ pid_t tid = error ? -1 : static_cast<pid_t>(tid64);
+#else
+ pid_t tid = static_cast<pid_t>(syscall(__NR_gettid));
+#endif
if (tid != -1) {
return tid;
}
@@ -269,22 +286,24 @@
// the value change to "true".
lacks_gettid = true;
}
-#endif // OS_LINUX || OS_MACOSX
+#endif // GLOG_OS_LINUX || GLOG_OS_MACOSX
// If gettid() could not be used, we use one of the following.
-#if defined OS_LINUX
+#if defined GLOG_OS_LINUX
return getpid(); // Linux: getpid returns thread ID when gettid is absent
-#elif defined OS_WINDOWS && !defined OS_CYGWIN
- return GetCurrentThreadId();
-#else
+#elif defined GLOG_OS_WINDOWS && !defined GLOG_OS_CYGWIN
+ return static_cast<pid_t>(GetCurrentThreadId());
+#elif defined(HAVE_PTHREAD)
// If none of the techniques above worked, we use pthread_self().
return (pid_t)(uintptr_t)pthread_self();
+#else
+ return -1;
#endif
}
const char* const_basename(const char* filepath) {
const char* base = strrchr(filepath, '/');
-#ifdef OS_WINDOWS // Look for either path separator in Windows
+#ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows
if (!base)
base = strrchr(filepath, '\\');
#endif
@@ -297,7 +316,7 @@
}
static void MyUserNameInitializer() {
// TODO(hamaji): Probably this is not portable.
-#if defined(OS_WINDOWS)
+#if defined(GLOG_OS_WINDOWS)
const char* user = getenv("USERNAME");
#else
const char* user = getenv("USER");
@@ -311,7 +330,7 @@
char buffer[1024] = {'\0'};
uid_t uid = geteuid();
int pwuid_res = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &result);
- if (pwuid_res == 0) {
+ if (pwuid_res == 0 && result) {
g_my_user_name = pwd.pw_name;
} else {
snprintf(buffer, sizeof(buffer), "uid%d", uid);
@@ -324,7 +343,7 @@
}
}
-REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer());
+REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer())
#ifdef HAVE_STACKTRACE
void DumpStackTraceToString(string* stacktrace) {
@@ -346,11 +365,10 @@
CHECK(!IsGoogleLoggingInitialized())
<< "You called InitGoogleLogging() twice!";
const char* slash = strrchr(argv0, '/');
-#ifdef OS_WINDOWS
+#ifdef GLOG_OS_WINDOWS
if (!slash) slash = strrchr(argv0, '\\');
#endif
g_program_invocation_short_name = slash ? slash + 1 : argv0;
- g_main_thread_id = pthread_self();
#ifdef HAVE_STACKTRACE
InstallFailureFunction(&DumpStackTraceAndExit);
diff --git a/src/utilities.h b/src/utilities.h
index ca21cfb..760c142 100644
--- a/src/utilities.h
+++ b/src/utilities.h
@@ -34,26 +34,6 @@
#ifndef UTILITIES_H__
#define UTILITIES_H__
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
-# define OS_WINDOWS
-#elif defined(__CYGWIN__) || defined(__CYGWIN32__)
-# define OS_CYGWIN
-#elif defined(linux) || defined(__linux) || defined(__linux__)
-# ifndef OS_LINUX
-# define OS_LINUX
-# endif
-#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
-# define OS_MACOSX
-#elif defined(__FreeBSD__)
-# define OS_FREEBSD
-#elif defined(__NetBSD__)
-# define OS_NETBSD
-#elif defined(__OpenBSD__)
-# define OS_OPENBSD
-#else
-// TODO(hamaji): Add other platforms.
-#endif
-
// printf macros for size_t, in the style of inttypes.h
#ifdef _LP64
#define __PRIS_PREFIX "z"
@@ -76,12 +56,13 @@
#include <string>
-#if defined(OS_WINDOWS)
+#include <glog/logging.h>
+
+#if defined(GLOG_OS_WINDOWS)
# include "port.h"
#endif
#include "config.h"
-#include "glog/logging.h"
// There are three different ways we can try to get the stack trace:
//
@@ -107,19 +88,19 @@
#if defined(HAVE_LIB_UNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
+#elif defined(HAVE__UNWIND_BACKTRACE) && defined(HAVE__UNWIND_GETIP)
+# define STACKTRACE_H "stacktrace_unwind-inl.h"
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
-# elif defined(__x86_64__) && __GNUC__ >= 2 && HAVE_UNWIND_H
-# define STACKTRACE_H "stacktrace_x86_64-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
-# elif defined(OS_WINDOWS)
+# elif defined(GLOG_OS_WINDOWS)
# define STACKTRACE_H "stacktrace_windows-inl.h"
# endif
#endif
-#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_H)
+#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE)
# define STACKTRACE_H "stacktrace_generic-inl.h"
#endif
@@ -127,18 +108,20 @@
# define HAVE_STACKTRACE
#endif
+#ifndef GLOG_NO_SYMBOLIZE_DETECTION
#ifndef HAVE_SYMBOLIZE
// defined by gcc
-#if defined(__ELF__) && defined(OS_LINUX)
+#if defined(__ELF__) && defined(GLOG_OS_LINUX)
# define HAVE_SYMBOLIZE
-#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
+#elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
// Use dladdr to symbolize.
# define HAVE_SYMBOLIZE
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
// Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE
#endif
#endif // !defined(HAVE_SYMBOLIZE)
+#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION)
#ifndef ARRAYSIZE
// There is a better way, but this is good enough for our purpose.
@@ -152,7 +135,7 @@
#ifdef HAVE___ATTRIBUTE__
# define ATTRIBUTE_NOINLINE __attribute__ ((noinline))
# define HAVE_ATTRIBUTE_NOINLINE
-#elif defined(OS_WINDOWS)
+#elif defined(GLOG_OS_WINDOWS)
# define ATTRIBUTE_NOINLINE __declspec(noinline)
# define HAVE_ATTRIBUTE_NOINLINE
#else
@@ -161,15 +144,9 @@
const char* ProgramInvocationShortName();
-bool IsGoogleLoggingInitialized();
-
-bool is_default_thread();
-
int64 CycleClock_Now();
int64 UsecToCycles(int64 usec);
-
-typedef double WallTime;
WallTime WallTime_Now();
int32 GetMainThreadPid();
diff --git a/src/utilities_unittest.cc b/src/utilities_unittest.cc
index 38e847d..93b1acd 100644
--- a/src/utilities_unittest.cc
+++ b/src/utilities_unittest.cc
@@ -30,7 +30,7 @@
// Author: Shinichiro Hamaji
#include "utilities.h"
#include "googletest.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
diff --git a/src/vlog_is_on.cc b/src/vlog_is_on.cc
index e8fdbae..e478a36 100644
--- a/src/vlog_is_on.cc
+++ b/src/vlog_is_on.cc
@@ -34,14 +34,14 @@
#include "utilities.h"
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
+#include <cstring>
+#include <cstdlib>
+#include <cerrno>
#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
@@ -63,19 +63,15 @@
namespace glog_internal_namespace_ {
// Used by logging_unittests.cc so can't make it static here.
-GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
- size_t patt_len,
- const char* str,
- size_t str_len);
+GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
+ const char* str, size_t str_len);
// Implementation of fnmatch that does not need 0-termination
// of arguments and does not allocate any memory,
// but we only support "*" and "?" wildcards, not the "[...]" patterns.
// It's not a static function for the unittest.
-GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
- size_t patt_len,
- const char* str,
- size_t str_len) {
+GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
+ const char* str, size_t str_len) {
size_t p = 0;
size_t s = 0;
while (1) {
@@ -105,8 +101,6 @@
using glog_internal_namespace_::SafeFNMatch_;
-int32 kLogSiteUninitialized = 1000;
-
// List of per-module log levels from FLAGS_vmodule.
// Once created each element is never deleted/modified
// except for the vlog_level: other threads will read VModuleInfo blobs
@@ -127,6 +121,8 @@
// Pointer to head of the VModuleInfo list.
// It's a map from module pattern to logging level for those module(s).
static VModuleInfo* vmodule_list = 0;
+static SiteFlag* cached_site_list = 0;
+
// Boolean initialization flag.
static bool inited_vmodule = false;
@@ -141,14 +137,17 @@
VModuleInfo* head = NULL;
VModuleInfo* tail = NULL;
while ((sep = strchr(vmodule, '=')) != NULL) {
- string pattern(vmodule, sep - vmodule);
+ string pattern(vmodule, static_cast<size_t>(sep - vmodule));
int module_level;
if (sscanf(sep, "=%d", &module_level) == 1) {
VModuleInfo* info = new VModuleInfo;
info->module_pattern = pattern;
info->vlog_level = module_level;
- if (head) tail->next = info;
- else head = info;
+ if (head) {
+ tail->next = info;
+ } else {
+ head = info;
+ }
tail = info;
}
// Skip past this entry
@@ -166,7 +165,7 @@
// This can be called very early, so we use SpinLock and RAW_VLOG here.
int SetVLOGLevel(const char* module_pattern, int log_level) {
int result = FLAGS_v;
- int const pattern_len = strlen(module_pattern);
+ size_t const pattern_len = strlen(module_pattern);
bool found = false;
{
MutexLock l(&vmodule_lock); // protect whole read-modify-write
@@ -192,6 +191,23 @@
info->vlog_level = log_level;
info->next = vmodule_list;
vmodule_list = info;
+
+ SiteFlag** item_ptr = &cached_site_list;
+ SiteFlag* item = cached_site_list;
+
+ // We traverse the list fully because the pattern can match several items
+ // from the list.
+ while (item) {
+ if (SafeFNMatch_(module_pattern, pattern_len, item->base_name,
+ item->base_len)) {
+ // Redirect the cached value to its module override.
+ item->level = &info->vlog_level;
+ *item_ptr = item->next; // Remove the item from the list.
+ } else {
+ item_ptr = &item->next;
+ }
+ item = *item_ptr;
+ }
}
}
RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
@@ -200,7 +216,7 @@
// NOTE: Individual VLOG statements cache the integer log level pointers.
// NOTE: This function must not allocate memory or require any locks.
-bool InitVLOG3__(int32** site_flag, int32* site_default,
+bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
const char* fname, int32 verbose_level) {
MutexLock l(&vmodule_lock);
bool read_vmodule_flag = inited_vmodule;
@@ -213,10 +229,17 @@
int old_errno = errno;
// site_default normally points to FLAGS_v
- int32* site_flag_value = site_default;
+ int32* site_flag_value = level_default;
// Get basename for file
const char* base = strrchr(fname, '/');
+
+#ifdef _WIN32
+ if (!base) {
+ base = strrchr(fname, '\\');
+ }
+#endif
+
base = base ? (base+1) : fname;
const char* base_end = strchr(base, '.');
size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
@@ -246,7 +269,20 @@
ANNOTATE_BENIGN_RACE(site_flag,
"*site_flag may be written by several threads,"
" but the value will be the same");
- if (read_vmodule_flag) *site_flag = site_flag_value;
+ if (read_vmodule_flag) {
+ site_flag->level = site_flag_value;
+ // If VLOG flag has been cached to the default site pointer,
+ // we want to add to the cached list in order to invalidate in case
+ // SetVModule is called afterwards with new modules.
+ // The performance penalty here is neglible, because InitVLOG3__ is called
+ // once per site.
+ if (site_flag_value == level_default && !site_flag->base_name) {
+ site_flag->base_name = base;
+ site_flag->base_len = base_length;
+ site_flag->next = cached_site_list;
+ cached_site_list = site_flag;
+ }
+ }
// restore the errno in case something recoverable went wrong during
// the initialization of the VLOG mechanism (see above note "protect the..")
diff --git a/src/windows/config.h b/src/windows/config.h
deleted file mode 100755
index 2d23fb0..0000000
--- a/src/windows/config.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* src/config.h.in. Generated from configure.ac by autoheader. */
-
-/* Namespace for Google classes */
-#define GOOGLE_NAMESPACE google
-
-/* Stops putting the code inside the Google namespace */
-#define _END_GOOGLE_NAMESPACE_ }
-
-/* Puts following code inside the Google namespace */
-#define _START_GOOGLE_NAMESPACE_ namespace google {
-
-/* Always the empty-string on non-windows systems. On windows, should be
- "__declspec(dllexport)". This way, when we compile the dll, we export our
- functions/classes. It's safe to define this here because config.h is only
- used internally, to compile the DLL, and every DLL source file #includes
- "config.h" before anything else. */
-#ifndef GOOGLE_GLOG_DLL_DECL
-# define GOOGLE_GLOG_IS_A_DLL 1 /* not set if you're statically linking */
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllexport)
-# define GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
-#endif
diff --git a/src/windows/dirent.h b/src/windows/dirent.h
new file mode 100644
index 0000000..12cf00a
--- /dev/null
+++ b/src/windows/dirent.h
@@ -0,0 +1,1159 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ *
+ * Copyright (C) 1998-2019 Toni Ronkko
+ * This file is part of dirent. Dirent may be freely distributed
+ * under the MIT license. For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/* Hide warnings about unreferenced local functions */
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+# pragma warning(disable:4505)
+#elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cwchar>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+# define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+# define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+# define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+# define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+# define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+# define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+# define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+# define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+# define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+# define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+# define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+# define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+# define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+# define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+# define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+# define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+# define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+# define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+# define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+# define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+# define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+# define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+# define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+# define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+# define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros. Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility. These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of the file name without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return the maximum size of a file name */
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+ /* Always zero */
+ long d_ino;
+
+ /* File position within stream */
+ long d_off;
+
+ /* Structure size */
+ unsigned short d_reclen;
+
+ /* Length of name without \0 */
+ size_t d_namlen;
+
+ /* File type */
+ int d_type;
+
+ /* File name */
+ wchar_t d_name[PATH_MAX+1];
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+ /* Current directory entry */
+ struct _wdirent ent;
+
+ /* Private file data */
+ WIN32_FIND_DATAW data;
+
+ /* True if data is valid */
+ int cached;
+
+ /* Win32 search handle */
+ HANDLE handle;
+
+ /* Initial directory name */
+ wchar_t *patt;
+};
+typedef struct _WDIR _WDIR;
+
+/* Multi-byte character version */
+struct dirent {
+ /* Always zero */
+ long d_ino;
+
+ /* File position within stream */
+ long d_off;
+
+ /* Structure size */
+ unsigned short d_reclen;
+
+ /* Length of name without \0 */
+ size_t d_namlen;
+
+ /* File type */
+ int d_type;
+
+ /* File name */
+ char d_name[PATH_MAX+1];
+};
+typedef struct dirent dirent;
+
+struct DIR {
+ struct dirent ent;
+ struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+
+/* Dirent functions */
+static DIR *opendir (const char *dirname);
+static _WDIR *_wopendir (const wchar_t *dirname);
+
+static struct dirent *readdir (DIR *dirp);
+static struct _wdirent *_wreaddir (_WDIR *dirp);
+
+static int readdir_r(
+ DIR *dirp, struct dirent *entry, struct dirent **result);
+static int _wreaddir_r(
+ _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
+
+static int closedir (DIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+
+static void rewinddir (DIR* dirp);
+static void _wrewinddir (_WDIR* dirp);
+
+static int scandir (const char *dirname, struct dirent ***namelist,
+ int (*filter)(const struct dirent*),
+ int (*compare)(const struct dirent**, const struct dirent**));
+
+static int alphasort (const struct dirent **a, const struct dirent **b);
+
+static int versionsort (const struct dirent **a, const struct dirent **b);
+
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+ size_t *pReturnValue,
+ wchar_t *wcstr,
+ size_t sizeInWords,
+ const char *mbstr,
+ size_t count);
+
+static int dirent_wcstombs_s(
+ size_t *pReturnValue,
+ char *mbstr,
+ size_t sizeInBytes,
+ const wchar_t *wcstr,
+ size_t count);
+
+static void dirent_set_errno (int error);
+
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+ const wchar_t *dirname)
+{
+ _WDIR *dirp;
+ DWORD n;
+ wchar_t *p;
+
+ /* Must have directory name */
+ if (dirname == NULL || dirname[0] == '\0') {
+ dirent_set_errno (ENOENT);
+ return NULL;
+ }
+
+ /* Allocate new _WDIR structure */
+ dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+ if (!dirp) {
+ return NULL;
+ }
+
+ /* Reset _WDIR structure */
+ dirp->handle = INVALID_HANDLE_VALUE;
+ dirp->patt = NULL;
+ dirp->cached = 0;
+
+ /*
+ * Compute the length of full path plus zero terminator
+ *
+ * Note that on WinRT there's no way to convert relative paths
+ * into absolute paths, so just assume it is an absolute path.
+ */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ /* Desktop */
+ n = GetFullPathNameW (dirname, 0, NULL, NULL);
+#else
+ /* WinRT */
+ n = wcslen (dirname);
+#endif
+
+ /* Allocate room for absolute directory name and search pattern */
+ dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+ if (dirp->patt == NULL) {
+ goto exit_closedir;
+ }
+
+ /*
+ * Convert relative directory name to an absolute one. This
+ * allows rewinddir() to function correctly even when current
+ * working directory is changed between opendir() and rewinddir().
+ *
+ * Note that on WinRT there's no way to convert relative paths
+ * into absolute paths, so just assume it is an absolute path.
+ */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ /* Desktop */
+ n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+ if (n <= 0) {
+ goto exit_closedir;
+ }
+#else
+ /* WinRT */
+ wcsncpy_s (dirp->patt, n+1, dirname, n);
+#endif
+
+ /* Append search pattern \* to the directory name */
+ p = dirp->patt + n;
+ switch (p[-1]) {
+ case '\\':
+ case '/':
+ case ':':
+ /* Directory ends in path separator, e.g. c:\temp\ */
+ /*NOP*/;
+ break;
+
+ default:
+ /* Directory name doesn't end in path separator */
+ *p++ = '\\';
+ }
+ *p++ = '*';
+ *p = '\0';
+
+ /* Open directory stream and retrieve the first entry */
+ if (!dirent_first (dirp)) {
+ goto exit_closedir;
+ }
+
+ /* Success */
+ return dirp;
+
+ /* Failure */
+exit_closedir:
+ _wclosedir (dirp);
+ return NULL;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns pointer to static directory entry which may be overwritten by
+ * subsequent calls to _wreaddir().
+ */
+static struct _wdirent*
+_wreaddir(
+ _WDIR *dirp)
+{
+ struct _wdirent *entry;
+
+ /*
+ * Read directory entry to buffer. We can safely ignore the return value
+ * as entry will be set to NULL in case of error.
+ */
+ (void) _wreaddir_r (dirp, &dirp->ent, &entry);
+
+ /* Return pointer to statically allocated directory entry */
+ return entry;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns zero on success. If end of directory stream is reached, then sets
+ * result to NULL and returns zero.
+ */
+static int
+_wreaddir_r(
+ _WDIR *dirp,
+ struct _wdirent *entry,
+ struct _wdirent **result)
+{
+ WIN32_FIND_DATAW *datap;
+
+ /* Read next directory entry */
+ datap = dirent_next (dirp);
+ if (datap) {
+ size_t n;
+ DWORD attr;
+
+ /*
+ * Copy file name as wide-character string. If the file name is too
+ * long to fit in to the destination buffer, then truncate file name
+ * to PATH_MAX characters and zero-terminate the buffer.
+ */
+ n = 0;
+ while (n < PATH_MAX && datap->cFileName[n] != 0) {
+ entry->d_name[n] = datap->cFileName[n];
+ n++;
+ }
+ entry->d_name[n] = 0;
+
+ /* Length of file name excluding zero terminator */
+ entry->d_namlen = n;
+
+ /* File type */
+ attr = datap->dwFileAttributes;
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+ entry->d_type = DT_CHR;
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ entry->d_type = DT_DIR;
+ } else {
+ entry->d_type = DT_REG;
+ }
+
+ /* Reset dummy fields */
+ entry->d_ino = 0;
+ entry->d_off = 0;
+ entry->d_reclen = sizeof (struct _wdirent);
+
+ /* Set result address */
+ *result = entry;
+
+ } else {
+
+ /* Return NULL to indicate end of directory */
+ *result = NULL;
+
+ }
+
+ return /*OK*/0;
+}
+
+/*
+ * Close directory stream opened by opendir() function. This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+ _WDIR *dirp)
+{
+ int ok;
+ if (dirp) {
+
+ /* Release search handle */
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
+ FindClose (dirp->handle);
+ }
+
+ /* Release search pattern */
+ free (dirp->patt);
+
+ /* Release directory structure */
+ free (dirp);
+ ok = /*success*/0;
+
+ } else {
+
+ /* Invalid directory stream */
+ dirent_set_errno (EBADF);
+ ok = /*failure*/-1;
+
+ }
+ return ok;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void
+_wrewinddir(
+ _WDIR* dirp)
+{
+ if (dirp) {
+ /* Release existing search handle */
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
+ FindClose (dirp->handle);
+ }
+
+ /* Open new search handle */
+ dirent_first (dirp);
+ }
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+ _WDIR *dirp)
+{
+ WIN32_FIND_DATAW *datap;
+ DWORD error;
+
+ /* Open directory and retrieve the first entry */
+ dirp->handle = FindFirstFileExW(
+ dirp->patt, FindExInfoStandard, &dirp->data,
+ FindExSearchNameMatch, NULL, 0);
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+ /* a directory entry is now waiting in memory */
+ datap = &dirp->data;
+ dirp->cached = 1;
+
+ } else {
+
+ /* Failed to open directory: no directory entry in memory */
+ dirp->cached = 0;
+ datap = NULL;
+
+ /* Set error code */
+ error = GetLastError ();
+ switch (error) {
+ case ERROR_ACCESS_DENIED:
+ /* No read access to directory */
+ dirent_set_errno (EACCES);
+ break;
+
+ case ERROR_DIRECTORY:
+ /* Directory name is invalid */
+ dirent_set_errno (ENOTDIR);
+ break;
+
+ case ERROR_PATH_NOT_FOUND:
+ default:
+ /* Cannot find the file */
+ dirent_set_errno (ENOENT);
+ }
+
+ }
+ return datap;
+}
+
+/*
+ * Get next directory entry (internal).
+ *
+ * Returns
+ */
+static WIN32_FIND_DATAW*
+dirent_next(
+ _WDIR *dirp)
+{
+ WIN32_FIND_DATAW *p;
+
+ /* Get next directory entry */
+ if (dirp->cached != 0) {
+
+ /* A valid directory entry already in memory */
+ p = &dirp->data;
+ dirp->cached = 0;
+
+ } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+ /* Get the next directory entry from stream */
+ if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+ /* Got a file */
+ p = &dirp->data;
+ } else {
+ /* The very last entry has been processed or an error occurred */
+ FindClose (dirp->handle);
+ dirp->handle = INVALID_HANDLE_VALUE;
+ p = NULL;
+ }
+
+ } else {
+
+ /* End of directory stream reached */
+ p = NULL;
+
+ }
+
+ return p;
+}
+
+/*
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+ const char *dirname)
+{
+ struct DIR *dirp;
+
+ /* Must have directory name */
+ if (dirname == NULL || dirname[0] == '\0') {
+ dirent_set_errno (ENOENT);
+ return NULL;
+ }
+
+ /* Allocate memory for DIR structure */
+ dirp = (DIR*) malloc (sizeof (struct DIR));
+ if (!dirp) {
+ return NULL;
+ }
+ {
+ int error;
+ wchar_t wname[PATH_MAX + 1];
+ size_t n;
+
+ /* Convert directory name to wide-character string */
+ error = dirent_mbstowcs_s(
+ &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
+ if (error) {
+ /*
+ * Cannot convert file name to wide-character string. This
+ * occurs if the string contains invalid multi-byte sequences or
+ * the output buffer is too small to contain the resulting
+ * string.
+ */
+ goto exit_free;
+ }
+
+
+ /* Open directory stream using wide-character name */
+ dirp->wdirp = _wopendir (wname);
+ if (!dirp->wdirp) {
+ goto exit_free;
+ }
+
+ }
+
+ /* Success */
+ return dirp;
+
+ /* Failure */
+exit_free:
+ free (dirp);
+ return NULL;
+}
+
+/*
+ * Read next directory entry.
+ */
+static struct dirent*
+readdir(
+ DIR *dirp)
+{
+ struct dirent *entry;
+
+ /*
+ * Read directory entry to buffer. We can safely ignore the return value
+ * as entry will be set to NULL in case of error.
+ */
+ (void) readdir_r (dirp, &dirp->ent, &entry);
+
+ /* Return pointer to statically allocated directory entry */
+ return entry;
+}
+
+/*
+ * Read next directory entry into called-allocated buffer.
+ *
+ * Returns zero on success. If the end of directory stream is reached, then
+ * sets result to NULL and returns zero.
+ */
+static int
+readdir_r(
+ DIR *dirp,
+ struct dirent *entry,
+ struct dirent **result)
+{
+ WIN32_FIND_DATAW *datap;
+
+ /* Read next directory entry */
+ datap = dirent_next (dirp->wdirp);
+ if (datap) {
+ size_t n;
+ int error;
+
+ /* Attempt to convert file name to multi-byte string */
+ error = dirent_wcstombs_s(
+ &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
+
+ /*
+ * If the file name cannot be represented by a multi-byte string,
+ * then attempt to use old 8+3 file name. This allows traditional
+ * Unix-code to access some file names despite of unicode
+ * characters, although file names may seem unfamiliar to the user.
+ *
+ * Be ware that the code below cannot come up with a short file
+ * name unless the file system provides one. At least
+ * VirtualBox shared folders fail to do this.
+ */
+ if (error && datap->cAlternateFileName[0] != '\0') {
+ error = dirent_wcstombs_s(
+ &n, entry->d_name, PATH_MAX + 1,
+ datap->cAlternateFileName, PATH_MAX + 1);
+ }
+
+ if (!error) {
+ DWORD attr;
+
+ /* Length of file name excluding zero terminator */
+ entry->d_namlen = n - 1;
+
+ /* File attributes */
+ attr = datap->dwFileAttributes;
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+ entry->d_type = DT_CHR;
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ entry->d_type = DT_DIR;
+ } else {
+ entry->d_type = DT_REG;
+ }
+
+ /* Reset dummy fields */
+ entry->d_ino = 0;
+ entry->d_off = 0;
+ entry->d_reclen = sizeof (struct dirent);
+
+ } else {
+
+ /*
+ * Cannot convert file name to multi-byte string so construct
+ * an erroneous directory entry and return that. Note that
+ * we cannot return NULL as that would stop the processing
+ * of directory entries completely.
+ */
+ entry->d_name[0] = '?';
+ entry->d_name[1] = '\0';
+ entry->d_namlen = 1;
+ entry->d_type = DT_UNKNOWN;
+ entry->d_ino = 0;
+ entry->d_off = -1;
+ entry->d_reclen = 0;
+
+ }
+
+ /* Return pointer to directory entry */
+ *result = entry;
+
+ } else {
+
+ /* No more directory entries */
+ *result = NULL;
+
+ }
+
+ return /*OK*/0;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+ DIR *dirp)
+{
+ int ok;
+ if (dirp) {
+
+ /* Close wide-character directory stream */
+ ok = _wclosedir (dirp->wdirp);
+ dirp->wdirp = NULL;
+
+ /* Release multi-byte character version */
+ free (dirp);
+
+ } else {
+
+ /* Invalid directory stream */
+ dirent_set_errno (EBADF);
+ ok = /*failure*/-1;
+
+ }
+ return ok;
+}
+
+/*
+ * Rewind directory stream to beginning.
+ */
+static void
+rewinddir(
+ DIR* dirp)
+{
+ /* Rewind wide-character string directory stream */
+ _wrewinddir (dirp->wdirp);
+}
+
+/*
+ * Scan directory for entries.
+ */
+static int
+scandir(
+ const char *dirname,
+ struct dirent ***namelist,
+ int (*filter)(const struct dirent*),
+ int (*compare)(const struct dirent**, const struct dirent**))
+{
+ struct dirent **files = NULL;
+ size_t size = 0;
+ size_t allocated = 0;
+ const size_t init_size = 1;
+ DIR *dir = NULL;
+ struct dirent *entry;
+ struct dirent *tmp = NULL;
+ size_t i;
+ int result = 0;
+
+ /* Open directory stream */
+ dir = opendir (dirname);
+ if (dir) {
+
+ /* Read directory entries to memory */
+ while (1) {
+
+ /* Enlarge pointer table to make room for another pointer */
+ if (size >= allocated) {
+ void *p;
+ size_t num_entries;
+
+ /* Compute number of entries in the enlarged pointer table */
+ if (size < init_size) {
+ /* Allocate initial pointer table */
+ num_entries = init_size;
+ } else {
+ /* Double the size */
+ num_entries = size * 2;
+ }
+
+ /* Allocate first pointer table or enlarge existing table */
+ p = realloc (files, sizeof (void*) * num_entries);
+ if (p != NULL) {
+ /* Got the memory */
+ files = (dirent**) p;
+ allocated = num_entries;
+ } else {
+ /* Out of memory */
+ result = -1;
+ break;
+ }
+
+ }
+
+ /* Allocate room for temporary directory entry */
+ if (tmp == NULL) {
+ tmp = (struct dirent*) malloc (sizeof (struct dirent));
+ if (tmp == NULL) {
+ /* Cannot allocate temporary directory entry */
+ result = -1;
+ break;
+ }
+ }
+
+ /* Read directory entry to temporary area */
+ if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
+
+ /* Did we get an entry? */
+ if (entry != NULL) {
+ int pass;
+
+ /* Determine whether to include the entry in result */
+ if (filter) {
+ /* Let the filter function decide */
+ pass = filter (tmp);
+ } else {
+ /* No filter function, include everything */
+ pass = 1;
+ }
+
+ if (pass) {
+ /* Store the temporary entry to pointer table */
+ files[size++] = tmp;
+ tmp = NULL;
+
+ /* Keep up with the number of files */
+ result++;
+ }
+
+ } else {
+
+ /*
+ * End of directory stream reached => sort entries and
+ * exit.
+ */
+ qsort (files, size, sizeof (void*),
+ (int (*) (const void*, const void*)) compare);
+ break;
+
+ }
+
+ } else {
+ /* Error reading directory entry */
+ result = /*Error*/ -1;
+ break;
+ }
+
+ }
+
+ } else {
+ /* Cannot open directory */
+ result = /*Error*/ -1;
+ }
+
+ /* Release temporary directory entry */
+ free (tmp);
+
+ /* Release allocated memory on error */
+ if (result < 0) {
+ for (i = 0; i < size; i++) {
+ free (files[i]);
+ }
+ free (files);
+ files = NULL;
+ }
+
+ /* Close directory stream */
+ if (dir) {
+ closedir (dir);
+ }
+
+ /* Pass pointer table to caller */
+ if (namelist) {
+ *namelist = files;
+ }
+ return result;
+}
+
+/* Alphabetical sorting */
+static int
+alphasort(
+ const struct dirent **a, const struct dirent **b)
+{
+ return strcoll ((*a)->d_name, (*b)->d_name);
+}
+
+/* Sort versions */
+static int
+versionsort(
+ const struct dirent **a, const struct dirent **b)
+{
+ /* FIXME: implement strverscmp and use that */
+ return alphasort (a, b);
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+ size_t *pReturnValue,
+ wchar_t *wcstr,
+ size_t sizeInWords,
+ const char *mbstr,
+ size_t count)
+{
+ int error;
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+
+ /* Microsoft Visual Studio 2005 or later */
+ error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+ /* Older Visual Studio or non-Microsoft compiler */
+ size_t n;
+
+ /* Convert to wide-character string (or count characters) */
+ n = mbstowcs (wcstr, mbstr, sizeInWords);
+ if (!wcstr || n < count) {
+
+ /* Zero-terminate output buffer */
+ if (wcstr && sizeInWords) {
+ if (n >= sizeInWords) {
+ n = sizeInWords - 1;
+ }
+ wcstr[n] = 0;
+ }
+
+ /* Length of resulting multi-byte string WITH zero terminator */
+ if (pReturnValue) {
+ *pReturnValue = n + 1;
+ }
+
+ /* Success */
+ error = 0;
+
+ } else {
+
+ /* Could not convert string */
+ error = 1;
+
+ }
+
+#endif
+ return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+ size_t *pReturnValue,
+ char *mbstr,
+ size_t sizeInBytes, /* max size of mbstr */
+ const wchar_t *wcstr,
+ size_t count)
+{
+ int error;
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+
+ /* Microsoft Visual Studio 2005 or later */
+ error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+ /* Older Visual Studio or non-Microsoft compiler */
+ size_t n;
+
+ /* Convert to multi-byte string (or count the number of bytes needed) */
+ n = wcstombs (mbstr, wcstr, sizeInBytes);
+ if (!mbstr || n < count) {
+
+ /* Zero-terminate output buffer */
+ if (mbstr && sizeInBytes) {
+ if (n >= sizeInBytes) {
+ n = sizeInBytes - 1;
+ }
+ mbstr[n] = '\0';
+ }
+
+ /* Length of resulting multi-bytes string WITH zero-terminator */
+ if (pReturnValue) {
+ *pReturnValue = n + 1;
+ }
+
+ /* Success */
+ error = 0;
+
+ } else {
+
+ /* Cannot convert string */
+ error = 1;
+
+ }
+
+#endif
+ return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+ int error)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+
+ /* Microsoft Visual Studio 2005 and later */
+ _set_errno (error);
+
+#else
+
+ /* Non-Microsoft compiler or older Microsoft compiler */
+ errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
diff --git a/src/windows/glog/log_severity.h b/src/windows/glog/log_severity.h
deleted file mode 100644
index 22a4191..0000000
--- a/src/windows/glog/log_severity.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// This file is automatically generated from src/glog/log_severity.h
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BASE_LOG_SEVERITY_H__
-#define BASE_LOG_SEVERITY_H__
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
-
-// Variables of type LogSeverity are widely taken to lie in the range
-// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
-// you ever need to change their values or add a new severity.
-typedef int LogSeverity;
-
-const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
- NUM_SEVERITIES = 4;
-#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
-# ifdef ERROR
-# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
-# endif
-const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
- ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
-#endif
-
-// DFATAL is FATAL in debug mode, ERROR in normal mode
-#ifdef NDEBUG
-#define DFATAL_LEVEL ERROR
-#else
-#define DFATAL_LEVEL FATAL
-#endif
-
-extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
-
-// NDEBUG usage helpers related to (RAW_)DCHECK:
-//
-// DEBUG_MODE is for small !NDEBUG uses like
-// if (DEBUG_MODE) foo.CheckThatFoo();
-// instead of substantially more verbose
-// #ifndef NDEBUG
-// foo.CheckThatFoo();
-// #endif
-//
-// IF_DEBUG_MODE is for small !NDEBUG uses like
-// IF_DEBUG_MODE( string error; )
-// DCHECK(Foo(&error)) << error;
-// instead of substantially more verbose
-// #ifndef NDEBUG
-// string error;
-// DCHECK(Foo(&error)) << error;
-// #endif
-//
-#ifdef NDEBUG
-enum { DEBUG_MODE = 0 };
-#define IF_DEBUG_MODE(x)
-#else
-enum { DEBUG_MODE = 1 };
-#define IF_DEBUG_MODE(x) x
-#endif
-
-#endif // BASE_LOG_SEVERITY_H__
diff --git a/src/windows/glog/logging.h b/src/windows/glog/logging.h
deleted file mode 100755
index 26e080b..0000000
--- a/src/windows/glog/logging.h
+++ /dev/null
@@ -1,1662 +0,0 @@
-// This file is automatically generated from src/glog/logging.h.in
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-
-// Copyright (c) 1999, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Ray Sidney
-//
-// This file contains #include information about logging-related stuff.
-// Pretty much everybody needs to #include this file so that they can
-// log various happenings.
-//
-#ifndef _LOGGING_H_
-#define _LOGGING_H_
-
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <iosfwd>
-#include <ostream>
-#include <sstream>
-#include <string>
-#if 0
-# include <unistd.h>
-#endif
-#include <vector>
-
-#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
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
-
-// We care a lot about number of bits things take up. Unfortunately,
-// systems define their bit-specific ints in a lot of different ways.
-// We use our own way, and have a typedef to get there.
-// Note: these commands below may look like "#if 1" or "#if 0", but
-// that's because they were constructed that way at ./configure time.
-// Look at logging.h.in to see how they're calculated (based on your config).
-#if 0
-#include <stdint.h> // the normal place uint16_t is defined
-#endif
-#if 0
-#include <sys/types.h> // the normal place u_int16_t is defined
-#endif
-#if 0
-#include <inttypes.h> // a third place for uint16_t or u_int16_t
-#endif
-
-#if 0
-#include <gflags/gflags.h>
-#endif
-
-namespace google {
-
-#if 0 // the C99 format
-typedef int32_t int32;
-typedef uint32_t uint32;
-typedef int64_t int64;
-typedef uint64_t uint64;
-#elif 0 // the BSD format
-typedef int32_t int32;
-typedef u_int32_t uint32;
-typedef int64_t int64;
-typedef u_int64_t uint64;
-#elif 1 // the windows (vc7) format
-typedef __int32 int32;
-typedef unsigned __int32 uint32;
-typedef __int64 int64;
-typedef unsigned __int64 uint64;
-#else
-#error Do not know how to define a 32-bit integer quantity on your system
-#endif
-
-}
-
-// The global value of GOOGLE_STRIP_LOG. All the messages logged to
-// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
-// If it can be determined at compile time that the message will not be
-// printed, the statement will be compiled out.
-//
-// Example: to strip out all INFO and WARNING messages, use the value
-// of 2 below. To make an exception for WARNING messages from a single
-// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
-// base/logging.h
-#ifndef GOOGLE_STRIP_LOG
-#define GOOGLE_STRIP_LOG 0
-#endif
-
-// GCC can be told that a certain branch is not likely to be taken (for
-// instance, a CHECK failure), and use that information in static analysis.
-// Giving it this information can help it optimize for the common case in
-// the absence of better information (ie. -fprofile-arcs).
-//
-#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
-#if 0
-#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
-#else
-#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_FALSE
-#if 0
-#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
-#else
-#define GOOGLE_PREDICT_FALSE(x) x
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_TRUE
-#if 0
-#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
-#else
-#define GOOGLE_PREDICT_TRUE(x) x
-#endif
-#endif
-
-
-// Make a bunch of macros for logging. The way to log things is to stream
-// things to LOG(<a particular severity level>). E.g.,
-//
-// LOG(INFO) << "Found " << num_cookies << " cookies";
-//
-// You can capture log messages in a string, rather than reporting them
-// immediately:
-//
-// vector<string> errors;
-// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
-//
-// This pushes back the new error onto 'errors'; if given a NULL pointer,
-// it reports the error via LOG(ERROR).
-//
-// You can also do conditional logging:
-//
-// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// You can also do occasional logging (log every n'th occurrence of an
-// event):
-//
-// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
-//
-// The above will cause log messages to be output on the 1st, 11th, 21st, ...
-// times it is executed. Note that the special google::COUNTER value is used
-// to identify which repetition is happening.
-//
-// You can also do occasional conditional logging (log every n'th
-// occurrence of an event, when condition is satisfied):
-//
-// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
-// << "th big cookie";
-//
-// You can log messages the first N times your code executes a line. E.g.
-//
-// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
-//
-// Outputs log messages for the first 20 times it is executed.
-//
-// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
-// These log to syslog as well as to the normal logs. If you use these at
-// all, you need to be aware that syslog can drastically reduce performance,
-// especially if it is configured for remote logging! Don't use these
-// unless you fully understand this and have a concrete need to use them.
-// Even then, try to minimize your use of them.
-//
-// There are also "debug mode" logging macros like the ones above:
-//
-// DLOG(INFO) << "Found cookies";
-//
-// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
-//
-// All "debug mode" logging is compiled away to nothing for non-debug mode
-// compiles.
-//
-// We also have
-//
-// LOG_ASSERT(assertion);
-// DLOG_ASSERT(assertion);
-//
-// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
-//
-// There are "verbose level" logging macros. They look like
-//
-// VLOG(1) << "I'm printed when you run the program with --v=1 or more";
-// VLOG(2) << "I'm printed when you run the program with --v=2 or more";
-//
-// These always log at the INFO log level (when they log at all).
-// The verbose logging can also be turned on module-by-module. For instance,
-// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
-// will cause:
-// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
-// b. VLOG(1) and lower messages to be printed from file.{h,cc}
-// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
-// d. VLOG(0) and lower messages to be printed from elsewhere
-//
-// The wildcarding functionality shown by (c) supports both '*' (match
-// 0 or more characters) and '?' (match any single character) wildcards.
-//
-// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
-//
-// if (VLOG_IS_ON(2)) {
-// // do some logging preparation and logging
-// // that can't be accomplished with just VLOG(2) << ...;
-// }
-//
-// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
-// condition macros for sample cases, when some extra computation and
-// preparation for logs is not needed.
-// VLOG_IF(1, (size > 1024))
-// << "I'm printed when size is more than 1024 and when you run the "
-// "program with --v=1 or more";
-// VLOG_EVERY_N(1, 10)
-// << "I'm printed every 10th occurrence, and when you run the program "
-// "with --v=1 or more. Present occurence is " << google::COUNTER;
-// VLOG_IF_EVERY_N(1, (size > 1024), 10)
-// << "I'm printed on every 10th occurence of case when size is more "
-// " than 1024, when you run the program with --v=1 or more. ";
-// "Present occurence is " << google::COUNTER;
-//
-// The supported severity levels for macros that allow you to specify one
-// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
-// Note that messages of a given severity are logged not only in the
-// logfile for that severity, but also in all logfiles of lower severity.
-// E.g., a message of severity FATAL will be logged to the logfiles of
-// severity FATAL, ERROR, WARNING, and INFO.
-//
-// There is also the special severity of DFATAL, which logs FATAL in
-// debug mode, ERROR in normal mode.
-//
-// Very important: logging a message at the FATAL severity level causes
-// the program to terminate (after the message is logged).
-//
-// Unless otherwise specified, logs will be written to the filename
-// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
-// by the date, time, and pid (you can't prevent the date, time, and pid
-// from being in the filename).
-//
-// The logging code takes two flags:
-// --v=# set the verbose level
-// --logtostderr log all the messages to stderr instead of to logfiles
-
-// LOG LINE PREFIX FORMAT
-//
-// Log lines have this form:
-//
-// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
-//
-// where the fields are defined as follows:
-//
-// L A single character, representing the log level
-// (eg 'I' for INFO)
-// mm The month (zero padded; ie May is '05')
-// dd The day (zero padded)
-// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
-// threadid The space-padded thread ID as returned by GetTID()
-// (this matches the PID on Linux)
-// file The file name
-// line The line number
-// msg The user-supplied message
-//
-// Example:
-//
-// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
-// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
-//
-// NOTE: although the microseconds are useful for comparing events on
-// a single machine, clocks on different machines may not be well
-// synchronized. Hence, use caution when comparing the low bits of
-// timestamps from different machines.
-
-#ifndef DECLARE_VARIABLE
-#define MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#define DECLARE_VARIABLE(type, shorttype, name, tn) \
- namespace fL##shorttype { \
- extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
- } \
- using fL##shorttype::FLAGS_##name
-
-// bool specialization
-#define DECLARE_bool(name) \
- DECLARE_VARIABLE(bool, B, name, bool)
-
-// int32 specialization
-#define DECLARE_int32(name) \
- DECLARE_VARIABLE(google::int32, I, name, int32)
-
-// Special case for string, because we have to specify the namespace
-// std::string, which doesn't play nicely with our FLAG__namespace hackery.
-#define DECLARE_string(name) \
- namespace fLS { \
- extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
- } \
- using fLS::FLAGS_##name
-#endif
-
-// Set whether log messages go to stderr instead of logfiles
-DECLARE_bool(logtostderr);
-
-// Set whether log messages go to stderr in addition to logfiles.
-DECLARE_bool(alsologtostderr);
-
-// Set color messages logged to stderr (if supported by terminal).
-DECLARE_bool(colorlogtostderr);
-
-// Log messages at a level >= this flag are automatically sent to
-// stderr in addition to log files.
-DECLARE_int32(stderrthreshold);
-
-// Set whether the log prefix should be prepended to each line of output.
-DECLARE_bool(log_prefix);
-
-// Log messages at a level <= this flag are buffered.
-// Log messages at a higher level are flushed immediately.
-DECLARE_int32(logbuflevel);
-
-// Sets the maximum number of seconds which logs may be buffered for.
-DECLARE_int32(logbufsecs);
-
-// Log suppression level: messages logged at a lower level than this
-// are suppressed.
-DECLARE_int32(minloglevel);
-
-// If specified, logfiles are written into this directory instead of the
-// default logging directory.
-DECLARE_string(log_dir);
-
-// Set the log file mode.
-DECLARE_int32(logfile_mode);
-
-// Sets the path of the directory into which to put additional links
-// to the log files.
-DECLARE_string(log_link);
-
-DECLARE_int32(v); // in vlog_is_on.cc
-
-// Sets the maximum log file size (in MB).
-DECLARE_int32(max_log_size);
-
-// Sets whether to avoid logging to the disk if the disk is full.
-DECLARE_bool(stop_logging_if_full_disk);
-
-#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS
-#undef DECLARE_VARIABLE
-#undef DECLARE_bool
-#undef DECLARE_int32
-#undef DECLARE_string
-#endif
-
-// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
-// security reasons. See LOG(severtiy) below.
-
-// A few definitions of macros that don't generate much code. Since
-// LOG(INFO) and its ilk are used all over our code, it's
-// better to have compact code for these operations.
-
-#if GOOGLE_STRIP_LOG == 0
-#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
- __FILE__, __LINE__)
-#define LOG_TO_STRING_INFO(message) google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_INFO, message)
-#else
-#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
-#define LOG_TO_STRING_INFO(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 1
-#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_WARNING)
-#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_WARNING, message)
-#else
-#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
-#define LOG_TO_STRING_WARNING(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 2
-#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_ERROR)
-#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_ERROR, message)
-#else
-#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
-#define LOG_TO_STRING_ERROR(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 3
-#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
- __FILE__, __LINE__)
-#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_FATAL, message)
-#else
-#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
-#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
-#endif
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define DCHECK_IS_ON() 0
-#else
-#define DCHECK_IS_ON() 1
-#endif
-
-// For DFATAL, we want to use LogMessage (as opposed to
-// LogMessageFatal), to be consistent with the original behavior.
-#if !DCHECK_IS_ON()
-#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
-#elif GOOGLE_STRIP_LOG <= 3
-#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_FATAL)
-#else
-#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
-#endif
-
-#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
-#define SYSLOG_INFO(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
- &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_WARNING(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
- &google::LogMessage::SendToLog)
-#define SYSLOG_WARNING(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
- &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_ERROR(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
- &google::LogMessage::SendToLog)
-#define SYSLOG_ERROR(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
- &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_FATAL(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
- &google::LogMessage::SendToLog)
-#define SYSLOG_FATAL(counter) \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
- &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_DFATAL(counter) \
- google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
- &google::LogMessage::SendToLog)
-#define SYSLOG_DFATAL(counter) \
- google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
- &google::LogMessage::SendToSyslogAndLog)
-
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-// A very useful logging macro to log windows errors:
-#define LOG_SYSRESULT(result) \
- if (FAILED(HRESULT_FROM_WIN32(result))) { \
- LPSTR message = NULL; \
- LPSTR msg = reinterpret_cast<LPSTR>(&message); \
- DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
- FORMAT_MESSAGE_FROM_SYSTEM, \
- 0, result, 0, msg, 100, NULL); \
- if (message_length > 0) { \
- google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
- &google::LogMessage::SendToLog).stream() \
- << reinterpret_cast<const char*>(message); \
- LocalFree(message); \
- } \
- }
-#endif
-
-// We use the preprocessor's merging operator, "##", so that, e.g.,
-// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny
-// subtle difference between ostream member streaming functions (e.g.,
-// ostream::operator<<(int) and ostream non-member streaming functions
-// (e.g., ::operator<<(ostream&, string&): it turns out that it's
-// impossible to stream something like a string directly to an unnamed
-// ostream. We employ a neat hack by calling the stream() member
-// function of LogMessage which seems to avoid the problem.
-#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
-#define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
-
-namespace google {
-
-// They need the definitions of integer types.
-#include "glog/log_severity.h"
-#include "glog/vlog_is_on.h"
-
-// Initialize google's logging library. You will see the program name
-// specified by argv0 in log outputs.
-GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0);
-
-// Shutdown google's logging library.
-GOOGLE_GLOG_DLL_DECL void ShutdownGoogleLogging();
-
-// Install a function which will be called after LOG(FATAL).
-GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)());
-
-class LogSink; // defined below
-
-// If a non-NULL sink pointer is given, we push this message to that sink.
-// For LOG_TO_SINK we then do normal LOG(severity) logging as well.
-// This is useful for capturing messages and passing/storing them
-// somewhere more specific than the global log of the process.
-// Argument types:
-// LogSink* sink;
-// LogSeverity severity;
-// The cast is to disambiguate NULL arguments.
-#define LOG_TO_SINK(sink, severity) \
- google::LogMessage( \
- __FILE__, __LINE__, \
- google::GLOG_ ## severity, \
- static_cast<google::LogSink*>(sink), true).stream()
-#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
- google::LogMessage( \
- __FILE__, __LINE__, \
- google::GLOG_ ## severity, \
- static_cast<google::LogSink*>(sink), false).stream()
-
-// If a non-NULL string pointer is given, we write this message to that string.
-// We then do normal LOG(severity) logging as well.
-// This is useful for capturing messages and storing them somewhere more
-// specific than the global log of the process.
-// Argument types:
-// string* message;
-// LogSeverity severity;
-// The cast is to disambiguate NULL arguments.
-// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
-// severity.
-#define LOG_TO_STRING(severity, message) \
- LOG_TO_STRING_##severity(static_cast<string*>(message)).stream()
-
-// If a non-NULL pointer is given, we push the message onto the end
-// of a vector of strings; otherwise, we report it with LOG(severity).
-// This is handy for capturing messages and perhaps passing them back
-// to the caller, rather than reporting them immediately.
-// Argument types:
-// LogSeverity severity;
-// vector<string> *outvec;
-// The cast is to disambiguate NULL arguments.
-#define LOG_STRING(severity, outvec) \
- LOG_TO_STRING_##severity(static_cast<std::vector<std::string>*>(outvec)).stream()
-
-#define LOG_IF(severity, condition) \
- !(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-#define SYSLOG_IF(severity, condition) \
- !(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity)
-
-#define LOG_ASSERT(condition) \
- LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
-#define SYSLOG_ASSERT(condition) \
- SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
-
-// CHECK dies with a fatal error if condition is not true. It is *not*
-// controlled by DCHECK_IS_ON(), so the check will be executed regardless of
-// compilation mode. Therefore, it is safe to do things like:
-// CHECK(fp->Write(x) == 4)
-#define CHECK(condition) \
- LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
- << "Check failed: " #condition " "
-
-// A container for a string pointer which can be evaluated to a bool -
-// true iff the pointer is NULL.
-struct CheckOpString {
- CheckOpString(std::string* str) : str_(str) { }
- // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
- // so there's no point in cleaning up str_.
- operator bool() const {
- return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL);
- }
- std::string* str_;
-};
-
-// Function is overloaded for integral types to allow static const
-// integrals declared in classes and not defined to be used as arguments to
-// CHECK* macros. It's not encouraged though.
-template <class T>
-inline const T& GetReferenceableValue(const T& t) { return t; }
-inline char GetReferenceableValue(char t) { return t; }
-inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
-inline signed char GetReferenceableValue(signed char t) { return t; }
-inline short GetReferenceableValue(short t) { return t; }
-inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
-inline int GetReferenceableValue(int t) { return t; }
-inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
-inline long GetReferenceableValue(long t) { return t; }
-inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
-inline long long GetReferenceableValue(long long t) { return t; }
-inline unsigned long long GetReferenceableValue(unsigned long long t) {
- return t;
-}
-
-// This is a dummy class to define the following operator.
-struct DummyClassToDefineOperator {};
-
-}
-
-// Define global operator<< to declare using ::operator<<.
-// This declaration will allow use to use CHECK macros for user
-// defined classes which have operator<< (e.g., stl_logging.h).
-inline std::ostream& operator<<(
- std::ostream& out, const google::DummyClassToDefineOperator&) {
- return out;
-}
-
-namespace google {
-
-// This formats a value for a failing CHECK_XX statement. Ordinarily,
-// it uses the definition for operator<<, with a few special cases below.
-template <typename T>
-inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
- (*os) << v;
-}
-
-// Overrides for char types provide readable values for unprintable
-// characters.
-template <> GOOGLE_GLOG_DLL_DECL
-void MakeCheckOpValueString(std::ostream* os, const char& v);
-template <> GOOGLE_GLOG_DLL_DECL
-void MakeCheckOpValueString(std::ostream* os, const signed char& v);
-template <> GOOGLE_GLOG_DLL_DECL
-void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
-
-// Build the error message string. Specify no inlining for code size.
-template <typename T1, typename T2>
-std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
- ;
-
-namespace base {
-namespace internal {
-
-// If "s" is less than base_logging::INFO, returns base_logging::INFO.
-// If "s" is greater than base_logging::FATAL, returns
-// base_logging::ERROR. Otherwise, returns "s".
-LogSeverity NormalizeSeverity(LogSeverity s);
-
-} // namespace internal
-
-// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
-// statement. See MakeCheckOpString for sample usage. Other
-// approaches were considered: use of a template method (e.g.,
-// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
-// base::Print<T2>, &v2), however this approach has complications
-// related to volatile arguments and function-pointer arguments).
-class GOOGLE_GLOG_DLL_DECL CheckOpMessageBuilder {
- public:
- // Inserts "exprtext" and " (" to the stream.
- explicit CheckOpMessageBuilder(const char *exprtext);
- // Deletes "stream_".
- ~CheckOpMessageBuilder();
- // For inserting the first variable.
- std::ostream* ForVar1() { return stream_; }
- // For inserting the second variable (adds an intermediate " vs. ").
- std::ostream* ForVar2();
- // Get the result (inserts the closing ")").
- std::string* NewString();
-
- private:
- std::ostringstream *stream_;
-};
-
-} // namespace base
-
-template <typename T1, typename T2>
-std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
- base::CheckOpMessageBuilder comb(exprtext);
- MakeCheckOpValueString(comb.ForVar1(), v1);
- MakeCheckOpValueString(comb.ForVar2(), v2);
- return comb.NewString();
-}
-
-// Helper functions for CHECK_OP macro.
-// The (int, int) specialization works around the issue that the compiler
-// will not instantiate the template version of the function on values of
-// unnamed enum type - see comment below.
-#define DEFINE_CHECK_OP_IMPL(name, op) \
- template <typename T1, typename T2> \
- inline std::string* name##Impl(const T1& v1, const T2& v2, \
- const char* exprtext) { \
- if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
- else return MakeCheckOpString(v1, v2, exprtext); \
- } \
- inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
- return name##Impl<int, int>(v1, v2, exprtext); \
- }
-
-// We use the full name Check_EQ, Check_NE, etc. in case the file including
-// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
-// This happens if, for example, those are used as token names in a
-// yacc grammar.
-DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
-DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
-DEFINE_CHECK_OP_IMPL(Check_LE, <=)
-DEFINE_CHECK_OP_IMPL(Check_LT, < )
-DEFINE_CHECK_OP_IMPL(Check_GE, >=)
-DEFINE_CHECK_OP_IMPL(Check_GT, > )
-#undef DEFINE_CHECK_OP_IMPL
-
-// Helper macro for binary operators.
-// Don't use this macro directly in your code, use CHECK_EQ et al below.
-
-#if defined(STATIC_ANALYSIS)
-// Only for static analysis tool to know that it is equivalent to assert
-#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
-#elif DCHECK_IS_ON()
-// In debug mode, avoid constructing CheckOpStrings if possible,
-// to reduce the overhead of CHECK statments by 2x.
-// Real DCHECK-heavy tests have seen 1.5x speedups.
-
-// The meaning of "string" might be different between now and
-// when this macro gets invoked (e.g., if someone is experimenting
-// with other string implementations that get defined after this
-// file is included). Save the current meaning now and use it
-// in the macro.
-typedef std::string _Check_string;
-#define CHECK_OP_LOG(name, op, val1, val2, log) \
- while (google::_Check_string* _result = \
- google::Check##name##Impl( \
- google::GetReferenceableValue(val1), \
- google::GetReferenceableValue(val2), \
- #val1 " " #op " " #val2)) \
- log(__FILE__, __LINE__, \
- google::CheckOpString(_result)).stream()
-#else
-// In optimized mode, use CheckOpString to hint to compiler that
-// the while condition is unlikely.
-#define CHECK_OP_LOG(name, op, val1, val2, log) \
- while (google::CheckOpString _result = \
- google::Check##name##Impl( \
- google::GetReferenceableValue(val1), \
- google::GetReferenceableValue(val2), \
- #val1 " " #op " " #val2)) \
- log(__FILE__, __LINE__, _result).stream()
-#endif // STATIC_ANALYSIS, DCHECK_IS_ON()
-
-#if GOOGLE_STRIP_LOG <= 3
-#define CHECK_OP(name, op, val1, val2) \
- CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
-#else
-#define CHECK_OP(name, op, val1, val2) \
- CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
-#endif // STRIP_LOG <= 3
-
-// Equality/Inequality checks - compare two values, and log a FATAL message
-// including the two values when the result is not as expected. The values
-// must have operator<<(ostream, ...) defined.
-//
-// You may append to the error message like so:
-// CHECK_NE(1, 2) << ": The world must be ending!";
-//
-// We are very careful to ensure that each argument is evaluated exactly
-// once, and that anything which is legal to pass as a function argument is
-// legal here. In particular, the arguments may be temporary expressions
-// which will end up being destroyed at the end of the apparent statement,
-// for example:
-// CHECK_EQ(string("abc")[1], 'b');
-//
-// WARNING: These don't compile correctly if one of the arguments is a pointer
-// and the other is NULL. To work around this, simply static_cast NULL to the
-// type of the desired pointer.
-
-#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
-#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
-#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
-#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
-#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
-#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
-
-// Check that the input is non NULL. This very useful in constructor
-// initializer lists.
-
-#define CHECK_NOTNULL(val) \
- google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
-
-// Helper functions for string comparisons.
-// To avoid bloat, the definitions are in logging.cc.
-#define DECLARE_CHECK_STROP_IMPL(func, expected) \
- GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \
- const char* s1, const char* s2, const char* names);
-DECLARE_CHECK_STROP_IMPL(strcmp, true)
-DECLARE_CHECK_STROP_IMPL(strcmp, false)
-DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
-DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
-#undef DECLARE_CHECK_STROP_IMPL
-
-// Helper macro for string comparisons.
-// Don't use this macro directly in your code, use CHECK_STREQ et al below.
-#define CHECK_STROP(func, op, expected, s1, s2) \
- while (google::CheckOpString _result = \
- google::Check##func##expected##Impl((s1), (s2), \
- #s1 " " #op " " #s2)) \
- LOG(FATAL) << *_result.str_
-
-
-// String (char*) equality/inequality checks.
-// CASE versions are case-insensitive.
-//
-// Note that "s1" and "s2" may be temporary strings which are destroyed
-// by the compiler at the end of the current "full expression"
-// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())).
-
-#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2)
-#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2)
-#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2)
-#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2)
-
-#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0])))
-#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0])))
-
-#define CHECK_DOUBLE_EQ(val1, val2) \
- do { \
- CHECK_LE((val1), (val2)+0.000000000000001L); \
- CHECK_GE((val1), (val2)-0.000000000000001L); \
- } while (0)
-
-#define CHECK_NEAR(val1, val2, margin) \
- do { \
- CHECK_LE((val1), (val2)+(margin)); \
- CHECK_GE((val1), (val2)-(margin)); \
- } while (0)
-
-// perror()..googly style!
-//
-// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and
-// CHECK equivalents with the addition that they postpend a description
-// of the current state of errno to their output lines.
-
-#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()
-
-#define GOOGLE_PLOG(severity, counter) \
- google::ErrnoLogMessage( \
- __FILE__, __LINE__, google::GLOG_ ## severity, counter, \
- &google::LogMessage::SendToLog)
-
-#define PLOG_IF(severity, condition) \
- !(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity)
-
-// A CHECK() macro that postpends errno if the condition is false. E.g.
-//
-// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... }
-#define PCHECK(condition) \
- PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
- << "Check failed: " #condition " "
-
-// A CHECK() macro that lets you assert the success of a function that
-// returns -1 and sets errno in case of an error. E.g.
-//
-// CHECK_ERR(mkdir(path, 0700));
-//
-// or
-//
-// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename;
-#define CHECK_ERR(invocation) \
-PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
- << #invocation
-
-// Use macro expansion to create, for each use of LOG_EVERY_N(), static
-// variables with the __LINE__ expansion as part of the variable name.
-#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line)
-#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line
-
-#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
-#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
-
-#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
- ++LOG_OCCURRENCES; \
- if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
- if (LOG_OCCURRENCES_MOD_N == 1) \
- google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
- &what_to_do).stream()
-
-#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
- ++LOG_OCCURRENCES; \
- if (condition && \
- ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
- google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
- &what_to_do).stream()
-
-#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \
- ++LOG_OCCURRENCES; \
- if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
- if (LOG_OCCURRENCES_MOD_N == 1) \
- google::ErrnoLogMessage( \
- __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
- &what_to_do).stream()
-
-#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
- static int LOG_OCCURRENCES = 0; \
- if (LOG_OCCURRENCES <= n) \
- ++LOG_OCCURRENCES; \
- if (LOG_OCCURRENCES <= n) \
- google::LogMessage( \
- __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
- &what_to_do).stream()
-
-namespace glog_internal_namespace_ {
-template <bool>
-struct CompileAssert {
-};
-struct CrashReason;
-
-// Returns true if FailureSignalHandler is installed.
-bool IsFailureSignalHandlerInstalled();
-} // namespace glog_internal_namespace_
-
-#define LOG_EVERY_N(severity, n) \
- SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
-
-#define SYSLOG_EVERY_N(severity, n) \
- SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog)
-
-#define PLOG_EVERY_N(severity, n) \
- SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
-
-#define LOG_FIRST_N(severity, n) \
- SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog)
-
-#define LOG_IF_EVERY_N(severity, condition, n) \
- SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog)
-
-// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
-enum PRIVATE_Counter {COUNTER};
-
-#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
-// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
-// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
-// to keep using this syntax, we define this macro to do the same thing
-// as COMPACT_GOOGLE_LOG_ERROR.
-#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
-#define SYSLOG_0 SYSLOG_ERROR
-#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
-// Needed for LOG_IS_ON(ERROR).
-const LogSeverity GLOG_0 = GLOG_ERROR;
-#else
-// Users may include windows.h after logging.h without
-// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
-// For this case, we cannot detect if ERROR is defined before users
-// actually use ERROR. Let's make an undefined symbol to warn users.
-# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
-# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
-# define SYSLOG_0 GLOG_ERROR_MSG
-# define LOG_TO_STRING_0 GLOG_ERROR_MSG
-# define GLOG_0 GLOG_ERROR_MSG
-#endif
-
-// Plus some debug-logging macros that get compiled to nothing for production
-
-#if DCHECK_IS_ON()
-
-#define DLOG(severity) LOG(severity)
-#define DVLOG(verboselevel) VLOG(verboselevel)
-#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
-#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
-#define DLOG_IF_EVERY_N(severity, condition, n) \
- LOG_IF_EVERY_N(severity, condition, n)
-#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
-
-// debug-only checking. executed if DCHECK_IS_ON().
-#define DCHECK(condition) CHECK(condition)
-#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
-#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
-#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
-#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
-#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
-#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
-#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
-#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
-#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
-#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
-#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
-
-#else // !DCHECK_IS_ON()
-
-#define DLOG(severity) \
- true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DVLOG(verboselevel) \
- (true || !VLOG_IS_ON(verboselevel)) ?\
- (void) 0 : google::LogMessageVoidify() & LOG(INFO)
-
-#define DLOG_IF(severity, condition) \
- (true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_EVERY_N(severity, n) \
- true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_IF_EVERY_N(severity, condition, n) \
- (true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_ASSERT(condition) \
- true ? (void) 0 : LOG_ASSERT(condition)
-
-// MSVC warning C4127: conditional expression is constant
-#define DCHECK(condition) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK(condition)
-
-#define DCHECK_EQ(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
-
-#define DCHECK_NE(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
-
-#define DCHECK_LE(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
-
-#define DCHECK_LT(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
-
-#define DCHECK_GE(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
-
-#define DCHECK_GT(val1, val2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
-
-// You may see warnings in release mode if you don't use the return
-// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
-#define DCHECK_NOTNULL(val) (val)
-
-#define DCHECK_STREQ(str1, str2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
-
-#define DCHECK_STRCASEEQ(str1, str2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
-
-#define DCHECK_STRNE(str1, str2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
-
-#define DCHECK_STRCASENE(str1, str2) \
- GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
- while (false) \
- GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
-
-#endif // DCHECK_IS_ON()
-
-// Log only in verbose mode.
-
-#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
-
-#define VLOG_IF(verboselevel, condition) \
- LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
-
-#define VLOG_EVERY_N(verboselevel, n) \
- LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n)
-
-#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
- LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
-
-namespace base_logging {
-
-// LogMessage::LogStream is a std::ostream backed by this streambuf.
-// This class ignores overflow and leaves two bytes at the end of the
-// buffer to allow for a '\n' and '\0'.
-class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
- public:
- // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\n'.
- LogStreamBuf(char *buf, int len) {
- setp(buf, buf + len - 2);
- }
-
- // Resets the buffer. Useful if we reuse it by means of TLS.
- void reset() {
- setp(pbase(), epptr());
- }
-
- // This effectively ignores overflow.
- virtual int_type overflow(int_type ch) {
- return ch;
- }
-
- // Legacy public ostrstream method.
- size_t pcount() const { return pptr() - pbase(); }
- char* pbase() const { return std::streambuf::pbase(); }
-};
-
-} // namespace base_logging
-
-//
-// This class more or less represents a particular log message. You
-// create an instance of LogMessage and then stream stuff to it.
-// When you finish streaming to it, ~LogMessage is called and the
-// full message gets streamed to the appropriate destination.
-//
-// You shouldn't actually use LogMessage's constructor to log things,
-// though. You should use the LOG() macro (and variants thereof)
-// above.
-class GOOGLE_GLOG_DLL_DECL LogMessage {
-public:
- enum {
- // Passing kNoLogPrefix for the line number disables the
- // log-message prefix. Useful for using the LogMessage
- // infrastructure as a printing utility. See also the --log_prefix
- // flag for controlling the log-message prefix on an
- // application-wide basis.
- kNoLogPrefix = -1
- };
-
- // LogStream inherit from non-DLL-exported class (std::ostrstream)
- // and VC++ produces a warning for this situation.
- // However, MSDN says "C4275 can be ignored in Microsoft Visual C++
- // 2005 if you are deriving from a type in the Standard C++ Library"
- // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
- // Let's just ignore the warning.
-GLOG_MSVC_PUSH_DISABLE_WARNING(4275)
- class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostream {
-GLOG_MSVC_POP_WARNING()
- public:
- LogStream(char *buf, int len, int ctr)
- : std::ostream(NULL),
- streambuf_(buf, len),
- ctr_(ctr),
- self_(this) {
- rdbuf(&streambuf_);
- }
-
- int ctr() const { return ctr_; }
- void set_ctr(int ctr) { ctr_ = ctr; }
- LogStream* self() const { return self_; }
-
- // Legacy std::streambuf methods.
- size_t pcount() const { return streambuf_.pcount(); }
- char* pbase() const { return streambuf_.pbase(); }
- char* str() const { return pbase(); }
- void reset() { streambuf_.reset(); }
-
- private:
- LogStream(const LogStream&);
- LogStream& operator=(const LogStream&);
- base_logging::LogStreamBuf streambuf_;
- int ctr_; // Counter hack (for the LOG_EVERY_X() macro)
- LogStream *self_; // Consistency check hack
- };
-
-public:
- // icc 8 requires this typedef to avoid an internal compiler error.
- typedef void (LogMessage::*SendMethod)();
-
- LogMessage(const char* file, int line, LogSeverity severity, int ctr,
- SendMethod send_method);
-
- // Two special constructors that generate reduced amounts of code at
- // LOG call sites for common cases.
-
- // Used for LOG(INFO): Implied are:
- // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog.
- //
- // Using this constructor instead of the more complex constructor above
- // saves 19 bytes per call site.
- LogMessage(const char* file, int line);
-
- // Used for LOG(severity) where severity != INFO. Implied
- // are: ctr = 0, send_method = &LogMessage::SendToLog
- //
- // Using this constructor instead of the more complex constructor above
- // saves 17 bytes per call site.
- LogMessage(const char* file, int line, LogSeverity severity);
-
- // Constructor to log this message to a specified sink (if not NULL).
- // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if
- // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise.
- LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink,
- bool also_send_to_log);
-
- // Constructor where we also give a vector<string> pointer
- // for storing the messages (if the pointer is not NULL).
- // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog.
- LogMessage(const char* file, int line, LogSeverity severity,
- std::vector<std::string>* outvec);
-
- // Constructor where we also give a string pointer for storing the
- // message (if the pointer is not NULL). Implied are: ctr = 0,
- // send_method = &LogMessage::WriteToStringAndLog.
- LogMessage(const char* file, int line, LogSeverity severity,
- std::string* message);
-
- // A special constructor used for check failures
- LogMessage(const char* file, int line, const CheckOpString& result);
-
- ~LogMessage();
-
- // Flush a buffered message to the sink set in the constructor. Always
- // called by the destructor, it may also be called from elsewhere if
- // needed. Only the first call is actioned; any later ones are ignored.
- void Flush();
-
- // An arbitrary limit on the length of a single log message. This
- // is so that streaming can be done more efficiently.
- static const size_t kMaxLogMessageLen;
-
- // Theses should not be called directly outside of logging.*,
- // only passed as SendMethod arguments to other LogMessage methods:
- void SendToLog(); // Actually dispatch to the logs
- void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs
-
- // Call abort() or similar to perform LOG(FATAL) crash.
- static void __declspec(noreturn) Fail();
-
- std::ostream& stream();
-
- int preserved_errno() const;
-
- // Must be called without the log_mutex held. (L < log_mutex)
- static int64 num_messages(int severity);
-
- struct LogMessageData;
-
-private:
- // Fully internal SendMethod cases:
- void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs
- void SendToSink(); // Send to sink if provided, do nothing otherwise.
-
- // Write to string if provided and dispatch to the logs.
- void WriteToStringAndLog();
-
- void SaveOrSendToLog(); // Save to stringvec if provided, else to logs
-
- void Init(const char* file, int line, LogSeverity severity,
- void (LogMessage::*send_method)());
-
- // Used to fill in crash information during LOG(FATAL) failures.
- void RecordCrashReason(glog_internal_namespace_::CrashReason* reason);
-
- // Counts of messages sent at each priority:
- static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex
-
- // We keep the data in a separate struct so that each instance of
- // LogMessage uses less stack space.
- LogMessageData* allocated_;
- LogMessageData* data_;
-
- friend class LogDestination;
-
- LogMessage(const LogMessage&);
- void operator=(const LogMessage&);
-};
-
-// This class happens to be thread-hostile because all instances share
-// a single data buffer, but since it can only be created just before
-// the process dies, we don't worry so much.
-class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage {
- public:
- LogMessageFatal(const char* file, int line);
- LogMessageFatal(const char* file, int line, const CheckOpString& result);
- __declspec(noreturn) ~LogMessageFatal();
-};
-
-// A non-macro interface to the log facility; (useful
-// when the logging level is not a compile-time constant).
-inline void LogAtLevel(int const severity, std::string const &msg) {
- LogMessage(__FILE__, __LINE__, severity).stream() << msg;
-}
-
-// A macro alternative of LogAtLevel. New code may want to use this
-// version since there are two advantages: 1. this version outputs the
-// file name and the line number where this macro is put like other
-// LOG macros, 2. this macro can be used as C++ stream.
-#define LOG_AT_LEVEL(severity) google::LogMessage(__FILE__, __LINE__, severity).stream()
-
-// Check if it's compiled in C++11 mode.
-//
-// GXX_EXPERIMENTAL_CXX0X is defined by gcc and clang up to at least
-// gcc-4.7 and clang-3.1 (2011-12-13). __cplusplus was defined to 1
-// in gcc before 4.7 (Crosstool 16) and clang before 3.1, but is
-// defined according to the language version in effect thereafter.
-// Microsoft Visual Studio 14 (2015) sets __cplusplus==199711 despite
-// reasonably good C++11 support, so we set LANG_CXX for it and
-// newer versions (_MSC_VER >= 1900).
-#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \
- (defined(_MSC_VER) && _MSC_VER >= 1900))
-// Helper for CHECK_NOTNULL().
-//
-// In C++11, all cases can be handled by a single function. Since the value
-// category of the argument is preserved (also for rvalue references),
-// member initializer lists like the one below will compile correctly:
-//
-// Foo()
-// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {}
-template <typename T>
-T CheckNotNull(const char* file, int line, const char* names, T&& t) {
- if (t == nullptr) {
- LogMessageFatal(file, line, new std::string(names));
- }
- return std::forward<T>(t);
-}
-
-#else
-
-// A small helper for CHECK_NOTNULL().
-template <typename T>
-T* CheckNotNull(const char *file, int line, const char *names, T* t) {
- if (t == NULL) {
- LogMessageFatal(file, line, new std::string(names));
- }
- return t;
-}
-#endif
-
-// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
-// only works if ostream is a LogStream. If the ostream is not a
-// LogStream you'll get an assert saying as much at runtime.
-GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os,
- const PRIVATE_Counter&);
-
-
-// Derived class for PLOG*() above.
-class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage {
- public:
-
- ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr,
- void (LogMessage::*send_method)());
-
- // Postpends ": strerror(errno) [errno]".
- ~ErrnoLogMessage();
-
- private:
- ErrnoLogMessage(const ErrnoLogMessage&);
- void operator=(const ErrnoLogMessage&);
-};
-
-
-// This class is used to explicitly ignore values in the conditional
-// logging macros. This avoids compiler warnings like "value computed
-// is not used" and "statement has no effect".
-
-class GOOGLE_GLOG_DLL_DECL LogMessageVoidify {
- public:
- LogMessageVoidify() { }
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(std::ostream&) { }
-};
-
-
-// Flushes all log files that contains messages that are at least of
-// the specified severity level. Thread-safe.
-GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity);
-
-// Flushes all log files that contains messages that are at least of
-// the specified severity level. Thread-hostile because it ignores
-// locking -- used for catastrophic failures.
-GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity);
-
-//
-// Set the destination to which a particular severity level of log
-// messages is sent. If base_filename is "", it means "don't log this
-// severity". Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity,
- const char* base_filename);
-
-//
-// Set the basename of the symlink to the latest log file at a given
-// severity. If symlink_basename is empty, do not make a symlink. If
-// you don't call this function, the symlink basename is the
-// invocation name of the program. Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity,
- const char* symlink_basename);
-
-//
-// Used to send logs to some other kind of destination
-// Users should subclass LogSink and override send to do whatever they want.
-// Implementations must be thread-safe because a shared instance will
-// be called from whichever thread ran the LOG(XXX) line.
-class GOOGLE_GLOG_DLL_DECL LogSink {
- public:
- virtual ~LogSink();
-
- // Sink's logging logic (message_len is such as to exclude '\n' at the end).
- // This method can't use LOG() or CHECK() as logging system mutex(s) are held
- // during this call.
- virtual void send(LogSeverity severity, const char* full_filename,
- const char* base_filename, int line,
- const struct ::tm* tm_time,
- const char* message, size_t message_len) = 0;
-
- // Redefine this to implement waiting for
- // the sink's logging logic to complete.
- // It will be called after each send() returns,
- // but before that LogMessage exits or crashes.
- // By default this function does nothing.
- // Using this function one can implement complex logic for send()
- // that itself involves logging; and do all this w/o causing deadlocks and
- // inconsistent rearrangement of log messages.
- // E.g. if a LogSink has thread-specific actions, the send() method
- // can simply add the message to a queue and wake up another thread that
- // handles real logging while itself making some LOG() calls;
- // WaitTillSent() can be implemented to wait for that logic to complete.
- // See our unittest for an example.
- virtual void WaitTillSent();
-
- // Returns the normal text output of the log message.
- // Can be useful to implement send().
- static std::string ToString(LogSeverity severity, const char* file, int line,
- const struct ::tm* tm_time,
- const char* message, size_t message_len);
-};
-
-// Add or remove a LogSink as a consumer of logging data. Thread-safe.
-GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination);
-GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination);
-
-//
-// Specify an "extension" added to the filename specified via
-// SetLogDestination. This applies to all severity levels. It's
-// often used to append the port we're listening on to the logfile
-// name. Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension(
- const char* filename_extension);
-
-//
-// Make it so that all log messages of at least a particular severity
-// are logged to stderr (in addition to logging to the usual log
-// file(s)). Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity);
-
-//
-// Make it so that all log messages go only to stderr. Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void LogToStderr();
-
-//
-// Make it so that all log messages of at least a particular severity are
-// logged via email to a list of addresses (in addition to logging to the
-// usual log file(s)). The list of addresses is just a string containing
-// the email addresses to send to (separated by spaces, say). Thread-safe.
-//
-GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity,
- const char* addresses);
-
-// A simple function that sends email. dest is a commma-separated
-// list of addressess. Thread-safe.
-GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest,
- const char *subject, const char *body);
-
-GOOGLE_GLOG_DLL_DECL const std::vector<std::string>& GetLoggingDirectories();
-
-// For tests only: Clear the internal [cached] list of logging directories to
-// force a refresh the next time GetLoggingDirectories is called.
-// Thread-hostile.
-void TestOnly_ClearLoggingDirectoriesList();
-
-// Returns a set of existing temporary directories, which will be a
-// subset of the directories returned by GetLogginDirectories().
-// Thread-safe.
-GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories(
- std::vector<std::string>* list);
-
-// Print any fatal message again -- useful to call from signal handler
-// so that the last thing in the output is the fatal message.
-// Thread-hostile, but a race is unlikely.
-GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage();
-
-// Truncate a log file that may be the append-only output of multiple
-// processes and hence can't simply be renamed/reopened (typically a
-// stdout/stderr). If the file "path" is > "limit" bytes, copy the
-// last "keep" bytes to offset 0 and truncate the rest. Since we could
-// be racing with other writers, this approach has the potential to
-// lose very small amounts of data. For security, only follow symlinks
-// if the path is /proc/self/fd/*
-GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path,
- int64 limit, int64 keep);
-
-// Truncate stdout and stderr if they are over the value specified by
-// --max_log_size; keep the final 1MB. This function has the same
-// race condition as TruncateLogFile.
-GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr();
-
-// Return the string representation of the provided LogSeverity level.
-// Thread-safe.
-GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity);
-
-// ---------------------------------------------------------------------
-// Implementation details that are not useful to most clients
-// ---------------------------------------------------------------------
-
-// A Logger is the interface used by logging modules to emit entries
-// to a log. A typical implementation will dump formatted data to a
-// sequence of files. We also provide interfaces that will forward
-// the data to another thread so that the invoker never blocks.
-// Implementations should be thread-safe since the logging system
-// will write to them from multiple threads.
-
-namespace base {
-
-class GOOGLE_GLOG_DLL_DECL Logger {
- public:
- virtual ~Logger();
-
- // Writes "message[0,message_len-1]" corresponding to an event that
- // occurred at "timestamp". If "force_flush" is true, the log file
- // is flushed immediately.
- //
- // The input message has already been formatted as deemed
- // appropriate by the higher level logging facility. For example,
- // textual log messages already contain timestamps, and the
- // file:linenumber header.
- virtual void Write(bool force_flush,
- time_t timestamp,
- const char* message,
- int message_len) = 0;
-
- // Flush any buffered messages
- virtual void Flush() = 0;
-
- // Get the current LOG file size.
- // The returned value is approximate since some
- // logged data may not have been flushed to disk yet.
- virtual uint32 LogSize() = 0;
-};
-
-// Get the logger for the specified severity level. The logger
-// remains the property of the logging module and should not be
-// deleted by the caller. Thread-safe.
-extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level);
-
-// Set the logger for the specified severity level. The logger
-// becomes the property of the logging module and should not
-// be deleted by the caller. Thread-safe.
-extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger);
-
-}
-
-// glibc has traditionally implemented two incompatible versions of
-// strerror_r(). There is a poorly defined convention for picking the
-// version that we want, but it is not clear whether it even works with
-// all versions of glibc.
-// So, instead, we provide this wrapper that automatically detects the
-// version that is in use, and then implements POSIX semantics.
-// N.B. In addition to what POSIX says, we also guarantee that "buf" will
-// be set to an empty string, if this function failed. This means, in most
-// cases, you do not need to check the error code and you can directly
-// use the value of "buf". It will never have an undefined value.
-// DEPRECATED: Use StrError(int) instead.
-GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len);
-
-// A thread-safe replacement for strerror(). Returns a string describing the
-// given POSIX error code.
-GOOGLE_GLOG_DLL_DECL std::string StrError(int err);
-
-// A class for which we define operator<<, which does nothing.
-class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
- public:
- // Initialize the LogStream so the messages can be written somewhere
- // (they'll never be actually displayed). This will be needed if a
- // NullStream& is implicitly converted to LogStream&, in which case
- // the overloaded NullStream::operator<< will not be invoked.
- NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
- NullStream(const char* /*file*/, int /*line*/,
- const CheckOpString& /*result*/) :
- LogMessage::LogStream(message_buffer_, 1, 0) { }
- NullStream &stream() { return *this; }
- private:
- // A very short buffer for messages (which we discard anyway). This
- // will be needed if NullStream& converted to LogStream& (e.g. as a
- // result of a conditional expression).
- char message_buffer_[2];
-};
-
-// Do nothing. This operator is inline, allowing the message to be
-// compiled away. The message will not be compiled away if we do
-// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when
-// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly
-// converted to LogStream and the message will be computed and then
-// quietly discarded.
-template<class T>
-inline NullStream& operator<<(NullStream &str, const T &) { return str; }
-
-// Similar to NullStream, but aborts the program (without stack
-// trace), like LogMessageFatal.
-class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream {
- public:
- NullStreamFatal() { }
- NullStreamFatal(const char* file, int line, const CheckOpString& result) :
- NullStream(file, line, result) { }
- __declspec(noreturn) ~NullStreamFatal() throw () { _exit(1); }
-};
-
-// Install a signal handler that will dump signal information and a stack
-// trace when the program crashes on certain signals. We'll install the
-// signal handler for the following signals.
-//
-// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
-//
-// By default, the signal handler will write the failure dump to the
-// standard error. You can customize the destination by installing your
-// own writer function by InstallFailureWriter() below.
-//
-// Note on threading:
-//
-// The function should be called before threads are created, if you want
-// to use the failure signal handler for all threads. The stack trace
-// will be shown only for the thread that receives the signal. In other
-// words, stack traces of other threads won't be shown.
-GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler();
-
-// Installs a function that is used for writing the failure dump. "data"
-// is the pointer to the beginning of a message to be written, and "size"
-// is the size of the message. You should not expect the data is
-// terminated with '\0'.
-GOOGLE_GLOG_DLL_DECL void InstallFailureWriter(
- void (*writer)(const char* data, int size));
-
-}
-
-#endif // _LOGGING_H_
diff --git a/src/windows/glog/raw_logging.h b/src/windows/glog/raw_logging.h
deleted file mode 100755
index 4757a71..0000000
--- a/src/windows/glog/raw_logging.h
+++ /dev/null
@@ -1,189 +0,0 @@
-// This file is automatically generated from src/glog/raw_logging.h.in
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Maxim Lifantsev
-//
-// Thread-safe logging routines that do not allocate any memory or
-// acquire any locks, and can therefore be used by low-level memory
-// allocation and synchronization code.
-
-#ifndef BASE_RAW_LOGGING_H_
-#define BASE_RAW_LOGGING_H_
-
-#include <time.h>
-
-namespace google {
-
-#include "glog/log_severity.h"
-#include "glog/vlog_is_on.h"
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
-
-// This is similar to LOG(severity) << format... and VLOG(level) << format..,
-// but
-// * it is to be used ONLY by low-level modules that can't use normal LOG()
-// * it is desiged to be a low-level logger that does not allocate any
-// memory and does not need any locks, hence:
-// * it logs straight and ONLY to STDERR w/o buffering
-// * it uses an explicit format and arguments list
-// * it will silently chop off really long message strings
-// Usage example:
-// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
-// RAW_VLOG(3, "status is %i", status);
-// These will print an almost standard log lines like this to stderr only:
-// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
-// I0821 211317 file.cc:142] RAW: status is 20
-#define RAW_LOG(severity, ...) \
- do { \
- switch (google::GLOG_ ## severity) { \
- case 0: \
- RAW_LOG_INFO(__VA_ARGS__); \
- break; \
- case 1: \
- RAW_LOG_WARNING(__VA_ARGS__); \
- break; \
- case 2: \
- RAW_LOG_ERROR(__VA_ARGS__); \
- break; \
- case 3: \
- RAW_LOG_FATAL(__VA_ARGS__); \
- break; \
- default: \
- break; \
- } \
- } while (0)
-
-// The following STRIP_LOG testing is performed in the header file so that it's
-// possible to completely compile out the logging code and the log messages.
-#if STRIP_LOG == 0
-#define RAW_VLOG(verboselevel, ...) \
- do { \
- if (VLOG_IS_ON(verboselevel)) { \
- RAW_LOG_INFO(__VA_ARGS__); \
- } \
- } while (0)
-#else
-#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG == 0
-
-#if STRIP_LOG == 0
-#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
- __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG == 0
-
-#if STRIP_LOG <= 1
-#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING, \
- __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG <= 1
-
-#if STRIP_LOG <= 2
-#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR, \
- __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG <= 2
-
-#if STRIP_LOG <= 3
-#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL, \
- __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_FATAL(...) \
- do { \
- google::RawLogStub__(0, __VA_ARGS__); \
- exit(1); \
- } while (0)
-#endif // STRIP_LOG <= 3
-
-// Similar to CHECK(condition) << message,
-// but for low-level modules: we use only RAW_LOG that does not allocate memory.
-// We do not want to provide args list here to encourage this usage:
-// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
-// so that the args are not computed when not needed.
-#define RAW_CHECK(condition, message) \
- do { \
- if (!(condition)) { \
- RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
- } \
- } while (0)
-
-// Debug versions of RAW_LOG and RAW_CHECK
-#ifndef NDEBUG
-
-#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
-#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
-
-#else // NDEBUG
-
-#define RAW_DLOG(severity, ...) \
- while (false) \
- RAW_LOG(severity, __VA_ARGS__)
-#define RAW_DCHECK(condition, message) \
- while (false) \
- RAW_CHECK(condition, message)
-
-#endif // NDEBUG
-
-// Stub log function used to work around for unused variable warnings when
-// building with STRIP_LOG > 0.
-static inline void RawLogStub__(int /* ignored */, ...) {
-}
-
-// Helper function to implement RAW_LOG and RAW_VLOG
-// Logs format... at "severity" level, reporting it
-// as called from file:line.
-// This does not allocate memory or acquire locks.
-GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
- const char* file,
- int line,
- const char* format, ...)
- ;
-
-// Hack to propagate time information into this module so that
-// this module does not have to directly call localtime_r(),
-// which could allocate memory.
-GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs);
-
-}
-
-#endif // BASE_RAW_LOGGING_H_
diff --git a/src/windows/glog/stl_logging.h b/src/windows/glog/stl_logging.h
deleted file mode 100755
index a97a908..0000000
--- a/src/windows/glog/stl_logging.h
+++ /dev/null
@@ -1,224 +0,0 @@
-// This file is automatically generated from src/glog/stl_logging.h.in
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-
-// Copyright (c) 2003, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Stream output operators for STL containers; to be used for logging *only*.
-// Inclusion of this file lets you do:
-//
-// list<string> x;
-// LOG(INFO) << "data: " << x;
-// vector<int> v1, v2;
-// CHECK_EQ(v1, v2);
-//
-// If you want to use this header file with hash_compare maps or slist, you
-// need to define macros before including this file:
-//
-// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
-// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
-// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
-// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
-//
-
-#ifndef UTIL_GTL_STL_LOGGING_INL_H_
-#define UTIL_GTL_STL_LOGGING_INL_H_
-
-#if !1
-# error We do not support stl_logging for this compiler
-#endif
-
-#include <deque>
-#include <list>
-#include <map>
-#include <ostream>
-#include <set>
-#include <utility>
-#include <vector>
-
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
-# include <unordered_map>
-# include <unordered_set>
-#endif
-
-#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
-# include <tr1/unordered_map>
-# include <tr1/unordered_set>
-#endif
-
-#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
-# include <ext/hash_set>
-# include <ext/hash_map>
-#endif
-#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
-# include <ext/slist>
-#endif
-
-// Forward declare these two, and define them after all the container streams
-// operators so that we can recurse from pair -> container -> container -> pair
-// properly.
-template<class First, class Second>
-std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
-
-namespace google {
-
-template<class Iter>
-void PrintSequence(std::ostream& out, Iter begin, Iter end);
-
-}
-
-#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
-template<class T1, class T2> \
-inline std::ostream& operator<<(std::ostream& out, \
- const Sequence<T1, T2>& seq) { \
- google::PrintSequence(out, seq.begin(), seq.end()); \
- return out; \
-}
-
-OUTPUT_TWO_ARG_CONTAINER(std::vector)
-OUTPUT_TWO_ARG_CONTAINER(std::deque)
-OUTPUT_TWO_ARG_CONTAINER(std::list)
-#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
-OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
-#endif
-
-#undef OUTPUT_TWO_ARG_CONTAINER
-
-#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3> \
-inline std::ostream& operator<<(std::ostream& out, \
- const Sequence<T1, T2, T3>& seq) { \
- google::PrintSequence(out, seq.begin(), seq.end()); \
- return out; \
-}
-
-OUTPUT_THREE_ARG_CONTAINER(std::set)
-OUTPUT_THREE_ARG_CONTAINER(std::multiset)
-
-#undef OUTPUT_THREE_ARG_CONTAINER
-
-#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3, class T4> \
-inline std::ostream& operator<<(std::ostream& out, \
- const Sequence<T1, T2, T3, T4>& seq) { \
- google::PrintSequence(out, seq.begin(), seq.end()); \
- return out; \
-}
-
-OUTPUT_FOUR_ARG_CONTAINER(std::map)
-OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
-OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
-OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
-#endif
-#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
-OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
-OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
-#endif
-#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
-OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
-OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
-#endif
-
-#undef OUTPUT_FOUR_ARG_CONTAINER
-
-#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3, class T4, class T5> \
-inline std::ostream& operator<<(std::ostream& out, \
- const Sequence<T1, T2, T3, T4, T5>& seq) { \
- google::PrintSequence(out, seq.begin(), seq.end()); \
- return out; \
-}
-
-#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
-OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
-OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
-#endif
-#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
-OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
-OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
-#endif
-#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
-OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
-OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
-#endif
-
-#undef OUTPUT_FIVE_ARG_CONTAINER
-
-template<class First, class Second>
-inline std::ostream& operator<<(std::ostream& out,
- const std::pair<First, Second>& p) {
- out << '(' << p.first << ", " << p.second << ')';
- return out;
-}
-
-namespace google {
-
-template<class Iter>
-inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
- // Output at most 100 elements -- appropriate if used for logging.
- for (int i = 0; begin != end && i < 100; ++i, ++begin) {
- if (i > 0) out << ' ';
- out << *begin;
- }
- if (begin != end) {
- out << " ...";
- }
-}
-
-}
-
-// Note that this is technically undefined behavior! We are adding things into
-// the std namespace for a reason though -- we are providing new operations on
-// types which are themselves defined with this namespace. Without this, these
-// operator overloads cannot be found via ADL. If these definitions are not
-// found via ADL, they must be #included before they're used, which requires
-// this header to be included before apparently independent other headers.
-//
-// For example, base/logging.h defines various template functions to implement
-// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
-// It does so via the function template MakeCheckOpValueString:
-// template<class T>
-// void MakeCheckOpValueString(strstream* ss, const T& v) {
-// (*ss) << v;
-// }
-// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
-// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
-// find these operator definitions via ADL.
-//
-// Even this solution has problems -- it may pull unintended operators into the
-// namespace as well, allowing them to also be found via ADL, and creating code
-// that only works with a particular order of includes. Long term, we need to
-// move all of the *definitions* into namespace std, bet we need to ensure no
-// one references them first. This lets us take that step. We cannot define them
-// in both because that would create ambiguous overloads when both are found.
-namespace std { using ::operator<<; }
-
-#endif // UTIL_GTL_STL_LOGGING_INL_H_
diff --git a/src/windows/glog/vlog_is_on.h b/src/windows/glog/vlog_is_on.h
deleted file mode 100755
index 409a401..0000000
--- a/src/windows/glog/vlog_is_on.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// This file is automatically generated from src/glog/vlog_is_on.h.in
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-
-// Copyright (c) 1999, 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Ray Sidney and many others
-//
-// Defines the VLOG_IS_ON macro that controls the variable-verbosity
-// conditional logging.
-//
-// It's used by VLOG and VLOG_IF in logging.h
-// and by RAW_VLOG in raw_logging.h to trigger the logging.
-//
-// It can also be used directly e.g. like this:
-// if (VLOG_IS_ON(2)) {
-// // do some logging preparation and logging
-// // that can't be accomplished e.g. via just VLOG(2) << ...;
-// }
-//
-// The truth value that VLOG_IS_ON(level) returns is determined by
-// the three verbosity level flags:
-// --v=<n> Gives the default maximal active V-logging level;
-// 0 is the default.
-// Normally positive values are used for V-logging levels.
-// --vmodule=<str> Gives the per-module maximal V-logging levels to override
-// the value given by --v.
-// E.g. "my_module=2,foo*=3" would change the logging level
-// for all code in source files "my_module.*" and "foo*.*"
-// ("-inl" suffixes are also disregarded for this matching).
-//
-// SetVLOGLevel helper function is provided to do limited dynamic control over
-// V-logging by overriding the per-module settings given via --vmodule flag.
-//
-// CAVEAT: --vmodule functionality is not available in non gcc compilers.
-//
-
-#ifndef BASE_VLOG_IS_ON_H_
-#define BASE_VLOG_IS_ON_H_
-
-#include "glog/log_severity.h"
-
-// Annoying stuff for windows -- makes sure clients can import these functions
-#ifndef GOOGLE_GLOG_DLL_DECL
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
-# else
-# define GOOGLE_GLOG_DLL_DECL
-# endif
-#endif
-
-#if defined(__GNUC__)
-// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
-// (Normally) the first time every VLOG_IS_ON(n) site is hit,
-// we determine what variable will dynamically control logging at this site:
-// it's either FLAGS_v or an appropriate internal variable
-// matching the current source file that represents results of
-// parsing of --vmodule flag and/or SetVLOGLevel calls.
-#define VLOG_IS_ON(verboselevel) \
- __extension__ \
- ({ static google::int32* vlocal__ = &google::kLogSiteUninitialized; \
- google::int32 verbose_level__ = (verboselevel); \
- (*vlocal__ >= verbose_level__) && \
- ((vlocal__ != &google::kLogSiteUninitialized) || \
- (google::InitVLOG3__(&vlocal__, &FLAGS_v, \
- __FILE__, verbose_level__))); })
-#else
-// GNU extensions not available, so we do not support --vmodule.
-// Dynamic value of FLAGS_v always controls the logging level.
-#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
-#endif
-
-// Set VLOG(_IS_ON) level for module_pattern to log_level.
-// This lets us dynamically control what is normally set by the --vmodule flag.
-// Returns the level that previously applied to module_pattern.
-// NOTE: To change the log level for VLOG(_IS_ON) sites
-// that have already executed after/during InitGoogleLogging,
-// one needs to supply the exact --vmodule pattern that applied to them.
-// (If no --vmodule pattern applied to them
-// the value of FLAGS_v will continue to control them.)
-extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
- int log_level);
-
-// Various declarations needed for VLOG_IS_ON above: =========================
-
-// Special value used to indicate that a VLOG_IS_ON site has not been
-// initialized. We make this a large value, so the common-case check
-// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
-// passes in such cases and InitVLOG3__ is then triggered.
-extern google::int32 kLogSiteUninitialized;
-
-// Helper routine which determines the logging info for a particalur VLOG site.
-// site_flag is the address of the site-local pointer to the controlling
-// verbosity level
-// site_default is the default to use for *site_flag
-// fname is the current source file name
-// verbose_level is the argument to VLOG_IS_ON
-// We will return the return value for VLOG_IS_ON
-// and if possible set *site_flag appropriately.
-extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
- google::int32** site_flag,
- google::int32* site_default,
- const char* fname,
- google::int32 verbose_level);
-
-#endif // BASE_VLOG_IS_ON_H_
diff --git a/src/windows/port.cc b/src/windows/port.cc
index 19bda36..f0022e7 100755
--- a/src/windows/port.cc
+++ b/src/windows/port.cc
@@ -1,10 +1,10 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -37,7 +37,7 @@
#endif
#include "config.h"
-#include <stdarg.h> // for va_list, va_start, va_end
+#include <cstdarg> // for va_list, va_start, va_end
#include "port.h"
// These call the windows _vsnprintf, but always NUL-terminate.
@@ -54,6 +54,12 @@
return result;
}
#endif // not HAVE_LOCALTIME_R
+#ifndef HAVE_GMTIME_R
+struct tm* gmtime_r(const time_t* timep, struct tm* result) {
+ gmtime_s(result, timep);
+ return result;
+}
+#endif // not HAVE_GMTIME_R
#ifndef HAVE_SNPRINTF
int snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
diff --git a/src/windows/port.h b/src/windows/port.h
index 7b4b9c8..a71979f 100755
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -1,10 +1,10 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -54,14 +54,16 @@
#include <io.h> /* because we so often use open/close/etc */
#include <direct.h> /* for _getcwd() */
#include <process.h> /* for _getpid() */
-#include <stdio.h> /* read in vsnprintf decl. before redifining it */
-#include <stdarg.h> /* template_dictionary.cc uses va_copy */
-#include <string.h> /* for _strnicmp(), strerror_s() */
-#include <time.h> /* for localtime_s() */
+#include <cstdarg> /* template_dictionary.cc uses va_copy */
+#include <cstdio> /* read in vsnprintf decl. before redifining it */
+#include <cstring> /* for _strnicmp(), strerror_s() */
+#include <ctime> /* for localtime_s() */
/* Note: the C++ #includes are all together at the bottom. This file is
* used by both C and C++ code, so we put all the C++ together.
*/
+#include <glog/logging.h>
+
#ifdef _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int
@@ -120,11 +122,11 @@
* name vsnprintf, since windows defines that (but not snprintf (!)).
*/
#ifndef HAVE_SNPRINTF
-extern int GOOGLE_GLOG_DLL_DECL snprintf(char *str, size_t size,
- const char *format, ...);
+extern int GLOG_EXPORT snprintf(char* str, size_t size, const char* format,
+ ...);
#endif
-extern int GOOGLE_GLOG_DLL_DECL safe_vsnprintf(char *str, size_t size,
- const char *format, va_list ap);
+extern int GLOG_EXPORT 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)
#ifndef va_copy
#define va_copy(dst, src) (dst) = (src)
@@ -156,9 +158,14 @@
#endif // HAVE_PTHREAD
#ifndef HAVE_LOCALTIME_R
-extern GOOGLE_GLOG_DLL_DECL struct tm* localtime_r(const time_t* timep, struct tm* result);
+extern GLOG_EXPORT struct tm* localtime_r(const time_t* timep,
+ struct tm* result);
#endif // not HAVE_LOCALTIME_R
+#ifndef HAVE_GMTIME_R
+extern GLOG_EXPORT struct tm* gmtime_r(const time_t* timep, struct tm* result);
+#endif // not HAVE_GMTIME_R
+
inline char* strerror_r(int errnum, char* buf, size_t buflen) {
strerror_s(buf, buflen, errnum);
return buf;
diff --git a/src/windows/preprocess.sh b/src/windows/preprocess.sh
deleted file mode 100755
index c35e929..0000000
--- a/src/windows/preprocess.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ---
-# Author: Craig Silverstein
-# Copied from google-perftools and modified by Shinichiro Hamaji
-#
-# This script is meant to be run at distribution-generation time, for
-# instance by autogen.sh. It does some of the work configure would
-# normally do, for windows systems. In particular, it expands all the
-# @...@ variables found in .in files, and puts them here, in the windows
-# directory.
-#
-# This script should be run before any new release.
-
-if [ -z "$1" ]; then
- echo "USAGE: $0 <src/ directory>"
- exit 1
-fi
-
-DLLDEF_MACRO_NAME="GLOG_DLL_DECL"
-
-# The text we put in every .h files we create. As a courtesy, we'll
-# include a helpful comment for windows users as to how to use
-# GLOG_DLL_DECL. Apparently sed expands \n into a newline. Good!
-DLLDEF_DEFINES="\
-// NOTE: if you are statically linking the template library into your binary\n\
-// (rather than using the template .dll), set '/D $DLLDEF_MACRO_NAME='\n\
-// as a compiler flag in your project file to turn off the dllimports.\n\
-#ifndef $DLLDEF_MACRO_NAME\n\
-# define $DLLDEF_MACRO_NAME __declspec(dllimport)\n\
-#endif"
-
-# Read all the windows config info into variables
-# In order for the 'set' to take, this requires putting all in a subshell.
-(
- while read define varname value; do
- [ "$define" != "#define" ] && continue
- eval "$varname='$value'"
- done
-
- # Process all the .in files in the "glog" subdirectory
- mkdir -p "$1/windows/glog"
- for file in `echo "$1"/glog/*.in`; do
- echo "Processing $file"
- outfile="$1/windows/glog/`basename $file .in`"
-
- echo "\
-// This file is automatically generated from $file
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-" > "$outfile"
- # Besides replacing @...@, we also need to turn on dllimport
- # We also need to replace hash by hash_compare (annoying we hard-code :-( )
- sed -e "s!@ac_windows_dllexport@!$DLLDEF_MACRO_NAME!g" \
- -e "s!@ac_windows_dllexport_defines@!$DLLDEF_DEFINES!g" \
- -e "s!@ac_cv_cxx_hash_map@!$HASH_MAP_H!g" \
- -e "s!@ac_cv_cxx_hash_namespace@!$HASH_NAMESPACE!g" \
- -e "s!@ac_cv_cxx_hash_set@!$HASH_SET_H!g" \
- -e "s!@ac_cv_have_stdint_h@!0!g" \
- -e "s!@ac_cv_have_systypes_h@!0!g" \
- -e "s!@ac_cv_have_inttypes_h@!0!g" \
- -e "s!@ac_cv_have_unistd_h@!0!g" \
- -e "s!@ac_cv_have_uint16_t@!0!g" \
- -e "s!@ac_cv_have_u_int16_t@!0!g" \
- -e "s!@ac_cv_have___uint16@!1!g" \
- -e "s!@ac_cv_have_libgflags@!0!g" \
- -e "s!@ac_cv_have___builtin_expect@!0!g" \
- -e "s!@ac_cv_cxx_using_operator@!1!g" \
- -e "s!@ac_cv___attribute___noreturn@!__declspec(noreturn)!g" \
- -e "s!@ac_cv___attribute___noinline@!!g" \
- -e "s!@ac_cv___attribute___printf_4_5@!!g" \
- -e "s!@ac_google_attribute@!${HAVE___ATTRIBUTE__:-0}!g" \
- -e "s!@ac_google_end_namespace@!$_END_GOOGLE_NAMESPACE_!g" \
- -e "s!@ac_google_namespace@!$GOOGLE_NAMESPACE!g" \
- -e "s!@ac_google_start_namespace@!$_START_GOOGLE_NAMESPACE_!g" \
- -e "s!@ac_htmlparser_namespace@!$HTMLPARSER_NAMESPACE!g" \
- -e "s!\\bhash\\b!hash_compare!g" \
- "$file" >> "$outfile"
- done
-) < "$1/windows/config.h"
-
-# log_severity.h isn't a .in file.
-echo "\
-// This file is automatically generated from $1/glog/log_severity.h
-// using src/windows/preprocess.sh.
-// DO NOT EDIT!
-" > "$1/windows/glog/log_severity.h"
-cat "$1/glog/log_severity.h" >> "$1/windows/glog/log_severity.h"
-
-echo "DONE"