LCOV - code coverage report
Current view: top level - sal/osl/all - log.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 0 100 0.0 %
Date: 2014-04-11 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "sal/config.h"
      11             : 
      12             : #include <cassert>
      13             : #include <cstdarg>
      14             : #include <cstddef>
      15             : #include <cstdio>
      16             : #include <cstdlib>
      17             : #include <cstring>
      18             : #include <sstream>
      19             : 
      20             : #include <stdio.h>
      21             : #include <string.h>
      22             : 
      23             : #include "osl/thread.hxx"
      24             : #include "rtl/string.h"
      25             : #include "sal/detail/log.h"
      26             : #include "sal/log.hxx"
      27             : #include "sal/types.h"
      28             : 
      29             : #include "logformat.hxx"
      30             : 
      31             : #if defined ANDROID
      32             : #include <android/log.h>
      33             : #elif defined WNT
      34             : #include <process.h>
      35             : #define OSL_DETAIL_GETPID _getpid()
      36             : #else
      37             : #include <unistd.h>
      38             : #define OSL_DETAIL_GETPID getpid()
      39             : #endif
      40             : 
      41             : #if HAVE_SYSLOG_H
      42             : #include <syslog.h>
      43             : // sal/osl/unx/salinit.cxx::sal_detail_initialize updates this:
      44             : bool sal_use_syslog;
      45             : #else
      46             : enum { sal_use_syslog = false };
      47             : #endif
      48             : 
      49             : // Avoid the use of other sal code in this file as much as possible, so that
      50             : // this code can be called from other sal code without causing endless
      51             : // recursion.
      52             : 
      53             : namespace {
      54             : 
      55           0 : bool equalStrings(
      56             :     char const * string1, std::size_t length1, char const * string2,
      57             :     std::size_t length2)
      58             : {
      59           0 :     return length1 == length2 && std::memcmp(string1, string2, length1) == 0;
      60             : }
      61             : 
      62             : #if !defined ANDROID
      63           0 : char const * toString(sal_detail_LogLevel level) {
      64           0 :     switch (level) {
      65             :     default:
      66             :         assert(false); // this cannot happen
      67             :         // fall through
      68             :     case SAL_DETAIL_LOG_LEVEL_INFO:
      69           0 :         return "info";
      70             :     case SAL_DETAIL_LOG_LEVEL_WARN:
      71           0 :         return "warn";
      72             :     case SAL_DETAIL_LOG_LEVEL_DEBUG:
      73           0 :         return "debug";
      74             :     }
      75             : }
      76             : #endif
      77             : 
      78             : // getenv is not thread safe, so minimize use of result; except on Android, see
      79             : // 60628799633ffde502cb105b98d3f254f93115aa "Notice if SAL_LOG is changed while
      80             : // the process is running":
      81             : #if defined ANDROID
      82             : 
      83             : char const * getEnvironmentVariable() {
      84             :     return std::getenv("SAL_LOG");
      85             : }
      86             : 
      87             : #else
      88             : 
      89           0 : char const * getEnvironmentVariable_() {
      90           0 :     char const * p1 = std::getenv("SAL_LOG");
      91           0 :     if (p1 == 0) {
      92           0 :         return 0;
      93             :     }
      94           0 :     char const * p2 = strdup(p1); // leaked
      95           0 :     if (p2 == 0) {
      96           0 :         std::abort(); // cannot do much here
      97             :     }
      98           0 :     return p2;
      99             : }
     100             : 
     101           0 : char const * getEnvironmentVariable() {
     102           0 :     static char const * env = getEnvironmentVariable_();
     103           0 :     return env;
     104             : }
     105             : 
     106             : #endif
     107             : 
     108           0 : bool report(sal_detail_LogLevel level, char const * area) {
     109           0 :     if (level == SAL_DETAIL_LOG_LEVEL_DEBUG)
     110           0 :         return true;
     111             :     assert(area != 0);
     112           0 :     char const * env = getEnvironmentVariable();
     113           0 :     if (env == 0) {
     114           0 :         env = "+WARN";
     115             :     }
     116           0 :     std::size_t areaLen = std::strlen(area);
     117             :     enum Sense { POSITIVE = 0, NEGATIVE = 1 };
     118           0 :     std::size_t senseLen[2] = { 0, 1 };
     119             :         // initial senseLen[POSITIVE] < senseLen[NEGATIVE], so that if there are
     120             :         // no matching switches at all, the result will be negative (and
     121             :         // initializing with 1 is safe as the length of a valid switch, even
     122             :         // without the "+"/"-" prefix, will always be > 1)
     123           0 :     for (char const * p = env;;) {
     124             :         Sense sense;
     125           0 :         switch (*p++) {
     126             :         case '\0':
     127           0 :             return senseLen[POSITIVE] >= senseLen[NEGATIVE];
     128             :                 // if a specific item is both postiive and negative
     129             :                 // (senseLen[POSITIVE] == senseLen[NEGATIVE]), default to
     130             :                 // positive
     131             :         case '+':
     132           0 :             sense = POSITIVE;
     133           0 :             break;
     134             :         case '-':
     135           0 :             sense = NEGATIVE;
     136           0 :             break;
     137             :         default:
     138           0 :             return true; // upon an illegal SAL_LOG value, enable everything
     139             :         }
     140           0 :         char const * p1 = p;
     141           0 :         while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
     142           0 :             ++p1;
     143             :         }
     144             :         bool match;
     145           0 :         if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("INFO"))) {
     146           0 :             match = level == SAL_DETAIL_LOG_LEVEL_INFO;
     147           0 :         } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN")))
     148             :         {
     149           0 :             match = level == SAL_DETAIL_LOG_LEVEL_WARN;
     150             :         } else {
     151           0 :             return true;
     152             :                 // upon an illegal SAL_LOG value, everything is considered
     153             :                 // positive
     154             :         }
     155           0 :         char const * p2 = p1;
     156           0 :         while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
     157           0 :             ++p2;
     158             :         }
     159           0 :         if (match) {
     160           0 :             if (*p1 == '.') {
     161           0 :                 ++p1;
     162           0 :                 std::size_t n = p2 - p1;
     163           0 :                 if ((n == areaLen && equalStrings(p1, n, area, areaLen))
     164           0 :                     || (n < areaLen && area[n] == '.'
     165           0 :                         && equalStrings(p1, n, area, n)))
     166             :                 {
     167           0 :                     senseLen[sense] = p2 - p;
     168             :                 }
     169             :             } else {
     170           0 :                 senseLen[sense] = p1 - p;
     171             :             }
     172             :         }
     173           0 :         p = p2;
     174           0 :     }
     175             : }
     176             : 
     177           0 : void log(
     178             :     sal_detail_LogLevel level, char const * area, char const * where,
     179             :     char const * message)
     180             : {
     181           0 :     std::ostringstream s;
     182             : #if !defined ANDROID
     183             :     // On Android, the area will be used as the "tag," and log info already
     184             :     // contains the PID
     185           0 :     if (!sal_use_syslog) {
     186           0 :         s << toString(level) << ':';
     187             :     }
     188           0 :     if (level != SAL_DETAIL_LOG_LEVEL_DEBUG) {
     189           0 :         s << area << ':';
     190             :     }
     191           0 :     s << OSL_DETAIL_GETPID << ':';
     192             : #endif
     193           0 :     s << osl::Thread::getCurrentIdentifier() << ':';
     194           0 :     if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) {
     195           0 :         s << ' ';
     196             :     } else {
     197             :         s << (where
     198           0 :               + (std::strncmp(where, SRCDIR "/", std::strlen(SRCDIR "/")) == 0
     199           0 :                  ? std::strlen(SRCDIR "/") : 0));
     200             :     }
     201           0 :     s << message << '\n';
     202             : #if defined ANDROID
     203             :     int android_log_level;
     204             :     switch (level) {
     205             :     case SAL_DETAIL_LOG_LEVEL_INFO:
     206             :         android_log_level = ANDROID_LOG_INFO;
     207             :         break;
     208             :     case SAL_DETAIL_LOG_LEVEL_WARN:
     209             :         android_log_level = ANDROID_LOG_WARN;
     210             :         break;
     211             :     case SAL_DETAIL_LOG_LEVEL_DEBUG:
     212             :         android_log_level = ANDROID_LOG_DEBUG;
     213             :         break;
     214             :     default:
     215             :         android_log_level = ANDROID_LOG_INFO;
     216             :         break;
     217             :     }
     218             :     __android_log_print(
     219             :         android_log_level, area == 0 ? "LibreOffice" : area, "%s",
     220             :         s.str().c_str());
     221             : #else
     222           0 :     if (sal_use_syslog) {
     223             : #if HAVE_SYSLOG_H
     224             :         int prio;
     225           0 :         switch (level) {
     226             :         case SAL_DETAIL_LOG_LEVEL_INFO:
     227           0 :             prio = LOG_INFO;
     228           0 :             break;
     229             :         default:
     230             :             assert(false); // this cannot happen
     231             :             // fall through
     232             :         case SAL_DETAIL_LOG_LEVEL_WARN:
     233           0 :             prio = LOG_WARNING;
     234           0 :             break;
     235             :         case SAL_DETAIL_LOG_LEVEL_DEBUG:
     236           0 :             prio = LOG_DEBUG;
     237           0 :             break;
     238             :         }
     239           0 :         syslog(prio, "%s", s.str().c_str());
     240             : #endif
     241             :     } else {
     242           0 :         std::fputs(s.str().c_str(), stderr);
     243           0 :     }
     244             : #endif
     245           0 : }
     246             : 
     247             : }
     248             : 
     249           0 : void sal_detail_log(
     250             :     sal_detail_LogLevel level, char const * area, char const * where,
     251             :     char const * message)
     252             : {
     253           0 :     if (report(level, area)) {
     254           0 :         log(level, area, where, message);
     255             :     }
     256           0 : }
     257             : 
     258           0 : void sal_detail_logFormat(
     259             :     sal_detail_LogLevel level, char const * area, char const * where,
     260             :     char const * format, ...)
     261             : {
     262           0 :     if (report(level, area)) {
     263             :         std::va_list args;
     264           0 :         va_start(args, format);
     265           0 :         osl::detail::logFormat(level, area, where, format, args);
     266           0 :         va_end(args);
     267             :     }
     268           0 : }
     269             : 
     270           0 : void osl::detail::logFormat(
     271             :     sal_detail_LogLevel level, char const * area, char const * where,
     272             :     char const * format, std::va_list arguments)
     273             : {
     274             :     char buf[1024];
     275           0 :     int const len = sizeof buf - RTL_CONSTASCII_LENGTH("...");
     276           0 :     int n = vsnprintf(buf, len, format, arguments);
     277           0 :     if (n < 0) {
     278           0 :         std::strcpy(buf, "???");
     279           0 :     } else if (n >= len) {
     280           0 :         std::strcpy(buf + len - 1, "...");
     281             :     }
     282           0 :     log(level, area, where, buf);
     283           0 : }
     284             : 
     285             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10