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