chore: apply clang-format
This commit is contained in:
parent
e3f5398aa1
commit
93549f3600
@ -58,7 +58,7 @@ ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
@ -84,7 +84,7 @@ IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
|
||||
@ -48,11 +48,12 @@
|
||||
#ifndef BASE_COMMANDLINEFLAGS_H__
|
||||
#define BASE_COMMANDLINEFLAGS_H__
|
||||
|
||||
#include "config.h"
|
||||
#include <cstdlib> // for getenv
|
||||
#include <cstring> // for memchr
|
||||
#include <string>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef GLOG_USE_GFLAGS
|
||||
|
||||
# include <gflags/gflags.h>
|
||||
@ -74,8 +75,7 @@
|
||||
using fL##shorttype::FLAGS_##name
|
||||
|
||||
// bool specialization
|
||||
#define DECLARE_bool(name) \
|
||||
DECLARE_VARIABLE(bool, B, name, bool)
|
||||
# define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name, bool)
|
||||
# define DEFINE_bool(name, value, meaning) \
|
||||
DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
|
||||
|
||||
@ -86,7 +86,8 @@
|
||||
|
||||
// uint32 specialization
|
||||
# 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
|
||||
# define DEFINE_uint32(name, value, meaning) \
|
||||
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
|
||||
// file), make it easier to initialize flags from the environment.
|
||||
|
||||
#define EnvToString(envname, dflt) \
|
||||
(!getenv(envname) ? (dflt) : getenv(envname))
|
||||
#define EnvToString(envname, dflt) (!getenv(envname) ? (dflt) : getenv(envname))
|
||||
|
||||
#define EnvToBool(envname, dflt) \
|
||||
(!getenv(envname) ? (dflt) \
|
||||
|
||||
@ -36,16 +36,14 @@
|
||||
class GoogleInitializer {
|
||||
public:
|
||||
using void_function = void (*)();
|
||||
GoogleInitializer(const char*, void_function f) {
|
||||
f();
|
||||
}
|
||||
GoogleInitializer(const char*, void_function f) { f(); }
|
||||
};
|
||||
|
||||
#define REGISTER_MODULE_INITIALIZER(name, body) \
|
||||
namespace { \
|
||||
static void google_init_module_##name() { body; } \
|
||||
GoogleInitializer google_initializer_module_##name(#name, \
|
||||
google_init_module_##name); \
|
||||
GoogleInitializer google_initializer_module_##name( \
|
||||
#name, google_init_module_##name); \
|
||||
}
|
||||
|
||||
#endif /* _GOOGLEINIT_H */
|
||||
|
||||
@ -134,7 +134,8 @@
|
||||
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
|
||||
// for locking there.)
|
||||
# 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
|
||||
# endif
|
||||
# endif
|
||||
@ -218,27 +219,40 @@ Mutex::~Mutex() { assert(mutex_ == 0); }
|
||||
void Mutex::Lock() { assert(--mutex_ == -1); }
|
||||
void Mutex::Unlock() { assert(mutex_++ == -1); }
|
||||
# ifdef GMUTEX_TRYLOCK
|
||||
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
|
||||
bool Mutex::TryLock() {
|
||||
if (mutex_) return false;
|
||||
Lock();
|
||||
return true;
|
||||
}
|
||||
# endif
|
||||
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
|
||||
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
|
||||
|
||||
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||
|
||||
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
|
||||
Mutex::Mutex() {
|
||||
InitializeCriticalSection(&mutex_);
|
||||
SetIsSafe();
|
||||
}
|
||||
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
|
||||
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
|
||||
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
|
||||
void Mutex::Lock() {
|
||||
if (is_safe_) EnterCriticalSection(&mutex_);
|
||||
}
|
||||
void Mutex::Unlock() {
|
||||
if (is_safe_) LeaveCriticalSection(&mutex_);
|
||||
}
|
||||
# ifdef GMUTEX_TRYLOCK
|
||||
bool Mutex::TryLock() { return is_safe_ ?
|
||||
TryEnterCriticalSection(&mutex_) != 0 : true; }
|
||||
bool Mutex::TryLock() {
|
||||
return is_safe_ ? TryEnterCriticalSection(&mutex_) != 0 : true;
|
||||
}
|
||||
# endif
|
||||
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
|
||||
void Mutex::ReaderUnlock() { Unlock(); }
|
||||
|
||||
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
|
||||
|
||||
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
|
||||
# define SAFE_PTHREAD(fncall) \
|
||||
do { /* run fncall if is_safe_ is true */ \
|
||||
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
|
||||
} while (0)
|
||||
|
||||
@ -250,9 +264,9 @@ Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
|
||||
# ifdef GMUTEX_TRYLOCK
|
||||
bool Mutex::TryLock() { return is_safe_ ?
|
||||
pthread_rwlock_trywrlock(&mutex_) == 0 :
|
||||
true; }
|
||||
bool Mutex::TryLock() {
|
||||
return is_safe_ ? pthread_rwlock_trywrlock(&mutex_) == 0 : true;
|
||||
}
|
||||
# endif
|
||||
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
|
||||
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
|
||||
@ -260,7 +274,8 @@ void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
|
||||
|
||||
#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(); \
|
||||
} while (0)
|
||||
|
||||
@ -272,8 +287,9 @@ Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
|
||||
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
|
||||
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
|
||||
# ifdef GMUTEX_TRYLOCK
|
||||
bool Mutex::TryLock() { return is_safe_ ?
|
||||
pthread_mutex_trylock(&mutex_) == 0 : true; }
|
||||
bool Mutex::TryLock() {
|
||||
return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true;
|
||||
}
|
||||
# endif
|
||||
void Mutex::ReaderLock() { Lock(); }
|
||||
void Mutex::ReaderUnlock() { Unlock(); }
|
||||
@ -289,6 +305,7 @@ class MutexLock {
|
||||
public:
|
||||
explicit MutexLock(Mutex* mu) : mu_(mu) { mu_->Lock(); }
|
||||
~MutexLock() { mu_->Unlock(); }
|
||||
|
||||
private:
|
||||
Mutex* const mu_;
|
||||
// Disallow "evil" constructors
|
||||
@ -301,6 +318,7 @@ class ReaderMutexLock {
|
||||
public:
|
||||
explicit ReaderMutexLock(Mutex* mu) : mu_(mu) { mu_->ReaderLock(); }
|
||||
~ReaderMutexLock() { mu_->ReaderUnlock(); }
|
||||
|
||||
private:
|
||||
Mutex* const mu_;
|
||||
// Disallow "evil" constructors
|
||||
@ -312,6 +330,7 @@ class WriterMutexLock {
|
||||
public:
|
||||
explicit WriterMutexLock(Mutex* mu) : mu_(mu) { mu_->WriterLock(); }
|
||||
~WriterMutexLock() { mu_->WriterUnlock(); }
|
||||
|
||||
private:
|
||||
Mutex* const mu_;
|
||||
// Disallow "evil" constructors
|
||||
|
||||
133
src/demangle.cc
133
src/demangle.cc
@ -140,15 +140,14 @@ static bool AtLeastNumCharsRemaining(const char *str, ssize_t n) {
|
||||
// Returns true if "str" has "prefix" as a prefix.
|
||||
static bool StrPrefix(const char* str, const char* prefix) {
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0' && prefix[i] != '\0' &&
|
||||
str[i] == prefix[i]) {
|
||||
while (str[i] != '\0' && prefix[i] != '\0' && str[i] == prefix[i]) {
|
||||
++i;
|
||||
}
|
||||
return prefix[i] == '\0'; // Consumed everything in "prefix".
|
||||
}
|
||||
|
||||
static void InitState(State *state, const char *mangled,
|
||||
char *out, size_t out_size) {
|
||||
static void InitState(State* state, const char* mangled, char* out,
|
||||
size_t out_size) {
|
||||
state->mangled_cur = mangled;
|
||||
state->out_cur = 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.
|
||||
static bool Optional(bool) {
|
||||
return true;
|
||||
}
|
||||
static bool Optional(bool) { return true; }
|
||||
|
||||
// This function is used for handling <non-terminal>+ syntax.
|
||||
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.
|
||||
static bool IsLower(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
static bool IsLower(char c) { return c >= 'a' && c <= 'z'; }
|
||||
|
||||
static bool IsAlpha(char c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
static bool IsDigit(char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
|
||||
|
||||
// Returns true if "str" is a function clone suffix. These suffixes are used
|
||||
// by GCC 4.5.x and later versions to indicate functions which have been
|
||||
@ -473,8 +466,7 @@ static bool ParseName(State *state) {
|
||||
}
|
||||
|
||||
State copy = *state;
|
||||
if (ParseUnscopedTemplateName(state) &&
|
||||
ParseTemplateArgs(state)) {
|
||||
if (ParseUnscopedTemplateName(state) && ParseTemplateArgs(state)) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -494,8 +486,7 @@ static bool ParseUnscopedName(State *state) {
|
||||
}
|
||||
|
||||
State copy = *state;
|
||||
if (ParseTwoCharToken(state, "St") &&
|
||||
MaybeAppend(state, "std::") &&
|
||||
if (ParseTwoCharToken(state, "St") && MaybeAppend(state, "std::") &&
|
||||
ParseUnqualifiedName(state)) {
|
||||
return true;
|
||||
}
|
||||
@ -513,10 +504,8 @@ static bool ParseUnscopedTemplateName(State *state) {
|
||||
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
|
||||
static bool ParseNestedName(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'N') &&
|
||||
EnterNestedName(state) &&
|
||||
Optional(ParseCVQualifiers(state)) &&
|
||||
ParsePrefix(state) &&
|
||||
if (ParseOneCharToken(state, 'N') && EnterNestedName(state) &&
|
||||
Optional(ParseCVQualifiers(state)) && ParsePrefix(state) &&
|
||||
LeaveNestedName(state, copy.nest_level) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
@ -540,8 +529,7 @@ static bool ParsePrefix(State *state) {
|
||||
bool has_something = false;
|
||||
while (true) {
|
||||
MaybeAppendSeparator(state);
|
||||
if (ParseTemplateParam(state) ||
|
||||
ParseSubstitution(state) ||
|
||||
if (ParseTemplateParam(state) || ParseSubstitution(state) ||
|
||||
ParseUnscopedName(state)) {
|
||||
has_something = true;
|
||||
MaybeIncreaseNestLevel(state);
|
||||
@ -562,8 +550,7 @@ static bool ParsePrefix(State *state) {
|
||||
// ::= <source-name> [<abi-tags>]
|
||||
// ::= <local-source-name> [<abi-tags>]
|
||||
static bool ParseUnqualifiedName(State* state) {
|
||||
return (ParseOperatorName(state) ||
|
||||
ParseCtorDtorName(state) ||
|
||||
return (ParseOperatorName(state) || ParseCtorDtorName(state) ||
|
||||
(ParseSourceName(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)
|
||||
static bool ParseIdentifier(State* state, ssize_t length) {
|
||||
if (length == -1 ||
|
||||
!AtLeastNumCharsRemaining(state->mangled_cur, length)) {
|
||||
if (length == -1 || !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
|
||||
return false;
|
||||
}
|
||||
if (IdentifierIsAnonymousNamespace(state, length)) {
|
||||
@ -712,10 +698,8 @@ static bool ParseOperatorName(State *state) {
|
||||
}
|
||||
// First check with "cv" (cast) case.
|
||||
State copy = *state;
|
||||
if (ParseTwoCharToken(state, "cv") &&
|
||||
MaybeAppend(state, "operator ") &&
|
||||
EnterNestedName(state) &&
|
||||
ParseType(state) &&
|
||||
if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") &&
|
||||
EnterNestedName(state) && ParseType(state) &&
|
||||
LeaveNestedName(state, copy.nest_level)) {
|
||||
return true;
|
||||
}
|
||||
@ -730,8 +714,7 @@ static bool ParseOperatorName(State *state) {
|
||||
|
||||
// Other operator names should start with a lower alphabet followed
|
||||
// by a lower/upper alphabet.
|
||||
if (!(IsLower(state->mangled_cur[0]) &&
|
||||
IsAlpha(state->mangled_cur[1]))) {
|
||||
if (!(IsLower(state->mangled_cur[0]) && IsAlpha(state->mangled_cur[1]))) {
|
||||
return false;
|
||||
}
|
||||
// We may want to perform a binary search if we really need speed.
|
||||
@ -771,8 +754,7 @@ static bool ParseOperatorName(State *state) {
|
||||
// stack traces. The are special data.
|
||||
static bool ParseSpecialName(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'T') &&
|
||||
ParseCharClass(state, "VTIS") &&
|
||||
if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
|
||||
ParseType(state)) {
|
||||
return true;
|
||||
}
|
||||
@ -784,8 +766,7 @@ static bool ParseSpecialName(State *state) {
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseTwoCharToken(state, "GV") &&
|
||||
ParseName(state)) {
|
||||
if (ParseTwoCharToken(state, "GV") && ParseName(state)) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -833,14 +814,14 @@ static bool ParseSpecialName(State *state) {
|
||||
// ::= v <v-offset> _
|
||||
static bool ParseCallOffset(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'h') &&
|
||||
ParseNVOffset(state) && ParseOneCharToken(state, '_')) {
|
||||
if (ParseOneCharToken(state, 'h') && ParseNVOffset(state) &&
|
||||
ParseOneCharToken(state, '_')) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseOneCharToken(state, 'v') &&
|
||||
ParseVOffset(state) && ParseOneCharToken(state, '_')) {
|
||||
if (ParseOneCharToken(state, 'v') && ParseVOffset(state) &&
|
||||
ParseOneCharToken(state, '_')) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -866,8 +847,7 @@ static bool ParseVOffset(State *state) {
|
||||
// ::= D0 | D1 | D2
|
||||
static bool ParseCtorDtorName(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'C') &&
|
||||
ParseCharClass(state, "123")) {
|
||||
if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "123")) {
|
||||
const char* const prev_name = state->prev_name;
|
||||
const ssize_t prev_name_length = state->prev_name_length;
|
||||
MaybeAppendWithLength(state, prev_name, prev_name_length);
|
||||
@ -875,8 +855,7 @@ static bool ParseCtorDtorName(State *state) {
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseOneCharToken(state, 'D') &&
|
||||
ParseCharClass(state, "012")) {
|
||||
if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "012")) {
|
||||
const char* const prev_name = state->prev_name;
|
||||
const ssize_t prev_name_length = state->prev_name_length;
|
||||
MaybeAppend(state, "~");
|
||||
@ -937,17 +916,13 @@ static bool ParseType(State *state) {
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseBuiltinType(state) ||
|
||||
ParseFunctionType(state) ||
|
||||
ParseClassEnumType(state) ||
|
||||
ParseArrayType(state) ||
|
||||
ParsePointerToMemberType(state) ||
|
||||
ParseSubstitution(state)) {
|
||||
if (ParseBuiltinType(state) || ParseFunctionType(state) ||
|
||||
ParseClassEnumType(state) || ParseArrayType(state) ||
|
||||
ParsePointerToMemberType(state) || ParseSubstitution(state)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParseTemplateTemplateParam(state) &&
|
||||
ParseTemplateArgs(state)) {
|
||||
if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -995,8 +970,8 @@ static bool ParseBuiltinType(State *state) {
|
||||
static bool ParseFunctionType(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'F') &&
|
||||
Optional(ParseOneCharToken(state, 'Y')) &&
|
||||
ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) {
|
||||
Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -1017,9 +992,7 @@ static bool ParseBareFunctionType(State *state) {
|
||||
}
|
||||
|
||||
// <class-enum-type> ::= <name>
|
||||
static bool ParseClassEnumType(State *state) {
|
||||
return ParseName(state);
|
||||
}
|
||||
static bool ParseClassEnumType(State* state) { return ParseName(state); }
|
||||
|
||||
// <array-type> ::= A <(positive dimension) number> _ <(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>
|
||||
static bool ParsePointerToMemberType(State* state) {
|
||||
State copy = *state;
|
||||
if (ParseOneCharToken(state, 'M') && ParseType(state) &&
|
||||
ParseType(state)) {
|
||||
if (ParseOneCharToken(state, 'M') && ParseType(state) && ParseType(state)) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
@ -1068,20 +1040,17 @@ static bool ParseTemplateParam(State *state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// <template-template-param> ::= <template-param>
|
||||
// ::= <substitution>
|
||||
static bool ParseTemplateTemplateParam(State* state) {
|
||||
return (ParseTemplateParam(state) ||
|
||||
ParseSubstitution(state));
|
||||
return (ParseTemplateParam(state) || ParseSubstitution(state));
|
||||
}
|
||||
|
||||
// <template-args> ::= I <template-arg>+ E
|
||||
static bool ParseTemplateArgs(State* state) {
|
||||
State copy = *state;
|
||||
DisableAppend(state);
|
||||
if (ParseOneCharToken(state, 'I') &&
|
||||
OneOrMore(ParseTemplateArg, state) &&
|
||||
if (ParseOneCharToken(state, 'I') && OneOrMore(ParseTemplateArg, state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
RestoreAppend(state, copy.append);
|
||||
MaybeAppend(state, "<>");
|
||||
@ -1107,15 +1076,13 @@ static bool ParseTemplateArg(State *state) {
|
||||
|
||||
State copy = *state;
|
||||
if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) &&
|
||||
ZeroOrMore(ParseTemplateArg, state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
ZeroOrMore(ParseTemplateArg, state) && ParseOneCharToken(state, 'E')) {
|
||||
--state->arg_level;
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseType(state) ||
|
||||
ParseExprPrimary(state)) {
|
||||
if (ParseType(state) || ParseExprPrimary(state)) {
|
||||
--state->arg_level;
|
||||
return true;
|
||||
}
|
||||
@ -1153,25 +1120,21 @@ static bool ParseExpression(State *state) {
|
||||
++state->expr_level;
|
||||
|
||||
State copy = *state;
|
||||
if (ParseOperatorName(state) &&
|
||||
ParseExpression(state) &&
|
||||
ParseExpression(state) &&
|
||||
if (ParseOperatorName(state) && ParseExpression(state) &&
|
||||
ParseExpression(state) && ParseExpression(state)) {
|
||||
--state->expr_level;
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseOperatorName(state) && ParseExpression(state) &&
|
||||
ParseExpression(state)) {
|
||||
--state->expr_level;
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseOperatorName(state) &&
|
||||
ParseExpression(state) &&
|
||||
ParseExpression(state)) {
|
||||
--state->expr_level;
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
if (ParseOperatorName(state) &&
|
||||
ParseExpression(state)) {
|
||||
if (ParseOperatorName(state) && ParseExpression(state)) {
|
||||
--state->expr_level;
|
||||
return true;
|
||||
}
|
||||
@ -1184,8 +1147,7 @@ static bool ParseExpression(State *state) {
|
||||
*state = copy;
|
||||
|
||||
if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
|
||||
ParseUnqualifiedName(state) &&
|
||||
ParseTemplateArgs(state)) {
|
||||
ParseUnqualifiedName(state) && ParseTemplateArgs(state)) {
|
||||
--state->expr_level;
|
||||
return true;
|
||||
}
|
||||
@ -1214,8 +1176,7 @@ static bool ParseExprPrimary(State *state) {
|
||||
*state = copy;
|
||||
|
||||
if (ParseOneCharToken(state, 'L') && ParseType(state) &&
|
||||
ParseFloatNumber(state) &&
|
||||
ParseOneCharToken(state, 'E')) {
|
||||
ParseFloatNumber(state) && ParseOneCharToken(state, 'E')) {
|
||||
return true;
|
||||
}
|
||||
*state = copy;
|
||||
|
||||
@ -67,14 +67,11 @@ static const char *DemangleIt(const char * const mangled) {
|
||||
|
||||
# if defined(HAVE_DBGHELP) && !defined(NDEBUG)
|
||||
TEST(Demangle, Windows) {
|
||||
EXPECT_STREQ(
|
||||
"public: static void __cdecl Foo::func(int)",
|
||||
EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
|
||||
DemangleIt("?func@Foo@@SAXH@Z"));
|
||||
EXPECT_STREQ(
|
||||
"public: static void __cdecl Foo::func(int)",
|
||||
EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
|
||||
DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
|
||||
EXPECT_STREQ(
|
||||
"int __cdecl foobarArray(int * const)",
|
||||
EXPECT_STREQ("int __cdecl foobarArray(int * const)",
|
||||
DemangleIt("?foobarArray@@YAHQAH@Z"));
|
||||
}
|
||||
# endif
|
||||
|
||||
@ -56,8 +56,8 @@ const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
|
||||
# ifdef ERROR
|
||||
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
|
||||
# endif
|
||||
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
|
||||
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
|
||||
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING, ERROR = GLOG_ERROR,
|
||||
FATAL = GLOG_FATAL;
|
||||
#endif
|
||||
|
||||
// DFATAL is FATAL in debug mode, ERROR in normal mode
|
||||
|
||||
@ -404,7 +404,8 @@ typedef void (*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l,
|
||||
|
||||
# if !defined(DECLARE_uint32)
|
||||
// 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)
|
||||
|
||||
// Special case for string, because we have to specify the namespace
|
||||
|
||||
@ -79,7 +79,8 @@
|
||||
__FILE__, __LINE__, &vlocal__, sizeof(google::SiteFlag), "")); \
|
||||
google::int32 verbose_level__ = (verboselevel); \
|
||||
(vlocal__.level == nullptr \
|
||||
? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, verbose_level__) \
|
||||
? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, \
|
||||
verbose_level__) \
|
||||
: *vlocal__.level >= verbose_level__); \
|
||||
})
|
||||
#else
|
||||
|
||||
@ -130,8 +130,8 @@ void InitGoogleTest(int*, char**) {}
|
||||
# define EXPECT_NEAR(val1, val2, abs_error) \
|
||||
do { \
|
||||
if (abs(val1 - val2) > abs_error) { \
|
||||
fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, #abs_error, \
|
||||
#val2); \
|
||||
fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, \
|
||||
#abs_error, #val2); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while (0)
|
||||
@ -196,13 +196,15 @@ vector<void (*)()> g_testlist; // the tests to run
|
||||
# define TEST(a, b) \
|
||||
struct Test_##a##_##b { \
|
||||
Test_##a##_##b() { g_testlist.push_back(&Run); } \
|
||||
static void Run() { FlagSaver fs; RunTest(); } \
|
||||
static void Run() { \
|
||||
FlagSaver fs; \
|
||||
RunTest(); \
|
||||
} \
|
||||
static void RunTest(); \
|
||||
}; \
|
||||
static Test_##a##_##b g_test_##a##_##b; \
|
||||
void Test_##a##_##b::RunTest()
|
||||
|
||||
|
||||
static inline int RUN_ALL_TESTS() {
|
||||
vector<void (*)()>::const_iterator it;
|
||||
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
|
||||
@ -317,8 +319,7 @@ class CapturedStream {
|
||||
CHECK(uncaptured_fd_ != -1);
|
||||
|
||||
// Open file to save stream to
|
||||
int cap_fd = open(filename_.c_str(),
|
||||
O_CREAT | O_TRUNC | O_WRONLY,
|
||||
int cap_fd = open(filename_.c_str(), O_CREAT | O_TRUNC | O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
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
|
||||
// pre-determined file size is reached.
|
||||
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;
|
||||
} 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) {
|
||||
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
|
||||
CapturedStream* const cap = s_captured_streams[fd];
|
||||
CHECK(cap)
|
||||
<< ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
|
||||
CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
|
||||
|
||||
// Make sure everything is flushed.
|
||||
cap->StopCapture();
|
||||
@ -468,8 +469,7 @@ static inline string MungeLine(const string& line) {
|
||||
MungeLine(rest));
|
||||
}
|
||||
|
||||
static inline void StringReplace(string* str,
|
||||
const string& oldsub,
|
||||
static inline void StringReplace(string* str, const string& oldsub,
|
||||
const string& newsub) {
|
||||
size_t pos = str->find(oldsub);
|
||||
if (pos != string::npos) {
|
||||
@ -589,9 +589,7 @@ class Thread {
|
||||
handle_ = CreateThread(nullptr, 0, &Thread::InvokeThreadW, this, 0, &th_);
|
||||
CHECK(handle_) << "CreateThread";
|
||||
}
|
||||
void Join() {
|
||||
WaitForSingleObject(handle_, INFINITE);
|
||||
}
|
||||
void Join() { WaitForSingleObject(handle_, INFINITE); }
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
void Start() { pthread_create(&th_, nullptr, &Thread::InvokeThread, this); }
|
||||
void Join() { pthread_join(th_, nullptr); }
|
||||
|
||||
432
src/logging.cc
432
src/logging.cc
@ -97,21 +97,21 @@
|
||||
typedef int mode_t;
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::setw;
|
||||
using std::setfill;
|
||||
using std::hex;
|
||||
using std::dec;
|
||||
using std::hex;
|
||||
using std::min;
|
||||
using std::ostream;
|
||||
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::fflush;
|
||||
using std::FILE;
|
||||
using std::fprintf;
|
||||
using std::fwrite;
|
||||
using std::perror;
|
||||
|
||||
#ifdef __QNX__
|
||||
@ -147,7 +147,9 @@ GLOG_DEFINE_bool(colorlogtostdout, false,
|
||||
GLOG_DEFINE_bool(logtostdout, BoolFromEnv("GOOGLE_LOGTOSTDOUT", false),
|
||||
"log messages go to stdout instead of logfiles");
|
||||
#ifdef GLOG_OS_LINUX
|
||||
GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "
|
||||
GLOG_DEFINE_bool(
|
||||
drop_log_memory, true,
|
||||
"Drop in-memory buffers of log contents. "
|
||||
"Logs can grow very quickly and they are rarely read before they "
|
||||
"need to be evicted from memory. Instead, drop them from memory "
|
||||
"as soon as they are flushed to disk.");
|
||||
@ -171,7 +173,8 @@ GLOG_DEFINE_bool(log_prefix, true,
|
||||
"Prepend the log prefix to the start of each log line");
|
||||
GLOG_DEFINE_bool(log_year_in_prefix, true,
|
||||
"Include the year in the log prefix");
|
||||
GLOG_DEFINE_int32(minloglevel, 0, "Messages logged at a lower level than this don't "
|
||||
GLOG_DEFINE_int32(minloglevel, 0,
|
||||
"Messages logged at a lower level than this don't "
|
||||
"actually get logged anywhere");
|
||||
GLOG_DEFINE_int32(logbuflevel, 0,
|
||||
"Buffer log messages logged at this level or lower"
|
||||
@ -187,8 +190,7 @@ GLOG_DEFINE_int32(logemaillevel, 999,
|
||||
"Email log messages logged at this level or higher"
|
||||
" (0 means email all; 3 means email FATAL only;"
|
||||
" ...)");
|
||||
GLOG_DEFINE_string(logmailer, "",
|
||||
"Mailer used to send logging email");
|
||||
GLOG_DEFINE_string(logmailer, "", "Mailer used to send logging email");
|
||||
|
||||
// Compute the default value for --log_dir
|
||||
static const char* DefaultLogDir() {
|
||||
@ -206,10 +208,12 @@ static const char* DefaultLogDir() {
|
||||
|
||||
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 "
|
||||
"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");
|
||||
|
||||
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, "",
|
||||
"Emit a backtrace when logging at file:linenum.");
|
||||
|
||||
GLOG_DEFINE_bool(log_utc_time, false,
|
||||
"Use UTC time for logging.");
|
||||
GLOG_DEFINE_bool(log_utc_time, false, "Use UTC time for logging.");
|
||||
|
||||
// TODO(hamaji): consider windows
|
||||
enum { PATH_SEPARATOR = '/' };
|
||||
@ -231,15 +234,11 @@ enum { PATH_SEPARATOR = '/' };
|
||||
#ifndef HAVE_PREAD
|
||||
static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
|
||||
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
|
||||
if (orig_offset == (off_t)-1)
|
||||
return -1;
|
||||
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
|
||||
return -1;
|
||||
if (orig_offset == (off_t)-1) return -1;
|
||||
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
|
||||
ssize_t len = read(fd, buf, count);
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
|
||||
return -1;
|
||||
if (len < 0) return len;
|
||||
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
|
||||
return len;
|
||||
}
|
||||
#endif // !HAVE_PREAD
|
||||
@ -247,15 +246,11 @@ static ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
|
||||
#ifndef HAVE_PWRITE
|
||||
static ssize_t pwrite(int fd, void* buf, size_t count, off_t offset) {
|
||||
off_t orig_offset = lseek(fd, 0, SEEK_CUR);
|
||||
if (orig_offset == (off_t)-1)
|
||||
return -1;
|
||||
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1)
|
||||
return -1;
|
||||
if (orig_offset == (off_t)-1) return -1;
|
||||
if (lseek(fd, offset, SEEK_CUR) == (off_t)-1) return -1;
|
||||
ssize_t len = write(fd, buf, count);
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1)
|
||||
return -1;
|
||||
if (len < 0) return len;
|
||||
if (lseek(fd, orig_offset, SEEK_SET) == (off_t)-1) return -1;
|
||||
return len;
|
||||
}
|
||||
#endif // !HAVE_PWRITE
|
||||
@ -294,16 +289,11 @@ static bool TerminalSupportsColor() {
|
||||
const char* const term = getenv("TERM");
|
||||
if (term != nullptr && term[0] != '\0') {
|
||||
term_supports_color =
|
||||
!strcmp(term, "xterm") ||
|
||||
!strcmp(term, "xterm-color") ||
|
||||
!strcmp(term, "xterm-256color") ||
|
||||
!strcmp(term, "screen-256color") ||
|
||||
!strcmp(term, "konsole") ||
|
||||
!strcmp(term, "konsole-16color") ||
|
||||
!strcmp(term, "konsole-256color") ||
|
||||
!strcmp(term, "screen") ||
|
||||
!strcmp(term, "linux") ||
|
||||
!strcmp(term, "cygwin");
|
||||
!strcmp(term, "xterm") || !strcmp(term, "xterm-color") ||
|
||||
!strcmp(term, "xterm-256color") || !strcmp(term, "screen-256color") ||
|
||||
!strcmp(term, "konsole") || !strcmp(term, "konsole-16color") ||
|
||||
!strcmp(term, "konsole-256color") || !strcmp(term, "screen") ||
|
||||
!strcmp(term, "linux") || !strcmp(term, "cygwin");
|
||||
}
|
||||
#endif
|
||||
return term_supports_color;
|
||||
@ -311,12 +301,7 @@ static bool TerminalSupportsColor() {
|
||||
|
||||
namespace google {
|
||||
|
||||
enum GLogColor {
|
||||
COLOR_DEFAULT,
|
||||
COLOR_RED,
|
||||
COLOR_GREEN,
|
||||
COLOR_YELLOW
|
||||
};
|
||||
enum GLogColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW };
|
||||
|
||||
static GLogColor SeverityToColor(LogSeverity severity) {
|
||||
assert(severity >= 0 && severity < NUM_SEVERITIES);
|
||||
@ -344,10 +329,14 @@ static GLogColor SeverityToColor(LogSeverity severity) {
|
||||
// Returns the character attribute for the given color.
|
||||
static WORD GetColorAttribute(GLogColor color) {
|
||||
switch (color) {
|
||||
case COLOR_RED: return FOREGROUND_RED;
|
||||
case COLOR_GREEN: return FOREGROUND_GREEN;
|
||||
case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
|
||||
default: return 0;
|
||||
case COLOR_RED:
|
||||
return FOREGROUND_RED;
|
||||
case COLOR_GREEN:
|
||||
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.
|
||||
static const char* GetAnsiColorCode(GLogColor color) {
|
||||
switch (color) {
|
||||
case COLOR_RED: return "1";
|
||||
case COLOR_GREEN: return "2";
|
||||
case COLOR_YELLOW: return "3";
|
||||
case COLOR_DEFAULT: return "";
|
||||
case COLOR_RED:
|
||||
return "1";
|
||||
case COLOR_GREEN:
|
||||
return "2";
|
||||
case COLOR_YELLOW:
|
||||
return "3";
|
||||
case COLOR_DEFAULT:
|
||||
return "";
|
||||
};
|
||||
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)
|
||||
static bool stop_writing = false;
|
||||
|
||||
const char*const LogSeverityNames[NUM_SEVERITIES] = {
|
||||
"INFO", "WARNING", "ERROR", "FATAL"
|
||||
};
|
||||
const char* const LogSeverityNames[NUM_SEVERITIES] = {"INFO", "WARNING",
|
||||
"ERROR", "FATAL"};
|
||||
|
||||
// Has the user called SetExitOnDFatal(true)?
|
||||
static bool exit_on_dfatal = true;
|
||||
@ -440,7 +432,7 @@ namespace {
|
||||
CustomPrefixCallback custom_prefix_callback = nullptr;
|
||||
// User-provided data to pass to the callback:
|
||||
void* custom_prefix_callback_data = nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
@ -509,8 +501,7 @@ class LogCleaner {
|
||||
// update next_cleanup_time_
|
||||
void UpdateCleanUpTime();
|
||||
|
||||
void Run(bool base_filename_selected,
|
||||
const string& base_filename,
|
||||
void Run(bool base_filename_selected, const string& base_filename,
|
||||
const string& filename_extension);
|
||||
|
||||
bool enabled() const { return enabled_; }
|
||||
@ -545,8 +536,7 @@ class LogDestination {
|
||||
// These methods are just forwarded to by their global versions.
|
||||
static void SetLogDestination(LogSeverity severity,
|
||||
const char* base_filename);
|
||||
static void SetLogSymlink(LogSeverity severity,
|
||||
const char* symlink_basename);
|
||||
static void SetLogSymlink(LogSeverity severity, const char* symlink_basename);
|
||||
static void AddLogSink(LogSink* destination);
|
||||
static void RemoveLogSink(LogSink* destination);
|
||||
static void SetLogFilenameExtension(const char* filename_extension);
|
||||
@ -584,14 +574,12 @@ class LogDestination {
|
||||
size_t len);
|
||||
// Take a log message of a particular severity and log it to a file
|
||||
// iff the base filename is not "" (which means "don't log to me")
|
||||
static void MaybeLogToLogfile(LogSeverity severity,
|
||||
time_t timestamp,
|
||||
static void MaybeLogToLogfile(LogSeverity severity, time_t timestamp,
|
||||
const char* message, size_t len);
|
||||
// Take a log message of a particular severity and log it to the file
|
||||
// for that severity and also for all files with severity less than
|
||||
// this severity.
|
||||
static void LogToAllLogfiles(LogSeverity severity,
|
||||
time_t timestamp,
|
||||
static void LogToAllLogfiles(LogSeverity severity, time_t timestamp,
|
||||
const char* message, size_t len);
|
||||
|
||||
// Send logging info to all registered sinks.
|
||||
@ -652,15 +640,10 @@ const string& LogDestination::hostname() {
|
||||
return hostname_;
|
||||
}
|
||||
|
||||
LogDestination::LogDestination(LogSeverity severity,
|
||||
const char* base_filename)
|
||||
: fileobject_(severity, base_filename),
|
||||
logger_(&fileobject_) {
|
||||
}
|
||||
LogDestination::LogDestination(LogSeverity severity, const char* base_filename)
|
||||
: fileobject_(severity, base_filename), logger_(&fileobject_) {}
|
||||
|
||||
LogDestination::~LogDestination() {
|
||||
ResetLoggerImpl();
|
||||
}
|
||||
LogDestination::~LogDestination() { ResetLoggerImpl(); }
|
||||
|
||||
void LogDestination::SetLoggerImpl(base::Logger* logger) {
|
||||
if (logger_ == logger) {
|
||||
@ -731,7 +714,8 @@ inline void LogDestination::RemoveLogSink(LogSink *destination) {
|
||||
MutexLock l(&sink_mutex_);
|
||||
// This doesn't keep the sinks in order, but who cares?
|
||||
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,
|
||||
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) {
|
||||
ColoredWriteToStderr(severity, message, message_len);
|
||||
#ifdef GLOG_OS_WINDOWS
|
||||
@ -859,11 +845,9 @@ inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
|
||||
const char* message, size_t len) {
|
||||
if (severity >= email_logging_severity_ ||
|
||||
severity >= FLAGS_logemaillevel) {
|
||||
if (severity >= email_logging_severity_ || severity >= FLAGS_logemaillevel) {
|
||||
string to(FLAGS_alsologtoemail);
|
||||
if (!addresses_.empty()) {
|
||||
if (!to.empty()) {
|
||||
@ -871,7 +855,8 @@ inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
|
||||
}
|
||||
to += addresses_;
|
||||
}
|
||||
const string subject(string("[LOG] ") + LogSeverityNames[severity] + ": " +
|
||||
const string subject(
|
||||
string("[LOG] ") + LogSeverityNames[severity] + ": " +
|
||||
glog_internal_namespace_::ProgramInvocationShortName());
|
||||
string body(hostname());
|
||||
body += "\n\n";
|
||||
@ -885,11 +870,9 @@ inline void LogDestination::MaybeLogToEmail(LogSeverity severity,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
|
||||
time_t timestamp,
|
||||
const char* message,
|
||||
size_t len) {
|
||||
const char* message, size_t len) {
|
||||
const bool should_flush = severity > FLAGS_logbuflevel;
|
||||
LogDestination* destination = log_destination(severity);
|
||||
destination->logger_->Write(should_flush, timestamp, message, len);
|
||||
@ -897,8 +880,7 @@ inline void LogDestination::MaybeLogToLogfile(LogSeverity severity,
|
||||
|
||||
inline void LogDestination::LogToAllLogfiles(LogSeverity severity,
|
||||
time_t timestamp,
|
||||
const char* message,
|
||||
size_t len) {
|
||||
const char* message, size_t len) {
|
||||
if (FLAGS_logtostdout) { // global flag: never log to file
|
||||
ColoredWriteToStdout(severity, message, len);
|
||||
} else if (FLAGS_logtostderr) { // global flag: never log to file
|
||||
@ -919,8 +901,8 @@ inline void LogDestination::LogToSinks(LogSeverity severity,
|
||||
ReaderMutexLock l(&sink_mutex_);
|
||||
if (sinks_) {
|
||||
for (size_t i = sinks_->size(); i-- > 0;) {
|
||||
(*sinks_)[i]->send(severity, full_filename, base_filename,
|
||||
line, logmsgtime, message, message_len);
|
||||
(*sinks_)[i]->send(severity, full_filename, base_filename, line,
|
||||
logmsgtime, message, message_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1056,8 +1038,8 @@ void LogFileObject::FlushUnlocked(){
|
||||
bytes_since_flush_ = 0;
|
||||
}
|
||||
// Figure out when we are due for another flush.
|
||||
const int64 next = (FLAGS_logbufsecs
|
||||
* static_cast<int64>(1000000)); // in usec
|
||||
const int64 next =
|
||||
(FLAGS_logbufsecs * static_cast<int64>(1000000)); // in usec
|
||||
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!
|
||||
close(fd);
|
||||
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;
|
||||
}
|
||||
#ifdef GLOG_OS_WINDOWS
|
||||
// https://github.com/golang/go/issues/27638 - make sure we seek to the end to append
|
||||
// empirically replicated with wine over mingw build
|
||||
// https://github.com/golang/go/issues/27638 - make sure we seek to the end to
|
||||
// append empirically replicated with wine over mingw build
|
||||
if (!FLAGS_timestamp_in_logfile_name) {
|
||||
if (fseek(file_, 0, SEEK_END) != 0) {
|
||||
return false;
|
||||
@ -1133,7 +1116,9 @@ bool LogFileObject::CreateLogfile(const string& time_pid_string) {
|
||||
const string linkname =
|
||||
symlink_basename_ + '.' + LogSeverityNames[severity_];
|
||||
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;
|
||||
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
|
||||
}
|
||||
|
||||
void LogFileObject::Write(bool force_flush,
|
||||
time_t timestamp,
|
||||
const char* message,
|
||||
size_t message_len) {
|
||||
void LogFileObject::Write(bool force_flush, time_t timestamp,
|
||||
const char* message, size_t message_len) {
|
||||
MutexLock l(&lock_);
|
||||
|
||||
// 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
|
||||
ostringstream time_pid_stream;
|
||||
time_pid_stream.fill('0');
|
||||
time_pid_stream << 1900+tm_time.tm_year
|
||||
<< setw(2) << 1+tm_time.tm_mon
|
||||
<< setw(2) << tm_time.tm_mday
|
||||
<< '-'
|
||||
<< setw(2) << tm_time.tm_hour
|
||||
<< setw(2) << tm_time.tm_min
|
||||
<< setw(2) << tm_time.tm_sec
|
||||
<< '.'
|
||||
<< GetMainThreadPid();
|
||||
time_pid_stream << 1900 + tm_time.tm_year << setw(2) << 1 + tm_time.tm_mon
|
||||
<< setw(2) << tm_time.tm_mday << '-' << setw(2)
|
||||
<< tm_time.tm_hour << setw(2) << tm_time.tm_min << setw(2)
|
||||
<< tm_time.tm_sec << '.' << GetMainThreadPid();
|
||||
const string& time_pid_string = time_pid_stream.str();
|
||||
|
||||
if (base_filename_selected_) {
|
||||
@ -1241,9 +1219,8 @@ void LogFileObject::Write(bool force_flush,
|
||||
// deadlock. Simply use a name like invalid-user.
|
||||
if (uidname.empty()) uidname = "invalid-user";
|
||||
|
||||
stripped_filename = stripped_filename+'.'+hostname+'.'
|
||||
+uidname+".log."
|
||||
+LogSeverityNames[severity_]+'.';
|
||||
stripped_filename = stripped_filename + '.' + hostname + '.' + uidname +
|
||||
".log." + LogSeverityNames[severity_] + '.';
|
||||
// We're going to (potentially) try to put logs in several different dirs
|
||||
const vector<string>& log_dirs = GetLoggingDirectories();
|
||||
|
||||
@ -1270,25 +1247,26 @@ void LogFileObject::Write(bool force_flush,
|
||||
if (FLAGS_log_file_header) {
|
||||
ostringstream file_header_stream;
|
||||
file_header_stream.fill('0');
|
||||
file_header_stream << "Log file created at: "
|
||||
<< 1900+tm_time.tm_year << '/'
|
||||
<< setw(2) << 1+tm_time.tm_mon << '/'
|
||||
<< setw(2) << tm_time.tm_mday
|
||||
<< ' '
|
||||
<< setw(2) << tm_time.tm_hour << ':'
|
||||
<< setw(2) << tm_time.tm_min << ':'
|
||||
<< setw(2) << tm_time.tm_sec << (FLAGS_log_utc_time ? " UTC\n" : "\n")
|
||||
<< "Running on machine: "
|
||||
<< LogDestination::hostname() << '\n';
|
||||
file_header_stream << "Log file created at: " << 1900 + tm_time.tm_year
|
||||
<< '/' << setw(2) << 1 + tm_time.tm_mon << '/'
|
||||
<< setw(2) << tm_time.tm_mday << ' ' << setw(2)
|
||||
<< tm_time.tm_hour << ':' << setw(2) << tm_time.tm_min
|
||||
<< ':' << setw(2) << tm_time.tm_sec
|
||||
<< (FLAGS_log_utc_time ? " UTC\n" : "\n")
|
||||
<< "Running on machine: " << LogDestination::hostname()
|
||||
<< '\n';
|
||||
|
||||
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
|
||||
? "yyyymmdd hh:mm:ss.uuuuuu"
|
||||
: "mmdd hh:mm:ss.uuuuuu";
|
||||
file_header_stream << "Running duration (h:mm:ss): "
|
||||
<< PrettyDuration(static_cast<int>(WallTime_Now() - start_time_)) << '\n'
|
||||
<< PrettyDuration(
|
||||
static_cast<int>(WallTime_Now() - start_time_))
|
||||
<< '\n'
|
||||
<< "Log line format: [IWEF]" << date_time_format << " "
|
||||
<< "threadid file:line] msg" << '\n';
|
||||
const string& file_header_string = file_header_stream.str();
|
||||
@ -1326,8 +1304,7 @@ void LogFileObject::Write(bool force_flush,
|
||||
|
||||
// See important msgs *now*. Also, flush logs at least every 10^6 chars,
|
||||
// or every "FLAGS_logbufsecs" seconds.
|
||||
if ( force_flush ||
|
||||
(bytes_since_flush_ >= 1000000) ||
|
||||
if (force_flush || (bytes_since_flush_ >= 1000000) ||
|
||||
(CycleClock_Now() >= next_flush_time_)) {
|
||||
FlushUnlocked();
|
||||
#ifdef GLOG_OS_LINUX
|
||||
@ -1355,8 +1332,7 @@ void LogFileObject::Write(bool force_flush,
|
||||
|
||||
// Remove old logs
|
||||
if (log_cleaner.enabled()) {
|
||||
log_cleaner.Run(base_filename_selected_,
|
||||
base_filename_,
|
||||
log_cleaner.Run(base_filename_selected_, base_filename_,
|
||||
filename_extension_);
|
||||
}
|
||||
}
|
||||
@ -1369,18 +1345,14 @@ void LogCleaner::Enable(unsigned int overdue_days) {
|
||||
overdue_days_ = overdue_days;
|
||||
}
|
||||
|
||||
void LogCleaner::Disable() {
|
||||
enabled_ = false;
|
||||
}
|
||||
void LogCleaner::Disable() { enabled_ = false; }
|
||||
|
||||
void LogCleaner::UpdateCleanUpTime() {
|
||||
const int64 next = (FLAGS_logcleansecs
|
||||
* 1000000); // in usec
|
||||
const int64 next = (FLAGS_logcleansecs * 1000000); // in usec
|
||||
next_cleanup_time_ = CycleClock_Now() + UsecToCycles(next);
|
||||
}
|
||||
|
||||
void LogCleaner::Run(bool base_filename_selected,
|
||||
const string& base_filename,
|
||||
void LogCleaner::Run(bool base_filename_selected, const string& base_filename,
|
||||
const string& filename_extension) {
|
||||
assert(enabled_);
|
||||
assert(!base_filename_selected || !base_filename.empty());
|
||||
@ -1441,7 +1413,8 @@ vector<string> LogCleaner::GetOverdueLogNames(
|
||||
filepath = log_directory + filepath;
|
||||
}
|
||||
|
||||
if (IsLogFromCurrentProject(filepath, base_filename, filename_extension) &&
|
||||
if (IsLogFromCurrentProject(filepath, base_filename,
|
||||
filename_extension) &&
|
||||
IsLogLastModifiedOver(filepath, days)) {
|
||||
overdue_log_names.push_back(filepath);
|
||||
}
|
||||
@ -1452,8 +1425,8 @@ vector<string> LogCleaner::GetOverdueLogNames(
|
||||
return overdue_log_names;
|
||||
}
|
||||
|
||||
bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
|
||||
const string& base_filename,
|
||||
bool LogCleaner::IsLogFromCurrentProject(
|
||||
const string& filepath, const string& base_filename,
|
||||
const string& filename_extension) const {
|
||||
// We should remove duplicated delimiters from `base_filename`, e.g.,
|
||||
// before: "/tmp//<base_filename>.<create_time>.<pid>"
|
||||
@ -1488,11 +1461,11 @@ bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
|
||||
return false;
|
||||
}
|
||||
// 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) {
|
||||
cleaned_base_filename += filename_extension;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// for new version, `filename_extension` is right of the `filepath`.
|
||||
if (filename_extension.size() >= real_filepath_size) {
|
||||
return false;
|
||||
@ -1510,19 +1483,29 @@ bool LogCleaner::IsLogFromCurrentProject(const string& filepath,
|
||||
const char& c = filepath[i];
|
||||
|
||||
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: -
|
||||
if (c != '-') { return false; }
|
||||
if (c != '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
} 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: .
|
||||
if (c != '.') { return false; }
|
||||
if (c != '.') {
|
||||
return false;
|
||||
}
|
||||
|
||||
} 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)
|
||||
|
||||
LogMessage::LogMessageData::LogMessageData()
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
|
||||
}
|
||||
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {}
|
||||
|
||||
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
|
||||
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,
|
||||
LogSink* sink, bool also_send_to_log)
|
||||
: allocated_(nullptr) {
|
||||
Init(file, line, severity, also_send_to_log ? &LogMessage::SendToSinkAndLog :
|
||||
&LogMessage::SendToSink);
|
||||
Init(file, line, severity,
|
||||
also_send_to_log ? &LogMessage::SendToSinkAndLog
|
||||
: &LogMessage::SendToSink);
|
||||
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
|
||||
}
|
||||
|
||||
void LogMessage::Init(const char* file,
|
||||
int line,
|
||||
LogSeverity severity,
|
||||
void LogMessage::Init(const char* file, int line, LogSeverity severity,
|
||||
void (LogMessage::*send_method)()) {
|
||||
allocated_ = nullptr;
|
||||
if (severity != GLOG_FATAL || !exit_on_dfatal) {
|
||||
@ -1727,8 +1708,7 @@ LogMessage::~LogMessage() {
|
||||
if (data_ == static_cast<void*>(&thread_msg_data)) {
|
||||
data_->~LogMessageData();
|
||||
thread_data_available = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete allocated_;
|
||||
}
|
||||
#else // !defined(GLOG_THREAD_LOCAL_STORAGE)
|
||||
@ -1736,13 +1716,9 @@ LogMessage::~LogMessage() {
|
||||
#endif // defined(GLOG_THREAD_LOCAL_STORAGE)
|
||||
}
|
||||
|
||||
int LogMessage::preserved_errno() const {
|
||||
return data_->preserved_errno_;
|
||||
}
|
||||
int LogMessage::preserved_errno() const { return data_->preserved_errno_; }
|
||||
|
||||
ostream& LogMessage::stream() {
|
||||
return data_->stream_;
|
||||
}
|
||||
ostream& LogMessage::stream() { return data_->stream_; }
|
||||
|
||||
// Flush buffered message, called by the destructor, or any other function
|
||||
// that needs to synchronize the log.
|
||||
@ -1824,12 +1800,14 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
|
||||
log_mutex.AssertHeld();
|
||||
|
||||
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
|
||||
|
||||
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";
|
||||
WriteToStderr(w, strlen(w));
|
||||
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.
|
||||
LogDestination::LogToSinks(data_->severity_,
|
||||
data_->fullname_, data_->basename_,
|
||||
data_->line_, logmsgtime_,
|
||||
data_->message_text_ + data_->num_prefix_chars_,
|
||||
(data_->num_chars_to_log_ -
|
||||
data_->num_prefix_chars_ - 1) );
|
||||
LogDestination::LogToSinks(
|
||||
data_->severity_, data_->fullname_, data_->basename_, data_->line_,
|
||||
logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
|
||||
(data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
|
||||
} else {
|
||||
// log this message to all log files of severity <= severity_
|
||||
LogDestination::LogToAllLogfiles(data_->severity_, logmsgtime_.timestamp(),
|
||||
@ -1865,12 +1841,10 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
|
||||
data_->num_prefix_chars_);
|
||||
LogDestination::MaybeLogToEmail(data_->severity_, data_->message_text_,
|
||||
data_->num_chars_to_log_);
|
||||
LogDestination::LogToSinks(data_->severity_,
|
||||
data_->fullname_, data_->basename_,
|
||||
data_->line_, logmsgtime_,
|
||||
data_->message_text_ + data_->num_prefix_chars_,
|
||||
(data_->num_chars_to_log_
|
||||
- data_->num_prefix_chars_ - 1) );
|
||||
LogDestination::LogToSinks(
|
||||
data_->severity_, data_->fullname_, data_->basename_, data_->line_,
|
||||
logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
|
||||
(data_->num_chars_to_log_ - data_->num_prefix_chars_ - 1));
|
||||
// NOTE: -1 removes trailing \n
|
||||
}
|
||||
|
||||
@ -1885,8 +1859,8 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
|
||||
SetCrashReason(&crash_reason);
|
||||
|
||||
// Store shortened fatal message for other logs and GWQ status
|
||||
const size_t copy = min(data_->num_chars_to_log_,
|
||||
sizeof(fatal_message)-1);
|
||||
const size_t copy =
|
||||
min(data_->num_chars_to_log_, sizeof(fatal_message) - 1);
|
||||
memcpy(fatal_message, data_->message_text_, copy);
|
||||
fatal_message[copy] = '\0';
|
||||
fatal_time = logmsgtime_.timestamp();
|
||||
@ -1955,20 +1929,18 @@ void InstallFailureFunction(logging_fail_func_t fail_func) {
|
||||
g_logging_fail_func = fail_func;
|
||||
}
|
||||
|
||||
void LogMessage::Fail() {
|
||||
g_logging_fail_func();
|
||||
}
|
||||
void LogMessage::Fail() { g_logging_fail_func(); }
|
||||
|
||||
// L >= log_mutex (callers must hold the log_mutex).
|
||||
void LogMessage::SendToSink() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
|
||||
if (data_->sink_ != nullptr) {
|
||||
RAW_DCHECK(data_->num_chars_to_log_ > 0 &&
|
||||
data_->message_text_[data_->num_chars_to_log_-1] == '\n', "");
|
||||
data_->sink_->send(data_->severity_, data_->fullname_, data_->basename_,
|
||||
data_->line_, logmsgtime_,
|
||||
data_->message_text_ + data_->num_prefix_chars_,
|
||||
(data_->num_chars_to_log_ -
|
||||
data_->num_prefix_chars_ - 1) );
|
||||
data_->message_text_[data_->num_chars_to_log_ - 1] == '\n',
|
||||
"");
|
||||
data_->sink_->send(
|
||||
data_->severity_, data_->fullname_, data_->basename_, data_->line_,
|
||||
logmsgtime_, data_->message_text_ + data_->num_prefix_chars_,
|
||||
(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) {
|
||||
if (data_->outvec_ != nullptr) {
|
||||
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_.
|
||||
const char* start = data_->message_text_ + data_->num_prefix_chars_;
|
||||
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) {
|
||||
if (data_->message_ != nullptr) {
|
||||
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_.
|
||||
const char* start = data_->message_text_ + data_->num_prefix_chars_;
|
||||
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;
|
||||
if (!openlog_already_called) {
|
||||
openlog(glog_internal_namespace_::ProgramInvocationShortName(),
|
||||
LOG_CONS | LOG_NDELAY | LOG_PID,
|
||||
LOG_USER);
|
||||
LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER);
|
||||
openlog_already_called = true;
|
||||
}
|
||||
|
||||
@ -2065,8 +2038,8 @@ ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
|
||||
ErrnoLogMessage::~ErrnoLogMessage() {
|
||||
// Don't access errno directly because it may have been altered
|
||||
// while streaming the message.
|
||||
stream() << ": " << StrError(preserved_errno()) << " ["
|
||||
<< preserved_errno() << "]";
|
||||
stream() << ": " << StrError(preserved_errno()) << " [" << preserved_errno()
|
||||
<< "]";
|
||||
}
|
||||
|
||||
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) {
|
||||
stream << setw(4) << 1900 + logmsgtime.year();
|
||||
}
|
||||
stream << setw(2) << 1 + logmsgtime.month()
|
||||
<< setw(2) << logmsgtime.day()
|
||||
<< ' '
|
||||
<< setw(2) << logmsgtime.hour() << ':'
|
||||
<< setw(2) << logmsgtime.min() << ':'
|
||||
<< setw(2) << logmsgtime.sec() << '.'
|
||||
<< setw(6) << logmsgtime.usec()
|
||||
<< ' '
|
||||
<< setfill(' ') << setw(5) << GetTID() << setfill('0')
|
||||
<< ' '
|
||||
<< file << ':' << line << "] ";
|
||||
stream << setw(2) << 1 + logmsgtime.month() << setw(2) << logmsgtime.day()
|
||||
<< ' ' << setw(2) << logmsgtime.hour() << ':' << setw(2)
|
||||
<< logmsgtime.min() << ':' << setw(2) << logmsgtime.sec() << '.'
|
||||
<< setw(6) << logmsgtime.usec() << ' ' << setfill(' ') << setw(5)
|
||||
<< GetTID() << setfill('0') << ' ' << file << ':' << line << "] ";
|
||||
|
||||
// A call to `write' is enclosed in parenthneses to prevent possible macro
|
||||
// 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);
|
||||
}
|
||||
|
||||
void LogToStderr() {
|
||||
LogDestination::LogToStderr();
|
||||
}
|
||||
void LogToStderr() { LogDestination::LogToStderr(); }
|
||||
|
||||
namespace base {
|
||||
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
|
||||
// pipe or dash, which could be misunderstood as a command-line flag by
|
||||
// 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
|
||||
if (!std::regex_match(
|
||||
s,
|
||||
@ -2281,8 +2247,7 @@ static bool SendEmailInternal(const char*dest, const char *subject,
|
||||
if (use_logging) {
|
||||
VLOG(1) << "Invalid destination email address:" << s;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid destination email address: %s\n",
|
||||
s.c_str());
|
||||
fprintf(stderr, "Invalid destination email address: %s\n", s.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2296,11 +2261,11 @@ static bool SendEmailInternal(const char*dest, const char *subject,
|
||||
dest = tmp.c_str();
|
||||
|
||||
if (use_logging) {
|
||||
VLOG(1) << "Trying to send TITLE:" << subject
|
||||
<< " BODY:" << body << " to " << dest;
|
||||
VLOG(1) << "Trying to send TITLE:" << subject << " BODY:" << body
|
||||
<< " to " << dest;
|
||||
} else {
|
||||
fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n",
|
||||
subject, body, dest);
|
||||
fprintf(stderr, "Trying to send TITLE: %s BODY: %s to %s\n", subject,
|
||||
body, dest);
|
||||
}
|
||||
|
||||
string logmailer;
|
||||
@ -2330,8 +2295,8 @@ static bool SendEmailInternal(const char*dest, const char *subject,
|
||||
LOG(ERROR) << "Problems sending mail to " << dest << ": "
|
||||
<< StrError(errno);
|
||||
} else {
|
||||
fprintf(stderr, "Problems sending mail to %s: %s\n",
|
||||
dest, StrError(errno).c_str());
|
||||
fprintf(stderr, "Problems sending mail to %s: %s\n", dest,
|
||||
StrError(errno).c_str());
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
@ -2367,8 +2332,7 @@ static void GetTempDirectories(vector<string>* list) {
|
||||
// C:/WINDOWS/ or C:/WINNT/
|
||||
// .
|
||||
char tmp[MAX_PATH];
|
||||
if (GetTempPathA(MAX_PATH, tmp))
|
||||
list->push_back(tmp);
|
||||
if (GetTempPathA(MAX_PATH, tmp)) list->push_back(tmp);
|
||||
list->push_back("C:\\tmp\\");
|
||||
list->push_back("C:\\temp\\");
|
||||
#else
|
||||
@ -2379,7 +2343,8 @@ static void GetTempDirectories(vector<string>* list) {
|
||||
getenv("TEST_TMPDIR"),
|
||||
|
||||
// Explicitly-supplied temp dirs
|
||||
getenv("TMPDIR"), getenv("TMP"),
|
||||
getenv("TMPDIR"),
|
||||
getenv("TMP"),
|
||||
|
||||
// If all else fails
|
||||
"/tmp",
|
||||
@ -2414,7 +2379,8 @@ const vector<string>& GetLoggingDirectories() {
|
||||
|
||||
if (!FLAGS_log_dir.empty()) {
|
||||
// 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)) {
|
||||
logging_directories_list->push_back(FLAGS_log_dir + "/");
|
||||
} else {
|
||||
@ -2436,7 +2402,8 @@ const vector<string>& GetLoggingDirectories() {
|
||||
}
|
||||
|
||||
void TestOnly_ClearLoggingDirectoriesList() {
|
||||
fprintf(stderr, "TestOnly_ClearLoggingDirectoriesList should only be "
|
||||
fprintf(stderr,
|
||||
"TestOnly_ClearLoggingDirectoriesList should only be "
|
||||
"called from test code.\n");
|
||||
delete logging_directories_list;
|
||||
logging_directories_list = nullptr;
|
||||
@ -2553,7 +2520,6 @@ void TruncateStdoutStderr() {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Helper functions for string comparisons.
|
||||
#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
|
||||
string* Check##func##expected##Impl(const char* s1, const char* s2, \
|
||||
@ -2613,7 +2579,8 @@ int posix_strerror_r(int err, char *buf, size_t len) {
|
||||
return 0;
|
||||
} else {
|
||||
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) {
|
||||
// This means an error on MacOSX or FreeBSD.
|
||||
return -1;
|
||||
@ -2634,12 +2601,12 @@ string StrError(int err) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char* file, int line) :
|
||||
LogMessage(file, line, GLOG_FATAL) {}
|
||||
LogMessageFatal::LogMessageFatal(const char* file, int line)
|
||||
: LogMessage(file, line, GLOG_FATAL) {}
|
||||
|
||||
LogMessageFatal::LogMessageFatal(const char* file, int line,
|
||||
const CheckOpString& result) :
|
||||
LogMessage(file, line, result) {}
|
||||
const CheckOpString& result)
|
||||
: LogMessage(file, line, result) {}
|
||||
|
||||
LogMessageFatal::~LogMessageFatal() {
|
||||
Flush();
|
||||
@ -2653,9 +2620,7 @@ CheckOpMessageBuilder::CheckOpMessageBuilder(const char *exprtext)
|
||||
*stream_ << exprtext << " (";
|
||||
}
|
||||
|
||||
CheckOpMessageBuilder::~CheckOpMessageBuilder() {
|
||||
delete stream_;
|
||||
}
|
||||
CheckOpMessageBuilder::~CheckOpMessageBuilder() { delete stream_; }
|
||||
|
||||
ostream* CheckOpMessageBuilder::ForVar2() {
|
||||
*stream_ << " vs. ";
|
||||
@ -2705,8 +2670,7 @@ void InitGoogleLogging(const char* argv0) {
|
||||
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
|
||||
}
|
||||
|
||||
void InitGoogleLogging(const char* argv0,
|
||||
CustomPrefixCallback prefix_callback,
|
||||
void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback,
|
||||
void* prefix_callback_data) {
|
||||
custom_prefix_callback = prefix_callback;
|
||||
custom_prefix_callback_data = prefix_callback_data;
|
||||
@ -2724,9 +2688,7 @@ void EnableLogCleaner(unsigned int overdue_days) {
|
||||
log_cleaner.Enable(overdue_days);
|
||||
}
|
||||
|
||||
void DisableLogCleaner() {
|
||||
log_cleaner.Disable();
|
||||
}
|
||||
void DisableLogCleaner() { log_cleaner.Disable(); }
|
||||
|
||||
LogMessageTime::LogMessageTime()
|
||||
: time_struct_(), timestamp_(0), usecs_(0), gmtoffset_(0) {}
|
||||
@ -2769,8 +2731,10 @@ void LogMessageTime::CalcGmtOffset() {
|
||||
|
||||
time_t gmt_sec = mktime(&gmt_struct);
|
||||
const long hour_secs = 3600;
|
||||
// If the Daylight Saving Time(isDst) is active subtract an hour from the current timestamp.
|
||||
gmtoffset_ = static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0) ) ;
|
||||
// If the Daylight Saving Time(isDst) is active subtract an hour from the
|
||||
// current timestamp.
|
||||
gmtoffset_ =
|
||||
static_cast<long int>(timestamp_ - gmt_sec + (isDst ? hour_secs : 0));
|
||||
}
|
||||
|
||||
} // namespace google
|
||||
|
||||
@ -29,10 +29,10 @@
|
||||
//
|
||||
// Author: Ray Sidney
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_GLOB_H
|
||||
# include <glob.h>
|
||||
#endif
|
||||
@ -69,6 +69,7 @@ using namespace GFLAGS_NAMESPACE;
|
||||
|
||||
#ifdef HAVE_LIB_GMOCK
|
||||
# include <gmock/gmock.h>
|
||||
|
||||
# include "mock-log.h"
|
||||
// Introduce several symbols from gmock.
|
||||
using google::glog_testing::ScopedMockLog;
|
||||
@ -132,7 +133,8 @@ static void BM_Check1(int n) {
|
||||
}
|
||||
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) {
|
||||
while (n-- > 0) {
|
||||
if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
|
||||
@ -165,8 +167,7 @@ static void BM_Check2(int n) {
|
||||
BENCHMARK(BM_Check2)
|
||||
|
||||
static void CheckFailure(int, int, const char* /* file */, int /* line */,
|
||||
const char* /* msg */) {
|
||||
}
|
||||
const char* /* msg */) {}
|
||||
|
||||
static void BM_logspeed(int n) {
|
||||
while (n-- > 0) {
|
||||
@ -182,7 +183,8 @@ static void BM_vlog(int n) {
|
||||
}
|
||||
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) {
|
||||
// Assert that `data` contains the expected contents before producing the
|
||||
// prefix (otherwise causing the tests to fail):
|
||||
@ -190,20 +192,12 @@ void PrefixAttacher(std::ostream &s, const LogMessageInfo &l, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
s << l.severity[0]
|
||||
<< setw(4) << 1900 + l.time.year()
|
||||
<< setw(2) << 1 + l.time.month()
|
||||
<< setw(2) << l.time.day()
|
||||
<< ' '
|
||||
<< setw(2) << l.time.hour() << ':'
|
||||
<< setw(2) << l.time.min() << ':'
|
||||
<< setw(2) << l.time.sec() << "."
|
||||
<< setw(6) << l.time.usec()
|
||||
<< ' '
|
||||
<< setfill(' ') << setw(5)
|
||||
<< l.thread_id << setfill('0')
|
||||
<< ' '
|
||||
<< l.filename << ':' << l.line_number << "]";
|
||||
s << l.severity[0] << setw(4) << 1900 + l.time.year() << setw(2)
|
||||
<< 1 + l.time.month() << setw(2) << l.time.day() << ' ' << setw(2)
|
||||
<< l.time.hour() << ':' << setw(2) << l.time.min() << ':' << setw(2)
|
||||
<< l.time.sec() << "." << setw(6) << l.time.usec() << ' ' << setfill(' ')
|
||||
<< setw(5) << l.thread_id << setfill('0') << ' ' << l.filename << ':'
|
||||
<< l.line_number << "]";
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
@ -216,8 +210,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Test some basics before InitGoogleLogging:
|
||||
CaptureTestStderr();
|
||||
LogWithLevels(FLAGS_v, FLAGS_stderrthreshold,
|
||||
FLAGS_logtostderr, FLAGS_alsologtostderr);
|
||||
LogWithLevels(FLAGS_v, FLAGS_stderrthreshold, FLAGS_logtostderr,
|
||||
FLAGS_alsologtostderr);
|
||||
LogWithLevels(0, 0, false, false); // simulate "before global c-tors"
|
||||
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
|
||||
// the golden outputs can be reused):
|
||||
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());
|
||||
|
||||
@ -249,7 +244,8 @@ int main(int argc, char **argv) {
|
||||
CaptureTestStderr();
|
||||
|
||||
// re-emit early_stderr
|
||||
LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr;
|
||||
LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
|
||||
<< early_stderr;
|
||||
|
||||
TestLogging(true);
|
||||
TestRawLogging();
|
||||
@ -341,7 +337,8 @@ void TestLogging(bool check_counts) {
|
||||
LOG(ERROR) << "inner";
|
||||
}
|
||||
|
||||
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
|
||||
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
|
||||
<< "no prefix";
|
||||
|
||||
if (check_counts) {
|
||||
CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO));
|
||||
@ -350,23 +347,17 @@ void TestLogging(bool check_counts) {
|
||||
}
|
||||
}
|
||||
|
||||
static void NoAllocNewHook() {
|
||||
LOG(FATAL) << "unexpected new";
|
||||
}
|
||||
static void NoAllocNewHook() { LOG(FATAL) << "unexpected new"; }
|
||||
|
||||
struct NewHook {
|
||||
NewHook() {
|
||||
g_new_hook = &NoAllocNewHook;
|
||||
}
|
||||
NewHook() { g_new_hook = &NoAllocNewHook; }
|
||||
~NewHook() { g_new_hook = nullptr; }
|
||||
};
|
||||
|
||||
TEST(DeathNoAllocNewHook, logging) {
|
||||
// tests that NewHook used below works
|
||||
NewHook new_hook;
|
||||
ASSERT_DEATH({
|
||||
new int;
|
||||
}, "unexpected new");
|
||||
ASSERT_DEATH({ new int; }, "unexpected new");
|
||||
}
|
||||
|
||||
void TestRawLogging() {
|
||||
@ -425,8 +416,8 @@ void TestRawLogging() {
|
||||
|
||||
void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
|
||||
RAW_LOG(INFO,
|
||||
"Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d",
|
||||
v, severity, err, alsoerr);
|
||||
"Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d", v,
|
||||
severity, err, alsoerr);
|
||||
|
||||
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";
|
||||
|
||||
int c;
|
||||
c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1);
|
||||
c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1);
|
||||
c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1);
|
||||
c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1);
|
||||
c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0);
|
||||
c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0);
|
||||
c = 1;
|
||||
VLOG_IF(100, c -= 2) << "vlog_if 100 expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 1;
|
||||
VLOG_IF(0, c -= 2) << "vlog_if 0 expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 1;
|
||||
LOG_IF(INFO, c -= 2) << "log_if info expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 1;
|
||||
LOG_IF(ERROR, c -= 2) << "log_if error expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 2;
|
||||
VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
c = 2;
|
||||
LOG_IF(ERROR, c -= 2) << "don't log_if error expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
|
||||
c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
|
||||
c = 3;
|
||||
LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
|
||||
c = 3;
|
||||
LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
|
||||
EXPECT_EQ(c, -1);
|
||||
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
|
||||
c = 4;
|
||||
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
|
||||
c = 4;
|
||||
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
|
||||
c = 5;
|
||||
VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
|
||||
EXPECT_EQ(c, 1);
|
||||
c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
|
||||
c = 5;
|
||||
VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
|
||||
EXPECT_EQ(c, 1);
|
||||
c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
|
||||
c = 6;
|
||||
VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
|
||||
c = 6;
|
||||
VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
|
||||
EXPECT_EQ(c, 0);
|
||||
}
|
||||
|
||||
@ -530,12 +541,17 @@ void TestLogString() {
|
||||
vector<string> errors;
|
||||
vector<string>* no_errors = nullptr;
|
||||
|
||||
LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info";
|
||||
LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning";
|
||||
LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error";
|
||||
LOG_STRING(INFO, &errors) << "LOG_STRING: "
|
||||
<< "collected info";
|
||||
LOG_STRING(WARNING, &errors) << "LOG_STRING: "
|
||||
<< "collected warning";
|
||||
LOG_STRING(ERROR, &errors) << "LOG_STRING: "
|
||||
<< "collected error";
|
||||
|
||||
LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info";
|
||||
LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning";
|
||||
LOG_STRING(INFO, no_errors) << "LOG_STRING: "
|
||||
<< "reported info";
|
||||
LOG_STRING(WARNING, no_errors) << "LOG_STRING: "
|
||||
<< "reported warning";
|
||||
LOG_STRING(ERROR, nullptr) << "LOG_STRING: "
|
||||
<< "reported error";
|
||||
|
||||
@ -548,15 +564,20 @@ void TestLogToString() {
|
||||
string error;
|
||||
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_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_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_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info";
|
||||
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning";
|
||||
LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: "
|
||||
<< "reported info";
|
||||
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: "
|
||||
<< "reported warning";
|
||||
LOG_TO_STRING(ERROR, nullptr) << "LOG_TO_STRING: "
|
||||
<< "reported error";
|
||||
}
|
||||
@ -568,8 +589,8 @@ class TestLogSinkImpl : public LogSink {
|
||||
const char* base_filename, int line,
|
||||
const LogMessageTime& logmsgtime, const char* message,
|
||||
size_t message_len) override {
|
||||
errors.push_back(
|
||||
ToString(severity, base_filename, line, logmsgtime, message, message_len));
|
||||
errors.push_back(ToString(severity, base_filename, line, logmsgtime,
|
||||
message, message_len));
|
||||
}
|
||||
};
|
||||
|
||||
@ -577,26 +598,36 @@ void TestLogSink() {
|
||||
TestLogSinkImpl sink;
|
||||
LogSink* no_sink = nullptr;
|
||||
|
||||
LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info";
|
||||
LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning";
|
||||
LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error";
|
||||
LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: "
|
||||
<< "collected info";
|
||||
LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: "
|
||||
<< "collected warning";
|
||||
LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: "
|
||||
<< "collected error";
|
||||
|
||||
LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info";
|
||||
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning";
|
||||
LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: "
|
||||
<< "reported info";
|
||||
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: "
|
||||
<< "reported warning";
|
||||
LOG_TO_SINK(nullptr, ERROR) << "LOG_TO_SINK: "
|
||||
<< "reported error";
|
||||
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info";
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "collected info";
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning";
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "collected warning";
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error";
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "collected error";
|
||||
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info";
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "thrashed info";
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning";
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "thrashed warning";
|
||||
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(nullptr, ERROR)
|
||||
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
|
||||
<< "thrashed error";
|
||||
@ -608,10 +639,7 @@ void TestLogSink() {
|
||||
}
|
||||
|
||||
// For testing using CHECK*() on anonymous enums.
|
||||
enum {
|
||||
CASE_A,
|
||||
CASE_B
|
||||
};
|
||||
enum { CASE_A, CASE_B };
|
||||
|
||||
void TestCHECK() {
|
||||
// Tests using CHECK*() on int values.
|
||||
@ -669,8 +697,7 @@ void TestSTREQ() {
|
||||
CHECK_STRCASENE("this", "that");
|
||||
CHECK_STRCASENE(nullptr, "that");
|
||||
CHECK_STREQ((string("a") + "b").c_str(), "ab");
|
||||
CHECK_STREQ(string("test").c_str(),
|
||||
(string("te") + string("st")).c_str());
|
||||
CHECK_STREQ(string("test").c_str(), (string("te") + string("st")).c_str());
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
GetFiles(name + "*", &files);
|
||||
CHECK_EQ(files.size(), 1UL);
|
||||
@ -760,7 +788,8 @@ static void CheckFile(const string& name, const string& expected_string, const b
|
||||
}
|
||||
}
|
||||
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() {
|
||||
@ -780,8 +809,11 @@ static void TestBasename() {
|
||||
}
|
||||
|
||||
static void TestBasenameAppendWhenNoTimestamp() {
|
||||
fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n");
|
||||
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
|
||||
fprintf(stderr,
|
||||
"==== Test setting log file basename without timestamp and appending "
|
||||
"properly\n");
|
||||
const string dest =
|
||||
FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
|
||||
DeleteFiles(dest + "*");
|
||||
|
||||
ofstream out(dest.c_str());
|
||||
@ -806,10 +838,14 @@ static void TestBasenameAppendWhenNoTimestamp() {
|
||||
}
|
||||
|
||||
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)
|
||||
fprintf(stderr, "==== Test setting log file basename and two processes writing - second should fail\n");
|
||||
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
|
||||
fprintf(stderr,
|
||||
"==== Test setting log file basename and two processes writing - "
|
||||
"second should fail\n");
|
||||
const string dest =
|
||||
FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
|
||||
DeleteFiles(dest + "*");
|
||||
|
||||
// make both processes write into the same file (easier test)
|
||||
@ -821,7 +857,8 @@ static void TestTwoProcessesWrite() {
|
||||
pid_t pid = fork();
|
||||
CHECK_ERR(pid);
|
||||
if (pid == 0) {
|
||||
LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file";
|
||||
LOG(INFO) << "message to new base, child - should only appear on STDERR "
|
||||
"not on the file";
|
||||
ShutdownGoogleLogging(); // for children proc
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (pid > 0) {
|
||||
@ -830,7 +867,10 @@ static void TestTwoProcessesWrite() {
|
||||
FLAGS_timestamp_in_logfile_name = true;
|
||||
|
||||
CheckFile(dest, "message to new base, parent");
|
||||
CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false);
|
||||
CheckFile(dest,
|
||||
"message to new base, child - should only appear on STDERR not on "
|
||||
"the file",
|
||||
false);
|
||||
|
||||
// Release
|
||||
LogToStderr();
|
||||
@ -1014,11 +1054,9 @@ static void TestTruncate() {
|
||||
}
|
||||
|
||||
struct RecordDeletionLogger : public base::Logger {
|
||||
RecordDeletionLogger(bool* set_on_destruction,
|
||||
base::Logger* wrapped_logger) :
|
||||
set_on_destruction_(set_on_destruction),
|
||||
wrapped_logger_(wrapped_logger)
|
||||
{
|
||||
RecordDeletionLogger(bool* set_on_destruction, base::Logger* wrapped_logger)
|
||||
: set_on_destruction_(set_on_destruction),
|
||||
wrapped_logger_(wrapped_logger) {
|
||||
*set_on_destruction_ = false;
|
||||
}
|
||||
~RecordDeletionLogger() override { *set_on_destruction_ = true; }
|
||||
@ -1095,8 +1133,8 @@ static void TestLogPeriodically() {
|
||||
// minimize error.
|
||||
int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1];
|
||||
for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) {
|
||||
nsBetweenCalls[i - 1] = elapsedTime_ns(
|
||||
timeLogger.m_callTimes[i - 1], timeLogger.m_callTimes[i]);
|
||||
nsBetweenCalls[i - 1] = elapsedTime_ns(timeLogger.m_callTimes[i - 1],
|
||||
timeLogger.m_callTimes[i]);
|
||||
}
|
||||
|
||||
for (long time_ns : nsBetweenCalls) {
|
||||
@ -1107,8 +1145,9 @@ static void TestLogPeriodically() {
|
||||
namespace google {
|
||||
namespace glog_internal_namespace_ {
|
||||
extern // in logging.cc
|
||||
bool SafeFNMatch_(const char* pattern, size_t patt_len,
|
||||
const char* str, size_t str_len);
|
||||
bool
|
||||
SafeFNMatch_(const char* pattern, size_t patt_len, const char* str,
|
||||
size_t str_len);
|
||||
} // namespace glog_internal_namespace_
|
||||
using glog_internal_namespace_::SafeFNMatch_;
|
||||
} // namespace google
|
||||
@ -1116,8 +1155,8 @@ using glog_internal_namespace_::SafeFNMatch_;
|
||||
static bool WrapSafeFNMatch(string pattern, string str) {
|
||||
pattern += "abc";
|
||||
str += "defgh";
|
||||
return SafeFNMatch_(pattern.data(), pattern.size() - 3,
|
||||
str.data(), str.size() - 5);
|
||||
return SafeFNMatch_(pattern.data(), pattern.size() - 3, str.data(),
|
||||
str.size() - 5);
|
||||
}
|
||||
|
||||
TEST(SafeFNMatch, logging) {
|
||||
@ -1184,7 +1223,6 @@ class TestLogSinkWriter : public Thread {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// helpers ---------------
|
||||
|
||||
// For creating a "Condition".
|
||||
@ -1239,7 +1277,6 @@ class TestLogSinkWriter : public Thread {
|
||||
// (that other thread can than use LOG() itself),
|
||||
class TestWaitingLogSink : public LogSink {
|
||||
public:
|
||||
|
||||
TestWaitingLogSink() {
|
||||
tid_ = pthread_self(); // for thread-specific behavior
|
||||
AddLogSink(this);
|
||||
@ -1260,8 +1297,8 @@ class TestWaitingLogSink : public LogSink {
|
||||
// Note: Something like ThreadLocalLogSink is a better choice
|
||||
// to do thread-specific LogSink logic for real.
|
||||
if (pthread_equal(tid_, pthread_self())) {
|
||||
writer_.Buffer(ToString(severity, base_filename, line,
|
||||
logmsgtime, message, message_len));
|
||||
writer_.Buffer(ToString(severity, base_filename, line, logmsgtime,
|
||||
message, message_len));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1271,7 +1308,6 @@ class TestWaitingLogSink : public LogSink {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pthread_t tid_;
|
||||
TestLogSinkWriter writer_;
|
||||
};
|
||||
@ -1282,7 +1318,8 @@ static void TestLogSinkWaitTillSent() {
|
||||
// Clear global_messages here to make sure that this test case can be
|
||||
// reentered
|
||||
global_messages.clear();
|
||||
{ TestWaitingLogSink sink;
|
||||
{
|
||||
TestWaitingLogSink sink;
|
||||
// Sleeps give the sink threads time to do all their work,
|
||||
// so that we get a reliable log capture to compare to the golden file.
|
||||
LOG(INFO) << "Message 1";
|
||||
@ -1308,7 +1345,8 @@ TEST(Strerror, logging) {
|
||||
CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
|
||||
CHECK_EQ(buf[0], 'A');
|
||||
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
|
||||
// no enough space.
|
||||
CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
|
||||
@ -1404,9 +1442,8 @@ TEST(TestExitOnDFatal, ToBeOrNotToBe) {
|
||||
|
||||
# ifdef GTEST_HAS_DEATH_TEST
|
||||
// Death comes on little cats' feet.
|
||||
EXPECT_DEBUG_DEATH({
|
||||
LOG(DFATAL) << "This should be fatal in debug mode";
|
||||
}, "This should be fatal in debug mode");
|
||||
EXPECT_DEBUG_DEATH({ LOG(DFATAL) << "This should be fatal in debug mode"; },
|
||||
"This should be fatal in debug mode");
|
||||
# endif
|
||||
}
|
||||
|
||||
@ -1443,10 +1480,10 @@ TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
|
||||
// the name of the containing function, followed by the log message.
|
||||
// We use HasSubstr()s instead of ContainsRegex() for environments
|
||||
// which don't have regexp.
|
||||
EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"),
|
||||
HasSubstr("BacktraceAtHelper"),
|
||||
HasSubstr("main"),
|
||||
HasSubstr("Backtrace me"))));
|
||||
EXPECT_CALL(
|
||||
log, Log(_, _,
|
||||
AllOf(HasSubstr("stacktrace:"), HasSubstr("BacktraceAtHelper"),
|
||||
HasSubstr("main"), HasSubstr("Backtrace me"))));
|
||||
// Other LOGs should not include a backtrace.
|
||||
EXPECT_CALL(log, Log(_, _, "Not me"));
|
||||
|
||||
@ -1480,7 +1517,8 @@ TEST(UserDefinedClass, logging) {
|
||||
TEST(LogMsgTime, gmtoff) {
|
||||
/*
|
||||
* Unit test for GMT offset API
|
||||
* TODO: To properly test this API, we need a platform independent way to set time-zone.
|
||||
* TODO: To properly test this API, we need a platform independent way to set
|
||||
* time-zone.
|
||||
* */
|
||||
google::LogMessage log_obj(__FILE__, __LINE__);
|
||||
|
||||
@ -1495,14 +1533,16 @@ TEST(EmailLogging, ValidAddress) {
|
||||
FlagSaver saver;
|
||||
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) {
|
||||
FlagSaver saver;
|
||||
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) {
|
||||
@ -1516,5 +1556,6 @@ TEST(EmailLogging, MaliciousAddress) {
|
||||
FlagSaver saver;
|
||||
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"));
|
||||
}
|
||||
|
||||
@ -33,11 +33,11 @@
|
||||
|
||||
#include "mock-log.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
using google::GLOG_ERROR;
|
||||
@ -57,8 +57,7 @@ TEST(ScopedMockLogTest, InterceptsLog) {
|
||||
InSequence s;
|
||||
EXPECT_CALL(log,
|
||||
Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy."));
|
||||
EXPECT_CALL(log, Log(GLOG_INFO, _, "Working..."))
|
||||
.Times(2);
|
||||
EXPECT_CALL(log, Log(GLOG_INFO, _, "Working...")).Times(2);
|
||||
EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!"));
|
||||
|
||||
LOG(WARNING) << "Fishy.";
|
||||
@ -67,13 +66,9 @@ TEST(ScopedMockLogTest, InterceptsLog) {
|
||||
LOG(ERROR) << "Bad!!";
|
||||
}
|
||||
|
||||
void LogBranch() {
|
||||
LOG(INFO) << "Logging a branch...";
|
||||
}
|
||||
void LogBranch() { LOG(INFO) << "Logging a branch..."; }
|
||||
|
||||
void LogTree() {
|
||||
LOG(INFO) << "Logging the whole tree...";
|
||||
}
|
||||
void LogTree() { LOG(INFO) << "Logging the whole tree..."; }
|
||||
|
||||
void LogForest() {
|
||||
LOG(INFO) << "Logging the entire forest.";
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
#include "glog/logging.h"
|
||||
|
||||
int main(int /*argc*/, char** argv)
|
||||
{
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
}
|
||||
int main(int /*argc*/, char** argv) { google::InitGoogleLogging(argv[0]); }
|
||||
|
||||
@ -103,8 +103,8 @@ static bool DoRawLog(char** buf, size_t* size, const char* format, ...) {
|
||||
}
|
||||
|
||||
// Helper for RawLog__ below.
|
||||
inline static bool VADoRawLog(char** buf, size_t* size,
|
||||
const char* format, va_list ap) {
|
||||
inline static bool VADoRawLog(char** buf, size_t* size, const char* format,
|
||||
va_list ap) {
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
@ -139,8 +139,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
|
||||
|
||||
// NOTE: this format should match the specification in base/logging.h
|
||||
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
|
||||
LogSeverityNames[severity][0],
|
||||
static_cast<unsigned int>(GetTID()),
|
||||
LogSeverityNames[severity][0], static_cast<unsigned int>(GetTID()),
|
||||
const_basename(const_cast<char*>(file)), line);
|
||||
|
||||
// Record the position and size of the buffer after the prefix
|
||||
|
||||
@ -63,10 +63,8 @@ const struct {
|
||||
int number;
|
||||
const char* name;
|
||||
} kFailureSignals[] = {
|
||||
{ SIGSEGV, "SIGSEGV" },
|
||||
{ SIGILL, "SIGILL" },
|
||||
{ SIGFPE, "SIGFPE" },
|
||||
{ SIGABRT, "SIGABRT" },
|
||||
{SIGSEGV, "SIGSEGV"}, {SIGILL, "SIGILL"},
|
||||
{SIGFPE, "SIGFPE"}, {SIGABRT, "SIGABRT"},
|
||||
#if !defined(GLOG_OS_WINDOWS)
|
||||
{SIGBUS, "SIGBUS"},
|
||||
#endif
|
||||
@ -78,7 +76,8 @@ static bool kFailureSignalHandlerInstalled = false;
|
||||
#if !defined(GLOG_OS_WINDOWS)
|
||||
// Returns the program counter from signal context, nullptr if unknown.
|
||||
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) {
|
||||
ucontext_t* context = reinterpret_cast<ucontext_t*>(ucontext_in_void);
|
||||
return (void*)context->PC_FROM_UCONTEXT;
|
||||
@ -95,13 +94,12 @@ void* GetPC(void* ucontext_in_void) {
|
||||
class MinimalFormatter {
|
||||
public:
|
||||
MinimalFormatter(char* buffer, size_t size)
|
||||
: buffer_(buffer),
|
||||
cursor_(buffer),
|
||||
end_(buffer + size) {
|
||||
}
|
||||
: buffer_(buffer), cursor_(buffer), end_(buffer + size) {}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
// Symbolizes the previous address of pc because pc may be in the
|
||||
// next function.
|
||||
if (Symbolize(reinterpret_cast<char *>(pc) - 1,
|
||||
symbolized, sizeof(symbolized))) {
|
||||
if (Symbolize(reinterpret_cast<char*>(pc) - 1, symbolized,
|
||||
sizeof(symbolized))) {
|
||||
symbol = symbolized;
|
||||
}
|
||||
|
||||
@ -279,8 +277,7 @@ static pthread_t* g_entered_thread_id_pointer = nullptr;
|
||||
#if defined(GLOG_OS_WINDOWS)
|
||||
void FailureSignalHandler(int signal_number)
|
||||
#else
|
||||
void FailureSignalHandler(int signal_number,
|
||||
siginfo_t *signal_info,
|
||||
void FailureSignalHandler(int signal_number, siginfo_t* signal_info,
|
||||
void* ucontext)
|
||||
#endif
|
||||
{
|
||||
@ -400,8 +397,7 @@ void InstallFailureSignalHandler() {
|
||||
kFailureSignalHandlerInstalled = true;
|
||||
#elif defined(GLOG_OS_WINDOWS)
|
||||
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
|
||||
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler),
|
||||
SIG_ERR);
|
||||
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler), SIG_ERR);
|
||||
}
|
||||
kFailureSignalHandlerInstalled = true;
|
||||
#endif // HAVE_SIGACTION
|
||||
|
||||
@ -89,7 +89,8 @@ int main(int argc, char **argv) {
|
||||
*a = 0;
|
||||
} else if (command == "loop") {
|
||||
fprintf(stderr, "looping\n");
|
||||
while (true);
|
||||
while (true)
|
||||
;
|
||||
} else if (command == "die_in_thread") {
|
||||
# if defined(HAVE_PTHREAD)
|
||||
pthread_t thread;
|
||||
|
||||
@ -114,7 +114,8 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
|
||||
result[n++] = *(sp + 2);
|
||||
#elif defined(_CALL_SYSV)
|
||||
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.
|
||||
result[n++] = *(sp + 2);
|
||||
#elif defined(__linux) || defined(__OpenBSD__)
|
||||
|
||||
@ -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
|
||||
// the recursive call.
|
||||
# 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
|
||||
// performing recursive call may end up later in the code then the return
|
||||
// instruction (this actually happens with FDO).
|
||||
@ -85,9 +88,8 @@ AddressRange expected_range[BACKTRACE_STEPS];
|
||||
void* ra = __builtin_return_address(0); \
|
||||
CHECK_LT((prange)->start, ra); \
|
||||
if (ra > (prange)->end) { \
|
||||
printf("Adjusting range from %p..%p to %p..%p\n", \
|
||||
(prange)->start, (prange)->end, \
|
||||
(prange)->start, ra); \
|
||||
printf("Adjusting range from %p..%p to %p..%p\n", (prange)->start, \
|
||||
(prange)->end, (prange)->start, ra); \
|
||||
(prange)->end = ra; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -98,14 +100,18 @@ AddressRange expected_range[BACKTRACE_STEPS];
|
||||
(prange)->start = reinterpret_cast<const void*>(&fn); \
|
||||
(prange)->end = reinterpret_cast<const char*>(&fn) + 256; \
|
||||
} while (0)
|
||||
#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
|
||||
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
|
||||
# define DECLARE_ADDRESS_LABEL(a_label) \
|
||||
do { \
|
||||
} while (0)
|
||||
# define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
|
||||
do { \
|
||||
} while (0)
|
||||
# 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_LE(ret_addr, range.end);
|
||||
}
|
||||
@ -149,8 +155,8 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
|
||||
# endif
|
||||
}
|
||||
for (int i = 0; i < BACKTRACE_STEPS; i++) {
|
||||
printf("Backtrace %d: expected: %p..%p actual: %p ... ",
|
||||
i, expected_range[i].start, expected_range[i].end, stack[i]);
|
||||
printf("Backtrace %d: expected: %p..%p actual: %p ... ", i,
|
||||
expected_range[i].start, expected_range[i].end, stack[i]);
|
||||
fflush(stdout);
|
||||
CheckRetAddrIsInFunction(stack[i], expected_range[i]);
|
||||
printf("OK\n");
|
||||
@ -207,7 +213,8 @@ static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
|
||||
// See https://github.com/google/glog/issues/421 for the detail.
|
||||
static
|
||||
# endif
|
||||
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
|
||||
void ATTRIBUTE_NOINLINE
|
||||
CheckStackTrace(int i) {
|
||||
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
|
||||
DECLARE_ADDRESS_LABEL(start);
|
||||
for (int j = i; j >= 0; j--) {
|
||||
|
||||
@ -45,11 +45,11 @@ struct trace_arg_t {
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
// This code is not considered ready to run until
|
||||
// static initializers run so that we are guaranteed
|
||||
// that any malloc-related initialization is done.
|
||||
|
||||
@ -31,10 +31,11 @@
|
||||
//
|
||||
// Windows implementation - just use CaptureStackBackTrace
|
||||
|
||||
#include <dbghelp.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "port.h"
|
||||
#include "stacktrace.h"
|
||||
#include <dbghelp.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
#include "utilities.h" // for OS_* macros
|
||||
|
||||
#if !defined(GLOG_OS_WINDOWS)
|
||||
#include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio> // for nullptr
|
||||
|
||||
114
src/symbolize.cc
114
src/symbolize.cc
@ -56,13 +56,12 @@
|
||||
|
||||
#if defined(HAVE_SYMBOLIZE)
|
||||
|
||||
#include <cstring>
|
||||
|
||||
# include <algorithm>
|
||||
# include <cstring>
|
||||
# include <limits>
|
||||
|
||||
#include "symbolize.h"
|
||||
# include "demangle.h"
|
||||
# include "symbolize.h"
|
||||
|
||||
namespace google {
|
||||
|
||||
@ -136,7 +135,9 @@ static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size) {
|
||||
# include "symbolize.h"
|
||||
|
||||
// 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 {
|
||||
|
||||
@ -147,7 +148,8 @@ namespace google {
|
||||
static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count,
|
||||
const size_t offset) {
|
||||
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);
|
||||
size_t num_bytes = 0;
|
||||
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
|
||||
// short reads and EINTR. On success, return true. Otherwise, return
|
||||
// false.
|
||||
static bool ReadFromOffsetExact(const int fd, void *buf,
|
||||
const size_t count, const size_t offset) {
|
||||
static bool ReadFromOffsetExact(const int fd, void* buf, const size_t count,
|
||||
const size_t offset) {
|
||||
ssize_t len = ReadFromOffset(fd, buf, count, offset);
|
||||
return static_cast<size_t>(len) == count;
|
||||
}
|
||||
@ -193,9 +195,11 @@ static int FileGetElfType(const int fd) {
|
||||
// and return true. Otherwise, return false.
|
||||
// To keep stack consumption low, we would like this function to not get
|
||||
// inlined.
|
||||
static ATTRIBUTE_NOINLINE bool
|
||||
GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const size_t sh_offset,
|
||||
ElfW(Word) type, ElfW(Shdr) *out) {
|
||||
static ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(const int fd,
|
||||
ElfW(Half) sh_num,
|
||||
const size_t sh_offset,
|
||||
ElfW(Word) type,
|
||||
ElfW(Shdr) * out) {
|
||||
// Read at most 16 section headers at a time to save read calls.
|
||||
ElfW(Shdr) buf[16];
|
||||
for (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) {
|
||||
size_t section_header_offset = (elf_header.e_shoff +
|
||||
elf_header.e_shentsize * i);
|
||||
size_t section_header_offset =
|
||||
(elf_header.e_shoff + elf_header.e_shentsize * i);
|
||||
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
|
||||
return false;
|
||||
}
|
||||
@ -277,9 +281,10 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
|
||||
// to out. Otherwise, return false.
|
||||
// To keep stack consumption low, we would like this function to not get
|
||||
// inlined.
|
||||
static ATTRIBUTE_NOINLINE bool
|
||||
FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size,
|
||||
uint64_t symbol_offset, const ElfW(Shdr) *strtab,
|
||||
static ATTRIBUTE_NOINLINE bool FindSymbol(uint64_t pc, const int fd, char* out,
|
||||
size_t out_size,
|
||||
uint64_t symbol_offset,
|
||||
const ElfW(Shdr) * strtab,
|
||||
const ElfW(Shdr) * symtab) {
|
||||
if (symtab == nullptr) {
|
||||
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,
|
||||
// write the symbol name to "out" and return true. Otherwise, return
|
||||
// false.
|
||||
static bool GetSymbolFromObjectFile(const int fd,
|
||||
uint64_t pc,
|
||||
char* out,
|
||||
size_t out_size,
|
||||
uint64_t base_address) {
|
||||
static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, char* out,
|
||||
size_t out_size, uint64_t base_address) {
|
||||
// Read the ELF header.
|
||||
ElfW(Ehdr) elf_header;
|
||||
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.
|
||||
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
|
||||
SHT_SYMTAB, &symtab)) {
|
||||
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
|
||||
symtab.sh_link * sizeof(symtab))) {
|
||||
if (!ReadFromOffsetExact(
|
||||
fd, &strtab, sizeof(strtab),
|
||||
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
|
||||
return false;
|
||||
}
|
||||
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 (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
|
||||
SHT_DYNSYM, &symtab)) {
|
||||
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
|
||||
symtab.sh_link * sizeof(symtab))) {
|
||||
if (!ReadFromOffsetExact(
|
||||
fd, &strtab, sizeof(strtab),
|
||||
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
|
||||
return false;
|
||||
}
|
||||
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
|
||||
@ -451,26 +455,21 @@ class LineReader {
|
||||
}
|
||||
|
||||
// Beginning of line.
|
||||
const char *bol() {
|
||||
return bol_;
|
||||
}
|
||||
const char* bol() { return bol_; }
|
||||
|
||||
// End of line.
|
||||
const char *eol() {
|
||||
return eol_;
|
||||
}
|
||||
const char* eol() { return eol_; }
|
||||
|
||||
private:
|
||||
LineReader(const LineReader&) = delete;
|
||||
void operator=(const LineReader&) = delete;
|
||||
|
||||
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() {
|
||||
return buf_ == eod_;
|
||||
}
|
||||
bool BufferIsEmpty() { return buf_ == eod_; }
|
||||
|
||||
bool HasCompleteLine() {
|
||||
return !BufferIsEmpty() && FindLineFeed() != nullptr;
|
||||
@ -493,9 +492,10 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
|
||||
const char* p;
|
||||
for (p = start; p < end; ++p) {
|
||||
int ch = *p;
|
||||
if ((ch >= '0' && ch <= '9') ||
|
||||
(ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
|
||||
*hex = (*hex << 4U) | (ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U);
|
||||
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
|
||||
(ch >= 'a' && ch <= 'f')) {
|
||||
*hex = (*hex << 4U) |
|
||||
(ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U);
|
||||
} else { // Encountered the first non-hex character.
|
||||
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,
|
||||
// returns -1. |out_file_name_size| is the size of the file name buffer
|
||||
// (including the null-terminator).
|
||||
static ATTRIBUTE_NOINLINE int
|
||||
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
|
||||
uint64_t &start_address,
|
||||
uint64_t &base_address,
|
||||
char *out_file_name,
|
||||
size_t out_file_name_size) {
|
||||
static ATTRIBUTE_NOINLINE int OpenObjectFileContainingPcAndGetStartAddress(
|
||||
uint64_t pc, uint64_t& start_address, uint64_t& base_address,
|
||||
char* out_file_name, size_t out_file_name_size) {
|
||||
int object_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
|
||||
// appended.
|
||||
// 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.
|
||||
size_t n = 1;
|
||||
if (n > sz) {
|
||||
@ -763,14 +761,11 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
|
||||
SafeAppendString("(", out, out_size);
|
||||
|
||||
if (g_symbolize_open_object_file_callback) {
|
||||
object_fd = g_symbolize_open_object_file_callback(pc0, start_address,
|
||||
base_address, out + 1,
|
||||
out_size - 1);
|
||||
object_fd = g_symbolize_open_object_file_callback(
|
||||
pc0, start_address, base_address, out + 1, out_size - 1);
|
||||
} else {
|
||||
object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address,
|
||||
base_address,
|
||||
out + 1,
|
||||
out_size - 1);
|
||||
object_fd = OpenObjectFileContainingPcAndGetStartAddress(
|
||||
pc0, start_address, base_address, out + 1, out_size - 1);
|
||||
}
|
||||
|
||||
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
|
||||
// wrong for prelinked shared libraries and PIE executables.
|
||||
uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0;
|
||||
int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(),
|
||||
pc, out, out_size,
|
||||
relocation);
|
||||
int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), pc,
|
||||
out, out_size, relocation);
|
||||
if (num_bytes_written > 0) {
|
||||
out += static_cast<size_t>(num_bytes_written);
|
||||
out_size -= static_cast<size_t>(num_bytes_written);
|
||||
}
|
||||
}
|
||||
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0,
|
||||
out, out_size, base_address)) {
|
||||
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, out, out_size,
|
||||
base_address)) {
|
||||
if (out[1] && !g_symbolize_callback) {
|
||||
// The object file containing PC was opened successfully however the
|
||||
// symbol was not found. The object may have been stripped. This is still
|
||||
@ -838,6 +832,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
|
||||
# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
|
||||
|
||||
# include <dlfcn.h>
|
||||
|
||||
# include <cstring>
|
||||
|
||||
namespace google {
|
||||
@ -862,8 +857,8 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
|
||||
|
||||
# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
|
||||
|
||||
#include <windows.h>
|
||||
# include <dbghelp.h>
|
||||
# include <windows.h>
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# pragma comment(lib, "dbghelp")
|
||||
@ -891,6 +886,7 @@ public:
|
||||
SymCleanup(process);
|
||||
// We do not need to close `HANDLE process` because it's a "pseudo handle."
|
||||
}
|
||||
|
||||
private:
|
||||
SymInitializer(const SymInitializer&);
|
||||
SymInitializer& operator=(const SymInitializer&);
|
||||
@ -910,8 +906,8 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
|
||||
symbol->MaxNameLen = MAX_SYM_NAME;
|
||||
// We use the ANSI version to ensure the string type is always `char *`.
|
||||
// This could break if a symbol has Unicode in it.
|
||||
BOOL ret = SymFromAddr(symInitializer.process,
|
||||
reinterpret_cast<DWORD64>(pc), 0, symbol);
|
||||
BOOL ret = SymFromAddr(symInitializer.process, reinterpret_cast<DWORD64>(pc),
|
||||
0, symbol);
|
||||
if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) {
|
||||
// `NameLen` does not include the null terminating character.
|
||||
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);
|
||||
|
||||
@ -130,8 +130,8 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
|
||||
// file is opened successfully, returns the file descriptor. Otherwise,
|
||||
// returns -1. |out_file_name_size| is the size of the file name buffer
|
||||
// (including the null-terminator).
|
||||
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t &,
|
||||
uint64_t &, char *, size_t);
|
||||
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&,
|
||||
char*, size_t);
|
||||
void InstallSymbolizeOpenObjectFileCallback(
|
||||
SymbolizeOpenObjectFileCallback callback);
|
||||
|
||||
|
||||
@ -79,7 +79,8 @@ static const char *TrySymbolize(void *pc) {
|
||||
# if defined(__GNUC__) && !defined(__OPENCC__)
|
||||
# if __GNUC__ >= 4
|
||||
# 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
|
||||
# define always_inline __attribute__((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.
|
||||
static const char* SymbolizeStackConsumption(void* pc, int* stack_consumed) {
|
||||
|
||||
g_pc_to_symbolize = pc;
|
||||
|
||||
// The alt-signal-stack cannot be heap allocated because there is a
|
||||
|
||||
@ -29,13 +29,13 @@
|
||||
//
|
||||
// Author: Shinichiro Hamaji
|
||||
|
||||
#include "config.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <csignal>
|
||||
#include "config.h"
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
@ -75,9 +75,9 @@ bool IsGoogleLoggingInitialized() {
|
||||
// The following APIs are all internal.
|
||||
#ifdef HAVE_STACKTRACE
|
||||
|
||||
# include "base/commandlineflags.h"
|
||||
# include "stacktrace.h"
|
||||
# include "symbolize.h"
|
||||
#include "base/commandlineflags.h"
|
||||
|
||||
GLOG_DEFINE_bool(symbolize_stacktrace, true,
|
||||
"Symbolize the stack trace in the tombstone");
|
||||
@ -199,7 +199,8 @@ struct timeval {
|
||||
long tv_sec, tv_usec;
|
||||
};
|
||||
|
||||
// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
|
||||
// Based on:
|
||||
// http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
|
||||
// See COPYING for copyright information.
|
||||
static int gettimeofday(struct timeval* tv, void* /*tz*/) {
|
||||
# ifdef __GNUC__
|
||||
@ -232,9 +233,7 @@ int64 CycleClock_Now() {
|
||||
return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
int64 UsecToCycles(int64 usec) {
|
||||
return usec;
|
||||
}
|
||||
int64 UsecToCycles(int64 usec) { return usec; }
|
||||
|
||||
WallTime WallTime_Now() {
|
||||
// Now, cycle clock is retuning microseconds since the epoch.
|
||||
@ -242,9 +241,7 @@ WallTime WallTime_Now() {
|
||||
}
|
||||
|
||||
static int32 g_main_thread_pid = getpid();
|
||||
int32 GetMainThreadPid() {
|
||||
return g_main_thread_pid;
|
||||
}
|
||||
int32 GetMainThreadPid() { return g_main_thread_pid; }
|
||||
|
||||
bool PidHasChanged() {
|
||||
int32 pid = getpid();
|
||||
@ -305,16 +302,13 @@ pid_t GetTID() {
|
||||
const char* const_basename(const char* filepath) {
|
||||
const char* base = strrchr(filepath, '/');
|
||||
#ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows
|
||||
if (!base)
|
||||
base = strrchr(filepath, '\\');
|
||||
if (!base) base = strrchr(filepath, '\\');
|
||||
#endif
|
||||
return base ? (base + 1) : filepath;
|
||||
}
|
||||
|
||||
static string g_my_user_name;
|
||||
const string& MyUserName() {
|
||||
return g_my_user_name;
|
||||
}
|
||||
const string& MyUserName() { return g_my_user_name; }
|
||||
static void MyUserNameInitializer() {
|
||||
// TODO(hamaji): Probably this is not portable.
|
||||
#if defined(GLOG_OS_WINDOWS)
|
||||
@ -356,8 +350,7 @@ void DumpStackTraceToString(string* stacktrace) {
|
||||
static const CrashReason* g_reason = nullptr;
|
||||
|
||||
void SetCrashReason(const CrashReason* r) {
|
||||
sync_val_compare_and_swap(&g_reason,
|
||||
reinterpret_cast<const CrashReason*>(0),
|
||||
sync_val_compare_and_swap(&g_reason, reinterpret_cast<const CrashReason*>(0),
|
||||
r);
|
||||
}
|
||||
|
||||
@ -377,7 +370,8 @@ void InitGoogleLoggingUtilities(const char* argv0) {
|
||||
|
||||
void ShutdownGoogleLoggingUtilities() {
|
||||
CHECK(IsGoogleLoggingInitialized())
|
||||
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
|
||||
<< "You called ShutdownGoogleLogging() without calling "
|
||||
"InitGoogleLogging() first!";
|
||||
g_program_invocation_short_name = nullptr;
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
closelog();
|
||||
@ -393,10 +387,10 @@ void ShutdownGoogleLoggingUtilities() {
|
||||
# include STACKTRACE_H
|
||||
# if 0
|
||||
// For include scanners which can't handle macro expansions.
|
||||
# include "stacktrace_generic-inl.h"
|
||||
# include "stacktrace_libunwind-inl.h"
|
||||
# include "stacktrace_powerpc-inl.h"
|
||||
# include "stacktrace_x86-inl.h"
|
||||
# include "stacktrace_x86_64-inl.h"
|
||||
# include "stacktrace_powerpc-inl.h"
|
||||
# include "stacktrace_generic-inl.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -49,10 +49,13 @@
|
||||
|
||||
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.");
|
||||
|
||||
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>."
|
||||
" <module name> is a glob pattern, matched against the filename base"
|
||||
" (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 (p + 1 == patt_len) return true;
|
||||
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;
|
||||
}
|
||||
s += 1;
|
||||
@ -177,8 +181,7 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
|
||||
found = true;
|
||||
}
|
||||
info->vlog_level = log_level;
|
||||
} else if (!found &&
|
||||
SafeFNMatch_(info->module_pattern.c_str(),
|
||||
} else if (!found && SafeFNMatch_(info->module_pattern.c_str(),
|
||||
info->module_pattern.size(),
|
||||
module_pattern, pattern_len)) {
|
||||
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: This function must not allocate memory or require any locks.
|
||||
bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
|
||||
const char* fname, int32 verbose_level) {
|
||||
bool InitVLOG3__(SiteFlag* site_flag, int32* level_default, const char* fname,
|
||||
int32 verbose_level) {
|
||||
MutexLock l(&vmodule_lock);
|
||||
bool read_vmodule_flag = inited_vmodule;
|
||||
if (!read_vmodule_flag) {
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <cerrno>
|
||||
@ -33,8 +35,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Indicates that d_type field is available in dirent structure */
|
||||
#define _DIRENT_HAVE_D_TYPE
|
||||
@ -211,12 +211,10 @@
|
||||
/* Return the maximum size of a file name */
|
||||
#define _D_ALLOC_NAMLEN(p) ((PATH_MAX) + 1)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Wide-character version */
|
||||
struct _wdirent {
|
||||
/* Always zero */
|
||||
@ -288,10 +286,9 @@ static _WDIR *_wopendir (const wchar_t *dirname);
|
||||
static struct dirent* readdir(DIR* dirp);
|
||||
static struct _wdirent* _wreaddir(_WDIR* dirp);
|
||||
|
||||
static int readdir_r(
|
||||
DIR *dirp, struct dirent *entry, struct dirent **result);
|
||||
static int _wreaddir_r(
|
||||
_WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
|
||||
static int readdir_r(DIR* dirp, struct dirent* entry, struct dirent** result);
|
||||
static int _wreaddir_r(_WDIR* dirp, struct _wdirent* entry,
|
||||
struct _wdirent** result);
|
||||
|
||||
static int closedir(DIR* dirp);
|
||||
static int _wclosedir(_WDIR* dirp);
|
||||
@ -301,13 +298,13 @@ static void _wrewinddir (_WDIR* dirp);
|
||||
|
||||
static int scandir(const char* dirname, struct dirent*** namelist,
|
||||
int (*filter)(const struct dirent*),
|
||||
int (*compare)(const struct dirent**, const struct dirent**));
|
||||
int (*compare)(const struct dirent**,
|
||||
const struct dirent**));
|
||||
|
||||
static int alphasort(const struct dirent** a, const struct dirent** b);
|
||||
|
||||
static int versionsort(const struct dirent** a, const struct dirent** b);
|
||||
|
||||
|
||||
/* For compatibility with Symbian */
|
||||
#define wdirent _wdirent
|
||||
#define WDIR _WDIR
|
||||
@ -316,37 +313,26 @@ static int versionsort (const struct dirent **a, const struct dirent **b);
|
||||
#define wclosedir _wclosedir
|
||||
#define wrewinddir _wrewinddir
|
||||
|
||||
|
||||
/* Internal utility functions */
|
||||
static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp);
|
||||
static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp);
|
||||
|
||||
static int dirent_mbstowcs_s(
|
||||
size_t *pReturnValue,
|
||||
wchar_t *wcstr,
|
||||
size_t sizeInWords,
|
||||
const char *mbstr,
|
||||
static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr,
|
||||
size_t sizeInWords, const char* mbstr,
|
||||
size_t count);
|
||||
|
||||
static int dirent_wcstombs_s(
|
||||
size_t *pReturnValue,
|
||||
char *mbstr,
|
||||
size_t sizeInBytes,
|
||||
const wchar_t *wcstr,
|
||||
static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr,
|
||||
size_t sizeInBytes, const wchar_t* wcstr,
|
||||
size_t count);
|
||||
|
||||
static void dirent_set_errno(int error);
|
||||
|
||||
|
||||
/*
|
||||
* Open directory stream DIRNAME for read and return a pointer to the
|
||||
* internal working area that is used to retrieve individual directory
|
||||
* entries.
|
||||
*/
|
||||
static _WDIR*
|
||||
_wopendir(
|
||||
const wchar_t *dirname)
|
||||
{
|
||||
static _WDIR* _wopendir(const wchar_t* dirname) {
|
||||
_WDIR* dirp;
|
||||
DWORD n;
|
||||
wchar_t* p;
|
||||
@ -444,10 +430,7 @@ exit_closedir:
|
||||
* Returns pointer to static directory entry which may be overwritten by
|
||||
* subsequent calls to _wreaddir().
|
||||
*/
|
||||
static struct _wdirent*
|
||||
_wreaddir(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
static struct _wdirent* _wreaddir(_WDIR* dirp) {
|
||||
struct _wdirent* entry;
|
||||
|
||||
/*
|
||||
@ -466,12 +449,8 @@ _wreaddir(
|
||||
* Returns zero on success. If end of directory stream is reached, then sets
|
||||
* result to nullptr and returns zero.
|
||||
*/
|
||||
static int
|
||||
_wreaddir_r(
|
||||
_WDIR *dirp,
|
||||
struct _wdirent *entry,
|
||||
struct _wdirent **result)
|
||||
{
|
||||
static int _wreaddir_r(_WDIR* dirp, struct _wdirent* entry,
|
||||
struct _wdirent** result) {
|
||||
WIN32_FIND_DATAW* datap;
|
||||
|
||||
/* Read next directory entry */
|
||||
@ -526,13 +505,9 @@ _wreaddir_r(
|
||||
* DIR structure as well as any directory entry read previously by
|
||||
* _wreaddir().
|
||||
*/
|
||||
static int
|
||||
_wclosedir(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
static int _wclosedir(_WDIR* dirp) {
|
||||
int ok;
|
||||
if (dirp) {
|
||||
|
||||
/* Release search handle */
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose(dirp->handle);
|
||||
@ -546,11 +521,9 @@ _wclosedir(
|
||||
ok = /*success*/ 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Invalid directory stream */
|
||||
dirent_set_errno(EBADF);
|
||||
ok = /*failure*/ -1;
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@ -559,10 +532,7 @@ _wclosedir(
|
||||
* Rewind directory stream such that _wreaddir() returns the very first
|
||||
* file name again.
|
||||
*/
|
||||
static void
|
||||
_wrewinddir(
|
||||
_WDIR* dirp)
|
||||
{
|
||||
static void _wrewinddir(_WDIR* dirp) {
|
||||
if (dirp) {
|
||||
/* Release existing search handle */
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
@ -575,10 +545,7 @@ _wrewinddir(
|
||||
}
|
||||
|
||||
/* Get first directory entry (internal) */
|
||||
static WIN32_FIND_DATAW*
|
||||
dirent_first(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp) {
|
||||
WIN32_FIND_DATAW* datap;
|
||||
DWORD error;
|
||||
|
||||
@ -586,13 +553,11 @@ dirent_first(
|
||||
dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data,
|
||||
FindExSearchNameMatch, nullptr, 0);
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
/* a directory entry is now waiting in memory */
|
||||
datap = &dirp->data;
|
||||
dirp->cached = 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* Failed to open directory: no directory entry in memory */
|
||||
dirp->cached = 0;
|
||||
datap = nullptr;
|
||||
@ -615,7 +580,6 @@ dirent_first(
|
||||
/* Cannot find the file */
|
||||
dirent_set_errno(ENOENT);
|
||||
}
|
||||
|
||||
}
|
||||
return datap;
|
||||
}
|
||||
@ -625,21 +589,16 @@ dirent_first(
|
||||
*
|
||||
* Returns
|
||||
*/
|
||||
static WIN32_FIND_DATAW*
|
||||
dirent_next(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp) {
|
||||
WIN32_FIND_DATAW* p;
|
||||
|
||||
/* Get next directory entry */
|
||||
if (dirp->cached != 0) {
|
||||
|
||||
/* A valid directory entry already in memory */
|
||||
p = &dirp->data;
|
||||
dirp->cached = 0;
|
||||
|
||||
} else if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
/* Get the next directory entry from stream */
|
||||
if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) {
|
||||
/* Got a file */
|
||||
@ -652,7 +611,6 @@ dirent_next(
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* End of directory stream reached */
|
||||
p = nullptr;
|
||||
}
|
||||
@ -663,10 +621,7 @@ dirent_next(
|
||||
/*
|
||||
* Open directory stream using plain old C-string.
|
||||
*/
|
||||
static DIR*
|
||||
opendir(
|
||||
const char *dirname)
|
||||
{
|
||||
static DIR* opendir(const char* dirname) {
|
||||
struct DIR* dirp;
|
||||
|
||||
/* Must have directory name */
|
||||
@ -686,8 +641,7 @@ opendir(
|
||||
size_t n;
|
||||
|
||||
/* Convert directory name to wide-character string */
|
||||
error = dirent_mbstowcs_s(
|
||||
&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
|
||||
error = dirent_mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
|
||||
if (error) {
|
||||
/*
|
||||
* Cannot convert file name to wide-character string. This
|
||||
@ -698,13 +652,11 @@ opendir(
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
|
||||
/* Open directory stream using wide-character name */
|
||||
dirp->wdirp = _wopendir(wname);
|
||||
if (!dirp->wdirp) {
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Success */
|
||||
@ -719,10 +671,7 @@ exit_free:
|
||||
/*
|
||||
* Read next directory entry.
|
||||
*/
|
||||
static struct dirent*
|
||||
readdir(
|
||||
DIR *dirp)
|
||||
{
|
||||
static struct dirent* readdir(DIR* dirp) {
|
||||
struct dirent* entry;
|
||||
|
||||
/*
|
||||
@ -741,12 +690,7 @@ readdir(
|
||||
* Returns zero on success. If the end of directory stream is reached, then
|
||||
* sets result to nullptr and returns zero.
|
||||
*/
|
||||
static int
|
||||
readdir_r(
|
||||
DIR *dirp,
|
||||
struct dirent *entry,
|
||||
struct dirent **result)
|
||||
{
|
||||
static int readdir_r(DIR* dirp, struct dirent* entry, struct dirent** result) {
|
||||
WIN32_FIND_DATAW* datap;
|
||||
|
||||
/* Read next directory entry */
|
||||
@ -756,8 +700,8 @@ readdir_r(
|
||||
int error;
|
||||
|
||||
/* Attempt to convert file name to multi-byte string */
|
||||
error = dirent_wcstombs_s(
|
||||
&n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
|
||||
error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1, datap->cFileName,
|
||||
PATH_MAX + 1);
|
||||
|
||||
/*
|
||||
* If the file name cannot be represented by a multi-byte string,
|
||||
@ -770,8 +714,7 @@ readdir_r(
|
||||
* VirtualBox shared folders fail to do this.
|
||||
*/
|
||||
if (error && datap->cAlternateFileName[0] != '\0') {
|
||||
error = dirent_wcstombs_s(
|
||||
&n, entry->d_name, PATH_MAX + 1,
|
||||
error = dirent_wcstombs_s(&n, entry->d_name, PATH_MAX + 1,
|
||||
datap->cAlternateFileName, PATH_MAX + 1);
|
||||
}
|
||||
|
||||
@ -810,14 +753,12 @@ readdir_r(
|
||||
entry->d_ino = 0;
|
||||
entry->d_off = -1;
|
||||
entry->d_reclen = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Return pointer to directory entry */
|
||||
*result = entry;
|
||||
|
||||
} else {
|
||||
|
||||
/* No more directory entries */
|
||||
*result = nullptr;
|
||||
}
|
||||
@ -828,13 +769,9 @@ readdir_r(
|
||||
/*
|
||||
* Close directory stream.
|
||||
*/
|
||||
static int
|
||||
closedir(
|
||||
DIR *dirp)
|
||||
{
|
||||
static int closedir(DIR* dirp) {
|
||||
int ok;
|
||||
if (dirp) {
|
||||
|
||||
/* Close wide-character directory stream */
|
||||
ok = _wclosedir(dirp->wdirp);
|
||||
dirp->wdirp = nullptr;
|
||||
@ -843,11 +780,9 @@ closedir(
|
||||
free(dirp);
|
||||
|
||||
} else {
|
||||
|
||||
/* Invalid directory stream */
|
||||
dirent_set_errno(EBADF);
|
||||
ok = /*failure*/ -1;
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@ -855,10 +790,7 @@ closedir(
|
||||
/*
|
||||
* Rewind directory stream to beginning.
|
||||
*/
|
||||
static void
|
||||
rewinddir(
|
||||
DIR* dirp)
|
||||
{
|
||||
static void rewinddir(DIR* dirp) {
|
||||
/* Rewind wide-character string directory stream */
|
||||
_wrewinddir(dirp->wdirp);
|
||||
}
|
||||
@ -866,13 +798,10 @@ rewinddir(
|
||||
/*
|
||||
* Scan directory for entries.
|
||||
*/
|
||||
static int
|
||||
scandir(
|
||||
const char *dirname,
|
||||
struct dirent ***namelist,
|
||||
static int scandir(const char* dirname, struct dirent*** namelist,
|
||||
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;
|
||||
size_t size = 0;
|
||||
size_t allocated = 0;
|
||||
@ -886,10 +815,8 @@ scandir(
|
||||
/* Open directory stream */
|
||||
dir = opendir(dirname);
|
||||
if (dir) {
|
||||
|
||||
/* Read directory entries to memory */
|
||||
while (1) {
|
||||
|
||||
/* Enlarge pointer table to make room for another pointer */
|
||||
if (size >= allocated) {
|
||||
void* p;
|
||||
@ -929,7 +856,6 @@ scandir(
|
||||
|
||||
/* Read directory entry to temporary area */
|
||||
if (readdir_r(dir, tmp, &entry) == /*OK*/ 0) {
|
||||
|
||||
/* Did we get an entry? */
|
||||
if (entry != nullptr) {
|
||||
int pass;
|
||||
@ -967,7 +893,6 @@ scandir(
|
||||
result = /*Error*/ -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1000,31 +925,20 @@ scandir(
|
||||
}
|
||||
|
||||
/* Alphabetical sorting */
|
||||
static int
|
||||
alphasort(
|
||||
const struct dirent **a, const struct dirent **b)
|
||||
{
|
||||
static int alphasort(const struct dirent** a, const struct dirent** b) {
|
||||
return strcoll((*a)->d_name, (*b)->d_name);
|
||||
}
|
||||
|
||||
/* Sort versions */
|
||||
static int
|
||||
versionsort(
|
||||
const struct dirent **a, const struct dirent **b)
|
||||
{
|
||||
static int versionsort(const struct dirent** a, const struct dirent** b) {
|
||||
/* FIXME: implement strverscmp and use that */
|
||||
return alphasort(a, b);
|
||||
}
|
||||
|
||||
/* Convert multi-byte string to wide character string */
|
||||
static int
|
||||
dirent_mbstowcs_s(
|
||||
size_t *pReturnValue,
|
||||
wchar_t *wcstr,
|
||||
size_t sizeInWords,
|
||||
const char *mbstr,
|
||||
size_t count)
|
||||
{
|
||||
static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr,
|
||||
size_t sizeInWords, const char* mbstr,
|
||||
size_t count) {
|
||||
int error;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
@ -1040,7 +954,6 @@ dirent_mbstowcs_s(
|
||||
/* Convert to wide-character string (or count characters) */
|
||||
n = mbstowcs(wcstr, mbstr, sizeInWords);
|
||||
if (!wcstr || n < count) {
|
||||
|
||||
/* Zero-terminate output buffer */
|
||||
if (wcstr && sizeInWords) {
|
||||
if (n >= sizeInWords) {
|
||||
@ -1058,10 +971,8 @@ dirent_mbstowcs_s(
|
||||
error = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Could not convert string */
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1069,14 +980,9 @@ dirent_mbstowcs_s(
|
||||
}
|
||||
|
||||
/* Convert wide-character string to multi-byte string */
|
||||
static int
|
||||
dirent_wcstombs_s(
|
||||
size_t *pReturnValue,
|
||||
char *mbstr,
|
||||
static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr,
|
||||
size_t sizeInBytes, /* max size of mbstr */
|
||||
const wchar_t *wcstr,
|
||||
size_t count)
|
||||
{
|
||||
const wchar_t* wcstr, size_t count) {
|
||||
int error;
|
||||
|
||||
#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) */
|
||||
n = wcstombs(mbstr, wcstr, sizeInBytes);
|
||||
if (!mbstr || n < count) {
|
||||
|
||||
/* Zero-terminate output buffer */
|
||||
if (mbstr && sizeInBytes) {
|
||||
if (n >= sizeInBytes) {
|
||||
@ -1110,10 +1015,8 @@ dirent_wcstombs_s(
|
||||
error = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Cannot convert string */
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1121,10 +1024,7 @@ dirent_wcstombs_s(
|
||||
}
|
||||
|
||||
/* Set errno variable */
|
||||
static void
|
||||
dirent_set_errno(
|
||||
int error)
|
||||
{
|
||||
static void dirent_set_errno(int error) {
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
|
||||
/* Microsoft Visual Studio 2005 and later */
|
||||
@ -1138,7 +1038,6 @@ dirent_set_errno(
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -132,7 +132,8 @@ typedef DWORD pthread_key_t;
|
||||
typedef LONG pthread_once_t;
|
||||
enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
|
||||
# define pthread_self GetCurrentThreadId
|
||||
#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
|
||||
# define pthread_equal(pthread_t_1, pthread_t_2) \
|
||||
((pthread_t_1) == (pthread_t_2))
|
||||
# endif // HAVE_PTHREAD
|
||||
|
||||
# ifndef HAVE_LOCALTIME_R
|
||||
|
||||
Loading…
Reference in New Issue
Block a user