merge with debug tree
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 16 Feb 2007 09:32:02 +0100
changeset 280 2fe90883716a
parent 264 128d8d1bfb51 (current diff)
parent 279 bd18192d2651 (diff)
child 281 98720464e80b
merge with debug tree
SConstruct
src/core/debug.cc
src/core/debug.h
--- 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 */