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