--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/log.cc Wed Sep 12 16:24:31 2007 -0700
@@ -0,0 +1,269 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include <list>
+#include <utility>
+#include <iostream>
+#include "log.h"
+#include "assert.h"
+#include "ns3/core-config.h"
+#include "fatal-error.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+namespace ns3 {
+
+typedef std::list<std::pair <std::string, LogComponent *> > ComponentList;
+typedef std::list<std::pair <std::string, LogComponent *> >::iterator ComponentListI;
+
+static
+ComponentList *GetComponentList (void)
+{
+ static ComponentList components;
+ return &components;
+}
+
+void
+LogComponentEnableEnvVar (void)
+{
+ static bool isFirstLog = true;
+ if (!isFirstLog)
+ {
+ return;
+ }
+#ifdef HAVE_GETENV
+ char *envVar = getenv("NS_LOG");
+ if (envVar == 0)
+ {
+ isFirstLog = false;
+ return;
+ }
+ std::string env = envVar;
+ if (env == "print-list")
+ {
+ LogComponentPrintList ();
+ isFirstLog = false;
+ return;
+ }
+ bool allFound = true;
+ std::string::size_type cur = 0;
+ std::string::size_type next = 0;
+ while (true)
+ {
+ next = env.find_first_of (";", cur);
+ std::string tmp = std::string (env, cur, next);
+ {
+ /* The following code is a workaround for a bug in the g++
+ * c++ string library. Its goal is to remove any trailing ';'
+ * from the string even though there should not be any in
+ * it. This code should be safe even if the bug is not there.
+ */
+ std::string::size_type trailing = tmp.find_first_of (";");
+ tmp = tmp.substr (0, trailing);
+ }
+ if (tmp.size () == 0)
+ {
+ break;
+ }
+ std::string::size_type equal = tmp.find ("=");
+ std::string component;
+ int level;
+ if (equal == std::string::npos)
+ {
+ component = tmp;
+ level = LOG_LEVEL_DEBUG;
+ }
+ else
+ {
+ component = tmp.substr (0, equal);
+ std::string::size_type cur_lev;
+ std::string::size_type next_lev = equal;
+ do
+ {
+ cur_lev = next_lev + 1;
+ next_lev = tmp.find ("|", cur_lev);
+ std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
+ if (lev == "debug")
+ {
+ level |= LOG_LEVEL_DEBUG;
+ }
+ else if (lev == "func")
+ {
+ level |= LOG_LEVEL_FUNCTION;
+ }
+ else if (lev == "param")
+ {
+ level |= LOG_LEVEL_PARAM;
+ }
+ else if (lev == "warn")
+ {
+ level |= LOG_LEVEL_WARN;
+ }
+ else if (lev == "error")
+ {
+ level |= LOG_LEVEL_ERROR;
+ }
+ } while (next_lev != std::string::npos);
+ }
+ bool found = false;
+ ComponentList *components = GetComponentList ();
+ for (ComponentListI i = components->begin ();
+ i != components->end ();
+ i++)
+ {
+ if (i->first.compare (component) == 0)
+ {
+ found = true;
+
+ i->second->Enable ((enum LogLevel)level);
+ break;
+ }
+ }
+ if (!found)
+ {
+ allFound = false;
+ }
+ if (next == std::string::npos)
+ {
+ break;
+ }
+ cur = next + 1;
+ if (cur >= env.size ())
+ {
+ break;
+ }
+ }
+ if (allFound)
+ {
+ isFirstLog = false;
+ }
+
+#endif
+}
+
+
+LogComponent::LogComponent (char const * name)
+ : m_levels (0)
+{
+ ComponentList *components = GetComponentList ();
+ for (ComponentListI i = components->begin ();
+ i != components->end ();
+ i++)
+ {
+ NS_ASSERT (i->first != name);
+ }
+ components->push_back (std::make_pair (name, this));
+}
+bool
+LogComponent::IsEnabled (enum LogLevel level) const
+{
+ LogComponentEnableEnvVar ();
+ return (level & m_levels) == 1;
+}
+bool
+LogComponent::IsNoneEnabled (void) const
+{
+ return m_levels == 0;
+}
+void
+LogComponent::Enable (enum LogLevel level)
+{
+ m_levels |= level;
+}
+void
+LogComponent::Disable (enum LogLevel level)
+{
+ m_levels &= ~level;
+}
+
+void
+LogComponentEnable (char const *name, enum LogLevel level)
+{
+ ComponentList *components = GetComponentList ();
+ for (ComponentListI i = components->begin ();
+ i != components->end ();
+ i++)
+ {
+ if (i->first.compare (name) == 0)
+ {
+ i->second->Enable (level);
+ break;
+ }
+ }
+}
+void
+LogComponentDisable (char const *name, enum LogLevel level)
+{
+ ComponentList *components = GetComponentList ();
+ for (ComponentListI i = components->begin ();
+ i != components->end ();
+ i++)
+ {
+ if (i->first.compare (name) == 0)
+ {
+ i->second->Disable (level);
+ break;
+ }
+ }
+}
+
+
+void
+LogComponentPrintList (void)
+{
+ ComponentList *components = GetComponentList ();
+ for (ComponentListI i = components->begin ();
+ i != components->end ();
+ i++)
+ {
+ std::cout << i->first << "=";
+ if (i->second->IsNoneEnabled ())
+ {
+ std::cout << "0" << std::endl;
+ continue;
+ }
+ if (i->second->IsEnabled (LOG_LEVEL_DEBUG))
+ {
+ std::cout << "debug";
+ }
+ if (i->second->IsEnabled (LOG_LEVEL_FUNCTION))
+ {
+ std::cout << "|func";
+ }
+ if (i->second->IsEnabled (LOG_LEVEL_PARAM))
+ {
+ std::cout << "|param";
+ }
+ if (i->second->IsEnabled (LOG_LEVEL_WARN))
+ {
+ std::cout << "|warn";
+ }
+ if (i->second->IsEnabled (LOG_LEVEL_ERROR))
+ {
+ std::cout << "|error";
+ }
+ std::cout << std::endl;
+ }
+}
+
+} // namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/log.h Wed Sep 12 16:24:31 2007 -0700
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef LOG_H
+#define LOG_H
+
+#include <string>
+#include <iostream>
+
+/**
+ * \defgroup logging Logging
+ * \brief Logging functions and macros
+ *
+ * LOG functionality: macros which allow developers to
+ * send information out on screen. All logging messages
+ * are disabled by default. To enable selected logging
+ * messages, use the ns3::LogComponentEnable
+ * function.
+ *
+ * Alternatively, you can use the NS_LOG
+ * environment variable to define a ';'-separated list of
+ * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
+ * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
+ *
+ * For each component, the "debug" log level is enabled by default
+ * but more components can be enabled selectively with the following
+ * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
+ * This example would enable the 'func', 'param', and 'warn' log
+ * levels for 'Component1' and the 'error' and 'debug' log levels
+ * for 'Component2'.
+ *
+ * The list of available log components can be printed on stdout
+ * with the NS_LOG=print-list syntax.
+ */
+
+/**
+ * \ingroup logging
+ * \param name a string
+ *
+ * Define a Log component with a specific name. This macro
+ * should be used at the top of every file in which you want
+ * to use the NS_LOG macro. This macro defines a new
+ * "log component" which can be later selectively enabled
+ * or disabled with the ns3::LogComponentEnable and
+ * ns3::LogComponentDisable functions or with the NS_LOG
+ * environment variable.
+ */
+#define NS_LOG_COMPONENT_DEFINE(name) \
+ static ns3::LogComponent g_log = ns3::LogComponent (name)
+
+/**
+ * \ingroup logging
+ * \param msg message to output
+ *
+ * Generate logging output in the "log component" of the
+ * current file. i.e., every call to NS_LOG from within
+ * a file implicitely generates out within the component
+ * defined with the NS_LOG_COMPONENT_DEFINE macro in the
+ * same file.
+ */
+#define NS_LOG(level,msg) \
+ do \
+ { \
+ if (g_log.IsEnabled (level)) \
+ { \
+ std::clog << msg << std::endl; \
+ } \
+ } \
+ while (false)
+
+#define NS_LOG_DEBUG(msg) \
+ NS_LOG (ns3::LOG_LEVEL_DEBUG,msg)
+
+#define NS_LOG_FUNCTION \
+ NS_LOG (ns3::LOG_LEVEL_FUNCTION, __PRETTY_PRINT__)
+
+#define NS_LOG_PARAM(msg) \
+ NS_LOG (ns3::LOG_LEVEL_PARAM,msg)
+
+#define NS_LOG_WARN(msg) \
+ NS_LOG (ns3::LOG_LEVEL_WARN,msg)
+
+#define NS_LOG_ERROR(msg) \
+ NS_LOG (ns3::LOG_LEVEL_ERROR,msg)
+
+#define NS_LOG_UNCOND(msg) \
+ do \
+ { \
+ std::clog << msg << std::endl; \
+ } \
+ while (false)
+
+
+
+namespace ns3 {
+
+enum LogLevel {
+ LOG_LEVEL_DEBUG = 1<<0,
+ LOG_LEVEL_FUNCTION = 1<<1,
+ LOG_LEVEL_PARAM = 1<<2,
+ LOG_LEVEL_WARN = 1<<3,
+ LOG_LEVEL_ERROR = 1<<4,
+ LOG_LEVEL_LAST = 1<<31
+};
+
+/**
+ * \param name a log component name
+ * \ingroup logging
+ *
+ * Enable the logging output associated with that log component.
+ * The logging output can be later disabled with a call
+ * to ns3::LogComponentDisable.
+ */
+void LogComponentEnable (char const *name, enum LogLevel level);
+
+/**
+ * \param name a log component name
+ * \ingroup logging
+ *
+ * Disable the logging output associated with that log component.
+ * The logging output can be later re-enabled with a call
+ * to ns3::LogComponentEnable.
+ */
+void LogComponentDisable (char const *name, enum LogLevel level);
+
+/**
+ * \ingroup logging
+ *
+ * Print the list of logging messages available.
+ * The output of this function can be obtained by setting
+ * the NS_LOG environment variable to the special value
+ * 'print-list'.
+ *
+ * For example: NS_LOG=print-list
+ */
+void LogComponentPrintList (void);
+
+class LogComponent {
+public:
+ LogComponent (char const *name);
+ bool IsEnabled (enum LogLevel level) const;
+ bool IsNoneEnabled (void) const;
+ void Enable (enum LogLevel level);
+ void Disable (enum LogLevel level);
+private:
+ uint32_t m_levels;
+};
+
+} // namespace ns3
+
+#endif /* LOG_H */
--- a/src/core/wscript Wed Sep 12 16:20:07 2007 -0700
+++ b/src/core/wscript Wed Sep 12 16:24:31 2007 -0700
@@ -30,6 +30,7 @@
core.source = [
'callback-test.cc',
'debug.cc',
+ 'log.cc',
'breakpoint.cc',
'ptr.cc',
'object.cc',
@@ -69,6 +70,7 @@
'ptr.h',
'object.h',
'debug.h',
+ 'log.h',
'assert.h',
'breakpoint.h',
'fatal-error.h',