chore: apply clang-format

This commit is contained in:
Sergiu Deitsch 2023-12-30 20:01:33 +01:00
parent e3f5398aa1
commit 93549f3600
43 changed files with 2661 additions and 2791 deletions

View File

@ -58,7 +58,7 @@ ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: true DeriveLineEnding: true
DerivePointerAlignment: true DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true FixNamespaceComments: true
@ -84,7 +84,7 @@ IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: '' IncludeIsMainSourceRegex: ''
IndentCaseLabels: true IndentCaseLabels: true
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: AfterHash
IndentWidth: 2 IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave JavaScriptQuotes: Leave

View File

@ -48,11 +48,12 @@
#ifndef BASE_COMMANDLINEFLAGS_H__ #ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__ #define BASE_COMMANDLINEFLAGS_H__
#include "config.h"
#include <cstdlib> // for getenv #include <cstdlib> // for getenv
#include <cstring> // for memchr #include <cstring> // for memchr
#include <string> #include <string>
#include "config.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
# include <gflags/gflags.h> # include <gflags/gflags.h>
@ -74,8 +75,7 @@
using fL##shorttype::FLAGS_##name using fL##shorttype::FLAGS_##name
// bool specialization // bool specialization
#define DECLARE_bool(name) \ # define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name, bool)
DECLARE_VARIABLE(bool, B, name, bool)
# define DEFINE_bool(name, value, meaning) \ # define DEFINE_bool(name, value, meaning) \
DEFINE_VARIABLE(bool, B, name, value, meaning, bool) DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
@ -86,7 +86,8 @@
// uint32 specialization // uint32 specialization
# ifndef DECLARE_uint32 # ifndef DECLARE_uint32
#define DECLARE_uint32(name) DECLARE_VARIABLE(google::uint32, U, name, uint32) # define DECLARE_uint32(name) \
DECLARE_VARIABLE(google::uint32, U, name, uint32)
# endif // DECLARE_uint64 # endif // DECLARE_uint64
# define DEFINE_uint32(name, value, meaning) \ # define DEFINE_uint32(name, value, meaning) \
DEFINE_VARIABLE(google::uint32, U, name, value, meaning, uint32) DEFINE_VARIABLE(google::uint32, U, name, value, meaning, uint32)
@ -130,8 +131,7 @@
// These macros (could be functions, but I don't want to bother with a .cc // These macros (could be functions, but I don't want to bother with a .cc
// file), make it easier to initialize flags from the environment. // file), make it easier to initialize flags from the environment.
#define EnvToString(envname, dflt) \ #define EnvToString(envname, dflt) (!getenv(envname) ? (dflt) : getenv(envname))
(!getenv(envname) ? (dflt) : getenv(envname))
#define EnvToBool(envname, dflt) \ #define EnvToBool(envname, dflt) \
(!getenv(envname) ? (dflt) \ (!getenv(envname) ? (dflt) \

View File

@ -36,16 +36,14 @@
class GoogleInitializer { class GoogleInitializer {
public: public:
using void_function = void (*)(); using void_function = void (*)();
GoogleInitializer(const char*, void_function f) { GoogleInitializer(const char*, void_function f) { f(); }
f();
}
}; };
#define REGISTER_MODULE_INITIALIZER(name, body) \ #define REGISTER_MODULE_INITIALIZER(name, body) \
namespace { \ namespace { \
static void google_init_module_##name() { body; } \ static void google_init_module_##name() { body; } \
GoogleInitializer google_initializer_module_##name(#name, \ GoogleInitializer google_initializer_module_##name( \
google_init_module_##name); \ #name, google_init_module_##name); \
} }
#endif /* _GOOGLEINIT_H */ #endif /* _GOOGLEINIT_H */

View File

@ -134,7 +134,8 @@
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.) // for locking there.)
# ifdef __linux__ # ifdef __linux__
# ifndef _XOPEN_SOURCE // Some other header might have already set it for us. # ifndef _XOPEN_SOURCE // Some other header might have already set it for
// us.
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif # endif
# endif # endif
@ -218,27 +219,40 @@ Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); } void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); } void Mutex::Unlock() { assert(mutex_++ == -1); }
# ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } bool Mutex::TryLock() {
if (mutex_) return false;
Lock();
return true;
}
# endif # endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); } void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN__) #elif defined(_WIN32) || defined(__CYGWIN__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); } Mutex::Mutex() {
InitializeCriticalSection(&mutex_);
SetIsSafe();
}
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } void Mutex::Lock() {
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } if (is_safe_) EnterCriticalSection(&mutex_);
}
void Mutex::Unlock() {
if (is_safe_) LeaveCriticalSection(&mutex_);
}
# ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() {
TryEnterCriticalSection(&mutex_) != 0 : true; } return is_safe_ ? TryEnterCriticalSection(&mutex_) != 0 : true;
}
# endif # endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); } void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ # define SAFE_PTHREAD(fncall) \
do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0) } while (0)
@ -250,9 +264,9 @@ Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
# ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() {
pthread_rwlock_trywrlock(&mutex_) == 0 : return is_safe_ ? pthread_rwlock_trywrlock(&mutex_) == 0 : true;
true; } }
# endif # endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
@ -260,7 +274,8 @@ void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ # define SAFE_PTHREAD(fncall) \
do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0) } while (0)
@ -272,8 +287,9 @@ Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
# ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() {
pthread_mutex_trylock(&mutex_) == 0 : true; } return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true;
}
# endif # endif
void Mutex::ReaderLock() { Lock(); } void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); } void Mutex::ReaderUnlock() { Unlock(); }
@ -289,6 +305,7 @@ class MutexLock {
public: public:
explicit MutexLock(Mutex* mu) : mu_(mu) { mu_->Lock(); } explicit MutexLock(Mutex* mu) : mu_(mu) { mu_->Lock(); }
~MutexLock() { mu_->Unlock(); } ~MutexLock() { mu_->Unlock(); }
private: private:
Mutex* const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors
@ -301,6 +318,7 @@ class ReaderMutexLock {
public: public:
explicit ReaderMutexLock(Mutex* mu) : mu_(mu) { mu_->ReaderLock(); } explicit ReaderMutexLock(Mutex* mu) : mu_(mu) { mu_->ReaderLock(); }
~ReaderMutexLock() { mu_->ReaderUnlock(); } ~ReaderMutexLock() { mu_->ReaderUnlock(); }
private: private:
Mutex* const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors
@ -312,6 +330,7 @@ class WriterMutexLock {
public: public:
explicit WriterMutexLock(Mutex* mu) : mu_(mu) { mu_->WriterLock(); } explicit WriterMutexLock(Mutex* mu) : mu_(mu) { mu_->WriterLock(); }
~WriterMutexLock() { mu_->WriterUnlock(); } ~WriterMutexLock() { mu_->WriterUnlock(); }
private: private:
Mutex* const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors

View File

@ -140,15 +140,14 @@ static bool AtLeastNumCharsRemaining(const char *str, ssize_t n) {
// Returns true if "str" has "prefix" as a prefix. // Returns true if "str" has "prefix" as a prefix.
static bool StrPrefix(const char* str, const char* prefix) { static bool StrPrefix(const char* str, const char* prefix) {
size_t i = 0; size_t i = 0;
while (str[i] != '\0' && prefix[i] != '\0' && while (str[i] != '\0' && prefix[i] != '\0' && str[i] == prefix[i]) {
str[i] == prefix[i]) {
++i; ++i;
} }
return prefix[i] == '\0'; // Consumed everything in "prefix". return prefix[i] == '\0'; // Consumed everything in "prefix".
} }
static void InitState(State *state, const char *mangled, static void InitState(State* state, const char* mangled, char* out,
char *out, size_t out_size) { size_t out_size) {
state->mangled_cur = mangled; state->mangled_cur = mangled;
state->out_cur = out; state->out_cur = out;
state->out_begin = out; state->out_begin = out;
@ -200,9 +199,7 @@ static bool ParseCharClass(State *state, const char *char_class) {
} }
// This function is used for handling an optional non-terminal. // This function is used for handling an optional non-terminal.
static bool Optional(bool) { static bool Optional(bool) { return true; }
return true;
}
// This function is used for handling <non-terminal>+ syntax. // This function is used for handling <non-terminal>+ syntax.
using ParseFunc = bool (*)(State*); using ParseFunc = bool (*)(State*);
@ -248,17 +245,13 @@ static void Append(State *state, const char * const str, ssize_t length) {
} }
// We don't use equivalents in libc to avoid locale issues. // We don't use equivalents in libc to avoid locale issues.
static bool IsLower(char c) { static bool IsLower(char c) { return c >= 'a' && c <= 'z'; }
return c >= 'a' && c <= 'z';
}
static bool IsAlpha(char c) { static bool IsAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
} }
static bool IsDigit(char c) { static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
return c >= '0' && c <= '9';
}
// Returns true if "str" is a function clone suffix. These suffixes are used // Returns true if "str" is a function clone suffix. These suffixes are used
// by GCC 4.5.x and later versions to indicate functions which have been // by GCC 4.5.x and later versions to indicate functions which have been
@ -473,8 +466,7 @@ static bool ParseName(State *state) {
} }
State copy = *state; State copy = *state;
if (ParseUnscopedTemplateName(state) && if (ParseUnscopedTemplateName(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -494,8 +486,7 @@ static bool ParseUnscopedName(State *state) {
} }
State copy = *state; State copy = *state;
if (ParseTwoCharToken(state, "St") && if (ParseTwoCharToken(state, "St") && MaybeAppend(state, "std::") &&
MaybeAppend(state, "std::") &&
ParseUnqualifiedName(state)) { ParseUnqualifiedName(state)) {
return true; return true;
} }
@ -513,10 +504,8 @@ static bool ParseUnscopedTemplateName(State *state) {
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
static bool ParseNestedName(State* state) { static bool ParseNestedName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'N') && if (ParseOneCharToken(state, 'N') && EnterNestedName(state) &&
EnterNestedName(state) && Optional(ParseCVQualifiers(state)) && ParsePrefix(state) &&
Optional(ParseCVQualifiers(state)) &&
ParsePrefix(state) &&
LeaveNestedName(state, copy.nest_level) && LeaveNestedName(state, copy.nest_level) &&
ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
return true; return true;
@ -540,8 +529,7 @@ static bool ParsePrefix(State *state) {
bool has_something = false; bool has_something = false;
while (true) { while (true) {
MaybeAppendSeparator(state); MaybeAppendSeparator(state);
if (ParseTemplateParam(state) || if (ParseTemplateParam(state) || ParseSubstitution(state) ||
ParseSubstitution(state) ||
ParseUnscopedName(state)) { ParseUnscopedName(state)) {
has_something = true; has_something = true;
MaybeIncreaseNestLevel(state); MaybeIncreaseNestLevel(state);
@ -562,8 +550,7 @@ static bool ParsePrefix(State *state) {
// ::= <source-name> [<abi-tags>] // ::= <source-name> [<abi-tags>]
// ::= <local-source-name> [<abi-tags>] // ::= <local-source-name> [<abi-tags>]
static bool ParseUnqualifiedName(State* state) { static bool ParseUnqualifiedName(State* state) {
return (ParseOperatorName(state) || return (ParseOperatorName(state) || ParseCtorDtorName(state) ||
ParseCtorDtorName(state) ||
(ParseSourceName(state) && Optional(ParseAbiTags(state))) || (ParseSourceName(state) && Optional(ParseAbiTags(state))) ||
(ParseLocalSourceName(state) && Optional(ParseAbiTags(state)))); (ParseLocalSourceName(state) && Optional(ParseAbiTags(state))));
} }
@ -669,8 +656,7 @@ static bool ParseSeqId(State *state) {
// <identifier> ::= <unqualified source code identifier> (of given length) // <identifier> ::= <unqualified source code identifier> (of given length)
static bool ParseIdentifier(State* state, ssize_t length) { static bool ParseIdentifier(State* state, ssize_t length) {
if (length == -1 || if (length == -1 || !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
!AtLeastNumCharsRemaining(state->mangled_cur, length)) {
return false; return false;
} }
if (IdentifierIsAnonymousNamespace(state, length)) { if (IdentifierIsAnonymousNamespace(state, length)) {
@ -712,10 +698,8 @@ static bool ParseOperatorName(State *state) {
} }
// First check with "cv" (cast) case. // First check with "cv" (cast) case.
State copy = *state; State copy = *state;
if (ParseTwoCharToken(state, "cv") && if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") &&
MaybeAppend(state, "operator ") && EnterNestedName(state) && ParseType(state) &&
EnterNestedName(state) &&
ParseType(state) &&
LeaveNestedName(state, copy.nest_level)) { LeaveNestedName(state, copy.nest_level)) {
return true; return true;
} }
@ -730,8 +714,7 @@ static bool ParseOperatorName(State *state) {
// Other operator names should start with a lower alphabet followed // Other operator names should start with a lower alphabet followed
// by a lower/upper alphabet. // by a lower/upper alphabet.
if (!(IsLower(state->mangled_cur[0]) && if (!(IsLower(state->mangled_cur[0]) && IsAlpha(state->mangled_cur[1]))) {
IsAlpha(state->mangled_cur[1]))) {
return false; return false;
} }
// We may want to perform a binary search if we really need speed. // We may want to perform a binary search if we really need speed.
@ -771,8 +754,7 @@ static bool ParseOperatorName(State *state) {
// stack traces. The are special data. // stack traces. The are special data.
static bool ParseSpecialName(State* state) { static bool ParseSpecialName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'T') && if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
ParseCharClass(state, "VTIS") &&
ParseType(state)) { ParseType(state)) {
return true; return true;
} }
@ -784,8 +766,7 @@ static bool ParseSpecialName(State *state) {
} }
*state = copy; *state = copy;
if (ParseTwoCharToken(state, "GV") && if (ParseTwoCharToken(state, "GV") && ParseName(state)) {
ParseName(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -833,14 +814,14 @@ static bool ParseSpecialName(State *state) {
// ::= v <v-offset> _ // ::= v <v-offset> _
static bool ParseCallOffset(State* state) { static bool ParseCallOffset(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'h') && if (ParseOneCharToken(state, 'h') && ParseNVOffset(state) &&
ParseNVOffset(state) && ParseOneCharToken(state, '_')) { ParseOneCharToken(state, '_')) {
return true; return true;
} }
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'v') && if (ParseOneCharToken(state, 'v') && ParseVOffset(state) &&
ParseVOffset(state) && ParseOneCharToken(state, '_')) { ParseOneCharToken(state, '_')) {
return true; return true;
} }
*state = copy; *state = copy;
@ -866,8 +847,7 @@ static bool ParseVOffset(State *state) {
// ::= D0 | D1 | D2 // ::= D0 | D1 | D2
static bool ParseCtorDtorName(State* state) { static bool ParseCtorDtorName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'C') && if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "123")) {
ParseCharClass(state, "123")) {
const char* const prev_name = state->prev_name; const char* const prev_name = state->prev_name;
const ssize_t prev_name_length = state->prev_name_length; const ssize_t prev_name_length = state->prev_name_length;
MaybeAppendWithLength(state, prev_name, prev_name_length); MaybeAppendWithLength(state, prev_name, prev_name_length);
@ -875,8 +855,7 @@ static bool ParseCtorDtorName(State *state) {
} }
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'D') && if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "012")) {
ParseCharClass(state, "012")) {
const char* const prev_name = state->prev_name; const char* const prev_name = state->prev_name;
const ssize_t prev_name_length = state->prev_name_length; const ssize_t prev_name_length = state->prev_name_length;
MaybeAppend(state, "~"); MaybeAppend(state, "~");
@ -937,17 +916,13 @@ static bool ParseType(State *state) {
} }
*state = copy; *state = copy;
if (ParseBuiltinType(state) || if (ParseBuiltinType(state) || ParseFunctionType(state) ||
ParseFunctionType(state) || ParseClassEnumType(state) || ParseArrayType(state) ||
ParseClassEnumType(state) || ParsePointerToMemberType(state) || ParseSubstitution(state)) {
ParseArrayType(state) ||
ParsePointerToMemberType(state) ||
ParseSubstitution(state)) {
return true; return true;
} }
if (ParseTemplateTemplateParam(state) && if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -995,8 +970,8 @@ static bool ParseBuiltinType(State *state) {
static bool ParseFunctionType(State* state) { static bool ParseFunctionType(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'F') && if (ParseOneCharToken(state, 'F') &&
Optional(ParseOneCharToken(state, 'Y')) && Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
return true; return true;
} }
*state = copy; *state = copy;
@ -1017,9 +992,7 @@ static bool ParseBareFunctionType(State *state) {
} }
// <class-enum-type> ::= <name> // <class-enum-type> ::= <name>
static bool ParseClassEnumType(State *state) { static bool ParseClassEnumType(State* state) { return ParseName(state); }
return ParseName(state);
}
// <array-type> ::= A <(positive dimension) number> _ <(element) type> // <array-type> ::= A <(positive dimension) number> _ <(element) type>
// ::= A [<(dimension) expression>] _ <(element) type> // ::= A [<(dimension) expression>] _ <(element) type>
@ -1042,8 +1015,7 @@ static bool ParseArrayType(State *state) {
// <pointer-to-member-type> ::= M <(class) type> <(member) type> // <pointer-to-member-type> ::= M <(class) type> <(member) type>
static bool ParsePointerToMemberType(State* state) { static bool ParsePointerToMemberType(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'M') && ParseType(state) && if (ParseOneCharToken(state, 'M') && ParseType(state) && ParseType(state)) {
ParseType(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -1068,20 +1040,17 @@ static bool ParseTemplateParam(State *state) {
return false; return false;
} }
// <template-template-param> ::= <template-param> // <template-template-param> ::= <template-param>
// ::= <substitution> // ::= <substitution>
static bool ParseTemplateTemplateParam(State* state) { static bool ParseTemplateTemplateParam(State* state) {
return (ParseTemplateParam(state) || return (ParseTemplateParam(state) || ParseSubstitution(state));
ParseSubstitution(state));
} }
// <template-args> ::= I <template-arg>+ E // <template-args> ::= I <template-arg>+ E
static bool ParseTemplateArgs(State* state) { static bool ParseTemplateArgs(State* state) {
State copy = *state; State copy = *state;
DisableAppend(state); DisableAppend(state);
if (ParseOneCharToken(state, 'I') && if (ParseOneCharToken(state, 'I') && OneOrMore(ParseTemplateArg, state) &&
OneOrMore(ParseTemplateArg, state) &&
ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
RestoreAppend(state, copy.append); RestoreAppend(state, copy.append);
MaybeAppend(state, "<>"); MaybeAppend(state, "<>");
@ -1107,15 +1076,13 @@ static bool ParseTemplateArg(State *state) {
State copy = *state; State copy = *state;
if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) && if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) &&
ZeroOrMore(ParseTemplateArg, state) && ZeroOrMore(ParseTemplateArg, state) && ParseOneCharToken(state, 'E')) {
ParseOneCharToken(state, 'E')) {
--state->arg_level; --state->arg_level;
return true; return true;
} }
*state = copy; *state = copy;
if (ParseType(state) || if (ParseType(state) || ParseExprPrimary(state)) {
ParseExprPrimary(state)) {
--state->arg_level; --state->arg_level;
return true; return true;
} }
@ -1153,25 +1120,21 @@ static bool ParseExpression(State *state) {
++state->expr_level; ++state->expr_level;
State copy = *state; State copy = *state;
if (ParseOperatorName(state) && if (ParseOperatorName(state) && ParseExpression(state) &&
ParseExpression(state) && ParseExpression(state) && ParseExpression(state)) {
ParseExpression(state) && --state->expr_level;
return true;
}
*state = copy;
if (ParseOperatorName(state) && ParseExpression(state) &&
ParseExpression(state)) { ParseExpression(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
*state = copy; *state = copy;
if (ParseOperatorName(state) && if (ParseOperatorName(state) && ParseExpression(state)) {
ParseExpression(state) &&
ParseExpression(state)) {
--state->expr_level;
return true;
}
*state = copy;
if (ParseOperatorName(state) &&
ParseExpression(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
@ -1184,8 +1147,7 @@ static bool ParseExpression(State *state) {
*state = copy; *state = copy;
if (ParseTwoCharToken(state, "sr") && ParseType(state) && if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
ParseUnqualifiedName(state) && ParseUnqualifiedName(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
@ -1214,8 +1176,7 @@ static bool ParseExprPrimary(State *state) {
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'L') && ParseType(state) && if (ParseOneCharToken(state, 'L') && ParseType(state) &&
ParseFloatNumber(state) && ParseFloatNumber(state) && ParseOneCharToken(state, 'E')) {
ParseOneCharToken(state, 'E')) {
return true; return true;
} }
*state = copy; *state = copy;

View File

@ -67,14 +67,11 @@ static const char *DemangleIt(const char * const mangled) {
# if defined(HAVE_DBGHELP) && !defined(NDEBUG) # if defined(HAVE_DBGHELP) && !defined(NDEBUG)
TEST(Demangle, Windows) { TEST(Demangle, Windows) {
EXPECT_STREQ( EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
"public: static void __cdecl Foo::func(int)",
DemangleIt("?func@Foo@@SAXH@Z")); DemangleIt("?func@Foo@@SAXH@Z"));
EXPECT_STREQ( EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
"public: static void __cdecl Foo::func(int)",
DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)")); DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
EXPECT_STREQ( EXPECT_STREQ("int __cdecl foobarArray(int * const)",
"int __cdecl foobarArray(int * const)",
DemangleIt("?foobarArray@@YAHQAH@Z")); DemangleIt("?foobarArray@@YAHQAH@Z"));
} }
# endif # endif

View File

@ -56,8 +56,8 @@ const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
# ifdef ERROR # ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail. # error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif # endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING, const int INFO = GLOG_INFO, WARNING = GLOG_WARNING, ERROR = GLOG_ERROR,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL; FATAL = GLOG_FATAL;
#endif #endif
// DFATAL is FATAL in debug mode, ERROR in normal mode // DFATAL is FATAL in debug mode, ERROR in normal mode

View File

@ -404,7 +404,8 @@ typedef void (*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l,
# if !defined(DECLARE_uint32) # if !defined(DECLARE_uint32)
// uint32 specialization // uint32 specialization
#define DECLARE_uint32(name) DECLARE_VARIABLE(google::uint32, U, name, uint32) # define DECLARE_uint32(name) \
DECLARE_VARIABLE(google::uint32, U, name, uint32)
# endif // !defined(DECLARE_uint32) && !defined(GLOG_USE_GFLAGS) # endif // !defined(DECLARE_uint32) && !defined(GLOG_USE_GFLAGS)
// Special case for string, because we have to specify the namespace // Special case for string, because we have to specify the namespace

View File

@ -79,7 +79,8 @@
__FILE__, __LINE__, &vlocal__, sizeof(google::SiteFlag), "")); \ __FILE__, __LINE__, &vlocal__, sizeof(google::SiteFlag), "")); \
google::int32 verbose_level__ = (verboselevel); \ google::int32 verbose_level__ = (verboselevel); \
(vlocal__.level == nullptr \ (vlocal__.level == nullptr \
? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, verbose_level__) \ ? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, \
verbose_level__) \
: *vlocal__.level >= verbose_level__); \ : *vlocal__.level >= verbose_level__); \
}) })
#else #else

View File

@ -130,8 +130,8 @@ void InitGoogleTest(int*, char**) {}
# define EXPECT_NEAR(val1, val2, abs_error) \ # define EXPECT_NEAR(val1, val2, abs_error) \
do { \ do { \
if (abs(val1 - val2) > abs_error) { \ if (abs(val1 - val2) > abs_error) { \
fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, #abs_error, \ fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, \
#val2); \ #abs_error, #val2); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
@ -196,13 +196,15 @@ vector<void (*)()> g_testlist; // the tests to run
# define TEST(a, b) \ # define TEST(a, b) \
struct Test_##a##_##b { \ struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \ Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \ static void Run() { \
FlagSaver fs; \
RunTest(); \
} \
static void RunTest(); \ static void RunTest(); \
}; \ }; \
static Test_##a##_##b g_test_##a##_##b; \ static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest() void Test_##a##_##b::RunTest()
static inline int RUN_ALL_TESTS() { static inline int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it; vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
@ -317,8 +319,7 @@ class CapturedStream {
CHECK(uncaptured_fd_ != -1); CHECK(uncaptured_fd_ != -1);
// Open file to save stream to // Open file to save stream to
int cap_fd = open(filename_.c_str(), int cap_fd = open(filename_.c_str(), O_CREAT | O_TRUNC | O_WRONLY,
O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
CHECK(cap_fd != -1); CHECK(cap_fd != -1);
@ -377,7 +378,8 @@ static inline string ReadEntireFile(FILE * file) {
// Keep reading the file until we cannot read further or the // Keep reading the file until we cannot read further or the
// pre-determined file size is reached. // pre-determined file size is reached.
do { do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); bytes_last_read =
fread(buffer + bytes_read, 1, file_size - bytes_read, file);
bytes_read += bytes_last_read; bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size); } while (bytes_last_read > 0 && bytes_read < file_size);
@ -391,8 +393,7 @@ static inline string ReadEntireFile(FILE * file) {
static inline string GetCapturedTestOutput(int fd) { static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO); CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
CapturedStream* const cap = s_captured_streams[fd]; CapturedStream* const cap = s_captured_streams[fd];
CHECK(cap) CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
<< ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
// Make sure everything is flushed. // Make sure everything is flushed.
cap->StopCapture(); cap->StopCapture();
@ -468,8 +469,7 @@ static inline string MungeLine(const string& line) {
MungeLine(rest)); MungeLine(rest));
} }
static inline void StringReplace(string* str, static inline void StringReplace(string* str, const string& oldsub,
const string& oldsub,
const string& newsub) { const string& newsub) {
size_t pos = str->find(oldsub); size_t pos = str->find(oldsub);
if (pos != string::npos) { if (pos != string::npos) {
@ -589,9 +589,7 @@ class Thread {
handle_ = CreateThread(nullptr, 0, &Thread::InvokeThreadW, this, 0, &th_); handle_ = CreateThread(nullptr, 0, &Thread::InvokeThreadW, this, 0, &th_);
CHECK(handle_) << "CreateThread"; CHECK(handle_) << "CreateThread";
} }
void Join() { void Join() { WaitForSingleObject(handle_, INFINITE); }
WaitForSingleObject(handle_, INFINITE);
}
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
void Start() { pthread_create(&th_, nullptr, &Thread::InvokeThread, this); } void Start() { pthread_create(&th_, nullptr, &Thread::InvokeThread, this); }
void Join() { pthread_join(th_, nullptr); } void Join() { pthread_join(th_, nullptr); }

View File

@ -97,21 +97,21 @@
typedef int mode_t; typedef int mode_t;
#endif #endif
using std::string;
using std::vector;
using std::setw;
using std::setfill;
using std::hex;
using std::dec; using std::dec;
using std::hex;
using std::min; using std::min;
using std::ostream; using std::ostream;
using std::ostringstream; using std::ostringstream;
using std::setfill;
using std::setw;
using std::string;
using std::vector;
using std::FILE;
using std::fwrite;
using std::fclose; using std::fclose;
using std::fflush; using std::fflush;
using std::FILE;
using std::fprintf; using std::fprintf;
using std::fwrite;
using std::perror; using std::perror;
#ifdef __QNX__ #ifdef __QNX__
@ -147,7 +147,9 @@ GLOG_DEFINE_bool(colorlogtostdout, false,
GLOG_DEFINE_bool(logtostdout, BoolFromEnv("GOOGLE_LOGTOSTDOUT", false), GLOG_DEFINE_bool(logtostdout, BoolFromEnv("GOOGLE_LOGTOSTDOUT", false),
"log messages go to stdout instead of logfiles"); "log messages go to stdout instead of logfiles");
#ifdef GLOG_OS_LINUX #ifdef GLOG_OS_LINUX
GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. " 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 " "Logs can grow very quickly and they are rarely read before they "
"need to be evicted from memory. Instead, drop them from memory " "need to be evicted from memory. Instead, drop them from memory "
"as soon as they are flushed to disk."); "as soon as they are flushed to disk.");
@ -171,7 +173,8 @@ GLOG_DEFINE_bool(log_prefix, true,
"Prepend the log prefix to the start of each log line"); "Prepend the log prefix to the start of each log line");
GLOG_DEFINE_bool(log_year_in_prefix, true, GLOG_DEFINE_bool(log_year_in_prefix, true,
"Include the year in the log prefix"); "Include the year in the log prefix");
GLOG_DEFINE_int32(minloglevel, 0, "Messages logged at a lower level than this don't " GLOG_DEFINE_int32(minloglevel, 0,
"Messages logged at a lower level than this don't "
"actually get logged anywhere"); "actually get logged anywhere");
GLOG_DEFINE_int32(logbuflevel, 0, GLOG_DEFINE_int32(logbuflevel, 0,
"Buffer log messages logged at this level or lower" "Buffer log messages logged at this level or lower"
@ -187,8 +190,7 @@ GLOG_DEFINE_int32(logemaillevel, 999,
"Email log messages logged at this level or higher" "Email log messages logged at this level or higher"
" (0 means email all; 3 means email FATAL only;" " (0 means email all; 3 means email FATAL only;"
" ...)"); " ...)");
GLOG_DEFINE_string(logmailer, "", GLOG_DEFINE_string(logmailer, "", "Mailer used to send logging email");
"Mailer used to send logging email");
// Compute the default value for --log_dir // Compute the default value for --log_dir
static const char* DefaultLogDir() { static const char* DefaultLogDir() {
@ -206,10 +208,12 @@ static const char* DefaultLogDir() {
GLOG_DEFINE_int32(logfile_mode, 0664, "Log file mode/permissions."); GLOG_DEFINE_int32(logfile_mode, 0664, "Log file mode/permissions.");
GLOG_DEFINE_string(log_dir, DefaultLogDir(), GLOG_DEFINE_string(
log_dir, DefaultLogDir(),
"If specified, logfiles are written into this directory instead " "If specified, logfiles are written into this directory instead "
"of the default logging directory."); "of the default logging directory.");
GLOG_DEFINE_string(log_link, "", "Put additional links to the log " GLOG_DEFINE_string(log_link, "",
"Put additional links to the log "
"files in this directory"); "files in this directory");
GLOG_DEFINE_uint32(max_log_size, 1800, GLOG_DEFINE_uint32(max_log_size, 1800,
@ -222,8 +226,7 @@ GLOG_DEFINE_bool(stop_logging_if_full_disk, false,
GLOG_DEFINE_string(log_backtrace_at, "", GLOG_DEFINE_string(log_backtrace_at, "",
"Emit a backtrace when logging at file:linenum."); "Emit a backtrace when logging at file:linenum.");
GLOG_DEFINE_bool(log_utc_time, false, GLOG_DEFINE_bool(log_utc_time, false, "Use UTC time for logging.");
"Use UTC time for logging.");
// TODO(hamaji): consider windows // TODO(hamaji): consider windows
enum { PATH_SEPARATOR = '/' }; enum { PATH_SEPARATOR = '/' };
@ -231,15 +234,11 @@ enum { PATH_SEPARATOR = '/' };
#ifndef HAVE_PREAD #ifndef HAVE_PREAD
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) { static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR); off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1) if (orig_offset == (off_t)-1) return -1;
return -1; if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
ssize_t len = read(fd, buf, count); ssize_t len = read(fd, buf, count);
if (len < 0) if (len < 0) return len;
return len; if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
return len; return len;
} }
#endif // !HAVE_PREAD #endif // !HAVE_PREAD
@ -247,15 +246,11 @@ static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
#ifndef HAVE_PWRITE #ifndef HAVE_PWRITE
static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) { static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) {
off_t orig_offset = lseek(fd, 0, SEEK_CUR); off_t orig_offset = lseek(fd, 0, SEEK_CUR);
if (orig_offset == (off_t)-1) if (orig_offset == (off_t)-1) return -1;
return -1; if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
return -1;
ssize_t len = write(fd, buf, count); ssize_t len = write(fd, buf, count);
if (len < 0) if (len < 0) return len;
return len; if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
return -1;
return len; return len;
} }
#endif // !HAVE_PWRITE #endif // !HAVE_PWRITE
@ -294,16 +289,11 @@ static bool TerminalSupportsColor() {
const char* const term = getenv("TERM"); const char* const term = getenv("TERM");
if (term != nullptr && term[0] != '\0') { if (term != nullptr && term[0] != '\0') {
term_supports_color = term_supports_color =
!strcmp(term, "xterm") || !strcmp(term, "xterm") || !strcmp(term, "xterm-color") ||
!strcmp(term, "xterm-color") || !strcmp(term, "xterm-256color") || !strcmp(term, "screen-256color") ||
!strcmp(term, "xterm-256color") || !strcmp(term, "konsole") || !strcmp(term, "konsole-16color") ||
!strcmp(term, "screen-256color") || !strcmp(term, "konsole-256color") || !strcmp(term, "screen") ||
!strcmp(term, "konsole") || !strcmp(term, "linux") || !strcmp(term, "cygwin");
!strcmp(term, "konsole-16color") ||
!strcmp(term, "konsole-256color") ||
!strcmp(term, "screen") ||
!strcmp(term, "linux") ||
!strcmp(term, "cygwin");
} }
#endif #endif
return term_supports_color; return term_supports_color;
@ -311,12 +301,7 @@ static bool TerminalSupportsColor() {
namespace google { namespace google {
enum GLogColor { enum GLogColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW };
COLOR_DEFAULT,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW
};
static GLogColor SeverityToColor(LogSeverity severity) { static GLogColor SeverityToColor(LogSeverity severity) {
assert(severity >= 0 && severity < NUM_SEVERITIES); assert(severity >= 0 && severity < NUM_SEVERITIES);
@ -344,10 +329,14 @@ static GLogColor SeverityToColor(LogSeverity severity) {
// Returns the character attribute for the given color. // Returns the character attribute for the given color.
static WORD GetColorAttribute(GLogColor color) { static WORD GetColorAttribute(GLogColor color) {
switch (color) { switch (color) {
case COLOR_RED: return FOREGROUND_RED; case COLOR_RED:
case COLOR_GREEN: return FOREGROUND_GREEN; return FOREGROUND_RED;
case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; case COLOR_GREEN:
default: return 0; return FOREGROUND_GREEN;
case COLOR_YELLOW:
return FOREGROUND_RED | FOREGROUND_GREEN;
default:
return 0;
} }
} }
@ -356,10 +345,14 @@ static WORD GetColorAttribute(GLogColor color) {
// Returns the ANSI color code for the given color. // Returns the ANSI color code for the given color.
static const char* GetAnsiColorCode(GLogColor color) { static const char* GetAnsiColorCode(GLogColor color) {
switch (color) { switch (color) {
case COLOR_RED: return "1"; case COLOR_RED:
case COLOR_GREEN: return "2"; return "1";
case COLOR_YELLOW: return "3"; case COLOR_GREEN:
case COLOR_DEFAULT: return ""; return "2";
case COLOR_YELLOW:
return "3";
case COLOR_DEFAULT:
return "";
}; };
return nullptr; // stop warning about return type. return nullptr; // stop warning about return type.
} }
@ -419,9 +412,8 @@ int64 LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
// Globally disable log writing (if disk is full) // Globally disable log writing (if disk is full)
static bool stop_writing = false; static bool stop_writing = false;
const char*const LogSeverityNames[NUM_SEVERITIES] = { const char* const LogSeverityNames[NUM_SEVERITIES] = {"INFO", "WARNING",
"INFO", "WARNING", "ERROR", "FATAL" "ERROR", "FATAL"};
};
// Has the user called SetExitOnDFatal(true)? // Has the user called SetExitOnDFatal(true)?
static bool exit_on_dfatal = true; static bool exit_on_dfatal = true;
@ -440,7 +432,7 @@ namespace {
CustomPrefixCallback custom_prefix_callback = nullptr; CustomPrefixCallback custom_prefix_callback = nullptr;
// User-provided data to pass to the callback: // User-provided data to pass to the callback:
void* custom_prefix_callback_data = nullptr; void* custom_prefix_callback_data = nullptr;
} } // namespace
namespace { namespace {
@ -509,8 +501,7 @@ class LogCleaner {
// update next_cleanup_time_ // update next_cleanup_time_
void UpdateCleanUpTime(); void UpdateCleanUpTime();
void Run(bool base_filename_selected, void Run(bool base_filename_selected, const string& base_filename,
const string& base_filename,
const string& filename_extension); const string& filename_extension);
bool enabled() const { return enabled_; } bool enabled() const { return enabled_; }
@ -545,8 +536,7 @@ class LogDestination {
// These methods are just forwarded to by their global versions. // These methods are just forwarded to by their global versions.
static void SetLogDestination(LogSeverity severity, static void SetLogDestination(LogSeverity severity,
const char* base_filename); const char* base_filename);
static void SetLogSymlink(LogSeverity severity, static void SetLogSymlink(LogSeverity severity, const char* symlink_basename);
const char* symlink_basename);
static void AddLogSink(LogSink* destination); static void AddLogSink(LogSink* destination);
static void RemoveLogSink(LogSink* destination); static void RemoveLogSink(LogSink* destination);
static void SetLogFilenameExtension(const char* filename_extension); static void SetLogFilenameExtension(const char* filename_extension);
@ -584,14 +574,12 @@ class LogDestination {
size_t len); size_t len);
// Take a log message of a particular severity and log it to a file // Take a log message of a particular severity and log it to a file
// iff the base filename is not "" (which means "don't log to me") // iff the base filename is not "" (which means "don't log to me")
static void MaybeLogToLogfile(LogSeverity severity, static void MaybeLogToLogfile(LogSeverity severity, time_t timestamp,
time_t timestamp,
const char* message, size_t len); const char* message, size_t len);
// Take a log message of a particular severity and log it to the file // Take a log message of a particular severity and log it to the file
// for that severity and also for all files with severity less than // for that severity and also for all files with severity less than
// this severity. // this severity.
static void LogToAllLogfiles(LogSeverity severity, static void LogToAllLogfiles(LogSeverity severity, time_t timestamp,
time_t timestamp,
const char* message, size_t len); const char* message, size_t len);
// Send logging info to all registered sinks. // Send logging info to all registered sinks.
@ -652,15 +640,10 @@ const string& LogDestination::hostname() {
return hostname_; return hostname_;
} }
LogDestination::LogDestination(LogSeverity severity, LogDestination::LogDestination(LogSeverity severity, const char* base_filename)
const char* base_filename) : fileobject_(severity, base_filename), logger_(&fileobject_) {}
: fileobject_(severity, base_filename),
logger_(&fileobject_) {
}
LogDestination::~LogDestination() { LogDestination::~LogDestination() { ResetLoggerImpl(); }
ResetLoggerImpl();
}
void LogDestination::SetLoggerImpl(base::Logger* logger) { void LogDestination::SetLoggerImpl(base::Logger* logger) {
if (logger_ == logger) { if (logger_ == logger) {
@ -731,7 +714,8 @@ inline void LogDestination::RemoveLogSink(LogSink *destination) {
MutexLock l(&sink_mutex_); MutexLock l(&sink_mutex_);
// This doesn't keep the sinks in order, but who cares? // This doesn't keep the sinks in order, but who cares?
if (sinks_) { if (sinks_) {
sinks_->erase(std::remove(sinks_->begin(), sinks_->end(), destination), sinks_->end()); sinks_->erase(std::remove(sinks_->begin(), sinks_->end(), destination),
sinks_->end());
} }
} }
@ -835,7 +819,9 @@ static void WriteToStderr(const char* message, size_t len) {
} }
inline void LogDestination::MaybeLogToStderr(LogSeverity severity, inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
const char* message, size_t message_len, size_t prefix_len) { const char* message,
size_t message_len,
size_t prefix_len) {
if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) { if ((severity >= FLAGS_stderrthreshold) || FLAGS_alsologtostderr) {
ColoredWriteToStderr(severity, message, message_len); ColoredWriteToStderr(severity, message, message_len);
#ifdef GLOG_OS_WINDOWS #ifdef GLOG_OS_WINDOWS
@ -859,11 +845,9 @@ inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
} }
} }
inline void LogDestination::MaybeLogToEmail(LogSeverity severity, inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
const char* message, size_t len) { const char* message, size_t len) {
if (severity >= email_logging_severity_ || if (severity >= email_logging_severity_ || severity >= FLAGS_logemaillevel) {
severity >= FLAGS_logemaillevel) {
string to(FLAGS_alsologtoemail); string to(FLAGS_alsologtoemail);
if (!addresses_.empty()) { if (!addresses_.empty()) {
if (!to.empty()) { if (!to.empty()) {
@ -871,7 +855,8 @@ inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
} }
to += addresses_; to += addresses_;
} }
const string subject(string("[LOG] ") + LogSeverityNames[severity] + ": " + const string subject(
string("[LOG] ") + LogSeverityNames[severity] + ": " +
glog_internal_namespace_::ProgramInvocationShortName()); glog_internal_namespace_::ProgramInvocationShortName());
string body(hostname()); string body(hostname());
body += "\n\n"; body += "\n\n";
@ -885,11 +870,9 @@ inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
} }
} }
inline void LogDestination::MaybeLogToLogfile(LogSeverity severity, inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
time_t timestamp, time_t timestamp,
const char* message, const char* message, size_t len) {
size_t len) {
const bool should_flush = severity > FLAGS_logbuflevel; const bool should_flush = severity > FLAGS_logbuflevel;
LogDestination* destination = log_destination(severity); LogDestination* destination = log_destination(severity);
destination->logger_->Write(should_flush, timestamp, message, len); destination->logger_->Write(should_flush, timestamp, message, len);
@ -897,8 +880,7 @@ inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
inline void LogDestination::LogToAllLogfiles(LogSeverity severity, inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
time_t timestamp, time_t timestamp,
const char* message, const char* message, size_t len) {
size_t len) {
if (FLAGS_logtostdout) { // global flag: never log to file if (FLAGS_logtostdout) { // global flag: never log to file
ColoredWriteToStdout(severity, message, len); ColoredWriteToStdout(severity, message, len);
} else if (FLAGS_logtostderr) { // global flag: never log to file } else if (FLAGS_logtostderr) { // global flag: never log to file
@ -919,8 +901,8 @@ inline void LogDestination::LogToSinks(LogSeverity severity,
ReaderMutexLock l(&sink_mutex_); ReaderMutexLock l(&sink_mutex_);
if (sinks_) { if (sinks_) {
for (size_t i = sinks_->size(); i-- > 0;) { for (size_t i = sinks_->size(); i-- > 0;) {
(*sinks_)[i]->send(severity, full_filename, base_filename, (*sinks_)[i]->send(severity, full_filename, base_filename, line,
line, logmsgtime, message, message_len); logmsgtime, message, message_len);
} }
} }
} }
@ -1056,8 +1038,8 @@ void LogFileObject::FlushUnlocked(){
bytes_since_flush_ = 0; bytes_since_flush_ = 0;
} }
// Figure out when we are due for another flush. // Figure out when we are due for another flush.
const int64 next = (FLAGS_logbufsecs const int64 next =
* static_cast<int64>(1000000)); // in usec (FLAGS_logbufsecs * static_cast<int64>(1000000)); // in usec
next_flush_time_ = CycleClock_Now() + UsecToCycles(next); next_flush_time_ = CycleClock_Now() + UsecToCycles(next);
} }
@ -1109,13 +1091,14 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
if (file_ == nullptr) { // Man, we're screwed! if (file_ == nullptr) { // Man, we're screwed!
close(fd); close(fd);
if (FLAGS_timestamp_in_logfile_name) { if (FLAGS_timestamp_in_logfile_name) {
unlink(filename); // Erase the half-baked evidence: an unusable log file, only if we just created it. unlink(filename); // Erase the half-baked evidence: an unusable log file,
// only if we just created it.
} }
return false; return false;
} }
#ifdef GLOG_OS_WINDOWS #ifdef GLOG_OS_WINDOWS
// https://github.com/golang/go/issues/27638 - make sure we seek to the end to append // https://github.com/golang/go/issues/27638 - make sure we seek to the end to
// empirically replicated with wine over mingw build // append empirically replicated with wine over mingw build
if (!FLAGS_timestamp_in_logfile_name) { if (!FLAGS_timestamp_in_logfile_name) {
if (fseek(file_, 0, SEEK_END) != 0) { if (fseek(file_, 0, SEEK_END) != 0) {
return false; return false;
@ -1133,7 +1116,9 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
const string linkname = const string linkname =
symlink_basename_ + '.' + LogSeverityNames[severity_]; symlink_basename_ + '.' + LogSeverityNames[severity_];
string linkpath; string linkpath;
if ( slash ) linkpath = string(filename, static_cast<size_t>(slash-filename+1)); // get dirname if (slash)
linkpath = string(
filename, static_cast<size_t>(slash - filename + 1)); // get dirname
linkpath += linkname; linkpath += linkname;
unlink(linkpath.c_str()); // delete old one if it exists unlink(linkpath.c_str()); // delete old one if it exists
@ -1163,10 +1148,8 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
return true; // Everything worked return true; // Everything worked
} }
void LogFileObject::Write(bool force_flush, void LogFileObject::Write(bool force_flush, time_t timestamp,
time_t timestamp, const char* message, size_t message_len) {
const char* message,
size_t message_len) {
MutexLock l(&lock_); MutexLock l(&lock_);
// We don't log if the base_name_ is "" (which means "don't write") // We don't log if the base_name_ is "" (which means "don't write")
@ -1199,15 +1182,10 @@ void LogFileObject::Write(bool force_flush,
// The logfile's filename will have the date/time & pid in it // The logfile's filename will have the date/time & pid in it
ostringstream time_pid_stream; ostringstream time_pid_stream;
time_pid_stream.fill('0'); time_pid_stream.fill('0');
time_pid_stream << 1900+tm_time.tm_year time_pid_stream << 1900 + tm_time.tm_year << setw(2) << 1 + tm_time.tm_mon
<< setw(2) << 1+tm_time.tm_mon << setw(2) << tm_time.tm_mday << '-' << setw(2)
<< setw(2) << tm_time.tm_mday << tm_time.tm_hour << setw(2) << tm_time.tm_min << setw(2)
<< '-' << tm_time.tm_sec << '.' << GetMainThreadPid();
<< setw(2) << tm_time.tm_hour
<< setw(2) << tm_time.tm_min
<< setw(2) << tm_time.tm_sec
<< '.'
<< GetMainThreadPid();
const string& time_pid_string = time_pid_stream.str(); const string& time_pid_string = time_pid_stream.str();
if (base_filename_selected_) { if (base_filename_selected_) {
@ -1241,9 +1219,8 @@ void LogFileObject::Write(bool force_flush,
// deadlock. Simply use a name like invalid-user. // deadlock. Simply use a name like invalid-user.
if (uidname.empty()) uidname = "invalid-user"; if (uidname.empty()) uidname = "invalid-user";
stripped_filename = stripped_filename+'.'+hostname+'.' stripped_filename = stripped_filename + '.' + hostname + '.' + uidname +
+uidname+".log." ".log." + LogSeverityNames[severity_] + '.';
+LogSeverityNames[severity_]+'.';
// We're going to (potentially) try to put logs in several different dirs // We're going to (potentially) try to put logs in several different dirs
const vector<string>& log_dirs = GetLoggingDirectories(); const vector<string>& log_dirs = GetLoggingDirectories();
@ -1270,25 +1247,26 @@ void LogFileObject::Write(bool force_flush,
if (FLAGS_log_file_header) { if (FLAGS_log_file_header) {
ostringstream file_header_stream; ostringstream file_header_stream;
file_header_stream.fill('0'); file_header_stream.fill('0');
file_header_stream << "Log file created at: " file_header_stream << "Log file created at: " << 1900 + tm_time.tm_year
<< 1900+tm_time.tm_year << '/' << '/' << setw(2) << 1 + tm_time.tm_mon << '/'
<< setw(2) << 1+tm_time.tm_mon << '/' << setw(2) << tm_time.tm_mday << ' ' << setw(2)
<< setw(2) << tm_time.tm_mday << tm_time.tm_hour << ':' << setw(2) << tm_time.tm_min
<< ' ' << ':' << setw(2) << tm_time.tm_sec
<< setw(2) << tm_time.tm_hour << ':' << (FLAGS_log_utc_time ? " UTC\n" : "\n")
<< setw(2) << tm_time.tm_min << ':' << "Running on machine: " << LogDestination::hostname()
<< setw(2) << tm_time.tm_sec << (FLAGS_log_utc_time ? " UTC\n" : "\n") << '\n';
<< "Running on machine: "
<< LogDestination::hostname() << '\n';
if (!g_application_fingerprint.empty()) { if (!g_application_fingerprint.empty()) {
file_header_stream << "Application fingerprint: " << g_application_fingerprint << '\n'; file_header_stream << "Application fingerprint: "
<< g_application_fingerprint << '\n';
} }
const char* const date_time_format = FLAGS_log_year_in_prefix const char* const date_time_format = FLAGS_log_year_in_prefix
? "yyyymmdd hh:mm:ss.uuuuuu" ? "yyyymmdd hh:mm:ss.uuuuuu"
: "mmdd hh:mm:ss.uuuuuu"; : "mmdd hh:mm:ss.uuuuuu";
file_header_stream << "Running duration (h:mm:ss): " file_header_stream << "Running duration (h:mm:ss): "
<< PrettyDuration(static_cast<int>(WallTime_Now() - start_time_)) << '\n' << PrettyDuration(
static_cast<int>(WallTime_Now() - start_time_))
<< '\n'
<< "Log line format: [IWEF]" << date_time_format << " " << "Log line format: [IWEF]" << date_time_format << " "
<< "threadid file:line] msg" << '\n'; << "threadid file:line] msg" << '\n';
const string& file_header_string = file_header_stream.str(); const string& file_header_string = file_header_stream.str();
@ -1326,8 +1304,7 @@ void LogFileObject::Write(bool force_flush,
// See important msgs *now*. Also, flush logs at least every 10^6 chars, // See important msgs *now*. Also, flush logs at least every 10^6 chars,
// or every "FLAGS_logbufsecs" seconds. // or every "FLAGS_logbufsecs" seconds.
if ( force_flush || if (force_flush || (bytes_since_flush_ >= 1000000) ||
(bytes_since_flush_ >= 1000000) ||
(CycleClock_Now() >= next_flush_time_)) { (CycleClock_Now() >= next_flush_time_)) {
FlushUnlocked(); FlushUnlocked();
#ifdef GLOG_OS_LINUX #ifdef GLOG_OS_LINUX
@ -1355,8 +1332,7 @@ void LogFileObject::Write(bool force_flush,
// Remove old logs // Remove old logs
if (log_cleaner.enabled()) { if (log_cleaner.enabled()) {
log_cleaner.Run(base_filename_selected_, log_cleaner.Run(base_filename_selected_, base_filename_,
base_filename_,
filename_extension_); filename_extension_);
} }
} }
@ -1369,18 +1345,14 @@ void LogCleaner::Enable(unsigned int overdue_days) {
overdue_days_ = overdue_days; overdue_days_ = overdue_days;
} }
void LogCleaner::Disable() { void LogCleaner::Disable() { enabled_ = false; }
enabled_ = false;
}
void LogCleaner::UpdateCleanUpTime() { void LogCleaner::UpdateCleanUpTime() {
const int64 next = (FLAGS_logcleansecs const int64 next = (FLAGS_logcleansecs * 1000000); // in usec
* 1000000); // in usec
next_cleanup_time_ = CycleClock_Now() + UsecToCycles(next); next_cleanup_time_ = CycleClock_Now() + UsecToCycles(next);
} }
void LogCleaner::Run(bool base_filename_selected, void LogCleaner::Run(bool base_filename_selected, const string& base_filename,
const string& base_filename,
const string& filename_extension) { const string& filename_extension) {
assert(enabled_); assert(enabled_);
assert(!base_filename_selected || !base_filename.empty()); assert(!base_filename_selected || !base_filename.empty());
@ -1441,7 +1413,8 @@ vector<string> LogCleaner::GetOverdueLogNames(
filepath = log_directory + filepath; filepath = log_directory + filepath;
} }
if (IsLogFromCurrentProject(filepath, base_filename, filename_extension) && if (IsLogFromCurrentProject(filepath, base_filename,
filename_extension) &&
IsLogLastModifiedOver(filepath, days)) { IsLogLastModifiedOver(filepath, days)) {
overdue_log_names.push_back(filepath); overdue_log_names.push_back(filepath);
} }
@ -1452,8 +1425,8 @@ vector<string> LogCleaner::GetOverdueLogNames(
return overdue_log_names; return overdue_log_names;
} }
bool LogCleaner::IsLogFromCurrentProject(const string& filepath, bool LogCleaner::IsLogFromCurrentProject(
const string& base_filename, const string& filepath, const string& base_filename,
const string& filename_extension) const { const string& filename_extension) const {
// We should remove duplicated delimiters from `base_filename`, e.g., // We should remove duplicated delimiters from `base_filename`, e.g.,
// before: "/tmp//<base_filename>.<create_time>.<pid>" // before: "/tmp//<base_filename>.<create_time>.<pid>"
@ -1488,11 +1461,11 @@ bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
return false; return false;
} }
// for origin version, `filename_extension` is middle of the `filepath`. // for origin version, `filename_extension` is middle of the `filepath`.
string ext = filepath.substr(cleaned_base_filename.size(), filename_extension.size()); string ext = filepath.substr(cleaned_base_filename.size(),
filename_extension.size());
if (ext == filename_extension) { if (ext == filename_extension) {
cleaned_base_filename += filename_extension; cleaned_base_filename += filename_extension;
} } else {
else {
// for new version, `filename_extension` is right of the `filepath`. // for new version, `filename_extension` is right of the `filepath`.
if (filename_extension.size() >= real_filepath_size) { if (filename_extension.size() >= real_filepath_size) {
return false; return false;
@ -1510,19 +1483,29 @@ bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
const char& c = filepath[i]; const char& c = filepath[i];
if (i <= cleaned_base_filename.size() + 7) { // 0 ~ 7 : YYYYMMDD if (i <= cleaned_base_filename.size() + 7) { // 0 ~ 7 : YYYYMMDD
if (c < '0' || c > '9') { return false; } if (c < '0' || c > '9') {
return false;
}
} else if (i == cleaned_base_filename.size() + 8) { // 8: - } else if (i == cleaned_base_filename.size() + 8) { // 8: -
if (c != '-') { return false; } if (c != '-') {
return false;
}
} else if (i <= cleaned_base_filename.size() + 14) { // 9 ~ 14: HHMMSS } else if (i <= cleaned_base_filename.size() + 14) { // 9 ~ 14: HHMMSS
if (c < '0' || c > '9') { return false; } if (c < '0' || c > '9') {
return false;
}
} else if (i == cleaned_base_filename.size() + 15) { // 15: . } else if (i == cleaned_base_filename.size() + 15) { // 15: .
if (c != '.') { return false; } if (c != '.') {
return false;
}
} else if (i >= cleaned_base_filename.size() + 16) { // 16+: pid } else if (i >= cleaned_base_filename.size() + 16) { // 16+: pid
if (c < '0' || c > '9') { return false; } if (c < '0' || c > '9') {
return false;
}
} }
} }
@ -1577,8 +1560,7 @@ static thread_local std::aligned_storage<
#endif // defined(GLOG_THREAD_LOCAL_STORAGE) #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
LogMessage::LogMessageData::LogMessageData() LogMessage::LogMessageData::LogMessageData()
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {}
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity, LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int64 ctr, void (LogMessage::*send_method)()) int64 ctr, void (LogMessage::*send_method)())
@ -1605,8 +1587,9 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
LogMessage::LogMessage(const char* file, int line, LogSeverity severity, LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
LogSink* sink, bool also_send_to_log) LogSink* sink, bool also_send_to_log)
: allocated_(nullptr) { : allocated_(nullptr) {
Init(file, line, severity, also_send_to_log ? &LogMessage::SendToSinkAndLog : Init(file, line, severity,
&LogMessage::SendToSink); also_send_to_log ? &LogMessage::SendToSinkAndLog
: &LogMessage::SendToSink);
data_->sink_ = sink; // override Init()'s setting to nullptr data_->sink_ = sink; // override Init()'s setting to nullptr
} }
@ -1624,9 +1607,7 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
data_->message_ = message; // override Init()'s setting to nullptr data_->message_ = message; // override Init()'s setting to nullptr
} }
void LogMessage::Init(const char* file, void LogMessage::Init(const char* file, int line, LogSeverity severity,
int line,
LogSeverity severity,
void (LogMessage::*send_method)()) { void (LogMessage::*send_method)()) {
allocated_ = nullptr; allocated_ = nullptr;
if (severity != GLOG_FATAL || !exit_on_dfatal) { if (severity != GLOG_FATAL || !exit_on_dfatal) {
@ -1727,8 +1708,7 @@ LogMessage::~LogMessage() {
if (data_ == static_cast<void*>(&thread_msg_data)) { if (data_ == static_cast<void*>(&thread_msg_data)) {
data_->~LogMessageData(); data_->~LogMessageData();
thread_data_available = true; thread_data_available = true;
} } else {
else {
delete allocated_; delete allocated_;
} }
#else // !defined(GLOG_THREAD_LOCAL_STORAGE) #else // !defined(GLOG_THREAD_LOCAL_STORAGE)
@ -1736,13 +1716,9 @@ LogMessage::~LogMessage() {
#endif // defined(GLOG_THREAD_LOCAL_STORAGE) #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
} }
int LogMessage::preserved_errno() const { int LogMessage::preserved_errno() const { return data_->preserved_errno_; }
return data_->preserved_errno_;
}
ostream& LogMessage::stream() { ostream& LogMessage::stream() { return data_->stream_; }
return data_->stream_;
}
// Flush buffered message, called by the destructor, or any other function // Flush buffered message, called by the destructor, or any other function
// that needs to synchronize the log. // that needs to synchronize the log.
@ -1824,12 +1800,14 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
log_mutex.AssertHeld(); log_mutex.AssertHeld();
RAW_DCHECK(data_->num_chars_to_log_ > 0 && RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', ""); data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
"");
// Messages of a given severity get logged to lower severity logs, too // Messages of a given severity get logged to lower severity logs, too
if (!already_warned_before_initgoogle && !IsGoogleLoggingInitialized()) { if (!already_warned_before_initgoogle && !IsGoogleLoggingInitialized()) {
const char w[] = "WARNING: Logging before InitGoogleLogging() is " const char w[] =
"WARNING: Logging before InitGoogleLogging() is "
"written to STDERR\n"; "written to STDERR\n";
WriteToStderr(w, strlen(w)); WriteToStderr(w, strlen(w));
already_warned_before_initgoogle = true; already_warned_before_initgoogle = true;
@ -1848,12 +1826,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
} }
// this could be protected by a flag if necessary. // this could be protected by a flag if necessary.
LogDestination::LogToSinks(data_->severity_, LogDestination::LogToSinks(
data_->fullname_, data_->basename_, data_->severity_, data_->fullname_, data_->basename_, data_->line_,
data_->line_, logmsgtime_, logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
data_->message_text_ + data_->num_prefix_chars_, (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
(data_->num_chars_to_log_ -
data_->num_prefix_chars_ - 1) );
} else { } else {
// log this message to all log files of severity <= severity_ // log this message to all log files of severity <= severity_
LogDestination::LogToAllLogfiles(data_->severity_, logmsgtime_.timestamp(), LogDestination::LogToAllLogfiles(data_->severity_, logmsgtime_.timestamp(),
@ -1865,12 +1841,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
data_->num_prefix_chars_); data_->num_prefix_chars_);
LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_, LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_,
data_->num_chars_to_log_); data_->num_chars_to_log_);
LogDestination::LogToSinks(data_->severity_, LogDestination::LogToSinks(
data_->fullname_, data_->basename_, data_->severity_, data_->fullname_, data_->basename_, data_->line_,
data_->line_, logmsgtime_, logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
data_->message_text_ + data_->num_prefix_chars_, (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
(data_->num_chars_to_log_
- data_->num_prefix_chars_ - 1) );
// NOTE: -1 removes trailing \n // NOTE: -1 removes trailing \n
} }
@ -1885,8 +1859,8 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
SetCrashReason(&crash_reason); SetCrashReason(&crash_reason);
// Store shortened fatal message for other logs and GWQ status // Store shortened fatal message for other logs and GWQ status
const size_t copy = min(data_->num_chars_to_log_, const size_t copy =
sizeof(fatal_message)-1); min(data_->num_chars_to_log_, sizeof(fatal_message) - 1);
memcpy(fatal_message, data_->message_text_, copy); memcpy(fatal_message, data_->message_text_, copy);
fatal_message[copy] = '\0'; fatal_message[copy] = '\0';
fatal_time = logmsgtime_.timestamp(); fatal_time = logmsgtime_.timestamp();
@ -1955,20 +1929,18 @@ void InstallFailureFunction(logging_fail_func_t fail_func) {
g_logging_fail_func = fail_func; g_logging_fail_func = fail_func;
} }
void LogMessage::Fail() { void LogMessage::Fail() { g_logging_fail_func(); }
g_logging_fail_func();
}
// L >= log_mutex (callers must hold the log_mutex). // L >= log_mutex (callers must hold the log_mutex).
void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) { void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->sink_ != nullptr) { if (data_->sink_ != nullptr) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 && RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', ""); data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_, "");
data_->line_, logmsgtime_, data_->sink_->send(
data_->message_text_ + data_->num_prefix_chars_, data_->severity_, data_->fullname_, data_->basename_, data_->line_,
(data_->num_chars_to_log_ - logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
data_->num_prefix_chars_ - 1) ); (data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
} }
} }
@ -1982,7 +1954,8 @@ void LogMessage::SendToSinkAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) { void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->outvec_ != nullptr) { if (data_->outvec_ != nullptr) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 && RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', ""); data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
"");
// Omit prefix of message and trailing newline when recording in outvec_. // Omit prefix of message and trailing newline when recording in outvec_.
const char* start = data_->message_text_ + data_->num_prefix_chars_; const char* start = data_->message_text_ + data_->num_prefix_chars_;
size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1; size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
@ -1995,7 +1968,8 @@ void LogMessage::SaveOrSendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) { void LogMessage::WriteToStringAndLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
if (data_->message_ != nullptr) { if (data_->message_ != nullptr) {
RAW_DCHECK(data_->num_chars_to_log_ > 0 && RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
data_->message_text_[data_->num_chars_to_log_-1] == '\n', ""); data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
"");
// Omit prefix of message and trailing newline when writing to message_. // Omit prefix of message and trailing newline when writing to message_.
const char* start = data_->message_text_ + data_->num_prefix_chars_; const char* start = data_->message_text_ + data_->num_prefix_chars_;
size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1; size_t len = data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1;
@ -2011,8 +1985,7 @@ void LogMessage::SendToSyslogAndLog() {
static bool openlog_already_called = false; static bool openlog_already_called = false;
if (!openlog_already_called) { if (!openlog_already_called) {
openlog(glog_internal_namespace_::ProgramInvocationShortName(), openlog(glog_internal_namespace_::ProgramInvocationShortName(),
LOG_CONS | LOG_NDELAY | LOG_PID, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
LOG_USER);
openlog_already_called = true; openlog_already_called = true;
} }
@ -2065,8 +2038,8 @@ ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
ErrnoLogMessage::~ErrnoLogMessage() { ErrnoLogMessage::~ErrnoLogMessage() {
// Don't access errno directly because it may have been altered // Don't access errno directly because it may have been altered
// while streaming the message. // while streaming the message.
stream() << ": " << StrError(preserved_errno()) << " [" stream() << ": " << StrError(preserved_errno()) << " [" << preserved_errno()
<< preserved_errno() << "]"; << "]";
} }
void FlushLogFiles(LogSeverity min_severity) { void FlushLogFiles(LogSeverity min_severity) {
@ -2133,17 +2106,11 @@ string LogSink::ToString(LogSeverity severity, const char* file, int line,
if (FLAGS_log_year_in_prefix) { if (FLAGS_log_year_in_prefix) {
stream << setw(4) << 1900 + logmsgtime.year(); stream << setw(4) << 1900 + logmsgtime.year();
} }
stream << setw(2) << 1 + logmsgtime.month() stream << setw(2) << 1 + logmsgtime.month() << setw(2) << logmsgtime.day()
<< setw(2) << logmsgtime.day() << ' ' << setw(2) << logmsgtime.hour() << ':' << setw(2)
<< ' ' << logmsgtime.min() << ':' << setw(2) << logmsgtime.sec() << '.'
<< setw(2) << logmsgtime.hour() << ':' << setw(6) << logmsgtime.usec() << ' ' << setfill(' ') << setw(5)
<< setw(2) << logmsgtime.min() << ':' << GetTID() << setfill('0') << ' ' << file << ':' << line << "] ";
<< setw(2) << logmsgtime.sec() << '.'
<< setw(6) << logmsgtime.usec()
<< ' '
<< setfill(' ') << setw(5) << GetTID() << setfill('0')
<< ' '
<< file << ':' << line << "] ";
// A call to `write' is enclosed in parenthneses to prevent possible macro // A call to `write' is enclosed in parenthneses to prevent possible macro
// expansion. On Windows, `write' could be a macro defined for portability. // expansion. On Windows, `write' could be a macro defined for portability.
@ -2171,9 +2138,7 @@ void SetEmailLogging(LogSeverity min_severity, const char* addresses) {
LogDestination::SetEmailLogging(min_severity, addresses); LogDestination::SetEmailLogging(min_severity, addresses);
} }
void LogToStderr() { void LogToStderr() { LogDestination::LogToStderr(); }
LogDestination::LogToStderr();
}
namespace base { namespace base {
namespace internal { namespace internal {
@ -2270,7 +2235,8 @@ static bool SendEmailInternal(const char*dest, const char *subject,
// allow email addresses that start with a special character, such as a // allow email addresses that start with a special character, such as a
// pipe or dash, which could be misunderstood as a command-line flag by // pipe or dash, which could be misunderstood as a command-line flag by
// certain versions of `mail` that are vulnerable to command injection.[2] // certain versions of `mail` that are vulnerable to command injection.[2]
// [1] https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address // [1]
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
// [2] e.g. https://nvd.nist.gov/vuln/detail/CVE-2004-2771 // [2] e.g. https://nvd.nist.gov/vuln/detail/CVE-2004-2771
if (!std::regex_match( if (!std::regex_match(
s, s,
@ -2281,8 +2247,7 @@ static bool SendEmailInternal(const char*dest, const char *subject,
if (use_logging) { if (use_logging) {
VLOG(1) << "Invalid destination email address:" << s; VLOG(1) << "Invalid destination email address:" << s;
} else { } else {
fprintf(stderr, "Invalid destination email address: %s\n", fprintf(stderr, "Invalid destination email address: %s\n", s.c_str());
s.c_str());
} }
return false; return false;
} }
@ -2296,11 +2261,11 @@ static bool SendEmailInternal(const char*dest, const char *subject,
dest = tmp.c_str(); dest = tmp.c_str();
if (use_logging) { if (use_logging) {
VLOG(1) << "Trying to send TITLE:" << subject VLOG(1) << "Trying to send TITLE:" << subject << " BODY:" << body
<< " BODY:" << body << " to " << dest; << " to " << dest;
} else { } else {
fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n", fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n", subject,
subject, body, dest); body, dest);
} }
string logmailer; string logmailer;
@ -2330,8 +2295,8 @@ static bool SendEmailInternal(const char*dest, const char *subject,
LOG(ERROR) << "Problems sending mail to " << dest << ": " LOG(ERROR) << "Problems sending mail to " << dest << ": "
<< StrError(errno); << StrError(errno);
} else { } else {
fprintf(stderr, "Problems sending mail to %s: %s\n", fprintf(stderr, "Problems sending mail to %s: %s\n", dest,
dest, StrError(errno).c_str()); StrError(errno).c_str());
} }
} }
return ok; return ok;
@ -2367,8 +2332,7 @@ static void GetTempDirectories(vector<string>* list) {
// C:/WINDOWS/ or C:/WINNT/ // C:/WINDOWS/ or C:/WINNT/
// . // .
char tmp[MAX_PATH]; char tmp[MAX_PATH];
if (GetTempPathA(MAX_PATH, tmp)) if (GetTempPathA(MAX_PATH, tmp)) list->push_back(tmp);
list->push_back(tmp);
list->push_back("C:\\tmp\\"); list->push_back("C:\\tmp\\");
list->push_back("C:\\temp\\"); list->push_back("C:\\temp\\");
#else #else
@ -2379,7 +2343,8 @@ static void GetTempDirectories(vector<string>* list) {
getenv("TEST_TMPDIR"), getenv("TEST_TMPDIR"),
// Explicitly-supplied temp dirs // Explicitly-supplied temp dirs
getenv("TMPDIR"), getenv("TMP"), getenv("TMPDIR"),
getenv("TMP"),
// If all else fails // If all else fails
"/tmp", "/tmp",
@ -2414,7 +2379,8 @@ const vector<string>& GetLoggingDirectories() {
if (!FLAGS_log_dir.empty()) { if (!FLAGS_log_dir.empty()) {
// Ensure the specified path ends with a directory delimiter. // Ensure the specified path ends with a directory delimiter.
if (std::find(std::begin(possible_dir_delim), std::end(possible_dir_delim), if (std::find(std::begin(possible_dir_delim),
std::end(possible_dir_delim),
FLAGS_log_dir.back()) == std::end(possible_dir_delim)) { FLAGS_log_dir.back()) == std::end(possible_dir_delim)) {
logging_directories_list->push_back(FLAGS_log_dir + "/"); logging_directories_list->push_back(FLAGS_log_dir + "/");
} else { } else {
@ -2436,7 +2402,8 @@ const vector<string>& GetLoggingDirectories() {
} }
void TestOnly_ClearLoggingDirectoriesList() { void TestOnly_ClearLoggingDirectoriesList() {
fprintf(stderr, "TestOnly_ClearLoggingDirectoriesList should only be " fprintf(stderr,
"TestOnly_ClearLoggingDirectoriesList should only be "
"called from test code.\n"); "called from test code.\n");
delete logging_directories_list; delete logging_directories_list;
logging_directories_list = nullptr; logging_directories_list = nullptr;
@ -2553,7 +2520,6 @@ void TruncateStdoutStderr() {
#endif #endif
} }
// Helper functions for string comparisons. // Helper functions for string comparisons.
#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
string* Check##func##expected##Impl(const char* s1, const char* s2, \ string* Check##func##expected##Impl(const char* s1, const char* s2, \
@ -2613,7 +2579,8 @@ int posix_strerror_r(int err, char *buf, size_t len) {
return 0; return 0;
} else { } else {
buf[0] = '\000'; buf[0] = '\000';
#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD) #if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || \
defined(GLOG_OS_OPENBSD)
if (reinterpret_cast<intptr_t>(rc) < sys_nerr) { if (reinterpret_cast<intptr_t>(rc) < sys_nerr) {
// This means an error on MacOSX or FreeBSD. // This means an error on MacOSX or FreeBSD.
return -1; return -1;
@ -2634,12 +2601,12 @@ string StrError(int err) {
return buf; return buf;
} }
LogMessageFatal::LogMessageFatal(const char* file, int line) : LogMessageFatal::LogMessageFatal(const char* file, int line)
LogMessage(file, line, GLOG_FATAL) {} : LogMessage(file, line, GLOG_FATAL) {}
LogMessageFatal::LogMessageFatal(const char* file, int line, LogMessageFatal::LogMessageFatal(const char* file, int line,
const CheckOpString& result) : const CheckOpString& result)
LogMessage(file, line, result) {} : LogMessage(file, line, result) {}
LogMessageFatal::~LogMessageFatal() { LogMessageFatal::~LogMessageFatal() {
Flush(); Flush();
@ -2653,9 +2620,7 @@ CheckOpMessageBuilder::CheckOpMessageBuilder(const char *exprtext)
*stream_ << exprtext << " ("; *stream_ << exprtext << " (";
} }
CheckOpMessageBuilder::~CheckOpMessageBuilder() { CheckOpMessageBuilder::~CheckOpMessageBuilder() { delete stream_; }
delete stream_;
}
ostream* CheckOpMessageBuilder::ForVar2() { ostream* CheckOpMessageBuilder::ForVar2() {
*stream_ << " vs. "; *stream_ << " vs. ";
@ -2705,8 +2670,7 @@ void InitGoogleLogging(const char* argv0) {
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0); glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
} }
void InitGoogleLogging(const char* argv0, void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback,
CustomPrefixCallback prefix_callback,
void* prefix_callback_data) { void* prefix_callback_data) {
custom_prefix_callback = prefix_callback; custom_prefix_callback = prefix_callback;
custom_prefix_callback_data = prefix_callback_data; custom_prefix_callback_data = prefix_callback_data;
@ -2724,9 +2688,7 @@ void EnableLogCleaner(unsigned int overdue_days) {
log_cleaner.Enable(overdue_days); log_cleaner.Enable(overdue_days);
} }
void DisableLogCleaner() { void DisableLogCleaner() { log_cleaner.Disable(); }
log_cleaner.Disable();
}
LogMessageTime::LogMessageTime() LogMessageTime::LogMessageTime()
: time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {} : time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
@ -2769,8 +2731,10 @@ void LogMessageTime::CalcGmtOffset() {
time_t gmt_sec = mktime(&gmt_struct); time_t gmt_sec = mktime(&gmt_struct);
const long hour_secs = 3600; const long hour_secs = 3600;
// If the Daylight Saving Time(isDst) is active subtract an hour from the current timestamp. // If the Daylight Saving Time(isDst) is active subtract an hour from the
gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0) ) ; // current timestamp.
gmtoffset_ =
static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
} }
} // namespace google } // namespace google

View File

@ -29,10 +29,10 @@
// //
// Author: Ray Sidney // Author: Ray Sidney
#include <fcntl.h>
#include "config.h" #include "config.h"
#include "utilities.h" #include "utilities.h"
#include <fcntl.h>
#ifdef HAVE_GLOB_H #ifdef HAVE_GLOB_H
# include <glob.h> # include <glob.h>
#endif #endif
@ -69,6 +69,7 @@ using namespace GFLAGS_NAMESPACE;
#ifdef HAVE_LIB_GMOCK #ifdef HAVE_LIB_GMOCK
# include <gmock/gmock.h> # include <gmock/gmock.h>
# include "mock-log.h" # include "mock-log.h"
// Introduce several symbols from gmock. // Introduce several symbols from gmock.
using google::glog_testing::ScopedMockLog; using google::glog_testing::ScopedMockLog;
@ -132,7 +133,8 @@ static void BM_Check1(int n) {
} }
BENCHMARK(BM_Check1) BENCHMARK(BM_Check1)
static void CheckFailure(int a, int b, const char* file, int line, const char* msg); static void CheckFailure(int a, int b, const char* file, int line,
const char* msg);
static void BM_Check3(int n) { static void BM_Check3(int n) {
while (n-- > 0) { while (n-- > 0) {
if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x"); if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
@ -165,8 +167,7 @@ static void BM_Check2(int n) {
BENCHMARK(BM_Check2) BENCHMARK(BM_Check2)
static void CheckFailure(int, int, const char* /* file */, int /* line */, static void CheckFailure(int, int, const char* /* file */, int /* line */,
const char* /* msg */) { const char* /* msg */) {}
}
static void BM_logspeed(int n) { static void BM_logspeed(int n) {
while (n-- > 0) { while (n-- > 0) {
@ -182,7 +183,8 @@ static void BM_vlog(int n) {
} }
BENCHMARK(BM_vlog) BENCHMARK(BM_vlog)
// Dynamically generate a prefix using the default format and write it to the stream. // Dynamically generate a prefix using the default format and write it to the
// stream.
void PrefixAttacher(std::ostream& s, const LogMessageInfo& l, void* data) { void PrefixAttacher(std::ostream& s, const LogMessageInfo& l, void* data) {
// Assert that `data` contains the expected contents before producing the // Assert that `data` contains the expected contents before producing the
// prefix (otherwise causing the tests to fail): // prefix (otherwise causing the tests to fail):
@ -190,20 +192,12 @@ void PrefixAttacher(std::ostream &s, const LogMessageInfo &l, void* data) {
return; return;
} }
s << l.severity[0] s << l.severity[0] << setw(4) << 1900 + l.time.year() << setw(2)
<< setw(4) << 1900 + l.time.year() << 1 + l.time.month() << setw(2) << l.time.day() << ' ' << setw(2)
<< setw(2) << 1 + l.time.month() << l.time.hour() << ':' << setw(2) << l.time.min() << ':' << setw(2)
<< setw(2) << l.time.day() << l.time.sec() << "." << setw(6) << l.time.usec() << ' ' << setfill(' ')
<< ' ' << setw(5) << l.thread_id << setfill('0') << ' ' << l.filename << ':'
<< setw(2) << l.time.hour() << ':' << l.line_number << "]";
<< 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) { int main(int argc, char** argv) {
@ -216,8 +210,8 @@ int main(int argc, char **argv) {
// Test some basics before InitGoogleLogging: // Test some basics before InitGoogleLogging:
CaptureTestStderr(); CaptureTestStderr();
LogWithLevels(FLAGS_v, FLAGS_stderrthreshold, LogWithLevels(FLAGS_v, FLAGS_stderrthreshold, FLAGS_logtostderr,
FLAGS_logtostderr, FLAGS_alsologtostderr); FLAGS_alsologtostderr);
LogWithLevels(0, 0, false, false); // simulate "before global c-tors" LogWithLevels(0, 0, false, false); // simulate "before global c-tors"
const string early_stderr = GetCapturedTestStderr(); const string early_stderr = GetCapturedTestStderr();
@ -226,7 +220,8 @@ int main(int argc, char **argv) {
// Setting a custom prefix generator (it will use the default format so that // Setting a custom prefix generator (it will use the default format so that
// the golden outputs can be reused): // the golden outputs can be reused):
string prefix_attacher_data = "good data"; string prefix_attacher_data = "good data";
InitGoogleLogging(argv[0], &PrefixAttacher, static_cast<void*>(&prefix_attacher_data)); InitGoogleLogging(argv[0], &PrefixAttacher,
static_cast<void*>(&prefix_attacher_data));
EXPECT_TRUE(IsGoogleLoggingInitialized()); EXPECT_TRUE(IsGoogleLoggingInitialized());
@ -249,7 +244,8 @@ int main(int argc, char **argv) {
CaptureTestStderr(); CaptureTestStderr();
// re-emit early_stderr // re-emit early_stderr
LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr; LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
<< early_stderr;
TestLogging(true); TestLogging(true);
TestRawLogging(); TestRawLogging();
@ -341,7 +337,8 @@ void TestLogging(bool check_counts) {
LOG(ERROR) << "inner"; LOG(ERROR) << "inner";
} }
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix"; LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
<< "no prefix";
if (check_counts) { if (check_counts) {
CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO)); CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO));
@ -350,23 +347,17 @@ void TestLogging(bool check_counts) {
} }
} }
static void NoAllocNewHook() { static void NoAllocNewHook() { LOG(FATAL) << "unexpected new"; }
LOG(FATAL) << "unexpected new";
}
struct NewHook { struct NewHook {
NewHook() { NewHook() { g_new_hook = &NoAllocNewHook; }
g_new_hook = &NoAllocNewHook;
}
~NewHook() { g_new_hook = nullptr; } ~NewHook() { g_new_hook = nullptr; }
}; };
TEST(DeathNoAllocNewHook, logging) { TEST(DeathNoAllocNewHook, logging) {
// tests that NewHook used below works // tests that NewHook used below works
NewHook new_hook; NewHook new_hook;
ASSERT_DEATH({ ASSERT_DEATH({ new int; }, "unexpected new");
new int;
}, "unexpected new");
} }
void TestRawLogging() { void TestRawLogging() {
@ -425,8 +416,8 @@ void TestRawLogging() {
void LogWithLevels(int v, int severity, bool err, bool alsoerr) { void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
RAW_LOG(INFO, RAW_LOG(INFO,
"Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d", "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d", v,
v, severity, err, alsoerr); severity, err, alsoerr);
FlagSaver saver; FlagSaver saver;
@ -463,28 +454,48 @@ void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
LOG_IF(ERROR, false) << "don't log_if error"; LOG_IF(ERROR, false) << "don't log_if error";
int c; int c;
c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1); c = 1;
c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1); VLOG_IF(100, c -= 2) << "vlog_if 100 expr";
c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1); c = 1;
c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0); VLOG_IF(0, c -= 2) << "vlog_if 0 expr";
c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0); 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"; c = 3;
LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr"; c = 3;
LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr"; c = 4;
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr"; c = 4;
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr"; c = 5;
VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
EXPECT_EQ(c, 1); EXPECT_EQ(c, 1);
c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr"; c = 5;
VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
EXPECT_EQ(c, 1); EXPECT_EQ(c, 1);
c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr"; c = 6;
VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr"; c = 6;
VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
} }
@ -530,12 +541,17 @@ void TestLogString() {
vector<string> errors; vector<string> errors;
vector<string>* no_errors = nullptr; vector<string>* no_errors = nullptr;
LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info"; LOG_STRING(INFO, &errors) << "LOG_STRING: "
LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning"; << "collected info";
LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error"; 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(INFO, no_errors) << "LOG_STRING: "
LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning"; << "reported info";
LOG_STRING(WARNING, no_errors) << "LOG_STRING: "
<< "reported warning";
LOG_STRING(ERROR, nullptr) << "LOG_STRING: " LOG_STRING(ERROR, nullptr) << "LOG_STRING: "
<< "reported error"; << "reported error";
@ -548,15 +564,20 @@ void TestLogToString() {
string error; string error;
string* no_error = nullptr; string* no_error = nullptr;
LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info"; LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: "
<< "collected info";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning"; LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: "
<< "collected warning";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error"; LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: "
<< "collected error";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info"; LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: "
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning"; << "reported info";
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: "
<< "reported warning";
LOG_TO_STRING(ERROR, nullptr) << "LOG_TO_STRING: " LOG_TO_STRING(ERROR, nullptr) << "LOG_TO_STRING: "
<< "reported error"; << "reported error";
} }
@ -568,8 +589,8 @@ class TestLogSinkImpl : public LogSink {
const char* base_filename, int line, const char* base_filename, int line,
const LogMessageTime& logmsgtime, const char* message, const LogMessageTime& logmsgtime, const char* message,
size_t message_len) override { size_t message_len) override {
errors.push_back( errors.push_back(ToString(severity, base_filename, line, logmsgtime,
ToString(severity, base_filename, line, logmsgtime, message, message_len)); message, message_len));
} }
}; };
@ -577,26 +598,36 @@ void TestLogSink() {
TestLogSinkImpl sink; TestLogSinkImpl sink;
LogSink* no_sink = nullptr; LogSink* no_sink = nullptr;
LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info"; LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: "
LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning"; << "collected info";
LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error"; 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, INFO) << "LOG_TO_SINK: "
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning"; << "reported info";
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: "
<< "reported warning";
LOG_TO_SINK(nullptr, ERROR) << "LOG_TO_SINK: " LOG_TO_SINK(nullptr, ERROR) << "LOG_TO_SINK: "
<< "reported error"; << "reported error";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO) 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: "
<< "collected info";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING) 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: "
<< "collected warning";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR) 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: "
<< "collected error";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO) 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: "
<< "thrashed info";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING) 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: "
<< "thrashed warning";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(nullptr, ERROR) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(nullptr, ERROR)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "thrashed error"; << "thrashed error";
@ -608,10 +639,7 @@ void TestLogSink() {
} }
// For testing using CHECK*() on anonymous enums. // For testing using CHECK*() on anonymous enums.
enum { enum { CASE_A, CASE_B };
CASE_A,
CASE_B
};
void TestCHECK() { void TestCHECK() {
// Tests using CHECK*() on int values. // Tests using CHECK*() on int values.
@ -669,8 +697,7 @@ void TestSTREQ() {
CHECK_STRCASENE("this", "that"); CHECK_STRCASENE("this", "that");
CHECK_STRCASENE(nullptr, "that"); CHECK_STRCASENE(nullptr, "that");
CHECK_STREQ((string("a") + "b").c_str(), "ab"); CHECK_STREQ((string("a") + "b").c_str(), "ab");
CHECK_STREQ(string("test").c_str(), CHECK_STREQ(string("test").c_str(), (string("te") + string("st")).c_str());
(string("te") + string("st")).c_str());
} }
TEST(DeathSTREQ, logging) { TEST(DeathSTREQ, logging) {
@ -742,7 +769,8 @@ static void DeleteFiles(const string& pattern) {
} }
// check string is in file (or is *NOT*, depending on optional checkInFileOrNot) // 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) { static void CheckFile(const string& name, const string& expected_string,
const bool checkInFileOrNot = true) {
vector<string> files; vector<string> files;
GetFiles(name + "*", &files); GetFiles(name + "*", &files);
CHECK_EQ(files.size(), 1UL); CHECK_EQ(files.size(), 1UL);
@ -760,7 +788,8 @@ static void CheckFile(const string& name, const string& expected_string, const b
} }
} }
fclose(file); fclose(file);
LOG(FATAL) << "Did " << (checkInFileOrNot? "not " : "") << "find " << expected_string << " in " << files[0]; LOG(FATAL) << "Did " << (checkInFileOrNot ? "not " : "") << "find "
<< expected_string << " in " << files[0];
} }
static void TestBasename() { static void TestBasename() {
@ -780,8 +809,11 @@ static void TestBasename() {
} }
static void TestBasenameAppendWhenNoTimestamp() { static void TestBasenameAppendWhenNoTimestamp() {
fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n"); fprintf(stderr,
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp"; "==== 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 + "*"); DeleteFiles(dest + "*");
ofstream out(dest.c_str()); ofstream out(dest.c_str());
@ -806,10 +838,14 @@ static void TestBasenameAppendWhenNoTimestamp() {
} }
static void TestTwoProcessesWrite() { static void TestTwoProcessesWrite() {
// test only implemented for platforms with fork & wait; the actual implementation relies on flock // 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) #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"); fprintf(stderr,
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing"; "==== 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 + "*"); DeleteFiles(dest + "*");
// make both processes write into the same file (easier test) // make both processes write into the same file (easier test)
@ -821,7 +857,8 @@ static void TestTwoProcessesWrite() {
pid_t pid = fork(); pid_t pid = fork();
CHECK_ERR(pid); CHECK_ERR(pid);
if (pid == 0) { if (pid == 0) {
LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file"; LOG(INFO) << "message to new base, child - should only appear on STDERR "
"not on the file";
ShutdownGoogleLogging(); // for children proc ShutdownGoogleLogging(); // for children proc
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (pid > 0) { } else if (pid > 0) {
@ -830,7 +867,10 @@ static void TestTwoProcessesWrite() {
FLAGS_timestamp_in_logfile_name = true; FLAGS_timestamp_in_logfile_name = true;
CheckFile(dest, "message to new base, parent"); CheckFile(dest, "message to new base, parent");
CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false); CheckFile(dest,
"message to new base, child - should only appear on STDERR not on "
"the file",
false);
// Release // Release
LogToStderr(); LogToStderr();
@ -1014,11 +1054,9 @@ static void TestTruncate() {
} }
struct RecordDeletionLogger : public base::Logger { struct RecordDeletionLogger : public base::Logger {
RecordDeletionLogger(bool* set_on_destruction, RecordDeletionLogger(bool* set_on_destruction, base::Logger* wrapped_logger)
base::Logger* wrapped_logger) : : set_on_destruction_(set_on_destruction),
set_on_destruction_(set_on_destruction), wrapped_logger_(wrapped_logger) {
wrapped_logger_(wrapped_logger)
{
*set_on_destruction_ = false; *set_on_destruction_ = false;
} }
~RecordDeletionLogger() override { *set_on_destruction_ = true; } ~RecordDeletionLogger() override { *set_on_destruction_ = true; }
@ -1095,8 +1133,8 @@ static void TestLogPeriodically() {
// minimize error. // minimize error.
int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1]; int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1];
for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) { for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) {
nsBetweenCalls[i - 1] = elapsedTime_ns( nsBetweenCalls[i - 1] = elapsedTime_ns(timeLogger.m_callTimes[i - 1],
timeLogger.m_callTimes[i - 1], timeLogger.m_callTimes[i]); timeLogger.m_callTimes[i]);
} }
for (long time_ns : nsBetweenCalls) { for (long time_ns : nsBetweenCalls) {
@ -1107,8 +1145,9 @@ static void TestLogPeriodically() {
namespace google { namespace google {
namespace glog_internal_namespace_ { namespace glog_internal_namespace_ {
extern // in logging.cc extern // in logging.cc
bool SafeFNMatch_(const char* pattern, size_t patt_len, bool
const char* str, size_t str_len); SafeFNMatch_(const char* pattern, size_t patt_len, const char* str,
size_t str_len);
} // namespace glog_internal_namespace_ } // namespace glog_internal_namespace_
using glog_internal_namespace_::SafeFNMatch_; using glog_internal_namespace_::SafeFNMatch_;
} // namespace google } // namespace google
@ -1116,8 +1155,8 @@ using glog_internal_namespace_::SafeFNMatch_;
static bool WrapSafeFNMatch(string pattern, string str) { static bool WrapSafeFNMatch(string pattern, string str) {
pattern += "abc"; pattern += "abc";
str += "defgh"; str += "defgh";
return SafeFNMatch_(pattern.data(), pattern.size() - 3, return SafeFNMatch_(pattern.data(), pattern.size() - 3, str.data(),
str.data(), str.size() - 5); str.size() - 5);
} }
TEST(SafeFNMatch, logging) { TEST(SafeFNMatch, logging) {
@ -1184,7 +1223,6 @@ class TestLogSinkWriter : public Thread {
} }
private: private:
// helpers --------------- // helpers ---------------
// For creating a "Condition". // For creating a "Condition".
@ -1239,7 +1277,6 @@ class TestLogSinkWriter : public Thread {
// (that other thread can than use LOG() itself), // (that other thread can than use LOG() itself),
class TestWaitingLogSink : public LogSink { class TestWaitingLogSink : public LogSink {
public: public:
TestWaitingLogSink() { TestWaitingLogSink() {
tid_ = pthread_self(); // for thread-specific behavior tid_ = pthread_self(); // for thread-specific behavior
AddLogSink(this); AddLogSink(this);
@ -1260,8 +1297,8 @@ class TestWaitingLogSink : public LogSink {
// Note: Something like ThreadLocalLogSink is a better choice // Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real. // to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) { if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line, writer_.Buffer(ToString(severity, base_filename, line, logmsgtime,
logmsgtime, message, message_len)); message, message_len));
} }
} }
@ -1271,7 +1308,6 @@ class TestWaitingLogSink : public LogSink {
} }
private: private:
pthread_t tid_; pthread_t tid_;
TestLogSinkWriter writer_; TestLogSinkWriter writer_;
}; };
@ -1282,7 +1318,8 @@ static void TestLogSinkWaitTillSent() {
// Clear global_messages here to make sure that this test case can be // Clear global_messages here to make sure that this test case can be
// reentered // reentered
global_messages.clear(); global_messages.clear();
{ TestWaitingLogSink sink; {
TestWaitingLogSink sink;
// Sleeps give the sink threads time to do all their work, // 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. // so that we get a reliable log capture to compare to the golden file.
LOG(INFO) << "Message 1"; LOG(INFO) << "Message 1";
@ -1308,7 +1345,8 @@ TEST(Strerror, logging) {
CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1); CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
CHECK_EQ(buf[0], 'A'); CHECK_EQ(buf[0], 'A');
CHECK_EQ(posix_strerror_r(errcode, nullptr, buf_size), -1); CHECK_EQ(posix_strerror_r(errcode, nullptr, buf_size), -1);
#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_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 // MacOSX or FreeBSD considers this case is an error since there is
// no enough space. // no enough space.
CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1); CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
@ -1404,9 +1442,8 @@ TEST(TestExitOnDFatal, ToBeOrNotToBe) {
# ifdef GTEST_HAS_DEATH_TEST # ifdef GTEST_HAS_DEATH_TEST
// Death comes on little cats' feet. // Death comes on little cats' feet.
EXPECT_DEBUG_DEATH({ EXPECT_DEBUG_DEATH({ LOG(DFATAL) << "This should be fatal in debug mode"; },
LOG(DFATAL) << "This should be fatal in debug mode"; "This should be fatal in debug mode");
}, "This should be fatal in debug mode");
# endif # endif
} }
@ -1443,10 +1480,10 @@ TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
// the name of the containing function, followed by the log message. // the name of the containing function, followed by the log message.
// We use HasSubstr()s instead of ContainsRegex() for environments // We use HasSubstr()s instead of ContainsRegex() for environments
// which don't have regexp. // which don't have regexp.
EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"), EXPECT_CALL(
HasSubstr("BacktraceAtHelper"), log, Log(_, _,
HasSubstr("main"), AllOf(HasSubstr("stacktrace:"), HasSubstr("BacktraceAtHelper"),
HasSubstr("Backtrace me")))); HasSubstr("main"), HasSubstr("Backtrace me"))));
// Other LOGs should not include a backtrace. // Other LOGs should not include a backtrace.
EXPECT_CALL(log, Log(_, _, "Not me")); EXPECT_CALL(log, Log(_, _, "Not me"));
@ -1480,7 +1517,8 @@ TEST(UserDefinedClass, logging) {
TEST(LogMsgTime, gmtoff) { TEST(LogMsgTime, gmtoff) {
/* /*
* Unit test for GMT offset API * Unit test for GMT offset API
* TODO: To properly test this API, we need a platform independent way to set time-zone. * TODO: To properly test this API, we need a platform independent way to set
* time-zone.
* */ * */
google::LogMessage log_obj(__FILE__, __LINE__); google::LogMessage log_obj(__FILE__, __LINE__);
@ -1495,14 +1533,16 @@ TEST(EmailLogging, ValidAddress) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_TRUE(SendEmail("example@example.com", "Example subject", "Example body")); EXPECT_TRUE(
SendEmail("example@example.com", "Example subject", "Example body"));
} }
TEST(EmailLogging, MultipleAddresses) { TEST(EmailLogging, MultipleAddresses) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_TRUE(SendEmail("example@example.com,foo@bar.com", "Example subject", "Example body")); EXPECT_TRUE(SendEmail("example@example.com,foo@bar.com", "Example subject",
"Example body"));
} }
TEST(EmailLogging, InvalidAddress) { TEST(EmailLogging, InvalidAddress) {
@ -1516,5 +1556,6 @@ TEST(EmailLogging, MaliciousAddress) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_FALSE(SendEmail("!/bin/true@example.com", "Example subject", "Example body")); EXPECT_FALSE(
SendEmail("!/bin/true@example.com", "Example subject", "Example body"));
} }

View File

@ -33,11 +33,11 @@
#include "mock-log.h" #include "mock-log.h"
#include <string>
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <string>
namespace { namespace {
using google::GLOG_ERROR; using google::GLOG_ERROR;
@ -57,8 +57,7 @@ TEST(ScopedMockLogTest, InterceptsLog) {
InSequence s; InSequence s;
EXPECT_CALL(log, EXPECT_CALL(log,
Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy.")); Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy."));
EXPECT_CALL(log, Log(GLOG_INFO, _, "Working...")) EXPECT_CALL(log, Log(GLOG_INFO, _, "Working...")).Times(2);
.Times(2);
EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!")); EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!"));
LOG(WARNING) << "Fishy."; LOG(WARNING) << "Fishy.";
@ -67,13 +66,9 @@ TEST(ScopedMockLogTest, InterceptsLog) {
LOG(ERROR) << "Bad!!"; LOG(ERROR) << "Bad!!";
} }
void LogBranch() { void LogBranch() { LOG(INFO) << "Logging a branch..."; }
LOG(INFO) << "Logging a branch...";
}
void LogTree() { void LogTree() { LOG(INFO) << "Logging the whole tree..."; }
LOG(INFO) << "Logging the whole tree...";
}
void LogForest() { void LogForest() {
LOG(INFO) << "Logging the entire forest."; LOG(INFO) << "Logging the entire forest.";

View File

@ -1,6 +1,3 @@
#include "glog/logging.h" #include "glog/logging.h"
int main(int /*argc*/, char** argv) int main(int /*argc*/, char** argv) { google::InitGoogleLogging(argv[0]); }
{
google::InitGoogleLogging(argv[0]);
}

View File

@ -103,8 +103,8 @@ static bool DoRawLog(char** buf, size_t* size, const char* format, ...) {
} }
// Helper for RawLog__ below. // Helper for RawLog__ below.
inline static bool VADoRawLog(char** buf, size_t* size, inline static bool VADoRawLog(char** buf, size_t* size, const char* format,
const char* format, va_list ap) { va_list ap) {
#if defined(__GNUC__) #if defined(__GNUC__)
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wformat-nonliteral" # pragma GCC diagnostic ignored "-Wformat-nonliteral"
@ -139,8 +139,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// NOTE: this format should match the specification in base/logging.h // NOTE: this format should match the specification in base/logging.h
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ", DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
LogSeverityNames[severity][0], LogSeverityNames[severity][0], static_cast<unsigned int>(GetTID()),
static_cast<unsigned int>(GetTID()),
const_basename(const_cast<char*>(file)), line); const_basename(const_cast<char*>(file)), line);
// Record the position and size of the buffer after the prefix // Record the position and size of the buffer after the prefix

View File

@ -63,10 +63,8 @@ const struct {
int number; int number;
const char* name; const char* name;
} kFailureSignals[] = { } kFailureSignals[] = {
{ SIGSEGV, "SIGSEGV" }, {SIGSEGV, "SIGSEGV"}, {SIGILL, "SIGILL"},
{ SIGILL, "SIGILL" }, {SIGFPE, "SIGFPE"}, {SIGABRT, "SIGABRT"},
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
{SIGBUS, "SIGBUS"}, {SIGBUS, "SIGBUS"},
#endif #endif
@ -78,7 +76,8 @@ static bool kFailureSignalHandlerInstalled = false;
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
// Returns the program counter from signal context, nullptr if unknown. // Returns the program counter from signal context, nullptr if unknown.
void* GetPC(void* ucontext_in_void) { void* GetPC(void* ucontext_in_void) {
#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT) # if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && \
defined(PC_FROM_UCONTEXT)
if (ucontext_in_void != nullptr) { if (ucontext_in_void != nullptr) {
ucontext_t* context = reinterpret_cast<ucontext_t*>(ucontext_in_void); ucontext_t* context = reinterpret_cast<ucontext_t*>(ucontext_in_void);
return (void*)context->PC_FROM_UCONTEXT; return (void*)context->PC_FROM_UCONTEXT;
@ -95,13 +94,12 @@ void* GetPC(void* ucontext_in_void) {
class MinimalFormatter { class MinimalFormatter {
public: public:
MinimalFormatter(char* buffer, size_t size) MinimalFormatter(char* buffer, size_t size)
: buffer_(buffer), : buffer_(buffer), cursor_(buffer), end_(buffer + size) {}
cursor_(buffer),
end_(buffer + size) {
}
// Returns the number of bytes written in the buffer. // Returns the number of bytes written in the buffer.
std::size_t num_bytes_written() const { return static_cast<std::size_t>(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. // Appends string from "str" and updates the internal cursor.
void AppendString(const char* str) { void AppendString(const char* str) {
@ -235,8 +233,8 @@ void DumpStackFrameInfo(const char* prefix, void* pc) {
char symbolized[1024]; // Big enough for a sane symbol. char symbolized[1024]; // Big enough for a sane symbol.
// Symbolizes the previous address of pc because pc may be in the // Symbolizes the previous address of pc because pc may be in the
// next function. // next function.
if (Symbolize(reinterpret_cast<char *>(pc) - 1, if (Symbolize(reinterpret_cast<char*>(pc) - 1, symbolized,
symbolized, sizeof(symbolized))) { sizeof(symbolized))) {
symbol = symbolized; symbol = symbolized;
} }
@ -279,8 +277,7 @@ static pthread_t* g_entered_thread_id_pointer = nullptr;
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
void FailureSignalHandler(int signal_number) void FailureSignalHandler(int signal_number)
#else #else
void FailureSignalHandler(int signal_number, void FailureSignalHandler(int signal_number, siginfo_t* signal_info,
siginfo_t *signal_info,
void* ucontext) void* ucontext)
#endif #endif
{ {
@ -400,8 +397,7 @@ void InstallFailureSignalHandler() {
kFailureSignalHandlerInstalled = true; kFailureSignalHandlerInstalled = true;
#elif defined(GLOG_OS_WINDOWS) #elif defined(GLOG_OS_WINDOWS)
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) { for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler), CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler), SIG_ERR);
SIG_ERR);
} }
kFailureSignalHandlerInstalled = true; kFailureSignalHandlerInstalled = true;
#endif // HAVE_SIGACTION #endif // HAVE_SIGACTION

View File

@ -89,7 +89,8 @@ int main(int argc, char **argv) {
*a = 0; *a = 0;
} else if (command == "loop") { } else if (command == "loop") {
fprintf(stderr, "looping\n"); fprintf(stderr, "looping\n");
while (true); while (true)
;
} else if (command == "die_in_thread") { } else if (command == "die_in_thread") {
# if defined(HAVE_PTHREAD) # if defined(HAVE_PTHREAD)
pthread_t thread; pthread_t thread;

View File

@ -114,7 +114,8 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
result[n++] = *(sp + 2); result[n++] = *(sp + 2);
#elif defined(_CALL_SYSV) #elif defined(_CALL_SYSV)
result[n++] = *(sp + 1); result[n++] = *(sp + 1);
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__)) #elif defined(__APPLE__) || \
((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc. // This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp + 2); result[n++] = *(sp + 2);
#elif defined(__linux) || defined(__OpenBSD__) #elif defined(__linux) || defined(__OpenBSD__)

View File

@ -75,7 +75,10 @@ AddressRange expected_range[BACKTRACE_STEPS];
// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before // (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
// the recursive call. // the recursive call.
# define DECLARE_ADDRESS_LABEL(a_label) \ # define DECLARE_ADDRESS_LABEL(a_label) \
a_label: do { __asm__ __volatile__(""); } while (0) a_label: \
do { \
__asm__ __volatile__(""); \
} while (0)
// Gcc 4.4.0 may split function into multiple chunks, and the chunk // Gcc 4.4.0 may split function into multiple chunks, and the chunk
// performing recursive call may end up later in the code then the return // performing recursive call may end up later in the code then the return
// instruction (this actually happens with FDO). // instruction (this actually happens with FDO).
@ -85,9 +88,8 @@ AddressRange expected_range[BACKTRACE_STEPS];
void* ra = __builtin_return_address(0); \ void* ra = __builtin_return_address(0); \
CHECK_LT((prange)->start, ra); \ CHECK_LT((prange)->start, ra); \
if (ra > (prange)->end) { \ if (ra > (prange)->end) { \
printf("Adjusting range from %p..%p to %p..%p\n", \ printf("Adjusting range from %p..%p to %p..%p\n", (prange)->start, \
(prange)->start, (prange)->end, \ (prange)->end, (prange)->start, ra); \
(prange)->start, ra); \
(prange)->end = ra; \ (prange)->end = ra; \
} \ } \
} while (0) } while (0)
@ -98,14 +100,18 @@ AddressRange expected_range[BACKTRACE_STEPS];
(prange)->start = reinterpret_cast<const void*>(&fn); \ (prange)->start = reinterpret_cast<const void*>(&fn); \
(prange)->end = reinterpret_cast<const char*>(&fn) + 256; \ (prange)->end = reinterpret_cast<const char*>(&fn) + 256; \
} while (0) } while (0)
#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0) # define DECLARE_ADDRESS_LABEL(a_label) \
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0) do { \
} while (0)
# define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
do { \
} while (0)
# endif // __GNUC__ # endif // __GNUC__
//-----------------------------------------------------------------------// //-----------------------------------------------------------------------//
static void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range) static void CheckRetAddrIsInFunction(void* ret_addr,
{ const AddressRange& range) {
CHECK_GE(ret_addr, range.start); CHECK_GE(ret_addr, range.start);
CHECK_LE(ret_addr, range.end); CHECK_LE(ret_addr, range.end);
} }
@ -149,8 +155,8 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
# endif # endif
} }
for (int i = 0; i < BACKTRACE_STEPS; i++) { for (int i = 0; i < BACKTRACE_STEPS; i++) {
printf("Backtrace %d: expected: %p..%p actual: %p ... ", printf("Backtrace %d: expected: %p..%p actual: %p ... ", i,
i, expected_range[i].start, expected_range[i].end, stack[i]); expected_range[i].start, expected_range[i].end, stack[i]);
fflush(stdout); fflush(stdout);
CheckRetAddrIsInFunction(stack[i], expected_range[i]); CheckRetAddrIsInFunction(stack[i], expected_range[i]);
printf("OK\n"); printf("OK\n");
@ -207,7 +213,8 @@ static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
// See https://github.com/google/glog/issues/421 for the detail. // See https://github.com/google/glog/issues/421 for the detail.
static static
# endif # endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) { void ATTRIBUTE_NOINLINE
CheckStackTrace(int i) {
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]); INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
DECLARE_ADDRESS_LABEL(start); DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--) { for (int j = i; j >= 0; j--) {

View File

@ -45,11 +45,11 @@ struct trace_arg_t {
}; };
// Workaround for the malloc() in _Unwind_Backtrace() issue. // 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; return _URC_NO_REASON;
} }
// This code is not considered ready to run until // This code is not considered ready to run until
// static initializers run so that we are guaranteed // static initializers run so that we are guaranteed
// that any malloc-related initialization is done. // that any malloc-related initialization is done.

View File

@ -31,10 +31,11 @@
// //
// Windows implementation - just use CaptureStackBackTrace // Windows implementation - just use CaptureStackBackTrace
#include <dbghelp.h>
#include "config.h" #include "config.h"
#include "port.h" #include "port.h"
#include "stacktrace.h" #include "stacktrace.h"
#include <dbghelp.h>
namespace google { namespace google {

View File

@ -34,8 +34,8 @@
#include "utilities.h" // for OS_* macros #include "utilities.h" // for OS_* macros
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
#include <unistd.h>
# include <sys/mman.h> # include <sys/mman.h>
# include <unistd.h>
#endif #endif
#include <cstdio> // for nullptr #include <cstdio> // for nullptr

View File

@ -56,13 +56,12 @@
#if defined(HAVE_SYMBOLIZE) #if defined(HAVE_SYMBOLIZE)
#include <cstring>
# include <algorithm> # include <algorithm>
# include <cstring>
# include <limits> # include <limits>
#include "symbolize.h"
# include "demangle.h" # include "demangle.h"
# include "symbolize.h"
namespace google { namespace google {
@ -136,7 +135,9 @@ static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size) {
# include "symbolize.h" # include "symbolize.h"
// Re-runs fn until it doesn't cause EINTR. // Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) # define NO_INTR(fn) \
do { \
} while ((fn) < 0 && errno == EINTR)
namespace google { namespace google {
@ -147,7 +148,8 @@ namespace google {
static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count, static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count,
const size_t offset) { const size_t offset) {
SAFE_ASSERT(fd >= 0); SAFE_ASSERT(fd >= 0);
SAFE_ASSERT(count <= static_cast<size_t>(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); char* buf0 = reinterpret_cast<char*>(buf);
size_t num_bytes = 0; size_t num_bytes = 0;
while (num_bytes < count) { while (num_bytes < count) {
@ -170,8 +172,8 @@ static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count,
// pointed by "fd" into the buffer starting at "buf" while handling // pointed by "fd" into the buffer starting at "buf" while handling
// short reads and EINTR. On success, return true. Otherwise, return // short reads and EINTR. On success, return true. Otherwise, return
// false. // false.
static bool ReadFromOffsetExact(const int fd, void *buf, static bool ReadFromOffsetExact(const int fd, void* buf, const size_t count,
const size_t count, const size_t offset) { const size_t offset) {
ssize_t len = ReadFromOffset(fd, buf, count, offset); ssize_t len = ReadFromOffset(fd, buf, count, offset);
return static_cast<size_t>(len) == count; return static_cast<size_t>(len) == count;
} }
@ -193,9 +195,11 @@ static int FileGetElfType(const int fd) {
// and return true. Otherwise, return false. // and return true. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get // To keep stack consumption low, we would like this function to not get
// inlined. // inlined.
static ATTRIBUTE_NOINLINE bool static ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(const int fd,
GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const size_t sh_offset, ElfW(Half) sh_num,
ElfW(Word) type, ElfW(Shdr) *out) { const size_t sh_offset,
ElfW(Word) type,
ElfW(Shdr) * out) {
// Read at most 16 section headers at a time to save read calls. // Read at most 16 section headers at a time to save read calls.
ElfW(Shdr) buf[16]; ElfW(Shdr) buf[16];
for (size_t i = 0; i < sh_num;) { for (size_t i = 0; i < sh_num;) {
@ -242,8 +246,8 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
} }
for (size_t i = 0; i < elf_header.e_shnum; ++i) { for (size_t i = 0; i < elf_header.e_shnum; ++i) {
size_t section_header_offset = (elf_header.e_shoff + size_t section_header_offset =
elf_header.e_shentsize * i); (elf_header.e_shoff + elf_header.e_shentsize * i);
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) { if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
return false; return false;
} }
@ -277,9 +281,10 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
// to out. Otherwise, return false. // to out. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get // To keep stack consumption low, we would like this function to not get
// inlined. // inlined.
static ATTRIBUTE_NOINLINE bool static ATTRIBUTE_NOINLINE bool FindSymbol(uint64_t pc, const int fd, char* out,
FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size, size_t out_size,
uint64_t symbol_offset, const ElfW(Shdr) *strtab, uint64_t symbol_offset,
const ElfW(Shdr) * strtab,
const ElfW(Shdr) * symtab) { const ElfW(Shdr) * symtab) {
if (symtab == nullptr) { if (symtab == nullptr) {
return false; return false;
@ -331,11 +336,8 @@ FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size,
// both regular and dynamic symbol tables if necessary. On success, // both regular and dynamic symbol tables if necessary. On success,
// write the symbol name to "out" and return true. Otherwise, return // write the symbol name to "out" and return true. Otherwise, return
// false. // false.
static bool GetSymbolFromObjectFile(const int fd, static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, char* out,
uint64_t pc, size_t out_size, uint64_t base_address) {
char* out,
size_t out_size,
uint64_t base_address) {
// Read the ELF header. // Read the ELF header.
ElfW(Ehdr) elf_header; ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@ -347,8 +349,9 @@ static bool GetSymbolFromObjectFile(const int fd,
// Consult a regular symbol table first. // Consult a regular symbol table first.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_SYMTAB, &symtab)) { SHT_SYMTAB, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + if (!ReadFromOffsetExact(
symtab.sh_link * sizeof(symtab))) { fd, &strtab, sizeof(strtab),
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
return false; return false;
} }
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) { if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
@ -359,8 +362,9 @@ static bool GetSymbolFromObjectFile(const int fd,
// If the symbol is not found, then consult a dynamic symbol table. // If the symbol is not found, then consult a dynamic symbol table.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_DYNSYM, &symtab)) { SHT_DYNSYM, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + if (!ReadFromOffsetExact(
symtab.sh_link * sizeof(symtab))) { fd, &strtab, sizeof(strtab),
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
return false; return false;
} }
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) { if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
@ -451,26 +455,21 @@ class LineReader {
} }
// Beginning of line. // Beginning of line.
const char *bol() { const char* bol() { return bol_; }
return bol_;
}
// End of line. // End of line.
const char *eol() { const char* eol() { return eol_; }
return eol_;
}
private: private:
LineReader(const LineReader&) = delete; LineReader(const LineReader&) = delete;
void operator=(const LineReader&) = delete; void operator=(const LineReader&) = delete;
char* FindLineFeed() { char* FindLineFeed() {
return reinterpret_cast<char *>(memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_))); return reinterpret_cast<char*>(
memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_)));
} }
bool BufferIsEmpty() { bool BufferIsEmpty() { return buf_ == eod_; }
return buf_ == eod_;
}
bool HasCompleteLine() { bool HasCompleteLine() {
return !BufferIsEmpty() && FindLineFeed() != nullptr; return !BufferIsEmpty() && FindLineFeed() != nullptr;
@ -493,9 +492,10 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
const char* p; const char* p;
for (p = start; p < end; ++p) { for (p = start; p < end; ++p) {
int ch = *p; int ch = *p;
if ((ch >= '0' && ch <= '9') || if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { (ch >= 'a' && ch <= 'f')) {
*hex = (*hex << 4U) | (ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U); *hex = (*hex << 4U) |
(ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U);
} else { // Encountered the first non-hex character. } else { // Encountered the first non-hex character.
break; break;
} }
@ -512,12 +512,9 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
// file is opened successfully, returns the file descriptor. Otherwise, // file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer // returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator). // (including the null-terminator).
static ATTRIBUTE_NOINLINE int static ATTRIBUTE_NOINLINE int OpenObjectFileContainingPcAndGetStartAddress(
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, uint64_t pc, uint64_t& start_address, uint64_t& base_address,
uint64_t &start_address, char* out_file_name, size_t out_file_name_size) {
uint64_t &base_address,
char *out_file_name,
size_t out_file_name_size) {
int object_fd; int object_fd;
int maps_fd; int maps_fd;
@ -672,7 +669,8 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// "sz" bytes. Output will be truncated as needed, and a NUL character is always // "sz" bytes. Output will be truncated as needed, and a NUL character is always
// appended. // appended.
// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
static char *itoa_r(uintptr_t i, char *buf, size_t sz, unsigned 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. // Make sure we can write at least one NUL byte.
size_t n = 1; size_t n = 1;
if (n > sz) { if (n > sz) {
@ -763,14 +761,11 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
SafeAppendString("(", out, out_size); SafeAppendString("(", out, out_size);
if (g_symbolize_open_object_file_callback) { if (g_symbolize_open_object_file_callback) {
object_fd = g_symbolize_open_object_file_callback(pc0, start_address, object_fd = g_symbolize_open_object_file_callback(
base_address, out + 1, pc0, start_address, base_address, out + 1, out_size - 1);
out_size - 1);
} else { } else {
object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address, object_fd = OpenObjectFileContainingPcAndGetStartAddress(
base_address, pc0, start_address, base_address, out + 1, out_size - 1);
out + 1,
out_size - 1);
} }
FileDescriptor wrapped_object_fd(object_fd); FileDescriptor wrapped_object_fd(object_fd);
@ -804,16 +799,15 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
// Note: relocation (and much of the rest of this code) will be // Note: relocation (and much of the rest of this code) will be
// wrong for prelinked shared libraries and PIE executables. // wrong for prelinked shared libraries and PIE executables.
uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0; uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0;
int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), pc,
pc, out, out_size, out, out_size, relocation);
relocation);
if (num_bytes_written > 0) { if (num_bytes_written > 0) {
out += static_cast<size_t>(num_bytes_written); out += static_cast<size_t>(num_bytes_written);
out_size -= static_cast<size_t>(num_bytes_written); out_size -= static_cast<size_t>(num_bytes_written);
} }
} }
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, out, out_size,
out, out_size, base_address)) { base_address)) {
if (out[1] && !g_symbolize_callback) { if (out[1] && !g_symbolize_callback) {
// The object file containing PC was opened successfully however the // The object file containing PC was opened successfully however the
// symbol was not found. The object may have been stripped. This is still // symbol was not found. The object may have been stripped. This is still
@ -838,6 +832,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) # elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
# include <dlfcn.h> # include <dlfcn.h>
# include <cstring> # include <cstring>
namespace google { namespace google {
@ -862,8 +857,8 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
#include <windows.h>
# include <dbghelp.h> # include <dbghelp.h>
# include <windows.h>
# ifdef _MSC_VER # ifdef _MSC_VER
# pragma comment(lib, "dbghelp") # pragma comment(lib, "dbghelp")
@ -891,6 +886,7 @@ public:
SymCleanup(process); SymCleanup(process);
// We do not need to close `HANDLE process` because it's a "pseudo handle." // We do not need to close `HANDLE process` because it's a "pseudo handle."
} }
private: private:
SymInitializer(const SymInitializer&); SymInitializer(const SymInitializer&);
SymInitializer& operator=(const SymInitializer&); SymInitializer& operator=(const SymInitializer&);
@ -910,8 +906,8 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
symbol->MaxNameLen = MAX_SYM_NAME; symbol->MaxNameLen = MAX_SYM_NAME;
// We use the ANSI version to ensure the string type is always `char *`. // We use the ANSI version to ensure the string type is always `char *`.
// This could break if a symbol has Unicode in it. // This could break if a symbol has Unicode in it.
BOOL ret = SymFromAddr(symInitializer.process, BOOL ret = SymFromAddr(symInitializer.process, reinterpret_cast<DWORD64>(pc),
reinterpret_cast<DWORD64>(pc), 0, symbol); 0, symbol);
if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) { if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) {
// `NameLen` does not include the null terminating character. // `NameLen` does not include the null terminating character.
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1); strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);

View File

@ -130,8 +130,8 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
// file is opened successfully, returns the file descriptor. Otherwise, // file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer // returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator). // (including the null-terminator).
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t &, using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&,
uint64_t &, char *, size_t); char*, size_t);
void InstallSymbolizeOpenObjectFileCallback( void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback); SymbolizeOpenObjectFileCallback callback);

View File

@ -79,7 +79,8 @@ static const char *TrySymbolize(void *pc) {
# if defined(__GNUC__) && !defined(__OPENCC__) # if defined(__GNUC__) && !defined(__OPENCC__)
# if __GNUC__ >= 4 # if __GNUC__ >= 4
# define TEST_WITH_MODERN_GCC # define TEST_WITH_MODERN_GCC
# if defined(__i386__) && __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 # undef always_inline
# define always_inline __attribute__((always_inline)) # define always_inline __attribute__((always_inline))
# define HAVE_ALWAYS_INLINE # define HAVE_ALWAYS_INLINE
@ -214,7 +215,6 @@ static int GetStackConsumption(const char* alt_stack) {
// Call Symbolize and figure out the stack footprint of this call. // Call Symbolize and figure out the stack footprint of this call.
static const char* SymbolizeStackConsumption(void* pc, int* stack_consumed) { static const char* SymbolizeStackConsumption(void* pc, int* stack_consumed) {
g_pc_to_symbolize = pc; g_pc_to_symbolize = pc;
// The alt-signal-stack cannot be heap allocated because there is a // The alt-signal-stack cannot be heap allocated because there is a

View File

@ -29,13 +29,13 @@
// //
// Author: Shinichiro Hamaji // Author: Shinichiro Hamaji
#include "config.h"
#include "utilities.h" #include "utilities.h"
#include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <csignal> #include "config.h"
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#endif #endif
@ -75,9 +75,9 @@ bool IsGoogleLoggingInitialized() {
// The following APIs are all internal. // The following APIs are all internal.
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
# include "base/commandlineflags.h"
# include "stacktrace.h" # include "stacktrace.h"
# include "symbolize.h" # include "symbolize.h"
#include "base/commandlineflags.h"
GLOG_DEFINE_bool(symbolize_stacktrace, true, GLOG_DEFINE_bool(symbolize_stacktrace, true,
"Symbolize the stack trace in the tombstone"); "Symbolize the stack trace in the tombstone");
@ -199,7 +199,8 @@ struct timeval {
long tv_sec, tv_usec; long tv_sec, tv_usec;
}; };
// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd // Based on:
// http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
// See COPYING for copyright information. // See COPYING for copyright information.
static int gettimeofday(struct timeval* tv, void* /*tz*/) { static int gettimeofday(struct timeval* tv, void* /*tz*/) {
# ifdef __GNUC__ # ifdef __GNUC__
@ -232,9 +233,7 @@ int64 CycleClock_Now() {
return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec; return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
} }
int64 UsecToCycles(int64 usec) { int64 UsecToCycles(int64 usec) { return usec; }
return usec;
}
WallTime WallTime_Now() { WallTime WallTime_Now() {
// Now, cycle clock is retuning microseconds since the epoch. // Now, cycle clock is retuning microseconds since the epoch.
@ -242,9 +241,7 @@ WallTime WallTime_Now() {
} }
static int32 g_main_thread_pid = getpid(); static int32 g_main_thread_pid = getpid();
int32 GetMainThreadPid() { int32 GetMainThreadPid() { return g_main_thread_pid; }
return g_main_thread_pid;
}
bool PidHasChanged() { bool PidHasChanged() {
int32 pid = getpid(); int32 pid = getpid();
@ -305,16 +302,13 @@ pid_t GetTID() {
const char* const_basename(const char* filepath) { const char* const_basename(const char* filepath) {
const char* base = strrchr(filepath, '/'); const char* base = strrchr(filepath, '/');
#ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows #ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows
if (!base) if (!base) base = strrchr(filepath, '\\');
base = strrchr(filepath, '\\');
#endif #endif
return base ? (base + 1) : filepath; return base ? (base + 1) : filepath;
} }
static string g_my_user_name; static string g_my_user_name;
const string& MyUserName() { const string& MyUserName() { return g_my_user_name; }
return g_my_user_name;
}
static void MyUserNameInitializer() { static void MyUserNameInitializer() {
// TODO(hamaji): Probably this is not portable. // TODO(hamaji): Probably this is not portable.
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
@ -356,8 +350,7 @@ void DumpStackTraceToString(string* stacktrace) {
static const CrashReason* g_reason = nullptr; static const CrashReason* g_reason = nullptr;
void SetCrashReason(const CrashReason* r) { void SetCrashReason(const CrashReason* r) {
sync_val_compare_and_swap(&g_reason, sync_val_compare_and_swap(&g_reason, reinterpret_cast<const CrashReason*>(0),
reinterpret_cast<const CrashReason*>(0),
r); r);
} }
@ -377,7 +370,8 @@ void InitGoogleLoggingUtilities(const char* argv0) {
void ShutdownGoogleLoggingUtilities() { void ShutdownGoogleLoggingUtilities() {
CHECK(IsGoogleLoggingInitialized()) CHECK(IsGoogleLoggingInitialized())
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!"; << "You called ShutdownGoogleLogging() without calling "
"InitGoogleLogging() first!";
g_program_invocation_short_name = nullptr; g_program_invocation_short_name = nullptr;
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
closelog(); closelog();
@ -393,10 +387,10 @@ void ShutdownGoogleLoggingUtilities() {
# include STACKTRACE_H # include STACKTRACE_H
# if 0 # if 0
// For include scanners which can't handle macro expansions. // For include scanners which can't handle macro expansions.
# include "stacktrace_generic-inl.h"
# include "stacktrace_libunwind-inl.h" # include "stacktrace_libunwind-inl.h"
# include "stacktrace_powerpc-inl.h"
# include "stacktrace_x86-inl.h" # include "stacktrace_x86-inl.h"
# include "stacktrace_x86_64-inl.h" # include "stacktrace_x86_64-inl.h"
# include "stacktrace_powerpc-inl.h"
# include "stacktrace_generic-inl.h"
# endif # endif
#endif #endif

View File

@ -49,10 +49,13 @@
using std::string; using std::string;
GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this." GLOG_DEFINE_int32(v, 0,
"Show all VLOG(m) messages for m <= this."
" Overridable by --vmodule."); " Overridable by --vmodule.");
GLOG_DEFINE_string(vmodule, "", "per-module verbose level." GLOG_DEFINE_string(
vmodule, "",
"per-module verbose level."
" Argument is a comma-separated list of <module name>=<log level>." " Argument is a comma-separated list of <module name>=<log level>."
" <module name> is a glob pattern, matched against the filename base" " <module name> is a glob pattern, matched against the filename base"
" (that is, name ignoring .cc/.h./-inl.h)." " (that is, name ignoring .cc/.h./-inl.h)."
@ -86,7 +89,8 @@ GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
if (pattern[p] == '*') { if (pattern[p] == '*') {
if (p + 1 == patt_len) return true; if (p + 1 == patt_len) return true;
do { do {
if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) { if (SafeFNMatch_(pattern + (p + 1), patt_len - (p + 1), str + s,
str_len - s)) {
return true; return true;
} }
s += 1; s += 1;
@ -177,8 +181,7 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
found = true; found = true;
} }
info->vlog_level = log_level; info->vlog_level = log_level;
} else if (!found && } else if (!found && SafeFNMatch_(info->module_pattern.c_str(),
SafeFNMatch_(info->module_pattern.c_str(),
info->module_pattern.size(), info->module_pattern.size(),
module_pattern, pattern_len)) { module_pattern, pattern_len)) {
result = info->vlog_level; result = info->vlog_level;
@ -216,8 +219,8 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
// NOTE: Individual VLOG statements cache the integer log level pointers. // NOTE: Individual VLOG statements cache the integer log level pointers.
// NOTE: This function must not allocate memory or require any locks. // NOTE: This function must not allocate memory or require any locks.
bool InitVLOG3__(SiteFlag* site_flag, int32* level_default, bool InitVLOG3__(SiteFlag* site_flag, int32* level_default, const char* fname,
const char* fname, int32 verbose_level) { int32 verbose_level) {
MutexLock l(&vmodule_lock); MutexLock l(&vmodule_lock);
bool read_vmodule_flag = inited_vmodule; bool read_vmodule_flag = inited_vmodule;
if (!read_vmodule_flag) { if (!read_vmodule_flag) {

View File

@ -25,6 +25,8 @@
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
#endif #endif
#include <sys/stat.h>
#include <sys/types.h>
#include <windows.h> #include <windows.h>
#include <cerrno> #include <cerrno>
@ -33,8 +35,6 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cwchar> #include <cwchar>
#include <sys/stat.h>
#include <sys/types.h>
/* Indicates that d_type field is available in dirent structure */ /* Indicates that d_type field is available in dirent structure */
#define _DIRENT_HAVE_D_TYPE #define _DIRENT_HAVE_D_TYPE
@ -211,12 +211,10 @@
/* Return the maximum size of a file name */ /* Return the maximum size of a file name */
#define _D_ALLOC_NAMLEN(p) ((PATH_MAX) + 1) #define _D_ALLOC_NAMLEN(p) ((PATH_MAX) + 1)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Wide-character version */ /* Wide-character version */
struct _wdirent { struct _wdirent {
/* Always zero */ /* Always zero */
@ -288,10 +286,9 @@ static _WDIR *_wopendir (const wchar_t *dirname);
static struct dirent* readdir(DIR* dirp); static struct dirent* readdir(DIR* dirp);
static struct _wdirent* _wreaddir(_WDIR* dirp); static struct _wdirent* _wreaddir(_WDIR* dirp);
static int readdir_r( static int readdir_r(DIR* dirp, struct dirent* entry, struct dirent** result);
DIR *dirp, struct dirent *entry, struct dirent **result); static int _wreaddir_r(_WDIR* dirp, struct _wdirent* entry,
static int _wreaddir_r( struct _wdirent** result);
_WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
static int closedir(DIR* dirp); static int closedir(DIR* dirp);
static int _wclosedir(_WDIR* dirp); static int _wclosedir(_WDIR* dirp);
@ -301,13 +298,13 @@ static void _wrewinddir (_WDIR* dirp);
static int scandir(const char* dirname, struct dirent*** namelist, static int scandir(const char* dirname, struct dirent*** namelist,
int (*filter)(const struct dirent*), int (*filter)(const struct dirent*),
int (*compare)(const struct dirent**, const struct dirent**)); int (*compare)(const struct dirent**,
const struct dirent**));
static int alphasort(const struct dirent** a, const struct dirent** b); static int alphasort(const struct dirent** a, const struct dirent** b);
static int versionsort(const struct dirent** a, const struct dirent** b); static int versionsort(const struct dirent** a, const struct dirent** b);
/* For compatibility with Symbian */ /* For compatibility with Symbian */
#define wdirent _wdirent #define wdirent _wdirent
#define WDIR _WDIR #define WDIR _WDIR
@ -316,37 +313,26 @@ static int versionsort (const struct dirent **a, const struct dirent **b);
#define wclosedir _wclosedir #define wclosedir _wclosedir
#define wrewinddir _wrewinddir #define wrewinddir _wrewinddir
/* Internal utility functions */ /* Internal utility functions */
static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp); static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp);
static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp); static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp);
static int dirent_mbstowcs_s( static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr,
size_t *pReturnValue, size_t sizeInWords, const char* mbstr,
wchar_t *wcstr,
size_t sizeInWords,
const char *mbstr,
size_t count); size_t count);
static int dirent_wcstombs_s( static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr,
size_t *pReturnValue, size_t sizeInBytes, const wchar_t* wcstr,
char *mbstr,
size_t sizeInBytes,
const wchar_t *wcstr,
size_t count); size_t count);
static void dirent_set_errno(int error); static void dirent_set_errno(int error);
/* /*
* Open directory stream DIRNAME for read and return a pointer to the * Open directory stream DIRNAME for read and return a pointer to the
* internal working area that is used to retrieve individual directory * internal working area that is used to retrieve individual directory
* entries. * entries.
*/ */
static _WDIR* static _WDIR* _wopendir(const wchar_t* dirname) {
_wopendir(
const wchar_t *dirname)
{
_WDIR* dirp; _WDIR* dirp;
DWORD n; DWORD n;
wchar_t* p; wchar_t* p;
@ -444,10 +430,7 @@ exit_closedir:
* Returns pointer to static directory entry which may be overwritten by * Returns pointer to static directory entry which may be overwritten by
* subsequent calls to _wreaddir(). * subsequent calls to _wreaddir().
*/ */
static struct _wdirent* static struct _wdirent* _wreaddir(_WDIR* dirp) {
_wreaddir(
_WDIR *dirp)
{
struct _wdirent* entry; struct _wdirent* entry;
/* /*
@ -466,12 +449,8 @@ _wreaddir(
* Returns zero on success. If end of directory stream is reached, then sets * Returns zero on success. If end of directory stream is reached, then sets
* result to nullptr and returns zero. * result to nullptr and returns zero.
*/ */
static int static int _wreaddir_r(_WDIR* dirp, struct _wdirent* entry,
_wreaddir_r( struct _wdirent** result) {
_WDIR *dirp,
struct _wdirent *entry,
struct _wdirent **result)
{
WIN32_FIND_DATAW* datap; WIN32_FIND_DATAW* datap;
/* Read next directory entry */ /* Read next directory entry */
@ -526,13 +505,9 @@ _wreaddir_r(
* DIR structure as well as any directory entry read previously by * DIR structure as well as any directory entry read previously by
* _wreaddir(). * _wreaddir().
*/ */
static int static int _wclosedir(_WDIR* dirp) {
_wclosedir(
_WDIR *dirp)
{
int ok; int ok;
if (dirp) { if (dirp) {
/* Release search handle */ /* Release search handle */
if (dirp->handle != INVALID_HANDLE_VALUE) { if (dirp->handle != INVALID_HANDLE_VALUE) {
FindClose(dirp->handle); FindClose(dirp->handle);
@ -546,11 +521,9 @@ _wclosedir(
ok = /*success*/ 0; ok = /*success*/ 0;
} else { } else {
/* Invalid directory stream */ /* Invalid directory stream */
dirent_set_errno(EBADF); dirent_set_errno(EBADF);
ok = /*failure*/ -1; ok = /*failure*/ -1;
} }
return ok; return ok;
} }
@ -559,10 +532,7 @@ _wclosedir(
* Rewind directory stream such that _wreaddir() returns the very first * Rewind directory stream such that _wreaddir() returns the very first
* file name again. * file name again.
*/ */
static void static void _wrewinddir(_WDIR* dirp) {
_wrewinddir(
_WDIR* dirp)
{
if (dirp) { if (dirp) {
/* Release existing search handle */ /* Release existing search handle */
if (dirp->handle != INVALID_HANDLE_VALUE) { if (dirp->handle != INVALID_HANDLE_VALUE) {
@ -575,10 +545,7 @@ _wrewinddir(
} }
/* Get first directory entry (internal) */ /* Get first directory entry (internal) */
static WIN32_FIND_DATAW* static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp) {
dirent_first(
_WDIR *dirp)
{
WIN32_FIND_DATAW* datap; WIN32_FIND_DATAW* datap;
DWORD error; DWORD error;
@ -586,13 +553,11 @@ dirent_first(
dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data, dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data,
FindExSearchNameMatch, nullptr, 0); FindExSearchNameMatch, nullptr, 0);
if (dirp->handle != INVALID_HANDLE_VALUE) { if (dirp->handle != INVALID_HANDLE_VALUE) {
/* a directory entry is now waiting in memory */ /* a directory entry is now waiting in memory */
datap = &dirp->data; datap = &dirp->data;
dirp->cached = 1; dirp->cached = 1;
} else { } else {
/* Failed to open directory: no directory entry in memory */ /* Failed to open directory: no directory entry in memory */
dirp->cached = 0; dirp->cached = 0;
datap = nullptr; datap = nullptr;
@ -615,7 +580,6 @@ dirent_first(
/* Cannot find the file */ /* Cannot find the file */
dirent_set_errno(ENOENT); dirent_set_errno(ENOENT);
} }
} }
return datap; return datap;
} }
@ -625,21 +589,16 @@ dirent_first(
* *
* Returns * Returns
*/ */
static WIN32_FIND_DATAW* static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp) {
dirent_next(
_WDIR *dirp)
{
WIN32_FIND_DATAW* p; WIN32_FIND_DATAW* p;
/* Get next directory entry */ /* Get next directory entry */
if (dirp->cached != 0) { if (dirp->cached != 0) {
/* A valid directory entry already in memory */ /* A valid directory entry already in memory */
p = &dirp->data; p = &dirp->data;
dirp->cached = 0; dirp->cached = 0;
} else if (dirp->handle != INVALID_HANDLE_VALUE) { } else if (dirp->handle != INVALID_HANDLE_VALUE) {
/* Get the next directory entry from stream */ /* Get the next directory entry from stream */
if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) {
/* Got a file */ /* Got a file */
@ -652,7 +611,6 @@ dirent_next(
} }
} else { } else {
/* End of directory stream reached */ /* End of directory stream reached */
p = nullptr; p = nullptr;
} }
@ -663,10 +621,7 @@ dirent_next(
/* /*
* Open directory stream using plain old C-string. * Open directory stream using plain old C-string.
*/ */
static DIR* static DIR* opendir(const char* dirname) {
opendir(
const char *dirname)
{
struct DIR* dirp; struct DIR* dirp;
/* Must have directory name */ /* Must have directory name */
@ -686,8 +641,7 @@ opendir(
size_t n; size_t n;
/* Convert directory name to wide-character string */ /* Convert directory name to wide-character string */
error = dirent_mbstowcs_s( error = dirent_mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
if (error) { if (error) {
/* /*
* Cannot convert file name to wide-character string. This * Cannot convert file name to wide-character string. This
@ -698,13 +652,11 @@ opendir(
goto exit_free; goto exit_free;
} }
/* Open directory stream using wide-character name */ /* Open directory stream using wide-character name */
dirp->wdirp = _wopendir(wname); dirp->wdirp = _wopendir(wname);
if (!dirp->wdirp) { if (!dirp->wdirp) {
goto exit_free; goto exit_free;
} }
} }
/* Success */ /* Success */
@ -719,10 +671,7 @@ exit_free:
/* /*
* Read next directory entry. * Read next directory entry.
*/ */
static struct dirent* static struct dirent* readdir(DIR* dirp) {
readdir(
DIR *dirp)
{
struct dirent* entry; struct dirent* entry;
/* /*
@ -741,12 +690,7 @@ readdir(
* Returns zero on success. If the end of directory stream is reached, then * Returns zero on success. If the end of directory stream is reached, then
* sets result to nullptr and returns zero. * sets result to nullptr and returns zero.
*/ */
static int static int readdir_r(DIR* dirp, struct dirent* entry, struct dirent** result) {
readdir_r(
DIR *dirp,
struct dirent *entry,
struct dirent **result)
{
WIN32_FIND_DATAW* datap; WIN32_FIND_DATAW* datap;
/* Read next directory entry */ /* Read next directory entry */
@ -756,8 +700,8 @@ readdir_r(
int error; int error;
/* Attempt to convert file name to multi-byte string */ /* Attempt to convert file name to multi-byte string */
error = dirent_wcstombs_s( error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1, datap->cFileName,
&n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); PATH_MAX + 1);
/* /*
* If the file name cannot be represented by a multi-byte string, * If the file name cannot be represented by a multi-byte string,
@ -770,8 +714,7 @@ readdir_r(
* VirtualBox shared folders fail to do this. * VirtualBox shared folders fail to do this.
*/ */
if (error && datap->cAlternateFileName[0] != '\0') { if (error && datap->cAlternateFileName[0] != '\0') {
error = dirent_wcstombs_s( error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1,
&n, entry->d_name, PATH_MAX + 1,
datap->cAlternateFileName, PATH_MAX + 1); datap->cAlternateFileName, PATH_MAX + 1);
} }
@ -810,14 +753,12 @@ readdir_r(
entry->d_ino = 0; entry->d_ino = 0;
entry->d_off = -1; entry->d_off = -1;
entry->d_reclen = 0; entry->d_reclen = 0;
} }
/* Return pointer to directory entry */ /* Return pointer to directory entry */
*result = entry; *result = entry;
} else { } else {
/* No more directory entries */ /* No more directory entries */
*result = nullptr; *result = nullptr;
} }
@ -828,13 +769,9 @@ readdir_r(
/* /*
* Close directory stream. * Close directory stream.
*/ */
static int static int closedir(DIR* dirp) {
closedir(
DIR *dirp)
{
int ok; int ok;
if (dirp) { if (dirp) {
/* Close wide-character directory stream */ /* Close wide-character directory stream */
ok = _wclosedir(dirp->wdirp); ok = _wclosedir(dirp->wdirp);
dirp->wdirp = nullptr; dirp->wdirp = nullptr;
@ -843,11 +780,9 @@ closedir(
free(dirp); free(dirp);
} else { } else {
/* Invalid directory stream */ /* Invalid directory stream */
dirent_set_errno(EBADF); dirent_set_errno(EBADF);
ok = /*failure*/ -1; ok = /*failure*/ -1;
} }
return ok; return ok;
} }
@ -855,10 +790,7 @@ closedir(
/* /*
* Rewind directory stream to beginning. * Rewind directory stream to beginning.
*/ */
static void static void rewinddir(DIR* dirp) {
rewinddir(
DIR* dirp)
{
/* Rewind wide-character string directory stream */ /* Rewind wide-character string directory stream */
_wrewinddir(dirp->wdirp); _wrewinddir(dirp->wdirp);
} }
@ -866,13 +798,10 @@ rewinddir(
/* /*
* Scan directory for entries. * Scan directory for entries.
*/ */
static int static int scandir(const char* dirname, struct dirent*** namelist,
scandir(
const char *dirname,
struct dirent ***namelist,
int (*filter)(const struct dirent*), int (*filter)(const struct dirent*),
int (*compare)(const struct dirent**, const struct dirent**)) int (*compare)(const struct dirent**,
{ const struct dirent**)) {
struct dirent** files = nullptr; struct dirent** files = nullptr;
size_t size = 0; size_t size = 0;
size_t allocated = 0; size_t allocated = 0;
@ -886,10 +815,8 @@ scandir(
/* Open directory stream */ /* Open directory stream */
dir = opendir(dirname); dir = opendir(dirname);
if (dir) { if (dir) {
/* Read directory entries to memory */ /* Read directory entries to memory */
while (1) { while (1) {
/* Enlarge pointer table to make room for another pointer */ /* Enlarge pointer table to make room for another pointer */
if (size >= allocated) { if (size >= allocated) {
void* p; void* p;
@ -929,7 +856,6 @@ scandir(
/* Read directory entry to temporary area */ /* Read directory entry to temporary area */
if (readdir_r(dir, tmp, &entry) == /*OK*/ 0) { if (readdir_r(dir, tmp, &entry) == /*OK*/ 0) {
/* Did we get an entry? */ /* Did we get an entry? */
if (entry != nullptr) { if (entry != nullptr) {
int pass; int pass;
@ -967,7 +893,6 @@ scandir(
result = /*Error*/ -1; result = /*Error*/ -1;
break; break;
} }
} }
} else { } else {
@ -1000,31 +925,20 @@ scandir(
} }
/* Alphabetical sorting */ /* Alphabetical sorting */
static int static int alphasort(const struct dirent** a, const struct dirent** b) {
alphasort(
const struct dirent **a, const struct dirent **b)
{
return strcoll((*a)->d_name, (*b)->d_name); return strcoll((*a)->d_name, (*b)->d_name);
} }
/* Sort versions */ /* Sort versions */
static int static int versionsort(const struct dirent** a, const struct dirent** b) {
versionsort(
const struct dirent **a, const struct dirent **b)
{
/* FIXME: implement strverscmp and use that */ /* FIXME: implement strverscmp and use that */
return alphasort(a, b); return alphasort(a, b);
} }
/* Convert multi-byte string to wide character string */ /* Convert multi-byte string to wide character string */
static int static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr,
dirent_mbstowcs_s( size_t sizeInWords, const char* mbstr,
size_t *pReturnValue, size_t count) {
wchar_t *wcstr,
size_t sizeInWords,
const char *mbstr,
size_t count)
{
int error; int error;
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
@ -1040,7 +954,6 @@ dirent_mbstowcs_s(
/* Convert to wide-character string (or count characters) */ /* Convert to wide-character string (or count characters) */
n = mbstowcs(wcstr, mbstr, sizeInWords); n = mbstowcs(wcstr, mbstr, sizeInWords);
if (!wcstr || n < count) { if (!wcstr || n < count) {
/* Zero-terminate output buffer */ /* Zero-terminate output buffer */
if (wcstr && sizeInWords) { if (wcstr && sizeInWords) {
if (n >= sizeInWords) { if (n >= sizeInWords) {
@ -1058,10 +971,8 @@ dirent_mbstowcs_s(
error = 0; error = 0;
} else { } else {
/* Could not convert string */ /* Could not convert string */
error = 1; error = 1;
} }
#endif #endif
@ -1069,14 +980,9 @@ dirent_mbstowcs_s(
} }
/* Convert wide-character string to multi-byte string */ /* Convert wide-character string to multi-byte string */
static int static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr,
dirent_wcstombs_s(
size_t *pReturnValue,
char *mbstr,
size_t sizeInBytes, /* max size of mbstr */ size_t sizeInBytes, /* max size of mbstr */
const wchar_t *wcstr, const wchar_t* wcstr, size_t count) {
size_t count)
{
int error; int error;
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
@ -1092,7 +998,6 @@ dirent_wcstombs_s(
/* Convert to multi-byte string (or count the number of bytes needed) */ /* Convert to multi-byte string (or count the number of bytes needed) */
n = wcstombs(mbstr, wcstr, sizeInBytes); n = wcstombs(mbstr, wcstr, sizeInBytes);
if (!mbstr || n < count) { if (!mbstr || n < count) {
/* Zero-terminate output buffer */ /* Zero-terminate output buffer */
if (mbstr && sizeInBytes) { if (mbstr && sizeInBytes) {
if (n >= sizeInBytes) { if (n >= sizeInBytes) {
@ -1110,10 +1015,8 @@ dirent_wcstombs_s(
error = 0; error = 0;
} else { } else {
/* Cannot convert string */ /* Cannot convert string */
error = 1; error = 1;
} }
#endif #endif
@ -1121,10 +1024,7 @@ dirent_wcstombs_s(
} }
/* Set errno variable */ /* Set errno variable */
static void static void dirent_set_errno(int error) {
dirent_set_errno(
int error)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400 #if defined(_MSC_VER) && _MSC_VER >= 1400
/* Microsoft Visual Studio 2005 and later */ /* Microsoft Visual Studio 2005 and later */
@ -1138,7 +1038,6 @@ dirent_set_errno(
#endif #endif
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -132,7 +132,8 @@ typedef DWORD pthread_key_t;
typedef LONG pthread_once_t; typedef LONG pthread_once_t;
enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
# define pthread_self GetCurrentThreadId # define pthread_self GetCurrentThreadId
#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2)) # define pthread_equal(pthread_t_1, pthread_t_2) \
((pthread_t_1) == (pthread_t_2))
# endif // HAVE_PTHREAD # endif // HAVE_PTHREAD
# ifndef HAVE_LOCALTIME_R # ifndef HAVE_LOCALTIME_R