text: // Copyright (c) 2005, Google Inc.
  // All rights reserved.
  // 
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  // 
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  // 
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  // ---
  // This file contains #include information about logging-related stuff.
  // Pretty much everybody needs to #include this file so that they can
  // log various happenings.
  //
  #ifndef _LOGGING_H_
  #define _LOGGING_H_
  
  #include <config.h>
  #include <stdarg.h>
  #include <stdlib.h>
  #include <stdio.h>
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>    // for write()
  #endif
  #include <string.h>    // for strlen(), strcmp()
  #include <assert.h>
  #include <errno.h>     // for errno
  #include "base/abort.h"
  #include "base/commandlineflags.h"
  
  // On some systems (like freebsd), we can't call write() at all in a
  // global constructor, perhaps because errno hasn't been set up.
  // (In windows, we can't call it because it might call malloc.)
  // Calling the write syscall is safer (it doesn't set errno), so we
  // prefer that.  Note we don't care about errno for logging: we just
  // do logging on a best-effort basis.
  #if defined(_MSC_VER)
  #define WRITE_TO_STDERR(buf, len) WriteToStderr(buf, len);  // in port.cc
  #elif defined(__ANDROID__) || defined(ANDROID)
  #include <android/log.h>
  #define WRITE_TO_STDERR(buf, len) \
      __android_log_write(ANDROID_LOG_ERROR, "gperftools", buf)
  #elif defined(HAVE_SYS_SYSCALL_H)
  #include <sys/syscall.h>
  #define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
  #else
  #define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
  #endif
  
  // MSVC and mingw define their own, safe version of vnsprintf (the
  // windows one in broken) in port.cc.  Everyone else can use the
  // version here.  We had to give it a unique name for windows.
  #ifndef _WIN32
  # define perftools_vsnprintf vsnprintf
  #endif
  
  
  // We log all messages at this log-level and below.
  // INFO == -1, WARNING == -2, ERROR == -3, FATAL == -4
  DECLARE_int32(verbose);
  
  // CHECK dies with a fatal error if condition is not true.  It is *not*
  // controlled by NDEBUG, so the check will be executed regardless of
  // compilation mode.  Therefore, it is safe to do things like:
  //    CHECK(fp->Write(x) == 4)
  // Note we use write instead of printf/puts to avoid the risk we'll
  // call malloc().
  #define CHECK(condition)                                                \
    do {                                                                  \
      if (!(condition)) {                                                 \
        WRITE_TO_STDERR("Check failed: " #condition "\n",                 \
                        sizeof("Check failed: " #condition "\n")-1);      \
        tcmalloc::Abort();                                                \
      }                                                                   \
    } while (0)
  
  // This takes a message to print.  The name is historical.
  #define RAW_CHECK(condition, message)                                          \
    do {                                                                         \
      if (!(condition)) {                                                        \
        WRITE_TO_STDERR("Check failed: " #condition ": " message "\n",           \
                        sizeof("Check failed: " #condition ": " message "\n")-1);\
        tcmalloc::Abort();                                                       \
      }                                                                          \
    } while (0)
  
  // This is like RAW_CHECK, but only in debug-mode
  #ifdef NDEBUG
  enum { DEBUG_MODE = 0 };
  #define RAW_DCHECK(condition, message)
  #else
  enum { DEBUG_MODE = 1 };
  #define RAW_DCHECK(condition, message)  RAW_CHECK(condition, message)
  #endif
  
  // This prints errno as well.  Note we use write instead of printf/puts to
  // avoid the risk we'll call malloc().
  #define PCHECK(condition)                                               \
    do {                                                                  \
      if (!(condition)) {                                                 \
        const int err_no = errno;                                         \
        WRITE_TO_STDERR("Check failed: " #condition ": ",                 \
                        sizeof("Check failed: " #condition ": ")-1);      \
        WRITE_TO_STDERR(strerror(err_no), strlen(strerror(err_no)));      \
        WRITE_TO_STDERR("\n", sizeof("\n")-1);                            \
        tcmalloc::Abort();                                                \
      }                                                                   \
    } while (0)
  
  // Helper macro for binary operators; prints the two values on error
  // Don't use this macro directly in your code, use CHECK_EQ et al below
  
  // WARNING: These don't compile correctly if one of the arguments is a pointer
  // and the other is NULL. To work around this, simply static_cast NULL to the
  // type of the desired pointer.
  
  // TODO(jandrews): Also print the values in case of failure.  Requires some
  // sort of type-sensitive ToString() function.
  #define CHECK_OP(op, val1, val2)                                        \
    do {                                                                  \
      if (!((val1) op (val2))) {                                          \
        fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2);   \
        tcmalloc::Abort();                                                \
      }                                                                   \
    } while (0)
  
  #define CHECK_EQ(val1, val2) CHECK_OP(==, val1, val2)
  #define CHECK_NE(val1, val2) CHECK_OP(!=, val1, val2)
  #define CHECK_LE(val1, val2) CHECK_OP(<=, val1, val2)
  #define CHECK_LT(val1, val2) CHECK_OP(< , val1, val2)
  #define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
  #define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
  
  // Synonyms for CHECK_* that are used in some unittests.
  #define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2)
  #define EXPECT_NE(val1, val2) CHECK_NE(val1, val2)
  #define EXPECT_LE(val1, val2) CHECK_LE(val1, val2)
  #define EXPECT_LT(val1, val2) CHECK_LT(val1, val2)
  #define EXPECT_GE(val1, val2) CHECK_GE(val1, val2)
  #define EXPECT_GT(val1, val2) CHECK_GT(val1, val2)
  #define ASSERT_EQ(val1, val2) EXPECT_EQ(val1, val2)
  #define ASSERT_NE(val1, val2) EXPECT_NE(val1, val2)
  #define ASSERT_LE(val1, val2) EXPECT_LE(val1, val2)
  #define ASSERT_LT(val1, val2) EXPECT_LT(val1, val2)
  #define ASSERT_GE(val1, val2) EXPECT_GE(val1, val2)
  #define ASSERT_GT(val1, val2) EXPECT_GT(val1, val2)
  // As are these variants.
  #define EXPECT_TRUE(cond)     CHECK(cond)
  #define EXPECT_FALSE(cond)    CHECK(!(cond))
  #define EXPECT_STREQ(a, b)    CHECK(strcmp(a, b) == 0)
  #define ASSERT_TRUE(cond)     EXPECT_TRUE(cond)
  #define ASSERT_FALSE(cond)    EXPECT_FALSE(cond)
  #define ASSERT_STREQ(a, b)    EXPECT_STREQ(a, b)
  
  // Used for (libc) functions that return -1 and set errno
  #define CHECK_ERR(invocation)  PCHECK((invocation) != -1)
  
  // A few more checks that only happen in debug mode
  #ifdef NDEBUG
  #define DCHECK_EQ(val1, val2)
  #define DCHECK_NE(val1, val2)
  #define DCHECK_LE(val1, val2)
  #define DCHECK_LT(val1, val2)
  #define DCHECK_GE(val1, val2)
  #define DCHECK_GT(val1, val2)
  #else
  #define DCHECK_EQ(val1, val2)  CHECK_EQ(val1, val2)
  #define DCHECK_NE(val1, val2)  CHECK_NE(val1, val2)
  #define DCHECK_LE(val1, val2)  CHECK_LE(val1, val2)
  #define DCHECK_LT(val1, val2)  CHECK_LT(val1, val2)
  #define DCHECK_GE(val1, val2)  CHECK_GE(val1, val2)
  #define DCHECK_GT(val1, val2)  CHECK_GT(val1, val2)
  #endif
  
  
  #ifdef ERROR
  #undef ERROR      // may conflict with ERROR macro on windows
  #endif
  enum LogSeverity {INFO = -1, WARNING = -2, ERROR = -3, FATAL = -4};
  
  // NOTE: we add a newline to the end of the output if it's not there already
  inline void LogPrintf(int severity, const char* pat, va_list ap) {
    // We write directly to the stderr file descriptor and avoid FILE
    // buffering because that may invoke malloc()
    char buf[1600];
    perftools_vsnprintf(buf, sizeof(buf)-1, pat, ap);
    if (buf[0] != '\0' && buf[strlen(buf)-1] != '\n') {
      assert(strlen(buf)+1 < sizeof(buf));
      strcat(buf, "\n");
    }
  #if defined(__ANDROID__) || defined(ANDROID)
    android_LogPriority priority = ANDROID_LOG_UNKNOWN;
    if (severity >= 0) {
      priority = ANDROID_LOG_VERBOSE;
    } else {
      switch (severity) {
        case INFO: {
          priority = ANDROID_LOG_INFO;
          break;
        }
        case WARNING: {
          priority = ANDROID_LOG_WARN;
          break;
        }
        case ERROR: {
          priority = ANDROID_LOG_ERROR;
          break;
        }
        case FATAL: {
          priority = ANDROID_LOG_FATAL;
          break;
        }
      }
    }
    __android_log_write(priority, "gperftools", buf);
  #else  // defined(__ANDROID__) || defined(ANDROID)
    WRITE_TO_STDERR(buf, strlen(buf));
  #endif  // defined(__ANDROID__) || defined(ANDROID)
    if ((severity) == FATAL) {
      // LOG(FATAL) indicates a big problem, so don't run atexit() calls
      tcmalloc::Abort();
    }
  }
  
  // Note that since the order of global constructors is unspecified,
  // global code that calls RAW_LOG may execute before FLAGS_verbose is set.
  // Such code will run with verbosity == 0 no matter what.
  #define VLOG_IS_ON(severity) (FLAGS_verbose >= severity)
  
  // In a better world, we'd use __VA_ARGS__, but VC++ 7 doesn't support it.
  #define LOG_PRINTF(severity, pat) do {          \
    if (VLOG_IS_ON(severity)) {                   \
      va_list ap;                                 \
      va_start(ap, pat);                          \
      LogPrintf(severity, pat, ap);               \
      va_end(ap);                                 \
    }                                             \
  } while (0)
  
  // RAW_LOG is the main function; some synonyms are used in unittests.
  inline void RAW_LOG(int lvl, const char* pat, ...)  { LOG_PRINTF(lvl, pat); }
  inline void RAW_VLOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); }
  inline void LOG(int lvl, const char* pat, ...)      { LOG_PRINTF(lvl, pat); }
  inline void VLOG(int lvl, const char* pat, ...)     { LOG_PRINTF(lvl, pat); }
  inline void LOG_IF(int lvl, bool cond, const char* pat, ...) {
    if (cond)  LOG_PRINTF(lvl, pat);
  }
  
  // This isn't technically logging, but it's also IO and also is an
  // attempt to be "raw" -- that is, to not use any higher-level libc
  // routines that might allocate memory or (ideally) try to allocate
  // locks.  We use an opaque file handle (not necessarily an int)
  // to allow even more low-level stuff in the future.
  // Like other "raw" routines, these functions are best effort, and
  // thus don't return error codes (except RawOpenForWriting()).
  #if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
  #ifndef NOMINMAX
  #define NOMINMAX     // @#!$& windows
  #endif
  #include <windows.h>
  typedef HANDLE RawFD;
  const RawFD kIllegalRawFD = INVALID_HANDLE_VALUE;
  #else
  typedef int RawFD;
  const RawFD kIllegalRawFD = -1;   // what open returns if it fails
  #endif  // defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
  
  RawFD RawOpenForWriting(const char* filename);   // uses default permissions
  void RawWrite(RawFD fd, const char* buf, size_t len);
  void RawClose(RawFD fd);
  
  #endif // _LOGGING_H_
  