Bump for 3.6-28
[LibreOffice.git] / sal / osl / all / log.cxx
blobbac0e93139191812e271dddec7a893b1f3051f6e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
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/
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.
15 * Major Contributor(s):
16 * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann <sbergman@redhat.com>
17 * (initial developer)
19 * All Rights Reserved.
21 * For minor contributions see the git repository.
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.
30 #include "sal/config.h"
32 #include <cassert>
33 #include <cstdarg>
34 #include <cstddef>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <sstream>
40 #include <stdio.h> // vsnprintf
42 #include "osl/thread.hxx"
43 #include "rtl/string.h"
44 #include "sal/detail/log.h"
45 #include "sal/log.hxx"
46 #include "sal/types.h"
48 #include "logformat.hxx"
50 #if defined WNT
51 #include <process.h>
52 #define OSL_DETAIL_GETPID _getpid()
53 #else
54 #include <unistd.h>
55 #define OSL_DETAIL_GETPID getpid()
56 #endif
58 // Avoid the use of other sal code in this file as much as possible, so that
59 // this code can be called from other sal code without causing endless
60 // recursion.
62 namespace {
64 bool equalStrings(
65 char const * string1, std::size_t length1, char const * string2,
66 std::size_t length2)
68 return length1 == length2 && std::memcmp(string1, string2, length1) == 0;
71 char const * toString(sal_detail_LogLevel level) {
72 switch (level) {
73 default:
74 assert(false); // this cannot happen
75 // fall through
76 case SAL_DETAIL_LOG_LEVEL_INFO:
77 return "info";
78 case SAL_DETAIL_LOG_LEVEL_WARN:
79 return "warn";
80 case SAL_DETAIL_LOG_LEVEL_DEBUG:
81 return "debug";
85 bool report(sal_detail_LogLevel level, char const * area) {
86 if (level == SAL_DETAIL_LOG_LEVEL_DEBUG)
87 return true;
88 assert(area != 0);
89 char const * env = std::getenv("SAL_LOG");
90 if (env == 0) {
91 env = "+WARN";
93 std::size_t areaLen = std::strlen(area);
94 enum Sense { POSITIVE = 0, NEGATIVE = 1 };
95 std::size_t senseLen[2] = { 0, 1 };
96 // initial senseLen[POSITIVE] < senseLen[NEGATIVE], so that if there are
97 // no matching switches at all, the result will be negative (and
98 // initializing with 1 is safe as the length of a valid switch, even
99 // without the "+"/"-" prefix, will always be > 1)
100 for (char const * p = env;;) {
101 Sense sense;
102 switch (*p++) {
103 case '\0':
104 return senseLen[POSITIVE] >= senseLen[NEGATIVE];
105 // if a specific item is both postiive and negative
106 // (senseLen[POSITIVE] == senseLen[NEGATIVE]), default to
107 // positive
108 case '+':
109 sense = POSITIVE;
110 break;
111 case '-':
112 sense = NEGATIVE;
113 break;
114 default:
115 return true; // upon an illegal SAL_LOG value, enable everything
117 char const * p1 = p;
118 while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
119 ++p1;
121 bool match;
122 if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("INFO"))) {
123 match = level == SAL_DETAIL_LOG_LEVEL_INFO;
124 } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN")))
126 match = level == SAL_DETAIL_LOG_LEVEL_WARN;
127 } else {
128 return true;
129 // upon an illegal SAL_LOG value, everything is considered
130 // positive
132 char const * p2 = p1;
133 while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
134 ++p2;
136 if (match) {
137 if (*p1 == '.') {
138 ++p1;
139 std::size_t n = p2 - p1;
140 if ((n == areaLen && equalStrings(p1, n, area, areaLen))
141 || (n < areaLen && area[n] == '.'
142 && equalStrings(p1, n, area, n)))
144 senseLen[sense] = p2 - p;
146 } else {
147 senseLen[sense] = p1 - p;
150 p = p2;
154 void log(
155 sal_detail_LogLevel level, char const * area, char const * where,
156 char const * message)
158 std::ostringstream s;
159 if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) {
160 s << toString(level) << ':' << /*no where*/' ' << message << '\n';
161 } else {
162 s << toString(level) << ':' << area << ':' << OSL_DETAIL_GETPID << ':'
163 << osl::Thread::getCurrentIdentifier() << ':' << where << message
164 << '\n';
166 std::fputs(s.str().c_str(), stderr);
171 SAL_DLLPUBLIC void sal_detail_log(
172 sal_detail_LogLevel level, char const * area, char const * where,
173 char const * message)
175 if (report(level, area)) {
176 log(level, area, where, message);
180 SAL_DLLPUBLIC void sal_detail_logFormat(
181 sal_detail_LogLevel level, char const * area, char const * where,
182 char const * format, ...)
184 if (report(level, area)) {
185 std::va_list args;
186 va_start(args, format);
187 osl::detail::logFormat(level, area, where, format, args);
188 va_end(args);
192 void osl::detail::logFormat(
193 sal_detail_LogLevel level, char const * area, char const * where,
194 char const * format, std::va_list arguments)
196 char buf[1024];
197 int const len = sizeof buf - RTL_CONSTASCII_LENGTH("...");
198 int n = vsnprintf(buf, len, format, arguments);
199 if (n < 0) {
200 std::strcpy(buf, "???");
201 } else if (n >= len) {
202 std::strcpy(buf + len - 1, "...");
204 log(level, area, where, buf);
207 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */