LCOV - code coverage report
Current view: top level - libreoffice/sal/osl/all - log.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 87 0.0 %
Date: 2012-12-27 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             :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4             :  *
       5             :  * The contents of this file are subject to the Mozilla Public License Version
       6             :  * 1.1 (the "License"); you may not use this file except in compliance with
       7             :  * the License or as specified alternatively below. You may obtain a copy of
       8             :  * the License at http://www.mozilla.org/MPL/
       9             :  *
      10             :  * Software distributed under the License is distributed on an "AS IS" basis,
      11             :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12             :  * for the specific language governing rights and limitations under the
      13             :  * License.
      14             :  *
      15             :  * Major Contributor(s):
      16             :  * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann <sbergman@redhat.com>
      17             :  *  (initial developer)
      18             :  *
      19             :  * All Rights Reserved.
      20             :  *
      21             :  * For minor contributions see the git repository.
      22             :  *
      23             :  * Alternatively, the contents of this file may be used under the terms of
      24             :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      25             :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      26             :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      27             :  * instead of those above.
      28             :  */
      29             : 
      30             : #include "sal/config.h"
      31             : 
      32             : #include <cassert>
      33             : #include <cstdarg>
      34             : #include <cstddef>
      35             : #include <cstdio>
      36             : #include <cstdlib>
      37             : #include <cstring>
      38             : #include <sstream>
      39             : 
      40             : #include <stdio.h> // vsnprintf
      41             : #include <string.h> // strdup
      42             : 
      43             : #include "osl/thread.hxx"
      44             : #include "rtl/string.h"
      45             : #include "sal/detail/log.h"
      46             : #include "sal/log.hxx"
      47             : #include "sal/types.h"
      48             : 
      49             : #include "logformat.hxx"
      50             : 
      51             : #if defined WNT
      52             : #include <process.h>
      53             : #define OSL_DETAIL_GETPID _getpid()
      54             : #else
      55             : #include <unistd.h>
      56             : #define OSL_DETAIL_GETPID getpid()
      57             : #endif
      58             : 
      59             : #ifdef HAVE_SYSLOG_H
      60             : #include <syslog.h>
      61             : // sal/osl/unx/salinit.cxx::sal_detail_initialize updates this:
      62             : bool sal_use_syslog;
      63             : #endif
      64             : 
      65             : // Avoid the use of other sal code in this file as much as possible, so that
      66             : // this code can be called from other sal code without causing endless
      67             : // recursion.
      68             : 
      69             : namespace {
      70             : 
      71           0 : bool equalStrings(
      72             :     char const * string1, std::size_t length1, char const * string2,
      73             :     std::size_t length2)
      74             : {
      75           0 :     return length1 == length2 && std::memcmp(string1, string2, length1) == 0;
      76             : }
      77             : 
      78           0 : char const * toString(sal_detail_LogLevel level) {
      79           0 :     switch (level) {
      80             :     default:
      81             :         assert(false); // this cannot happen
      82             :         // fall through
      83             :     case SAL_DETAIL_LOG_LEVEL_INFO:
      84           0 :         return "info";
      85             :     case SAL_DETAIL_LOG_LEVEL_WARN:
      86           0 :         return "warn";
      87             :     case SAL_DETAIL_LOG_LEVEL_DEBUG:
      88           0 :         return "debug";
      89             :     }
      90             : }
      91             : 
      92             : // getenv is not thread safe, so minimize use of result:
      93           0 : char const * getEnvironmentVariable() {
      94           0 :     char const * p1 = std::getenv("SAL_LOG");
      95           0 :     if (p1 == 0) {
      96           0 :         return "+WARN";
      97             :     }
      98           0 :     char const * p2 = strdup(p1); // leaked
      99           0 :     if (p2 == 0) {
     100           0 :         std::abort(); // cannot do much here
     101             :     }
     102           0 :     return p2;
     103             : }
     104             : 
     105             : #ifdef HAVE_SYSLOG_H
     106           0 : int toSyslogPriority(sal_detail_LogLevel level) {
     107           0 :     switch (level) {
     108             :     default:
     109             :         assert(false); // this cannot happen
     110             :         // fall through
     111             :     case SAL_DETAIL_LOG_LEVEL_INFO:
     112           0 :         return LOG_INFO;
     113             :     case SAL_DETAIL_LOG_LEVEL_WARN:
     114           0 :         return LOG_WARNING;
     115             :     case SAL_DETAIL_LOG_LEVEL_DEBUG:
     116           0 :         return LOG_DEBUG;
     117             :     }
     118             : }
     119             : #endif
     120             : 
     121           0 : bool report(sal_detail_LogLevel level, char const * area) {
     122           0 :     if (level == SAL_DETAIL_LOG_LEVEL_DEBUG)
     123           0 :         return true;
     124             :     assert(area != 0);
     125           0 :     static char const * env = getEnvironmentVariable();
     126           0 :     std::size_t areaLen = std::strlen(area);
     127             :     enum Sense { POSITIVE = 0, NEGATIVE = 1 };
     128           0 :     std::size_t senseLen[2] = { 0, 1 };
     129             :         // initial senseLen[POSITIVE] < senseLen[NEGATIVE], so that if there are
     130             :         // no matching switches at all, the result will be negative (and
     131             :         // initializing with 1 is safe as the length of a valid switch, even
     132             :         // without the "+"/"-" prefix, will always be > 1)
     133           0 :     for (char const * p = env;;) {
     134             :         Sense sense;
     135           0 :         switch (*p++) {
     136             :         case '\0':
     137           0 :             return senseLen[POSITIVE] >= senseLen[NEGATIVE];
     138             :                 // if a specific item is both postiive and negative
     139             :                 // (senseLen[POSITIVE] == senseLen[NEGATIVE]), default to
     140             :                 // positive
     141             :         case '+':
     142           0 :             sense = POSITIVE;
     143           0 :             break;
     144             :         case '-':
     145           0 :             sense = NEGATIVE;
     146           0 :             break;
     147             :         default:
     148           0 :             return true; // upon an illegal SAL_LOG value, enable everything
     149             :         }
     150           0 :         char const * p1 = p;
     151           0 :         while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
     152           0 :             ++p1;
     153             :         }
     154             :         bool match;
     155           0 :         if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("INFO"))) {
     156           0 :             match = level == SAL_DETAIL_LOG_LEVEL_INFO;
     157           0 :         } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN")))
     158             :         {
     159           0 :             match = level == SAL_DETAIL_LOG_LEVEL_WARN;
     160             :         } else {
     161           0 :             return true;
     162             :                 // upon an illegal SAL_LOG value, everything is considered
     163             :                 // positive
     164             :         }
     165           0 :         char const * p2 = p1;
     166           0 :         while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
     167           0 :             ++p2;
     168             :         }
     169           0 :         if (match) {
     170           0 :             if (*p1 == '.') {
     171           0 :                 ++p1;
     172           0 :                 std::size_t n = p2 - p1;
     173           0 :                 if ((n == areaLen && equalStrings(p1, n, area, areaLen))
     174           0 :                     || (n < areaLen && area[n] == '.'
     175           0 :                         && equalStrings(p1, n, area, n)))
     176             :                 {
     177           0 :                     senseLen[sense] = p2 - p;
     178             :                 }
     179             :             } else {
     180           0 :                 senseLen[sense] = p1 - p;
     181             :             }
     182             :         }
     183           0 :         p = p2;
     184             :     }
     185             : }
     186             : 
     187           0 : void log(
     188             :     sal_detail_LogLevel level, char const * area, char const * where,
     189             :     char const * message)
     190             : {
     191           0 :     std::ostringstream s;
     192             : #ifdef HAVE_SYSLOG_H
     193           0 :     if (!sal_use_syslog)
     194             : #endif
     195           0 :         s << toString(level) << ':';
     196           0 :     if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) {
     197           0 :         s << /*no where*/' ' << message << '\n';
     198             :     } else {
     199           0 :         s << area << ':' << OSL_DETAIL_GETPID << ':'
     200           0 :             << osl::Thread::getCurrentIdentifier() << ':' << where << message
     201           0 :             << '\n';
     202             :     }
     203             : #ifdef HAVE_SYSLOG_H
     204           0 :     if (sal_use_syslog)
     205           0 :         syslog(toSyslogPriority(level), "%s", s.str().c_str());
     206             :     else
     207             : #endif
     208           0 :         std::fputs(s.str().c_str(), stderr);
     209           0 : }
     210             : 
     211             : }
     212             : 
     213           0 : void sal_detail_log(
     214             :     sal_detail_LogLevel level, char const * area, char const * where,
     215             :     char const * message)
     216             : {
     217           0 :     if (report(level, area)) {
     218           0 :         log(level, area, where, message);
     219             :     }
     220           0 : }
     221             : 
     222           0 : void sal_detail_logFormat(
     223             :     sal_detail_LogLevel level, char const * area, char const * where,
     224             :     char const * format, ...)
     225             : {
     226           0 :     if (report(level, area)) {
     227             :         std::va_list args;
     228           0 :         va_start(args, format);
     229           0 :         osl::detail::logFormat(level, area, where, format, args);
     230           0 :         va_end(args);
     231             :     }
     232           0 : }
     233             : 
     234           0 : void osl::detail::logFormat(
     235             :     sal_detail_LogLevel level, char const * area, char const * where,
     236             :     char const * format, std::va_list arguments)
     237             : {
     238             :     char buf[1024];
     239           0 :     int const len = sizeof buf - RTL_CONSTASCII_LENGTH("...");
     240           0 :     int n = vsnprintf(buf, len, format, arguments);
     241           0 :     if (n < 0) {
     242           0 :         std::strcpy(buf, "???");
     243           0 :     } else if (n >= len) {
     244           0 :         std::strcpy(buf + len - 1, "...");
     245             :     }
     246           0 :     log(level, area, where, buf);
     247           0 : }
     248             : 
     249             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10