src/core/command-line.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3929 909b0a724ed3
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2008 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 #include "command-line.h"
    21 #include "log.h"
    22 #include "config.h"
    23 #include "global-value.h"
    24 #include "type-id.h"
    25 #include "string.h"
    26 #include <stdlib.h>
    27 
    28 NS_LOG_COMPONENT_DEFINE ("CommandLine");
    29 
    30 namespace ns3 {
    31 
    32 CommandLine::~CommandLine ()
    33 {
    34   for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
    35     {
    36       delete *i;
    37     }
    38   m_items.clear ();
    39 }
    40 
    41 CommandLine::Item::~Item ()
    42 {}
    43 
    44 void 
    45 CommandLine::Parse (int iargc, char *argv[]) const
    46 {
    47   int argc = iargc;
    48   for (argc--, argv++; argc > 0; argc--, argv++)
    49     {
    50       // remove "--" or "-" heading.
    51       std::string param = *argv;
    52       std::string::size_type cur = param.find ("--");
    53       if (cur == 0)
    54 	{
    55 	  param = param.substr (2, param.size () - 2);
    56 	}
    57       else
    58 	{
    59 	  cur = param.find ("-");
    60 	  if (cur == 0)
    61 	    {
    62 	      param = param.substr (1, param.size () - 1);
    63 	    }
    64 	  else
    65 	    {
    66 	      // invalid argument. ignore.
    67 	      continue;
    68 	    }
    69 	}
    70       cur = param.find ("=");
    71       std::string name, value;
    72       if (cur == std::string::npos)
    73         {
    74 	  name = param;
    75 	  value = "";
    76         }
    77       else
    78         {
    79           name = param.substr (0, cur);
    80           value = param.substr (cur + 1, param.size () - (cur+1));
    81         }
    82       HandleArgument (name, value);
    83     }
    84 }
    85 
    86 void
    87 CommandLine::PrintHelp (void) const
    88 {
    89   std::cout << "--PrintHelp: Print this help message." << std::endl;
    90   std::cout << "--PrintGroups: Print the list of groups." << std::endl;
    91   std::cout << "--PrintTypeIds: Print all TypeIds." << std::endl;  
    92   std::cout << "--PrintGroup=[group]: Print all TypeIds of group." << std::endl;
    93   std::cout << "--PrintAttributes=[typeid]: Print all attributes of typeid." << std::endl;
    94   std::cout << "--PrintGlobals: Print the list of globals." << std::endl;
    95   if (!m_items.empty ())
    96     {
    97       std::cout << "User Arguments:" << std::endl;
    98       for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
    99 	{
   100 	  std::cout << "    --" << (*i)->m_name << ": " << (*i)->m_help << std::endl;
   101 	}
   102     }
   103 }
   104 
   105 void
   106 CommandLine::PrintGlobals (void) const
   107 {
   108   for (GlobalValue::Iterator i = GlobalValue::Begin (); i != GlobalValue::End (); ++i)
   109     {
   110       std::cout << "    --" << (*i)->GetName () << "=[";
   111       Ptr<const AttributeChecker> checker = (*i)->GetChecker ();
   112       StringValue v;
   113       (*i)->GetValue (v);
   114       std::cout << v.Get () << "]:  "
   115 		<< (*i)->GetHelp () << std::endl;      
   116     }
   117 }
   118 
   119 void
   120 CommandLine::PrintAttributes (std::string type) const
   121 {
   122   TypeId tid;
   123   if (!TypeId::LookupByNameFailSafe (type, &tid))
   124     {
   125       NS_FATAL_ERROR ("Unknown type="<<type<<" in --PrintAttributes");
   126     }
   127   for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
   128     {
   129       std::cout << "    --"<<tid.GetAttributeFullName (i)<<"=[";
   130       Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
   131       Ptr<const AttributeValue> initial = tid.GetAttributeInitialValue (i);
   132       std::cout << initial->SerializeToString (checker) << "]:  "
   133 		<< tid.GetAttributeHelp (i) << std::endl;
   134     }
   135 }
   136 
   137 
   138 void
   139 CommandLine::PrintGroup (std::string group) const
   140 {
   141   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
   142     {
   143       TypeId tid = TypeId::GetRegistered (i);
   144       if (tid.GetGroupName () == group)
   145 	{
   146 	  std::cout << "    --PrintAttributes=" <<tid.GetName ()<<std::endl;
   147 	}
   148     }
   149 }
   150 
   151 void
   152 CommandLine::PrintTypeIds (void) const
   153 {
   154   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
   155     {
   156       TypeId tid = TypeId::GetRegistered (i);
   157       std::cout << "    --PrintAttributes=" <<tid.GetName ()<<std::endl;
   158     }
   159 }
   160 
   161 void
   162 CommandLine::PrintGroups (void) const
   163 {
   164   std::list<std::string> groups;
   165   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
   166     {
   167       TypeId tid = TypeId::GetRegistered (i);
   168       std::string group = tid.GetGroupName ();
   169       if (group == "")
   170 	{
   171 	  continue;
   172 	}
   173       bool found = false;
   174       for (std::list<std::string>::const_iterator j = groups.begin (); j != groups.end (); ++j)
   175 	{
   176 	  if (*j == group)
   177 	    {
   178 	      found = true;
   179 	      break;
   180 	    }
   181 	}
   182       if (!found)
   183 	{
   184 	  groups.push_back (group);
   185 	}
   186     }
   187   for (std::list<std::string>::const_iterator k = groups.begin (); k != groups.end (); ++k)
   188     {
   189       std::cout << "    --PrintGroup="<<*k<<std::endl;
   190     }
   191 }
   192 
   193 void
   194 CommandLine::HandleArgument (std::string name, std::string value) const
   195 {
   196   NS_LOG_DEBUG ("Handle arg name="<<name<<" value="<<value);
   197   if (name == "PrintHelp")
   198     {
   199       // method below never returns.
   200       PrintHelp ();
   201       exit (0);
   202     } 
   203   else if (name == "PrintGroups")
   204     {
   205       // method below never returns.
   206       PrintGroups ();
   207       exit (0);
   208     }
   209   else if (name == "PrintTypeIds")
   210     {
   211       // method below never returns.
   212       PrintTypeIds ();
   213       exit (0);
   214     }
   215   else if (name == "PrintGlobals")
   216     {
   217       // method below never returns.
   218       PrintGlobals ();
   219       exit (0);
   220     }
   221   else if (name == "PrintGroup")
   222     {
   223       // method below never returns.
   224       PrintGroup (value);
   225       exit (0);
   226     }
   227   else if (name == "PrintAttributes")
   228     {
   229       // method below never returns.
   230       PrintAttributes (value);
   231       exit (0);
   232     }
   233   else
   234     {
   235       for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
   236         {
   237           if ((*i)->m_name == name)
   238             {
   239               if (!(*i)->Parse (value))
   240                 {
   241                   std::cerr << "Invalid argument value: "<<name<<"="<<value << std::endl;
   242                   exit (1);
   243                 }
   244               else
   245                 {
   246                   return;
   247                 }
   248             }
   249         }
   250     }
   251   if (!Config::SetGlobalFailSafe (name, StringValue (value))
   252       && !Config::SetDefaultFailSafe (name, StringValue (value)))
   253     {
   254       std::cerr << "Invalid command-line arguments: --"<<name<<"="<<value<<std::endl;
   255       PrintHelp ();
   256       exit (1);
   257     }
   258 }
   259 
   260 bool
   261 CommandLine::CallbackItem::Parse (std::string value)
   262 {
   263   NS_LOG_DEBUG ("CommandLine::CallbackItem::Parse \"" << value << "\"");
   264   return m_callback (value);
   265 }
   266 
   267 void
   268 CommandLine::AddValue (const std::string &name,
   269                        const std::string &help,
   270                        Callback<bool, std::string> callback)
   271 {
   272   NS_LOG_FUNCTION (this << name << help << "callback");
   273   CallbackItem *item = new CallbackItem ();
   274   item->m_name = name;
   275   item->m_help = help;
   276   item->m_callback = callback;
   277   m_items.push_back (item);
   278 }
   279 
   280 
   281 } // namespace ns3
   282 
   283 #ifdef RUN_SELF_TESTS
   284 
   285 #include "test.h"
   286 #include <stdarg.h>
   287 
   288 using namespace ns3;
   289 
   290 class CommandLineTest : public Test
   291 {
   292 public:
   293   CommandLineTest ();
   294   virtual bool RunTests (void);
   295 private:
   296   void Parse (const CommandLine &cmd, int n, ...);
   297 };
   298 
   299 CommandLineTest::CommandLineTest ()
   300   : Test ("CommandLine")
   301 {}
   302 void
   303 CommandLineTest::Parse (const CommandLine &cmd, int n, ...)
   304 {
   305   char **args = new char* [n+1];
   306   args[0] = (char *) "Test";
   307   va_list ap;
   308   va_start (ap, n);
   309   int i = 0;
   310   while (i < n)
   311     {
   312       char *arg = va_arg (ap, char *);
   313       args[i+1] = arg;
   314       i++;
   315     }
   316   int argc = n + 1;
   317   cmd.Parse (argc, args);
   318   delete [] args;
   319 }
   320 bool 
   321 CommandLineTest::RunTests (void)
   322 {
   323   bool result = true;
   324 
   325   bool myBool = false;
   326   uint32_t myUint32 = 10;
   327   std::string myStr = "MyStr";
   328   int32_t myInt32 = -1;
   329   CommandLine cmd;
   330 
   331   cmd.AddValue ("my-bool", "help", myBool);
   332   Parse (cmd, 1, "--my-bool=0");
   333   NS_TEST_ASSERT_EQUAL (myBool, false);
   334   Parse (cmd, 1, "--my-bool=1");
   335   NS_TEST_ASSERT_EQUAL (myBool, true);
   336 
   337   cmd.AddValue ("my-uint32", "help", myUint32);
   338   Parse (cmd, 2, "--my-bool=0", "--my-uint32=9");
   339   NS_TEST_ASSERT_EQUAL (myUint32, 9);
   340 
   341   cmd.AddValue ("my-str", "help", myStr);
   342   Parse (cmd, 2, "--my-bool=0", "--my-str=XX");
   343   NS_TEST_ASSERT_EQUAL (myStr, "XX");
   344 
   345   cmd.AddValue ("my-int32", "help", myInt32);
   346   Parse (cmd, 2, "--my-bool=0", "--my-int32=-3");
   347   NS_TEST_ASSERT_EQUAL (myInt32, -3);
   348   Parse (cmd, 2, "--my-bool=0", "--my-int32=+2");
   349   NS_TEST_ASSERT_EQUAL (myInt32, +2);
   350 
   351   return result;
   352 }
   353 
   354 
   355 static CommandLineTest g_cmdLineTest;
   356 
   357 #endif /* RUN_SELF_TESTS */