A Discrete-Event Network Simulator
API
command-line.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  */
19 
20 #include "command-line.h"
21 
22 #include "config.h"
23 #include "des-metrics.h"
24 #include "environment-variable.h"
25 #include "global-value.h"
26 #include "log.h"
27 #include "string.h"
28 #include "system-path.h"
29 #include "type-id.h"
30 
31 #if defined(ENABLE_BUILD_VERSION)
32 #include "version.h"
33 #endif
34 
35 #include <algorithm> // transform
36 #include <cctype> // tolower
37 #include <cstdlib> // exit
38 #include <cstring> // strlen
39 #include <iomanip> // setw, boolalpha
40 #include <set>
41 #include <sstream>
42 
50 namespace
51 {
60 std::string
61 Encode(const std::string& source)
62 {
63  std::string buffer;
64  buffer.reserve(1.1 * source.size());
65 
66  for (size_t pos = 0; pos != source.size(); ++pos)
67  {
68  switch (source[pos])
69  {
70  case '&':
71  buffer.append("&amp;");
72  break;
73  case '\"':
74  buffer.append("&quot;");
75  break;
76  case '\'':
77  buffer.append("&apos;");
78  break;
79  // case '>': buffer.append ("&gt;"); break;
80 
81  case '<':
82  // Special case:
83  // "...blah <file..." is not allowed
84  // "...foo<bar..." is allowed
85  if (buffer.empty() || buffer.back() == ' ')
86  {
87  buffer.append("&lt;");
88  }
89  else
90  {
91  buffer.append("<");
92  }
93 
94  break;
95 
96  default:
97  buffer.append(&source[pos], 1);
98  break;
99  }
100  }
101  return buffer;
102 }
103 
104 } // anonymous namespace
105 
106 namespace ns3
107 {
108 
109 NS_LOG_COMPONENT_DEFINE("CommandLine");
110 
112  : m_NNonOptions(0),
113  m_nonOptionCount(0),
114  m_usage(),
115  m_shortName()
116 {
117  NS_LOG_FUNCTION(this);
118 }
119 
120 CommandLine::CommandLine(const std::string& filename)
121  : m_NNonOptions(0),
122  m_nonOptionCount(0),
123  m_usage()
124 {
125  NS_LOG_FUNCTION(this << filename);
126  std::string basename = SystemPath::Split(filename).back();
127  m_shortName = basename.substr(0, basename.rfind(".cc"));
128  m_shortName = m_shortName.substr(basename.find_last_of('/') + 1);
129 }
130 
132 {
133  Copy(cmd);
134 }
135 
138 {
139  Clear();
140  Copy(cmd);
141  return *this;
142 }
143 
145 {
146  NS_LOG_FUNCTION(this);
147  Clear();
148 }
149 
150 void
152 {
154 
155  std::copy(cmd.m_options.begin(), cmd.m_options.end(), m_options.end());
156  std::copy(cmd.m_nonOptions.begin(), cmd.m_nonOptions.end(), m_nonOptions.end());
157 
158  m_NNonOptions = cmd.m_NNonOptions;
159  m_nonOptionCount = 0;
160  m_usage = cmd.m_usage;
161  m_shortName = cmd.m_shortName;
162 }
163 
164 void
166 {
167  NS_LOG_FUNCTION(this);
168 
169  m_options.clear();
170  m_nonOptions.clear();
171  m_NNonOptions = 0;
172  m_usage = "";
173  m_shortName = "";
174 }
175 
176 void
177 CommandLine::Usage(const std::string& usage)
178 {
179  m_usage = usage;
180 }
181 
182 std::string
184 {
185  return m_shortName;
186 }
187 
189 {
190  NS_LOG_FUNCTION(this);
191 }
192 
193 void
194 CommandLine::Parse(std::vector<std::string> args)
195 {
196  NS_LOG_FUNCTION(this << args.size() << args);
197 
199 
200  m_nonOptionCount = 0;
201 
202  if (!args.empty())
203  {
204  args.erase(args.begin()); // discard the program name
205 
207 
208  for (const auto& param : args)
209  {
210  if (HandleOption(param))
211  {
212  continue;
213  }
214  if (HandleNonOption(param))
215  {
216  continue;
217  }
218 
219  // is this possible?
220  NS_ASSERT_MSG(false,
221  "unexpected error parsing command line parameter: '" << param << "'");
222  }
223  }
224 
225 #ifdef ENABLE_DES_METRICS
227 #endif
228 }
229 
231 CommandLine::GetOptionName(const std::string& param) const
232 {
233  // remove leading "--" or "-"
234  std::string arg = param;
235  std::string::size_type cur = arg.find("--");
236  if (cur == 0)
237  {
238  arg = arg.substr(2, arg.size() - 2);
239  }
240  else
241  {
242  cur = arg.find('-');
243  if (cur == 0)
244  {
245  arg = arg.substr(1, arg.size() - 1);
246  }
247  else
248  {
249  // non-option argument?
250  return {false, param, ""};
251  }
252  }
253 
254  // find any value following '='
255  cur = arg.find('=');
256  std::string name;
257  std::string value;
258  if (cur == std::string::npos)
259  {
260  name = arg;
261  value = "";
262  }
263  else
264  {
265  name = arg.substr(0, cur);
266  value = arg.substr(cur + 1, arg.size() - (cur + 1));
267  }
268 
269  return {true, name, value};
270 }
271 
272 void
273 CommandLine::HandleHardOptions(const std::vector<std::string>& args) const
274 {
275  NS_LOG_FUNCTION(this << args.size() << args);
276 
277  for (const auto& param : args)
278  {
279  auto [isOpt, name, value] = GetOptionName(param);
280  if (!isOpt)
281  {
282  continue;
283  }
284 
285  // Hard-coded options
286  if (name == "PrintHelp" || name == "help")
287  {
288  // method below never returns.
289  PrintHelp(std::cout);
290  std::exit(0);
291  }
292  if (name == "PrintVersion" || name == "version")
293  {
294  // Print the version, then exit the program
295  PrintVersion(std::cout);
296  std::exit(0);
297  }
298  else if (name == "PrintGroups")
299  {
300  // method below never returns.
301  PrintGroups(std::cout);
302  std::exit(0);
303  }
304  else if (name == "PrintTypeIds")
305  {
306  // method below never returns.
307  PrintTypeIds(std::cout);
308  std::exit(0);
309  }
310  else if (name == "PrintGlobals")
311  {
312  // method below never returns.
313  PrintGlobals(std::cout);
314  std::exit(0);
315  }
316  else if (name == "PrintGroup")
317  {
318  // method below never returns.
319  PrintGroup(std::cout, value);
320  std::exit(0);
321  }
322  else if (name == "PrintAttributes")
323  {
324  // method below never returns.
325  PrintAttributes(std::cout, value);
326  std::exit(0);
327  }
328  }
329 }
330 
331 bool
332 CommandLine::HandleOption(const std::string& param) const
333 {
334  auto [isOpt, name, value] = GetOptionName(param);
335  if (!isOpt)
336  {
337  return false;
338  }
339 
340  HandleArgument(name, value);
341 
342  return true;
343 }
344 
345 bool
346 CommandLine::HandleNonOption(const std::string& value)
347 {
348  NS_LOG_FUNCTION(this << value);
349 
350  if (m_nonOptionCount == m_nonOptions.size())
351  {
352  // Add an unspecified non-option as a string
353  NS_LOG_LOGIC("adding StringItem, NOCount:" << m_nonOptionCount
354  << ", NOSize:" << m_nonOptions.size());
355  auto item = std::make_shared<StringItem>();
356  item->m_name = "extra-non-option-argument";
357  item->m_help = "Extra non-option argument encountered.";
358  item->m_value = value;
359  m_nonOptions.push_back(item);
360  }
361 
362  auto i = m_nonOptions[m_nonOptionCount];
363  if (!i->Parse(value))
364  {
365  std::cerr << "Invalid non-option argument value " << value << " for " << i->m_name
366  << std::endl;
367  PrintHelp(std::cerr);
368  std::exit(1);
369  }
371  return true;
372 }
373 
374 void
375 CommandLine::Parse(int argc, char* argv[])
376 {
377  NS_LOG_FUNCTION(this << argc);
378  std::vector<std::string> args(argv, argv + argc);
379  Parse(args);
380 }
381 
382 void
383 CommandLine::PrintHelp(std::ostream& os) const
384 {
385  NS_LOG_FUNCTION(this);
386 
387  // Hack to show just the declared non-options
388  Items nonOptions(m_nonOptions.begin(), m_nonOptions.begin() + m_NNonOptions);
389  os << m_shortName << (!m_options.empty() ? " [Program Options]" : "")
390  << (!nonOptions.empty() ? " [Program Arguments]" : "") << " [General Arguments]"
391  << std::endl;
392 
393  if (!m_usage.empty())
394  {
395  os << std::endl;
396  os << m_usage << std::endl;
397  }
398 
399  std::size_t width = 0;
400  auto max_width = [&width](const std::shared_ptr<Item> item) {
401  width = std::max(width, item->m_name.size());
402  };
403  std::for_each(m_options.begin(), m_options.end(), max_width);
404  std::for_each(nonOptions.begin(), nonOptions.end(), max_width);
405  width += 3; // room for ": " between option and help
406 
407  auto optionsHelp = [&os, width](const std::string& head, bool option, const Items& items) {
408  os << "\n" << head << "\n";
409  for (const auto& item : items)
410  {
411  os << " " << (option ? "--" : " ") << std::left << std::setw(width)
412  << (item->m_name + ":") << std::right << item->m_help;
413 
414  if (item->HasDefault())
415  {
416  os << " [" << item->GetDefault() << "]";
417  }
418  os << "\n";
419  }
420  };
421 
422  if (!m_options.empty())
423  {
424  optionsHelp("Program Options:", true, m_options);
425  }
426 
427  if (!nonOptions.empty())
428  {
429  optionsHelp("Program Arguments:", false, nonOptions);
430  }
431 
432  os << std::endl;
433  os << "General Arguments:\n"
434  << " --PrintGlobals: Print the list of globals.\n"
435  << " --PrintGroups: Print the list of groups.\n"
436  << " --PrintGroup=[group]: Print all TypeIds of group.\n"
437  << " --PrintTypeIds: Print all TypeIds.\n"
438  << " --PrintAttributes=[typeid]: Print all attributes of typeid.\n"
439  << " --PrintVersion: Print the ns-3 version.\n"
440  << " --PrintHelp: Print this help message.\n"
441  << std::endl;
442 }
443 
444 std::string
446 {
447 #if defined(ENABLE_BUILD_VERSION)
448  return Version::LongVersion();
449 #else
450  return std::string{"Build version support is not enabled, reconfigure with "
451  "--enable-build-version flag"};
452 #endif
453 }
454 
455 void
456 CommandLine::PrintVersion(std::ostream& os) const
457 {
458  os << GetVersion() << std::endl;
459 }
460 
461 void
463 {
464  NS_LOG_FUNCTION(this);
465 
466  auto [found, path] = EnvironmentVariable::Get("NS_COMMANDLINE_INTROSPECTION");
467  if (!found)
468  {
469  return;
470  }
471 
472  if (m_shortName.empty())
473  {
474  NS_FATAL_ERROR("No file name on example-to-run; forgot to use CommandLine var (__FILE__)?");
475  return;
476  }
477 
478  // Hack to show just the declared non-options
479  Items nonOptions(m_nonOptions.begin(), m_nonOptions.begin() + m_NNonOptions);
480 
481  std::string outf = SystemPath::Append(path, m_shortName + ".command-line");
482 
483  NS_LOG_INFO("Writing CommandLine doxy to " << outf);
484 
485  std::fstream os(outf, std::fstream::out);
486 
487  os << "/**\n \\file " << m_shortName << ".cc\n"
488  << "<h3>Usage</h3>\n"
489  << "<code>$ ./ns3 run \"" << m_shortName << (!m_options.empty() ? " [Program Options]" : "")
490  << (!nonOptions.empty() ? " [Program Arguments]" : "") << "\"</code>\n";
491 
492  if (!m_usage.empty())
493  {
494  os << Encode(m_usage) << "\n";
495  }
496 
497  auto listOptions = [&os](const std::string& head, const Items& items, std::string pre) {
498  os << "\n<h3>" << head << "</h3>\n<dl>\n";
499  for (const auto& i : items)
500  {
501  os << " <dt>" << pre << i->m_name << " </dt>\n"
502  << " <dd>" << Encode(i->m_help);
503 
504  if (i->HasDefault())
505  {
506  os << " [" << Encode(i->GetDefault()) << "]";
507  }
508  os << " </dd>\n";
509  }
510  os << "</dl>\n";
511  };
512 
513  if (!m_options.empty())
514  {
515  listOptions("Program Options", m_options, "\\c --");
516  }
517 
518  if (!nonOptions.empty())
519  {
520  listOptions("Program Arguments", nonOptions, "\\c ");
521  }
522 
523  os << "*/" << std::endl;
524 
525  // All done, don't need to actually run the example
526  os.close();
527  std::exit(0);
528 }
529 
530 void
531 CommandLine::PrintGlobals(std::ostream& os) const
532 {
533  NS_LOG_FUNCTION(this);
534 
535  os << "Global values:" << std::endl;
536 
537  // Sort output
538  std::vector<std::string> globals;
539 
540  for (auto i = GlobalValue::Begin(); i != GlobalValue::End(); ++i)
541  {
542  std::stringstream ss;
543  ss << " --" << (*i)->GetName() << "=[";
544  Ptr<const AttributeChecker> checker = (*i)->GetChecker();
545  StringValue v;
546  (*i)->GetValue(v);
547  ss << v.Get() << "]" << std::endl;
548  ss << " " << (*i)->GetHelp() << std::endl;
549  globals.push_back(ss.str());
550  }
551  std::sort(globals.begin(), globals.end());
552  for (const auto& s : globals)
553  {
554  os << s;
555  }
556 }
557 
558 void
559 CommandLine::PrintAttributeList(std::ostream& os, const TypeId tid, std::stringstream& header) const
560 {
561  NS_LOG_FUNCTION(this);
562 
563  if (!tid.GetAttributeN())
564  {
565  return;
566  }
567  os << header.str() << "\n";
568  // To sort output
569  std::vector<std::string> attributes;
570 
571  for (uint32_t i = 0; i < tid.GetAttributeN(); ++i)
572  {
573  std::stringstream ss;
574  ss << " --" << tid.GetAttributeFullName(i) << "=[";
576  ss << info.initialValue->SerializeToString(info.checker) << "]\n"
577  << " " << info.help << "\n";
578  attributes.push_back(ss.str());
579  }
580  std::sort(attributes.begin(), attributes.end());
581  for (const auto& s : attributes)
582  {
583  os << s;
584  }
585 }
586 
587 void
588 CommandLine::PrintAttributes(std::ostream& os, const std::string& type) const
589 {
590  NS_LOG_FUNCTION(this);
591 
592  TypeId tid;
594  {
595  NS_FATAL_ERROR("Unknown type=" << type << " in --PrintAttributes");
596  }
597 
598  std::stringstream header;
599  header << "Attributes for TypeId " << tid.GetName();
600  PrintAttributeList(os, tid, header);
601  header.str("");
602 
603  // Parent Attributes
604  if (tid.GetParent() != tid)
605  {
606  TypeId tmp = tid.GetParent();
607  while (tmp.GetParent() != tmp)
608  {
609  header << "Attributes defined in parent class " << tmp.GetName();
610  PrintAttributeList(os, tmp, header);
611  header.str("");
612  tmp = tmp.GetParent();
613  }
614  }
615 }
616 
617 void
618 CommandLine::PrintGroup(std::ostream& os, const std::string& group) const
619 {
620  NS_LOG_FUNCTION(this);
621 
622  os << "TypeIds in group " << group << ":" << std::endl;
623 
624  // Sort output
625  std::vector<std::string> groupTypes;
626 
627  for (uint16_t i = 0; i < TypeId::GetRegisteredN(); ++i)
628  {
629  std::stringstream ss;
630  TypeId tid = TypeId::GetRegistered(i);
631  if (tid.GetGroupName() == group)
632  {
633  ss << " " << tid.GetName() << std::endl;
634  }
635  groupTypes.push_back(ss.str());
636  }
637  std::sort(groupTypes.begin(), groupTypes.end());
638  for (const auto& s : groupTypes)
639  {
640  os << s;
641  }
642 }
643 
644 void
645 CommandLine::PrintTypeIds(std::ostream& os) const
646 {
647  NS_LOG_FUNCTION(this);
648  os << "Registered TypeIds:" << std::endl;
649 
650  // Sort output
651  std::vector<std::string> types;
652 
653  for (uint16_t i = 0; i < TypeId::GetRegisteredN(); ++i)
654  {
655  std::stringstream ss;
656  TypeId tid = TypeId::GetRegistered(i);
657  ss << " " << tid.GetName() << std::endl;
658  types.push_back(ss.str());
659  }
660  std::sort(types.begin(), types.end());
661  for (const auto& s : types)
662  {
663  os << s;
664  }
665 }
666 
667 void
668 CommandLine::PrintGroups(std::ostream& os) const
669 {
670  NS_LOG_FUNCTION(this);
671 
672  std::set<std::string> groups;
673  for (uint16_t i = 0; i < TypeId::GetRegisteredN(); ++i)
674  {
675  TypeId tid = TypeId::GetRegistered(i);
676  groups.insert(tid.GetGroupName());
677  }
678 
679  os << "Registered TypeId groups:" << std::endl;
680  // Sets are already sorted
681  for (const auto& s : groups)
682  {
683  os << " " << s << std::endl;
684  }
685 }
686 
687 bool
688 CommandLine::HandleArgument(const std::string& name, const std::string& value) const
689 {
690  NS_LOG_FUNCTION(this << name << value);
691 
692  NS_LOG_DEBUG("Handle arg name=" << name << " value=" << value);
693 
694  auto errorExit = [this, name, value]() {
695  std::cerr << "Invalid command-line argument: --" << name;
696  if (!value.empty())
697  {
698  std::cerr << "=" << value;
699  }
700  std::cerr << std::endl;
701  this->PrintHelp(std::cerr);
702  std::exit(1);
703  };
704 
705  auto item = std::find_if(m_options.begin(), m_options.end(), [name](std::shared_ptr<Item> it) {
706  return it->m_name == name;
707  });
708  if (item != m_options.end())
709  {
710  if (!(*item)->Parse(value))
711  {
712  errorExit();
713  }
714  return true;
715  }
716 
717  // Global or ConfigPath options
718  if (!HandleAttribute(name, value))
719  {
720  errorExit();
721  }
722  return true;
723 }
724 
725 bool
727 {
728  return !m_default.empty();
729 }
730 
731 std::string
733 {
734  return m_default;
735 }
736 
737 bool
738 CommandLine::CallbackItem::Parse(const std::string& value) const
739 {
740  NS_LOG_FUNCTION(this);
741  NS_LOG_DEBUG("CommandLine::CallbackItem::Parse \"" << value << "\"");
742  return m_callback(value);
743 }
744 
745 void
746 CommandLine::AddValue(const std::string& name,
747  const std::string& help,
748  char* value,
749  std::size_t num)
750 {
751  NS_LOG_FUNCTION(this << name << help << value << num);
752  auto item = std::make_shared<CharStarItem>();
753  item->m_name = name;
754  item->m_help = help;
755  item->m_buffer = value;
756  item->m_size = num;
757  item->m_default.assign(value);
758  m_options.push_back(item);
759 }
760 
761 void
762 CommandLine::AddValue(const std::string& name,
763  const std::string& help,
765  const std::string& defaultValue /* = "" */)
766 
767 {
768  NS_LOG_FUNCTION(this << &name << &help << &callback);
769  auto item = std::make_shared<CallbackItem>();
770  item->m_name = name;
771  item->m_help = help;
772  item->m_callback = callback;
773  item->m_default = defaultValue;
774  m_options.push_back(item);
775 }
776 
777 void
778 CommandLine::AddValue(const std::string& name, const std::string& attributePath)
779 {
780  NS_LOG_FUNCTION(this << name << attributePath);
781  // Attribute name is last token
782  std::size_t colon = attributePath.rfind("::");
783  const std::string typeName = attributePath.substr(0, colon);
784  NS_LOG_DEBUG("typeName: '" << typeName << "', colon: " << colon);
785 
786  TypeId tid;
787  if (!TypeId::LookupByNameFailSafe(typeName, &tid))
788  {
789  NS_FATAL_ERROR("Unknown type=" << typeName);
790  }
791 
792  const std::string attrName = attributePath.substr(colon + 2);
794  if (!tid.LookupAttributeByName(attrName, &info))
795  {
796  NS_FATAL_ERROR("Attribute not found: " << attributePath);
797  }
798 
799  std::stringstream ss;
800  ss << info.help << " (" << attributePath << ") ["
801  << info.initialValue->SerializeToString(info.checker) << "]";
802 
803  AddValue(name, ss.str(), MakeBoundCallback(CommandLine::HandleAttribute, attributePath));
804 }
805 
806 std::string
807 CommandLine::GetExtraNonOption(std::size_t i) const
808 {
809  std::string value;
810 
811  if (m_nonOptions.size() >= i + m_NNonOptions)
812  {
813  auto ip = std::dynamic_pointer_cast<StringItem>(m_nonOptions[i + m_NNonOptions]);
814  if (ip != nullptr)
815  {
816  value = ip->m_value;
817  }
818  }
819  return value;
820 }
821 
822 std::size_t
824 {
825  if (m_nonOptions.size() > m_NNonOptions)
826  {
827  return m_nonOptions.size() - m_NNonOptions;
828  }
829  else
830  {
831  return 0;
832  }
833 }
834 
835 /* static */
836 bool
837 CommandLine::HandleAttribute(const std::string& name, const std::string& value)
838 {
839  return Config::SetGlobalFailSafe(name, StringValue(value)) ||
841 }
842 
843 bool
845 {
846  return false;
847 }
848 
849 bool
850 CommandLine::StringItem::Parse(const std::string& value) const
851 {
852  m_value = value; // mutable
853  return true;
854 }
855 
856 bool
858 {
859  return false;
860 }
861 
862 std::string
864 {
865  return "";
866 }
867 
868 bool
869 CommandLine::CharStarItem::Parse(const std::string& value) const
870 {
871  if (value.size() > m_size - 1)
872  {
873  std::cerr << "Value \"" << value << "\" (" << value.size() << " bytes) is too long for "
874  << m_name << " buffer (" << m_size << " bytes, including terminating null)."
875  << std::endl;
876  return false;
877  }
878 
879  std::strncpy(m_buffer, value.c_str(), m_size);
880  return true;
881 }
882 
883 bool
885 {
886  return true;
887 }
888 
889 std::string
891 {
892  return m_default;
893 }
894 
895 template <>
896 std::string
897 CommandLineHelper::GetDefault<bool>(const std::string& defaultValue)
898 {
899  bool value;
900  std::istringstream iss(defaultValue);
901  iss >> value;
902  std::ostringstream oss;
903  oss << std::boolalpha << value;
904  return oss.str();
905 }
906 
907 template <>
908 bool
909 CommandLineHelper::UserItemParse<bool>(const std::string& value, bool& dest)
910 {
911  // No new value, so just toggle it
912  if (value.empty())
913  {
914  dest = !dest;
915  return true;
916  }
917 
918  std::string src = value;
919  std::transform(src.begin(), src.end(), src.begin(), [](char c) {
920  return static_cast<char>(std::tolower(c));
921  });
922  if (src == "true" || src == "t")
923  {
924  dest = true;
925  return true;
926  }
927  else if (src == "false" || src == "f")
928  {
929  dest = false;
930  return true;
931  }
932  else
933  {
934  std::istringstream iss;
935  iss.str(src);
936  iss >> dest;
937  return !iss.bad() && !iss.fail();
938  }
939 }
940 
941 template <>
942 std::string
943 CommandLineHelper::GetDefault<Time>(const std::string& defaultValue)
944 {
945  std::ostringstream oss;
946  oss << Time(defaultValue).As();
947  return oss.str();
948 }
949 
950 template <>
951 bool
952 CommandLineHelper::UserItemParse<uint8_t>(const std::string& value, uint8_t& dest)
953 {
954  uint8_t oldDest = dest;
955  int newDest;
956 
957  try
958  {
959  newDest = std::stoi(value);
960  }
961  catch (std::invalid_argument& ia)
962  {
963  NS_LOG_WARN("invalid argument: " << ia.what());
964  dest = oldDest;
965  return false;
966  }
967  catch (std::out_of_range& oor)
968  {
969  NS_LOG_WARN("out of range: " << oor.what());
970  dest = oldDest;
971  return false;
972  }
973  if (newDest < 0 || newDest > 255)
974  {
975  return false;
976  }
977  dest = newDest;
978  return true;
979 }
980 
981 std::ostream&
982 operator<<(std::ostream& os, const CommandLine& cmd)
983 {
984  cmd.PrintHelp(os);
985  return os;
986 }
987 
988 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:42
bool HasDefault() const override
std::string GetDefault() const override
bool Parse(const std::string &value) const override
Parse from a string.
bool Parse(const std::string &value) const override
Parse from a string.
std::string GetDefault() const override
bool HasDefault() const override
virtual ~Item()
Destructor.
virtual bool HasDefault() const
bool Parse(const std::string &value) const override
Parse from a string.
std::string GetDefault() const override
bool HasDefault() const override
Parse command-line arguments.
Definition: command-line.h:232
void PrintAttributeList(std::ostream &os, const TypeId tid, std::stringstream &header) const
Print the Attributes for a single type.
HasOptionName GetOptionName(const std::string &param) const
Strip leading -- or - from options.
std::tuple< bool, std::string, std::string > HasOptionName
Tuple type returned by GetOptionName().
Definition: command-line.h:549
void PrintGroups(std::ostream &os) const
Handler for --PrintGroups: print all TypeId group names.
void PrintTypeIds(std::ostream &os) const
Handler for --PrintTypeIds: print all TypeId names.
std::string GetExtraNonOption(std::size_t i) const
Get extra non-option arguments by index.
std::vector< std::shared_ptr< Item > > Items
Argument list container.
Definition: command-line.h:657
std::size_t m_nonOptionCount
The number of actual non-option arguments seen so far.
Definition: command-line.h:667
std::size_t GetNExtraNonOptions() const
Get the total number of non-option arguments found, including those configured with AddNonOption() an...
void PrintDoxygenUsage() const
Append usage message in Doxygen format to the file indicated by the NS_COMMANDLINE_INTROSPECTION envi...
~CommandLine()
Destructor.
std::string GetName() const
Get the program name.
Items m_options
The list of option arguments.
Definition: command-line.h:660
bool HandleNonOption(const std::string &value)
Handle a non-option.
void Parse(int argc, char *argv[])
Parse the program arguments.
void PrintGroup(std::ostream &os, const std::string &group) const
Handler for --PrintGroup: print all types belonging to a given group.
void Copy(const CommandLine &cmd)
Copy constructor implementation.
std::size_t m_NNonOptions
The expected number of non-option arguments.
Definition: command-line.h:665
void PrintGlobals(std::ostream &os) const
Handler for --PrintGlobals: print all global variables and values.
Items m_nonOptions
The list of non-option arguments.
Definition: command-line.h:662
void PrintVersion(std::ostream &os) const
Print ns-3 version to the desired output stream.
void HandleHardOptions(const std::vector< std::string > &args) const
Handle hard-coded options.
std::string m_shortName
The source file name (without .cc), as would be given to ns3 run
Definition: command-line.h:671
bool HandleOption(const std::string &param) const
Handle an option in the form param=value.
std::string m_usage
The Usage string.
Definition: command-line.h:669
void Clear()
Remove all arguments, Usage(), name.
void PrintAttributes(std::ostream &os, const std::string &type) const
Handler for --PrintAttributes: print the attributes for a given type as well as its parents.
bool HandleArgument(const std::string &name, const std::string &value) const
Match name against the program or general arguments, and dispatch to the appropriate handler.
void AddValue(const std::string &name, const std::string &help, T &value)
Add a program argument, assigning to POD.
Definition: command-line.h:746
static bool HandleAttribute(const std::string &name, const std::string &value)
Callback function to handle attributes.
CommandLine()
Constructor.
void PrintHelp(std::ostream &os) const
Print program usage to the desired output stream.
std::string GetVersion() const
Get the program version.
CommandLine & operator=(const CommandLine &cmd)
Assignment.
void Usage(const std::string &usage)
Supply the program usage and documentation.
void Initialize(std::vector< std::string > args, std::string outDir="")
Open the DesMetrics trace file and print the header.
Definition: des-metrics.cc:42
static KeyFoundType Get(const std::string &envvar, const std::string &key="", const std::string &delim=";")
Get the value corresponding to a key from an environment variable.
static Iterator Begin()
The Begin iterator.
static Iterator End()
The End iterator.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static DesMetrics * Get()
Get a pointer to the singleton instance.
Definition: singleton.h:100
Hold variables of type string.
Definition: string.h:56
std::string Get() const
Definition: string.cc:31
a unique identifier for an interface.
Definition: type-id.h:59
std::string GetGroupName() const
Get the group name.
Definition: type-id.cc:983
static uint16_t GetRegisteredN()
Get the number of registered TypeIds.
Definition: type-id.cc:879
std::string GetAttributeFullName(std::size_t i) const
Get the Attribute name by index.
Definition: type-id.cc:1115
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1100
TypeId GetParent() const
Get the parent of this TypeId.
Definition: type-id.cc:955
static TypeId GetRegistered(uint16_t i)
Get a TypeId by index.
Definition: type-id.cc:886
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1108
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition: type-id.cc:844
bool LookupAttributeByName(std::string name, AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:893
std::string GetName() const
Get the name.
Definition: type-id.cc:991
static std::string LongVersion()
Constructs a string containing all of the build details.
Definition: version.cc:133
ns3::CommandLine declaration.
Declaration of the various ns3::Config functions and classes.
ns3::DesMetrics declaration.
Class Environment declaration.
ns3::GlobalValue declaration.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
std::string GetDefault< Time >(const std::string &defaultValue)
Helper to specialize CommandLine::UserItem::GetDefault() on types needing special handling.
std::string GetDefault< bool >(const std::string &defaultValue)
Helper to specialize CommandLine::UserItem::GetDefault() on types needing special handling.
bool SetGlobalFailSafe(std::string name, const AttributeValue &value)
Definition: config.cc:943
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:900
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:765
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:258
std::string Append(std::string left, std::string right)
Join two file system path elements.
Definition: system-path.cc:240
Debug message logging.
std::string Encode(const std::string &source)
HTML-encode a string, for PrintDoxygenUsage().
Definition: command-line.cc:61
bool UserItemParse< bool >(const std::string &value, bool &dest)
Specialization of CommandLine::UserItem::Parse() to bool.
bool UserItemParse< uint8_t >(const std::string &value, uint8_t &dest)
Specialization of CommandLine::UserItem::Parse() to uint8_t to distinguish from char.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
cmd
Definition: second.py:40
ns3::StringValue attribute value declarations.
Attribute implementation.
Definition: type-id.h:81
Ptr< const AttributeChecker > checker
Checker object.
Definition: type-id.h:95
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:91
std::string help
Attribute help string.
Definition: type-id.h:85
ns3::SystemPath declarations.
ns3::TypeId declaration; inline and template implementations.
class ns3::Version definition