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 #ifndef COMMAND_LINE_H
21 #define COMMAND_LINE_H
22
23 #include <string>
24 #include <sstream>
25 #include <vector>
26
27 #include "callback.h"
28 #include "nstime.h"
29
30 /**
31 * \file
32 * \ingroup commandline
33 * ns3::CommandLine declaration.
34 */
35
36 namespace ns3 {
37
38 /**
39 * \ingroup core
40 * \defgroup commandline Command Line Parsing
41 *
42 * A uniform way to specify program documentation,
43 * allowed command line arguments and help strings,
44 * and set any attribute or global value, all from
45 * the command line directly.
46 *
47 * The main entry point is CommandLine
48 */
49
50 /**
51 * \ingroup commandline
52 * \brief Parse command-line arguments
53 *
54 * Instances of this class can be used to parse command-line
55 * arguments. Programs can register a general usage message with
56 * CommandLine::Usage, and arguments with CommandLine::AddValue.
57 * Argument variable types with input streamers (`operator>>`)
58 * can be set directly; more complex argument parsing
59 * can be accomplished by providing a Callback.
60 *
61 * CommandLine also provides handlers for these standard arguments:
62 * \verbatim
63 --PrintGlobals: Print the list of globals.
64 --PrintGroups: Print the list of groups.
65 --PrintGroup=[group]: Print all TypeIds of group.
66 --PrintTypeIds: Print all TypeIds.
67 --PrintAttributes=[typeid]: Print all attributes of typeid.
68 --PrintVersion: Print the ns-3 version.
69 --PrintHelp: Print this help message. \endverbatim
70 *
71 * The more common \c \--version is a synonym for \c \--PrintVersion.
72 *
73 * The more common \c \--help is a synonym for \c \--PrintHelp; an example
74 * is given below.
75 *
76 * CommandLine can also handle non-option arguments
77 * (often called simply "positional" parameters: arguments which don't begin
78 * with "-" or "--"). These can be parsed directly in to variables,
79 * by registering arguments with AddNonOption in the order expected.
80 * Additional non-option arguments encountered will be captured as strings.
81 *
82 * Finally, CommandLine processes Attribute and GlobalValue arguments.
83 * Default values for specific attributes can be set using a shorthand
84 * argument name.
85 *
86 * In use, arguments are given in the form
87 * \verbatim
88 --arg=value --toggle first-non-option\endverbatim
89 * Most arguments expect a value, as in the first form, \c \--arg=value.
90 * Toggles, corresponding to boolean arguments, can be given in any of
91 * the forms
92 * \verbatim
93 --toggle1 --toggle2=1 --toggle3=t --toggle4=true \endverbatim
94 * The first form changes the state of toggle1 from its default;
95 * all the rest set the corresponding boolean variable to true.
96 * \c 0, \c f and \c false are accepted to set the variable to false.
97 * Option arguments can appear in any order on the command line,
98 * even intermixed with non-option arguments.
99 * The order of non-option arguments is preserved.
100 *
101 * Option arguments can be repeated on the command line; the last value given
102 * will be the final value used. For example,
103 * \verbatim
104 --arg=one --toggle=f --arg=another --toggle \endverbatim
105 * The variable set by \c \--arg will end up with the value \c "another";
106 * the boolean set by \c \--toggle will end up as \c true.
107 *
108 * Because arguments can be repeated it can be hard to decipher what
109 * value each variable ended up with, especially when using boolean toggles.
110 * Suggested best practice is for scripts to report the values of all items
111 * settable through CommandLine, as done by the example below.
112 *
113 *
114 * CommandLine can set the initial value of every attribute in the system
115 * with the \c \--TypeIdName::AttributeName=value syntax, for example
116 * \verbatim
117 --Application::StartTime=3s \endverbatim
118 * In some cases you may want to highlight the use of a particular
119 * attribute for a simulation script. For example, you might want
120 * to make it easy to set the \c Application::StartTime using
121 * the argument \c \--start, and have its help string show as part
122 * of the help message. This can be done using the
123 * \link AddValue(const std::string&, const std::string&) AddValue (name, attributePath) \endlink
124 * method.
125 *
126 * CommandLine can also set the value of every GlobalValue
127 * in the system with the \c \--GlobalValueName=value syntax, for example
128 * \verbatim
129 --SchedulerType=HeapScheduler \endverbatim
130 *
131 * A simple example of CommandLine is in `src/core/example/``command-line-example.cc`
132 * See that file for an example of handling non-option arguments.
133 *
134 * The heart of that example is this code:
135 *
136 * \code
137 * int intArg = 1;
138 * bool boolArg = false;
139 * std::string strArg = "strArg default";
140 *
141 * CommandLine cmd (__FILE__);
142 * cmd.Usage ("CommandLine example program.\n"
143 * "\n"
144 * "This little program demonstrates how to use CommandLine.");
145 * cmd.AddValue ("intArg", "an int argument", intArg);
146 * cmd.AddValue ("boolArg", "a bool argument", boolArg);
147 * cmd.AddValue ("strArg", "a string argument", strArg);
148 * cmd.AddValue ("anti", "ns3::RandomVariableStream::Antithetic");
149 * cmd.AddValue ("cbArg", "a string via callback", MakeCallback (SetCbArg));
150 * cmd.Parse (argc, argv);
151 * \endcode
152 * after which it prints the values of each variable. (The \c SetCbArg function
153 * is not shown here; see `src/core/example/``command-line-example.cc`)
154 *
155 * Here is the output from a few runs of that program:
156 *
157 * \verbatim
158 $ ./waf --run="command-line-example"
159 intArg: 1
160 boolArg: false
161 strArg: "strArg default"
162 cbArg: "cbArg default"
163
164 $ ./waf --run="command-line-example --intArg=2 --boolArg --strArg=Hello --cbArg=World"
165 intArg: 2
166 boolArg: true
167 strArg: "Hello"
168 cbArg: "World"
169
170 $ ./waf --run="command-line-example --help"
171 ns3-dev-command-line-example-debug [Program Arguments] [General Arguments]
172
173 CommandLine example program.
174
175 This little program demonstrates how to use CommandLine.
176
177 Program Arguments:
178 --intArg: an int argument [1]
179 --boolArg: a bool argument [false]
180 --strArg: a string argument [strArg default]
181 --anti: Set this RNG stream to generate antithetic values (ns3::RandomVariableStream::Antithetic) [false]
182 --cbArg: a string via callback
183
184 General Arguments:
185 --PrintGlobals: Print the list of globals.
186 --PrintGroups: Print the list of groups.
187 --PrintGroup=[group]: Print all TypeIds of group.
188 --PrintTypeIds: Print all TypeIds.
189 --PrintAttributes=[typeid]: Print all attributes of typeid.
190 --PrintVersion: Print the ns-3 version.
191 --PrintHelp: Print this help message. \endverbatim
192 *
193 * Having parsed the arguments, some programs will need to perform
194 * some additional validation of the received values. A common issue at this
195 * point is to discover that the supplied arguments are incomplete or
196 * incompatible. Suggested best practice is to supply an error message
197 * and the complete usage message. For example,
198 *
199 * \code
200 * int value1;
201 * int value2;
202 *
203 * CommandLine cmd (__FILE__);
204 * cmd.Usage ("...");
205 * cmd.AddValue ("value1", "first value", value1);
206 * cmd.AddValue ("value2", "second value", value1);
207 *
208 * cmd.Parse (argc, argv);
209 *
210 * if (value1 * value2 < 0)
211 * {
212 * std::cerr << "value1 and value2 must have the same sign!" << std::endl;
213 * std::cerr << cmd;
214 * exit (-1);
215 * }
216 * \endcode
217 *
218 * Finally, note that for examples which will be run by \c test.py
219 * the preferred declaration of a CommandLine instance is
220 *
221 * \code
222 * CommandLine cmd (__FILE__);
223 * \endcode
224 * This will ensure that the program usage and arguments can be added to
225 * the Doxygen documentation automatically.
226 */
227 class CommandLine
228 {
229 public:
230 /** Constructor */
231 CommandLine (void);
232 /**
233 * Construct and register the source file name.
234 * This would typically be called by
235 * CommandLine cmd (__FILE__);
236 *
237 * This form is required to generate Doxygen documentation of the
238 * arguments and options.
239 *
240 * \param [in] filename The source file name.
241 */
242 CommandLine (const std::string filename);
243 /**
244 * Copy constructor
245 *
246 * \param [in] cmd The CommandLine to copy from
247 */
248 CommandLine (const CommandLine &cmd);
249 /**
250 * Assignment
251 *
252 * \param [in] cmd The CommandLine to assign from
253 * \return The CommandLine
254 */
255 CommandLine &operator = (const CommandLine &cmd);
256 /** Destructor */
257 ~CommandLine ();
258
259 /**
260 * Supply the program usage and documentation.
261 *
262 * \param [in] usage Program usage message to write with \c \--help.
263 */
264 void Usage (const std::string usage);
265
266 /**
267 * Add a program argument, assigning to POD
268 *
269 * \param [in] name The name of the program-supplied argument
270 * \param [in] help The help text used by \c \--PrintHelp
271 * \param [out] value A reference to the variable where the
272 * value parsed will be stored (if no value
273 * is parsed, this variable is not modified).
274 */
275 template <typename T>
276 void AddValue (const std::string &name,
277 const std::string &help,
278 T &value);
279
280 /**
281 * Callback function signature for
282 * AddValue(const std::string&,const std::string&,Callback<bool,const std::string>).
283 *
284 * \param [in] value The argument value.
285 */
286 typedef bool (* Callback) (const std::string value);
287
288 /**
289 * Add a program argument, using a Callback to parse the value
290 *
291 * \param [in] name The name of the program-supplied argument
292 * \param [in] help The help text used by \c \--help
293 * \param [in] callback A Callback function that will be invoked to parse and
294 * store the value.
295 * \param [in] defaultValue Optional default value for argument.
296 *
297 * The callback should have the signature
298 * CommandLine::Callback
299 */
300 void AddValue (const std::string &name,
301 const std::string &help,
302 ns3::Callback<bool, std::string> callback,
303 const std::string defaultValue = "");
304
305
306 /**
307 * Add a program argument as a shorthand for an Attribute.
308 *
309 * \param [in] name The name of the program-supplied argument.
310 * \param [out] attributePath The fully-qualified name of the Attribute
311 */
312 void AddValue (const std::string &name,
313 const std::string &attributePath);
314
315 /**
316 * Add a non-option argument, assigning to POD
317 *
318 * \param [in] name The name of the program-supplied argument
319 * \param [in] help The help text used by \c \--PrintHelp
320 * \param [out] value A reference to the variable where the
321 * value parsed will be stored (if no value
322 * is parsed, this variable is not modified).
323 */
324 template <typename T>
325 void AddNonOption (const std::string name, const std::string help, T & value);
326
327 /**
328 * Get extra non-option arguments by index.
329 * This allows CommandLine to accept more non-option arguments than
330 * have been configured explicitly with AddNonOption().
331 *
332 * This is only valid after calling Parse().
333 *
334 * \param [in] i The index of the non-option argument to return.
335 * \return The i'th non-option argument, as a string.
336 */
337 std::string GetExtraNonOption (std::size_t i) const;
338
339 /**
340 * Get the total number of non-option arguments found,
341 * including those configured with AddNonOption() and extra non-option
342 * arguments.
343 *
344 * This is only valid after calling Parse().
345 *
346 * \returns the number of non-option arguments found.
347 */
348 std::size_t GetNExtraNonOptions (void) const;
349
350 /**
351 * Parse the program arguments
352 *
353 * \param [in] argc The 'argc' variable: number of arguments (including the
354 * main program name as first element).
355 * \param [in] argv The 'argv' variable: a null-terminated array of strings,
356 * each of which identifies a command-line argument.
357 *
358 * Obviously, this method will parse the input command-line arguments and
359 * will attempt to handle them all.
360 *
361 * As a side effect, this method saves the program basename, which
362 * can be retrieved by GetName().
363 */
364 void Parse (int argc, char *argv[]);
365
366 /**
367 * Parse the program arguments.
368 *
369 * This version may be convenient when synthesizing arguments
370 * programmatically. Other than the type of argument this behaves
371 * identically to Parse(int, char *)
372 *
373 * \param [in] args The vector of arguments.
374 */
375 void Parse (std::vector<std::string> args);
376
377 /**
378 * Get the program name
379 *
380 * \return The program name. Only valid after calling Parse()
381 */
382 std::string GetName () const;
383
384 /**
385 * \brief Print program usage to the desired output stream
386 *
387 * Handler for \c \--PrintHelp and \c \--help: print Usage(), argument names, and help strings
388 *
389 * Alternatively, an overloaded operator << can be used:
390 * \code
391 * CommandLine cmd (__FILE__);
392 * cmd.Parse (argc, argv);
393 * ...
394 *
395 * std::cerr << cmd;
396 * \endcode
397 *
398 * \param [in,out] os The output stream to print on.
399 */
400 void PrintHelp (std::ostream &os) const;
401
402 /**
403 * Get the program version.
404 *
405 * \return The program version
406 */
407 std::string GetVersion () const;
408
409 /**
410 * Print ns-3 version to the desired output stream
411 *
412 * Handler for \c \--PrintVersion and \c \--version.
413 *
414 * \param [in,out] os The output stream to print on.
415 */
416 void PrintVersion (std::ostream &os) const;
417
418 private:
419
420 /**
421 * \ingroup commandline
422 * \brief The argument abstract base class
423 */
424 class Item
425 {
426 public:
427 std::string m_name; /**< Argument label: \c \--m_name=... */
428 std::string m_help; /**< Argument help string */
429 virtual ~Item (); /**< Destructor */
430 /**
431 * Parse from a string.
432 *
433 * \param [in] value The string representation
434 * \return \c true if parsing the value succeeded
435 */
436 virtual bool Parse (const std::string value) = 0;
437 /**
438 * \return \c true if this item has a default value.
439 */
440 virtual bool HasDefault () const;
441 /**
442 * \return The default value
443 */
444 virtual std::string GetDefault () const = 0;
445 }; // class Item
446
447 /**
448 * \ingroup commandline
449 *\brief An argument Item assigning to POD
450 */
451 template <typename T>
452 class UserItem : public Item
453 {
454 public:
455 // Inherited
456 virtual bool Parse (const std::string value);
457 bool HasDefault () const;
458 std::string GetDefault () const;
459
460 T *m_valuePtr; /**< Pointer to the POD location */
461 std::string m_default; /**< String representation of default value */
462 }; // class UserItem
463
464 /**
465 * \ingroup commandline
466 * \brief Extension of Item for strings.
467 */
468 class StringItem : public Item
469 {
470 public:
471 // Inherited
472 bool Parse (const std::string value);
473 bool HasDefault (void) const;
474 std::string GetDefault (void) const;
475
476 std::string m_value; /**< The argument value. */
477 }; // class StringItem
478
479 /**
480 * \ingroup commandline
481 * \brief An argument Item using a Callback to parse the input
482 */
483 class CallbackItem : public Item
484 {
485 public:
486 // Inherited
487 bool HasDefault (void) const;
488 std::string GetDefault (void) const;
489
490 /**
491 * Parse from a string.
492 *
493 * \param [in] value The string representation
494 * \return \c true if parsing the value succeeded
495 */
496 virtual bool Parse (const std::string value);
497 ns3::Callback<bool, std::string> m_callback; /**< The Callback */
498 std::string m_default; /**< The default value, as a string, if it exists. */
499 }; // class CallbackItem
500
501
502 /**
503 * Handle an option in the form \c param=value.
504 *
505 * \param [in] param The option string.
506 * \returns \c true if this was really an option.
507 */
508 bool HandleOption (const std::string & param) const;
509
510 /**
511 * Handle a non-option
512 *
513 * \param [in] value The command line non-option value.
514 * \return \c true if \c value could be parsed correctly.
515 */
516 bool HandleNonOption (const std::string &value);
517
518 /**
519 * Match name against the program or general arguments,
520 * and dispatch to the appropriate handler.
521 *
522 * \param [in] name The argument name
523 * \param [in] value The command line value
524 */
525 void HandleArgument (const std::string &name, const std::string &value) const;
526 /**
527 * Callback function to handle attributes.
528 *
529 * \param [in] name The full name of the Attribute.
530 * \param [in] value The value to assign to \pname{name}.
531 * \return \c true if the value was set successfully, false otherwise.
532 */
533 static bool HandleAttribute (const std::string name, const std::string value);
534
535 /**
536 * Handler for \c \--PrintGlobals: print all global variables and values
537 * \param [in,out] os The output stream to print on.
538 */
539 void PrintGlobals (std::ostream &os) const;
540 /**
541 * Handler for \c \--PrintAttributes: print the attributes for a given type.
542 *
543 * \param [in,out] os the output stream.
544 * \param [in] type The TypeId whose Attributes should be displayed
545 */
546 void PrintAttributes (std::ostream &os, const std::string &type) const;
547 /**
548 * Handler for \c \--PrintGroup: print all types belonging to a given group.
549 *
550 * \param [in,out] os The output stream.
551 * \param [in] group The name of the TypeId group to display
552 */
553 void PrintGroup (std::ostream &os, const std::string &group) const;
554 /**
555 * Handler for \c \--PrintTypeIds: print all TypeId names.
556 *
557 * \param [in,out] os The output stream.
558 */
559 void PrintTypeIds (std::ostream &os) const;
560 /**
561 * Handler for \c \--PrintGroups: print all TypeId group names
562 *
563 * \param [in,out] os The output stream.
564 */
565 void PrintGroups (std::ostream &os) const;
566 /**
567 * Copy constructor
568 *
569 * \param [in] cmd CommandLine to copy
570 */
571 void Copy (const CommandLine &cmd);
572 /** Remove all arguments, Usage(), name */
573 void Clear (void);
574 /**
575 * Append usage message in Doxygen format to the file indicated
576 * by the NS_COMMANDLINE_INTROSPECTION environment variable.
577 */
578 void PrintDoxygenUsage (void) const;
579
580 typedef std::vector<Item *> Items; /**< Argument list container */
581 Items m_options; /**< The list of option arguments */
582 Items m_nonOptions; /**< The list of non-option arguments */
583 std::size_t m_NNonOptions; /**< The expected number of non-option arguments */
584 std::size_t m_nonOptionCount; /**< The number of actual non-option arguments seen so far. */
585 std::string m_usage; /**< The Usage string */
586 std::string m_shortName; /**< The source file name (without `.cc`), as would be given to `waf --run` */
587
588 }; // class CommandLine
589
590
591 /** \ingroup commandline
592 * \defgroup commandlinehelper Helpers to Specialize on bool
593 */
594 /**
595 * \ingroup commandlinehelper
596 * \brief Helpers for CommandLine to specialize on bool
597 */
598 namespace CommandLineHelper {
599
600 /**
601 * \ingroup commandlinehelper
602 * \brief Helpers to specialize CommandLine::UserItem::Parse()
603 *
604 * \param [in] value The argument name
605 * \param [out] val The argument location
606 * \tparam \deduced T The type being specialized
607 * \return \c true if parsing was successful
608 */
609 template <typename T>
610 bool UserItemParse (const std::string value, T & val);
611 /**
612 * \brief Specialization of CommandLine::UserItem to \c bool
613 *
614 * \param [in] value The argument name
615 * \param [out] val The boolean variable to set
616 * \return \c true if parsing was successful
617 */
618 template <>
619 bool UserItemParse<bool> (const std::string value, bool & val);
620 /**
621 * \brief Specialization of CommandLine::UserItem to \c uint8_t
622 * to distinguish from \c char
623 *
624 * \param [in] value The argument name
625 * \param [out] val The \c uint8_t variable to set
626 * \return \c true if parsing was successful
627 */
628 template <>
629 bool UserItemParse<uint8_t> (const std::string value, uint8_t & val);
630
631 /**
632 * \ingroup commandlinehelper
633 * \brief Helper to specialize CommandLine::UserItem::GetDefault() on types
634 * needing special handling.
635 *
636 * \param [in] val The argument value
637 * \return The string representation of value
638 * @{
639 */
640 template <typename T> std::string GetDefault (const T & val);
641 template <> std::string GetDefault<bool> (const bool & val);
642 template <> std::string GetDefault<Time> (const Time & val);
643 /**@}*/
644
645 } // namespace CommandLineHelper
646
647
648 } // namespace ns3
649
650
651 /********************************************************************
652 * Implementation of the templates declared above.
653 ********************************************************************/
654
655 namespace ns3 {
656
657 template <typename T>
658 void
AddValue(const std::string & name,const std::string & help,T & value)659 CommandLine::AddValue (const std::string &name,
660 const std::string &help,
661 T &value)
662 {
663 UserItem<T> *item = new UserItem<T> ();
664 item->m_name = name;
665 item->m_help = help;
666 item->m_valuePtr = &value;
667
668 std::stringstream ss;
669 ss << value;
670 ss >> item->m_default;
671
672 m_options.push_back (item);
673 }
674
675 template <typename T>
676 void
AddNonOption(const std::string name,const std::string help,T & value)677 CommandLine::AddNonOption (const std::string name,
678 const std::string help,
679 T & value)
680 {
681 UserItem<T> *item = new UserItem<T> ();
682 item->m_name = name;
683 item->m_help = help;
684 item->m_valuePtr = &value;
685
686 std::stringstream ss;
687 ss << value;
688 ss >> item->m_default;
689 m_nonOptions.push_back (item);
690 ++m_NNonOptions;
691
692 }
693
694 template <typename T>
695 bool
HasDefault()696 CommandLine::UserItem<T>::HasDefault () const
697 {
698 return true;
699 }
700
701 template <typename T>
702 std::string
GetDefault()703 CommandLine::UserItem<T>::GetDefault () const
704 {
705 return CommandLineHelper::GetDefault<T> (*m_valuePtr);
706 }
707
708 template <typename T>
709 std::string
GetDefault(const T & val)710 CommandLineHelper::GetDefault (const T & val)
711 {
712 std::ostringstream oss;
713 oss << val;
714 return oss.str ();
715 }
716
717 template <typename T>
718 bool
Parse(const std::string value)719 CommandLine::UserItem<T>::Parse (const std::string value)
720 {
721 return CommandLineHelper::UserItemParse<T> (value, *m_valuePtr);
722 }
723
724 template <typename T>
725 bool
UserItemParse(const std::string value,T & val)726 CommandLineHelper::UserItemParse (const std::string value, T & val)
727 {
728 std::istringstream iss;
729 iss.str (value);
730 iss >> val;
731 return !iss.bad () && !iss.fail ();
732 }
733
734 /**
735 * Overloaded operator << to print program usage
736 * (shortcut for CommandLine::PrintHelper)
737 *
738 * \see CommandLine::PrintHelper
739 *
740 * Example usage:
741 * \code
742 * CommandLine cmd (__FILE__);
743 * cmd.Parse (argc, argv);
744 * ...
745 *
746 * std::cerr << cmd;
747 * \endcode
748 *
749 * \param [in,out] os The stream to print on.
750 * \param [in] cmd The CommandLine describing the program.
751 * \returns The stream.
752 */
753 std::ostream & operator << (std::ostream & os, const CommandLine & cmd);
754
755 } // namespace ns3
756
757 #endif /* COMMAND_LINE_H */
758