summaryrefslogtreecommitdiff
path: root/sal/osl/all/log.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/all/log.cxx')
-rw-r--r--sal/osl/all/log.cxx199
1 files changed, 199 insertions, 0 deletions
diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx
new file mode 100644
index 000000000000..be45cf629b81
--- /dev/null
+++ b/sal/osl/all/log.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * [ Copyright (C) 2011 Stephan Bergmann, Red Hat <sbergman@redhat.com> (initial
+ * developer) ]
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include "precompiled_sal.hxx"
+#include "sal/config.h"
+
+#include <cassert>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+
+#include <stdio.h> // vsnprintf
+
+#include "osl/thread.hxx"
+#include "rtl/string.h"
+#include "sal/log.h"
+#include "sal/types.h"
+
+#include "logformat.hxx"
+
+#if defined WNT
+#include <process.h>
+#define OSL_DETAIL_GETPID _getpid()
+#else
+#include <unistd.h>
+#define OSL_DETAIL_GETPID getpid()
+#endif
+
+// Avoid the use of other sal code in this file as much as possible, so that
+// this code can be called from other sal code without causing endless
+// recursion.
+
+namespace {
+
+bool equalStrings(
+ char const * string1, std::size_t length1, char const * string2,
+ std::size_t length2)
+{
+ return length1 == length2 && std::memcmp(string1, string2, length1) == 0;
+}
+
+char const * toString(sal_detail_LogLevel level) {
+ switch (level) {
+ default:
+ assert(false); // this cannot happen
+ // fall through
+ case SAL_DETAIL_LOG_LEVEL_INFO:
+ return "info";
+ case SAL_DETAIL_LOG_LEVEL_WARN:
+ return "warn";
+ }
+}
+
+bool report(sal_detail_LogLevel level, char const * area) {
+ assert(area != 0);
+ char const * env = std::getenv("SAL_LOG");
+ if (env == 0) {
+ env = "+WARN";
+ }
+ std::size_t areaLen = std::strlen(area);
+ enum Sense { POSITIVE = 0, NEGATIVE = 1 };
+ std::size_t senseLen[2] = { 0, 1 };
+ // initial senseLen[POSITIVE] < senseLen[NEGATIVE], so that if there are
+ // no matching switches at all, the result will be negative (and
+ // initializing with 1 is safe as the length of a valid switch, even
+ // without the "+"/"-" prefix, will always be > 1)
+ for (char const * p = env;;) {
+ Sense sense;
+ switch (*p++) {
+ case '\0':
+ return senseLen[POSITIVE] >= senseLen[NEGATIVE];
+ // if a specific item is both postiive and negative
+ // (senseLen[POSITIVE] == senseLen[NEGATIVE]), default to
+ // positive
+ case '+':
+ sense = POSITIVE;
+ break;
+ case '-':
+ sense = NEGATIVE;
+ break;
+ default:
+ return true; // upon an illegal SAL_LOG value, enable everything
+ }
+ char const * p1 = p;
+ while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
+ ++p1;
+ }
+ bool match;
+ if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("INFO"))) {
+ match = level == SAL_DETAIL_LOG_LEVEL_INFO;
+ } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN")))
+ {
+ match = level == SAL_DETAIL_LOG_LEVEL_WARN;
+ } else {
+ return true;
+ // upon an illegal SAL_LOG value, everything is considered
+ // positive
+ }
+ char const * p2 = p1;
+ while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
+ ++p2;
+ }
+ if (match) {
+ if (*p1 == '.') {
+ ++p1;
+ std::size_t n = p2 - p1;
+ if ((n == areaLen && equalStrings(p1, n, area, areaLen))
+ || (n < areaLen && area[n] == '.'
+ && equalStrings(p1, n, area, n)))
+ {
+ senseLen[sense] = p2 - p;
+ }
+ } else {
+ senseLen[sense] = p1 - p;
+ }
+ }
+ p = p2;
+ }
+}
+
+void log(
+ sal_detail_LogLevel level, char const * area, char const * where,
+ char const * message)
+{
+ std::ostringstream s;
+ s << toString(level) << ':' << area << ':' << OSL_DETAIL_GETPID << ':'
+ << osl::Thread::getCurrentIdentifier() << ':' << where << message
+ << '\n';
+ std::fputs(s.str().c_str(), stderr);
+}
+
+}
+
+void sal_detail_log(
+ sal_detail_LogLevel level, char const * area, char const * where,
+ char const * message)
+{
+ if (report(level, area)) {
+ log(level, area, where, message);
+ }
+}
+
+void sal_detail_logFormat(
+ sal_detail_LogLevel level, char const * area, char const * where,
+ char const * format, ...)
+{
+ if (report(level, area)) {
+ std::va_list args;
+ va_start(args, format);
+ osl::detail::logFormat(level, area, where, format, args);
+ va_end(args);
+ }
+}
+
+void osl::detail::logFormat(
+ sal_detail_LogLevel level, char const * area, char const * where,
+ char const * format, std::va_list arguments)
+{
+ char buf[1024];
+ int const len = sizeof buf - RTL_CONSTASCII_LENGTH("...");
+ int n = vsnprintf(buf, len, format, arguments);
+ if (n < 0) {
+ std::strcpy(buf, "???");
+ } else if (n >= len) {
+ std::strcpy(buf + len - 1, "...");
+ }
+ log(level, area, where, buf);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */