--- a/SConstruct Thu Feb 15 16:52:39 2007 -0800
+++ b/SConstruct Fri Feb 16 09:32:02 2007 +0100
@@ -18,6 +18,8 @@
core.add_sources([
'reference-list-test.cc',
'callback-test.cc',
+ 'debug.cc',
+ 'assert.cc',
'ptr.cc',
'debug.cc',
'test.cc'
@@ -41,9 +43,25 @@
'callback.h',
'ptr.h',
'debug.h',
+ 'assert.h',
+ 'fatal-error.h',
'test.h'
])
+def config_core (env, config):
+ retval = []
+ # XXX This check is primitive but it should be
+ # good enough for now.
+ if config.CheckCHeader ('stdlib.h') == 1:
+ retval.append ('#define HAVE_STDLIB_H 1')
+ retval.append ('#define HAVE_GETENV 1')
+ else:
+ retval.append ('#undef HAVE_STDLIB_H')
+ retval.append ('#undef HAVE_GETENV')
+ return retval
+core.add_config (config_core)
+
+
#
# The Simu module
@@ -247,6 +265,13 @@
# samples
+sample_debug = build.Ns3Module('sample-debug', 'samples')
+sample_debug.set_executable()
+ns3.add(sample_debug)
+sample_debug.add_dep('core')
+sample_debug.add_source('main-debug.cc')
+sample_debug.add_source('main-debug-other.cc')
+
sample_callback = build.Ns3Module('sample-callback', 'samples')
sample_callback.set_executable()
ns3.add(sample_callback)
--- a/build.py Thu Feb 15 16:52:39 2007 -0800
+++ b/build.py Fri Feb 16 09:32:02 2007 +0100
@@ -458,8 +458,10 @@
dbg_env = env.Copy()
- env.Append(CFLAGS = debug_flags,
- CXXFLAGS = debug_flags, )
+ dbg_env.Append(CFLAGS = debug_flags,
+ CXXFLAGS = debug_flags,
+ CPPDEFINES = ['NS3_DEBUG_ENABLE',
+ 'NS3_ASSERT_ENABLE'])
# debug static support
variant.static = True
variant.env = dbg_env
@@ -469,8 +471,10 @@
dbg_env.Alias('dbg-static', builder)
dbg_env = env.Copy()
- env.Append(CFLAGS=debug_flags,
- CXXFLAGS=debug_flags, )
+ dbg_env.Append(CFLAGS=debug_flags,
+ CXXFLAGS=debug_flags,
+ CPPDEFINES = ['NS3_DEBUG_ENABLE',
+ 'NS3_ASSERT_ENABLE'])
# debug shared support
variant.static = False
variant.env = dbg_env
--- a/doc/doxygen.conf Thu Feb 15 16:52:39 2007 -0800
+++ b/doc/doxygen.conf Fri Feb 16 09:32:02 2007 +0100
@@ -996,7 +996,7 @@
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = RUN_SELF_TESTS
+PREDEFINED = RUN_SELF_TESTS NS3_DEBUG_ENABLE
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-debug-other.cc Fri Feb 16 09:32:02 2007 +0100
@@ -0,0 +1,13 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#include "ns3/debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("MyComponentB");
+
+namespace foo {
+
+void OneFunction (void)
+{
+ NS_DEBUG ("OneFunction debug");
+}
+
+}; // namespace foo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-debug.cc Fri Feb 16 09:32:02 2007 +0100
@@ -0,0 +1,27 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#include "ns3/debug.h"
+#include "ns3/assert.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("MyComponentA");
+
+// declare other function
+namespace foo {
+void OneFunction (void);
+}
+
+int main (int argc, int argv)
+{
+ NS_DEBUG ("nargc="<<argc);
+
+ foo::OneFunction ();
+
+ NS_DEBUG ("other debug output");
+
+ int a;
+ a = 0;
+
+ NS_ASSERT (a == 0);
+ NS_ASSERT_MSG (a == 0, "my msg");
+ NS_ASSERT (a != 0)
+ NS_ASSERT_MSG (a != 0, "my 2 msg");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/assert.cc Fri Feb 16 09:32:02 2007 +0100
@@ -0,0 +1,41 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * 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 "assert.h"
+
+namespace ns3 {
+
+void
+AssertBreakpoint (void)
+{
+ int *a = 0;
+ /**
+ * we test here to allow a debugger to change the value of
+ * the variable 'a' to allow the debugger to avoid the
+ * subsequent segfault.
+ */
+ if (a == 0)
+ {
+ *a = 0;
+ }
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/assert.h Fri Feb 16 09:32:02 2007 +0100
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * 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 ASSERT_H
+#define ASSERT_H
+
+/**
+ * \defgroup assert
+ * \brief assert functions and macros
+ *
+ * The assert macros are used to verify
+ * at runtime that a certain condition is true. If it is
+ * not true, the program halts. These checks are built
+ * into the program only in debugging builds. They are
+ * removed in optimized builds.
+ */
+
+namespace ns3 {
+
+/**
+ * \ingroup debugging
+ *
+ * When an NS_ASSERT cannot verify its condition,
+ * this function is called. This is where you should
+ * be able to put a breakpoint with a debugger if
+ * you want to catch assertions before the program
+ * halts.
+ */
+void AssertBreakpoint (void);
+
+}//namespace ns3
+
+#ifdef NS3_ASSERT_ENABLE
+
+#include <iostream>
+
+/**
+ * \ingroup assert
+ * \param condition condition to verifiy.
+ *
+ * At runtime, in debugging builds, if this condition is not
+ * true, the program prints the source file, line number and
+ * unverified condition and halts in the ns3::AssertBreakpoint
+ * function.
+ */
+#define NS_ASSERT(condition) \
+ if (!(condition)) \
+ { \
+ std::cout << "assert failed. file=" << __FILE__ << \
+ ", line=" << __LINE__ << ", cond=\""#condition << \
+ "\"" << std::endl; \
+ ns3::AssertBreakpoint (); \
+ }
+
+/**
+ * \ingroup assert
+ * \param condition condition to verifiy.
+ * \param message message to output
+ *
+ * At runtime, in debugging builds, if this condition is not
+ * true, the program prints the message to output and
+ * halts in the ns3::AssertBreakpoint function.
+ */
+#define NS_ASSERT_MSG(condition, message) \
+ if (!(condition)) \
+ { \
+ std::cout << message << std::endl; \
+ ns3::AssertBreakpoint (); \
+ }
+
+#else /* NS3_ASSERT_ENABLE */
+
+#define NS_ASSERT(cond)
+#define NS_ASSERT_MSG(cond,msg)
+
+#endif /* NS3_ASSERT_ENABLE */
+
+#endif /* ASSERT_H */
--- a/src/core/debug.cc Thu Feb 15 16:52:39 2007 -0800
+++ b/src/core/debug.cc Fri Feb 16 09:32:02 2007 +0100
@@ -23,8 +23,7 @@
#include <utility>
#include <iostream>
#include "debug.h"
-
-// #include "ns3/core-config.h"
+#include "ns3/core-config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -53,33 +52,51 @@
while (true)
{
next = env.find_first_of (";", cur);
- if (next == std::string::npos)
- {
- std::string tmp = env.substr (cur, next);
- bool found = false;
- for (ComponentListI i = g_components.begin ();
- i != g_components.end ();
- i++)
+ 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;
+ }
+ bool found = false;
+ for (ComponentListI i = g_components.begin ();
+ i != g_components.end ();
+ i++)
+ {
+ if (i->first.compare (tmp) == 0)
{
- if (i->first.compare (tmp) == 0)
- {
- found = true;
- i->second->Enable ();
- break;
- }
+ found = true;
+ i->second->Enable ();
+ break;
}
- if (!found)
- {
- std::cout << "No debug component named=\"" << tmp << "\"" << std::endl;
- }
- }
- cur = next;
+ }
+ if (!found)
+ {
+ std::cout << "No debug component named=\"" << tmp << "\"" << std::endl;
+ }
+ if (next == std::string::npos)
+ {
+ break;
+ }
+ cur = next + 1;
+ if (cur >= env.size ())
+ {
+ break;
+ }
}
#endif
}
-DebugComponent::DebugComponent (std::string name)
+DebugComponent::DebugComponent (char const * name)
: m_isEnabled (false)
{
for (ComponentListI i = g_components.begin ();
@@ -93,15 +110,15 @@
bool
DebugComponent::IsEnabled (void)
{
+ if (g_firstDebug) {
+ DebugComponentEnableEnvVar ();
+ g_firstDebug = false;
+ }
return m_isEnabled;
}
void
DebugComponent::Enable (void)
{
- if (g_firstDebug) {
- DebugComponentEnableEnvVar ();
- g_firstDebug = false;
- }
m_isEnabled = true;
}
void
@@ -151,6 +168,6 @@
}
}
+}; // namespace ns3
-}; // namespace ns3
--- a/src/core/debug.h Thu Feb 15 16:52:39 2007 -0800
+++ b/src/core/debug.h Fri Feb 16 09:32:02 2007 +0100
@@ -21,38 +21,49 @@
#ifndef DEBUG_H
#define DEBUG_H
-#include <string>
-#include <iostream>
-
-#ifndef NDEBUG
-#define NS3_DEBUG_ENABLE
-#endif
-
-#ifdef NS3_DEBUG_ENABLE
-#define NS3_DEBUG(x) x
-#else
-#define NS3_DEBUG(x)
-#endif
-
-#define NS3_TRACEALL(traceout) NS3_DEBUG(std::cerr << traceout << std::endl;)
-
-#define NS3_TRACE(boolLevel, traceout) \
- NS3_DEBUG( \
- if (boolLevel) { \
- std::cerr << traceout << std::endl; \
- } \
- )
-
+/**
+ * \defgroup debugging
+ * \brief Debugging functions and macros
+ *
+ * - DEBUG functionality: macros which allow developers to
+ * send information out on screen only in debugging builds.
+ * All debug messages are disabled by default. To enable
+ * selected debug messages, use the ns3::DebugComponentEnable
+ * function. Alternatively, you can use the NS_DEBUG
+ * environment variable to define a ';'-separated list of
+ * messages to enable. For example, NS_DEBUG=a;b;c;DAFD;GH
+ * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
+ */
namespace ns3 {
+/**
+ * \param name a debug component name
+ * \ingroup debugging
+ *
+ * Enable the debugging output associated with that debug component.
+ * The debugging output can be later disabled with a call
+ * to ns3::DebugComponentDisable.
+ */
void DebugComponentEnable (char const *name);
+/**
+ * \param name a debug component name
+ * \ingroup debugging
+ *
+ * Disable the debugging output associated with that debug component.
+ * The debugging output can be later re-enabled with a call
+ * to ns3::DebugComponentEnable.
+ */
void DebugComponentDisable (char const *name);
+/**
+ * \ingroup debugging
+ * Print the list of debugging messages available.
+ */
void DebugComponentPrintList (void);
class DebugComponent {
public:
- DebugComponent (std::string name);
+ DebugComponent (char const *name);
bool IsEnabled (void);
void Enable (void);
void Disable (void);
@@ -65,18 +76,56 @@
#ifdef NS3_DEBUG_ENABLE
-#define DEBUG_COMPONENT_DEFINE(name) \
- static DebugComponent g_debug = DebugComponent (name);
+#include <string>
+#include <iostream>
+
-#define DEBUG(x) \
+/**
+ * \ingroup debugging
+ * \param name a string
+ *
+ * Define a Debug component with a specific name. This macro
+ * should be used at the top of every file in which you want
+ * to use the NS_DEBUG macro. This macro defines a new
+ * "debug component" which can be later selectively enabled
+ * or disabled with the ns3::DebugComponentEnable and
+ * ns3::DebugComponentDisable functions or with the NS_DEBUG
+ * environment variable.
+ */
+#define NS_DEBUG_COMPONENT_DEFINE(name) \
+ static ns3::DebugComponent g_debug = ns3::DebugComponent (name);
+
+/**
+ * \ingroup debugging
+ * \param msg message to output
+ *
+ * Generate debugging output in the "debug component" of the
+ * current file. i.e., every call to NS_DEBUG from within
+ * a file implicitely generates out within the component
+ * defined with the NS_DEBUG_COMPONENT_DEFINE macro in the
+ * same file.
+ */
+#define NS_DEBUG(msg) \
if (g_debug.IsEnabled ()) \
{ \
- std::cout << x << std::endl; \
+ std::cout << msg << std::endl; \
}
+
+/**
+ * \ingroup debugging
+ * \param msg message to output
+ *
+ * Generate debugging output unconditionally in all
+ * debug builds.
+ */
+#define NS_DEBUG_UNCOND (msg) \
+ std::cout << msg << std::endl;
+
#else /* NS3_DEBUG_ENABLE */
-#define DEBUG_COMPONENT_DEFINE(name)
-#define DEBUG(x)
+#define NS_DEBUG_COMPONENT_DEFINE(name)
+#define NS_DEBUG(x)
+#define NS_DEBUG_UNCOND(msg)
#endif /* NS3_DEBUG_ENABLE */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/fatal-error.h Fri Feb 16 09:32:02 2007 +0100
@@ -0,0 +1,43 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * 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 FATAL_ERROR_H
+#define FATAL_ERROR_H
+
+#include "assert.h"
+
+/**
+ * \defgroup error
+ * \brief fatal error handling
+ *
+ * \param msg message to output when this macro is hit.
+ *
+ * When this macro is hit at runtime, the user-specified
+ * error message is output and the program is halted by calling
+ * the ns3::AssertBreakpoint function. This macro is enabled
+ * unconditionally in all builds, including debug and optimized
+ * builds.
+ */
+#define NS_FATAL_ERROR(msg) \
+ std::cout << msg << std::endl; \
+ ns3::AssertBreakpoint ();
+
+
+#endif /* FATAL_ERROR_H */