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