A Discrete-Event Network Simulator
API
command-line.cc
Go to the documentation of this file.
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 
21 #include <algorithm> // for transform
22 #include <cctype> // for tolower
23 #include <cstdlib> // for exit
24 #include <iomanip> // for setw, boolalpha
25 #include <set>
26 #include <sstream>
27 
28 #include "command-line.h"
29 #include "log.h"
30 #include "config.h"
31 #include "global-value.h"
32 #include "system-path.h"
33 #include "type-id.h"
34 #include "string.h"
35 
36 
43 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("CommandLine");
46 
48 {
49  NS_LOG_FUNCTION (this);
50 }
52 {
53  Copy (cmd);
54 }
57 {
58  Clear ();
59  Copy (cmd);
60  return *this;
61 }
63 {
64  NS_LOG_FUNCTION (this);
65  Clear ();
66 }
67 void
69 {
70  NS_LOG_FUNCTION (&cmd);
71 
72  for (Items::const_iterator i = cmd.m_items.begin ();
73  i != cmd.m_items.end (); ++i)
74  {
75  m_items.push_back (*i);
76  }
77  m_usage = cmd.m_usage;
78  m_name = cmd.m_name;
79 }
80 void
82 {
83  NS_LOG_FUNCTION (this);
84 
85  for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
86  {
87  delete *i;
88  }
89  m_items.clear ();
90  m_usage = "";
91  m_name = "";
92 }
93 
94 void
95 CommandLine::Usage (const std::string usage)
96 {
97  m_usage = usage;
98 }
99 
100 std::string
102 {
103  return m_name;
104 }
105 
107 {
108  NS_LOG_FUNCTION (this);
109 }
110 
111 void
112 CommandLine::Parse (int iargc, char *argv[])
113 {
114  NS_LOG_FUNCTION (this << iargc << argv);
115 
116  m_name = SystemPath::Split (argv[0]).back ();
117 
118  int argc = iargc;
119  for (argc--, argv++; argc > 0; argc--, argv++)
120  {
121  // remove "--" or "-" heading.
122  std::string param = *argv;
123  std::string::size_type cur = param.find ("--");
124  if (cur == 0)
125  {
126  param = param.substr (2, param.size () - 2);
127  }
128  else
129  {
130  cur = param.find ("-");
131  if (cur == 0)
132  {
133  param = param.substr (1, param.size () - 1);
134  }
135  else
136  {
137  // invalid argument. ignore.
138  continue;
139  }
140  }
141  cur = param.find ("=");
142  std::string name, value;
143  if (cur == std::string::npos)
144  {
145  name = param;
146  value = "";
147  }
148  else
149  {
150  name = param.substr (0, cur);
151  value = param.substr (cur + 1, param.size () - (cur+1));
152  }
153  HandleArgument (name, value);
154  }
155 }
156 
157 void
158 CommandLine::PrintHelp (std::ostream &os) const
159 {
160  NS_LOG_FUNCTION (this);
161 
162  os << m_name << " [Program Arguments] [General Arguments]"
163  << std::endl;
164 
165  if (m_usage.length ())
166  {
167  os << std::endl;
168  os << m_usage << std::endl;
169  }
170 
171  if (!m_items.empty ())
172  {
173  size_t width = 0;
174  for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
175  {
176  width = std::max (width, (*i)->m_name.size ());
177  }
178  width += 3;
179 
180  os << std::endl;
181  os << "Program Arguments:" << std::endl;
182  for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
183  {
184  os << " --"
185  << std::left << std::setw (width) << ( (*i)->m_name + ":")
186  << std::right
187  << (*i)->m_help;
188 
189  if ( (*i)->HasDefault ())
190  {
191  os << " [" << (*i)->GetDefault () << "]";
192  }
193  os << std::endl;
194  }
195  }
196 
197  os << std::endl;
198  os
199  << "General Arguments:\n"
200  << " --PrintGlobals: Print the list of globals.\n"
201  << " --PrintGroups: Print the list of groups.\n"
202  << " --PrintGroup=[group]: Print all TypeIds of group.\n"
203  << " --PrintTypeIds: Print all TypeIds.\n"
204  << " --PrintAttributes=[typeid]: Print all attributes of typeid.\n"
205  << " --PrintHelp: Print this help message.\n"
206  << std::endl;
207 }
208 
209 void
210 CommandLine::PrintGlobals (std::ostream &os) const
211 {
212  NS_LOG_FUNCTION (this);
213 
214  os << "Global values:" << std::endl;
215 
216  // Sort output
217  std::vector<std::string> globals;
218 
220  i != GlobalValue::End ();
221  ++i)
222  {
223  std::stringstream ss;
224  ss << " --" << (*i)->GetName () << "=[";
225  Ptr<const AttributeChecker> checker = (*i)->GetChecker ();
226  StringValue v;
227  (*i)->GetValue (v);
228  ss << v.Get () << "]" << std::endl;
229  ss << " " << (*i)->GetHelp () << std::endl;
230  globals.push_back (ss.str ());
231  }
232  std::sort (globals.begin (), globals.end ());
233  for (std::vector<std::string>::const_iterator it = globals.begin ();
234  it < globals.end ();
235  ++it)
236  {
237  os << *it;
238  }
239 }
240 
241 void
242 CommandLine::PrintAttributes (std::ostream &os, const std::string &type) const
243 {
244  NS_LOG_FUNCTION (this);
245 
246  TypeId tid;
247  if (!TypeId::LookupByNameFailSafe (type, &tid))
248  {
249  NS_FATAL_ERROR ("Unknown type=" << type << " in --PrintAttributes");
250  }
251 
252  os << "Attributes for TypeId " << tid.GetName () << std::endl;
253 
254  // Sort output
255  std::vector<std::string> attributes;
256 
257  for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
258  {
259  std::stringstream ss;
260  ss << " --" << tid.GetAttributeFullName (i) << "=[";
261  struct TypeId::AttributeInformation info = tid.GetAttribute (i);
262  ss << info.initialValue->SerializeToString (info.checker) << "]"
263  << std::endl;
264  ss << " " << info.help << std::endl;
265  attributes.push_back (ss.str ());
266  }
267  std::sort (attributes.begin (), attributes.end ());
268  for (std::vector<std::string>::const_iterator it = attributes.begin ();
269  it < attributes.end ();
270  ++it)
271  {
272  os << *it;
273  }
274 }
275 
276 
277 void
278 CommandLine::PrintGroup (std::ostream &os, const std::string &group) const
279 {
280  NS_LOG_FUNCTION (this);
281 
282  os << "TypeIds in group " << group << ":" << std::endl;
283 
284  // Sort output
285  std::vector<std::string> groupTypes;
286 
287  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
288  {
289  std::stringstream ss;
290  TypeId tid = TypeId::GetRegistered (i);
291  if (tid.GetGroupName () == group)
292  {
293  ss << " " <<tid.GetName () << std::endl;
294  }
295  groupTypes.push_back (ss.str ());
296  }
297  std::sort (groupTypes.begin (), groupTypes.end ());
298  for (std::vector<std::string>::const_iterator it = groupTypes.begin ();
299  it < groupTypes.end ();
300  ++it)
301  {
302  os << *it;
303  }
304 }
305 
306 void
307 CommandLine::PrintTypeIds (std::ostream &os) const
308 {
309  NS_LOG_FUNCTION (this);
310  os << "Registered TypeIds:" << std::endl;
311 
312  // Sort output
313  std::vector<std::string> types;
314 
315  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
316  {
317  std::stringstream ss;
318  TypeId tid = TypeId::GetRegistered (i);
319  ss << " " << tid.GetName () << std::endl;
320  types.push_back (ss.str ());
321  }
322  std::sort (types.begin (), types.end ());
323  for (std::vector<std::string>::const_iterator it = types.begin ();
324  it < types.end ();
325  ++it)
326  {
327  os << *it;
328  }
329 }
330 
331 void
332 CommandLine::PrintGroups (std::ostream &os) const
333 {
334  NS_LOG_FUNCTION (this);
335 
336  std::set<std::string> groups;
337  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
338  {
339  TypeId tid = TypeId::GetRegistered (i);
340  groups.insert (tid.GetGroupName ());
341  }
342 
343  os << "Registered TypeId groups:" << std::endl;
344  // Sets are already sorted
345  for (std::set<std::string>::const_iterator k = groups.begin ();
346  k != groups.end ();
347  ++k)
348  {
349  os << " " << *k << std::endl;
350  }
351 }
352 
353 void
354 CommandLine::HandleArgument (const std::string &name, const std::string &value) const
355 {
356  NS_LOG_FUNCTION (this << name << value);
357 
358  NS_LOG_DEBUG ("Handle arg name=" << name << " value=" << value);
359  if (name == "PrintHelp" || name == "help")
360  {
361  // method below never returns.
362  PrintHelp (std::cout);
363  std::exit (0);
364  }
365  else if (name == "PrintGroups")
366  {
367  // method below never returns.
368  PrintGroups (std::cout);
369  std::exit (0);
370  }
371  else if (name == "PrintTypeIds")
372  {
373  // method below never returns.
374  PrintTypeIds (std::cout);
375  std::exit (0);
376  }
377  else if (name == "PrintGlobals")
378  {
379  // method below never returns.
380  PrintGlobals (std::cout);
381  std::exit (0);
382  }
383  else if (name == "PrintGroup")
384  {
385  // method below never returns.
386  PrintGroup (std::cout, value);
387  std::exit (0);
388  }
389  else if (name == "PrintAttributes")
390  {
391  // method below never returns.
392  PrintAttributes (std::cout, value);
393  std::exit (0);
394  }
395  else
396  {
397  for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
398  {
399  if ((*i)->m_name == name)
400  {
401  if (!(*i)->Parse (value))
402  {
403  std::cerr << "Invalid argument value: "
404  << name << "=" << value << std::endl;
405  std::exit (1);
406  }
407  else
408  {
409  return;
410  }
411  }
412  }
413  }
414  if (!Config::SetGlobalFailSafe (name, StringValue (value))
415  && !Config::SetDefaultFailSafe (name, StringValue (value)))
416  {
417  std::cerr << "Invalid command-line arguments: --"
418  << name << "=" << value << std::endl;
419  PrintHelp (std::cerr);
420  std::exit (1);
421  }
422 }
423 
424 bool
425 CommandLine::CallbackItem::Parse (const std::string value)
426 {
427  NS_LOG_FUNCTION (this);
428  NS_LOG_DEBUG ("CommandLine::CallbackItem::Parse \"" << value << "\"");
429  return m_callback (value);
430 }
431 
432 void
433 CommandLine::AddValue (const std::string &name,
434  const std::string &help,
436 {
437  NS_LOG_FUNCTION (this << &name << &help << &callback);
438  CallbackItem *item = new CallbackItem ();
439  item->m_name = name;
440  item->m_help = help;
441  item->m_callback = callback;
442  m_items.push_back (item);
443 }
444 
445 void
446 CommandLine::AddValue (const std::string &name,
447  const std::string &attributePath)
448 {
449  NS_LOG_FUNCTION (this << name << attributePath);
450  // Attribute name is last token
451  size_t colon = attributePath.rfind ("::");
452  const std::string typeName = attributePath.substr (0, colon);
453  NS_LOG_DEBUG ("typeName: '" << typeName << "', colon: " << colon);
454 
455  TypeId tid;
456  if (!TypeId::LookupByNameFailSafe (typeName, &tid))
457  {
458  NS_FATAL_ERROR ("Unknown type=" << typeName);
459  }
460 
461  const std::string attrName = attributePath.substr (colon + 2);
462  struct TypeId::AttributeInformation info;
463  if (!tid.LookupAttributeByName (attrName, &info))
464  {
465  NS_FATAL_ERROR ("Attribute not found: " << attributePath);
466  }
467 
468  std::stringstream ss;
469  ss << info.help
470  << " (" << attributePath << ") ["
471  << info.initialValue->SerializeToString (info.checker) << "]";
472 
473  AddValue (name, ss.str (),
475 }
476 
477 
478 /* static */
479 bool
480 CommandLine::HandleAttribute (const std::string name,
481  const std::string value)
482 {
483  bool success = true;
484  if (!Config::SetGlobalFailSafe (name, StringValue (value))
485  && !Config::SetDefaultFailSafe (name, StringValue (value)))
486  {
487  success = false;
488  }
489  return success;
490 }
491 
492 
493 bool
495 {
496  return false;
497 }
498 
499 std::string
501 {
502  return "";
503 }
504 
505 template <>
506 std::string
508 {
509  std::ostringstream oss;
510  oss << std::boolalpha << val;
511  return oss.str ();
512 }
513 
514 template <>
515 bool
516 CommandLineHelper::UserItemParse<bool> (const std::string value, bool & val)
517 {
518  std::string src = value;
519  std::transform(src.begin(), src.end(), src.begin(), ::tolower);
520 
521  if (src.length () == 0)
522  {
523  val = ! val;
524  return true;
525  }
526  else if ( (src == "true") || (src == "t") )
527  {
528  val = true;
529  return true;
530  }
531  else if ( (src == "false") || (src == "f"))
532  {
533  val = false;
534  return true;
535  }
536  else
537  {
538  std::istringstream iss;
539  iss.str (src);
540  iss >> val;
541  return !iss.bad () && !iss.fail ();
542  }
543 }
544 
545 std::ostream &
546 operator << (std::ostream & os, const CommandLine & cmd)
547 {
548  cmd.PrintHelp (os);
549  return os;
550 }
551 
552 } // namespace ns3
~CommandLine()
Destructor.
Definition: command-line.cc:62
uint32_t GetAttributeN(void) const
Get the number of attributes.
Definition: type-id.cc:968
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:782
std::string Get(void) const
Definition: string.cc:31
Items m_items
The list of arguments.
Definition: command-line.h:432
Hold variables of type string.
Definition: string.h:41
String attribute value declarations.
bool SetGlobalFailSafe(std::string name, const AttributeValue &value)
Definition: config.cc:819
void PrintGlobals(std::ostream &os) const
Handler for --PrintGlobals: print all global variables and values.
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1677
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Vector::const_iterator Iterator
Iterator type for the list of all global values.
Definition: global-value.h:61
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:145
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition: type-id.cc:759
std::string GetDefault< bool >(const bool &val)
Helper to specialize CommandLine::UserItem::GetDefault() on bool.
Declaration of the various ns3::Config functions and classes.
tuple cmd
Definition: second.py:35
std::list< std::string > Split(std::string path)
Split a file system path into directories according to the local path separator.
Definition: system-path.cc:204
std::string GetName() const
Get the program name.
void Usage(const std::string usage)
Supply the program usage and documentation.
Definition: command-line.cc:95
System-independent file and directory function declarations.
void Clear(void)
Remove all arguments, Usage(), name.
Definition: command-line.cc:81
void PrintAttributes(std::ostream &os, const std::string &type) const
Handler for --PrintAttributes: print the attributes for a given type.
An argument Item using a Callback to parse the input.
Definition: command-line.h:364
void PrintHelp(std::ostream &os) const
Print program usage to the desired output stream.
static bool HandleAttribute(const std::string name, const std::string value)
Callback function to handle attributes.
std::string m_usage
The Usage string.
Definition: command-line.h:433
static uint32_t GetRegisteredN(void)
Get the number of registered TypeIds.
Definition: type-id.cc:791
virtual std::string GetDefault() const
static Iterator Begin(void)
The Begin iterator.
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:79
static TypeId GetRegistered(uint32_t i)
Get a TypeId by index.
Definition: type-id.cc:797
std::string m_name
The program name.
Definition: command-line.h:434
Attribute implementation.
Definition: type-id.h:69
Parse command-line arguments.
Definition: command-line.h:201
virtual bool Parse(const std::string value)
Parse from a string.
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
void PrintGroups(std::ostream &os) const
Handler for --PrintGroups: print all TypeId group names.
CommandLine class declaration.
Ptr< const AttributeChecker > checker
Checker object.
Definition: type-id.h:83
Every class exported by the ns3 library is enclosed in the ns3 namespace.
CommandLine & operator=(const CommandLine &cmd)
Assignment.
Definition: command-line.cc:56
bool LookupAttributeByName(std::string name, struct AttributeInformation *info) const
Find an Attribute by name.
Definition: type-id.cc:804
ns3::TypeId declaration; inline and template implementations.
std::string m_name
Argument label: ---m_name=...
Definition: command-line.h:317
bool UserItemParse< bool >(const std::string value, bool &val)
Helpers to specialize CommandLine::UserItem::Parse() on bool.
Callback< bool, std::string > m_callback
The Callback.
Definition: command-line.h:374
std::string GetName(void) const
Get the name.
Definition: type-id.cc:880
ns3::GlobalValue declaration.
virtual bool HasDefault() const
virtual ~Item()
Destructor.
std::string m_help
Argument help string.
Definition: command-line.h:318
CommandLine()
Constructor.
Definition: command-line.cc:47
void AddValue(const std::string &name, const std::string &help, T &value)
Add a program argument, assigning to POD.
Definition: command-line.h:491
static Iterator End(void)
The End iterator.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
void PrintTypeIds(std::ostream &os) const
Handler for --PrintTypeIds: print all TypeId names.
void Copy(const CommandLine &cmd)
Copy constructor.
Definition: command-line.cc:68
void PrintGroup(std::ostream &os, const std::string &group) const
Handler for --PrintGroup: print all types belonging to a given group.
std::string GetAttributeFullName(uint32_t i) const
Get the Attribute name by index.
Definition: type-id.cc:981
void Parse(int argc, char *argv[])
Parse the program arguments.
std::string GetGroupName(void) const
Get the group name.
Definition: type-id.cc:872
struct TypeId::AttributeInformation GetAttribute(uint32_t i) const
Get Attribute information by index.
Definition: type-id.cc:975
Debug message logging.
a unique identifier for an interface.
Definition: type-id.h:58
void HandleArgument(const std::string &name, const std::string &value) const
Match name against the program or general arguments, and dispatch to the appropriate handler...
std::string help
Attribute help string.
Definition: type-id.h:73