//============================================================================= // drt/sys/scmdargs.hpp // Command line option argument parsing classes. // These classes provide a simple command line argument parsing capability // so that the program can parse its command line arguments easily. // // Usage // To set up the syntax objects for the allowable command options used by // the program, define an DrtCmdOptDef object for each allowable option. // // For example, we want the program to accept the following options: // -a A flag option (without an arg). // -b arg An option with a required arg. // -c [arg] An option with an optional arg. // -d [arg] An option with an optional arg with a default setting. // -e arg=val An option with an arg having a required value. // -f arg[=val] // An option with an arg having an optional value. // -g [arg=val] // An option with an optional arg having a required value. // -h [arg[=val]] // An option with an optional arg having an optional // value. // // So we define an array of command option objects which specify the // options: // static const DrtCmdOptDef opts[] = // { // // -a // DrtCmdOptDef('a', DrtCmdOptDef::NOARG), // // -b arg // DrtCmdOptDef('b', DrtCmdOptDef::REQARG), // // -c [arg] // DrtCmdOptDef('c', DrtCmdOptDef::OPTARG), // // -d [arg] // DrtCmdOptDef('d', DrtCmdOptDef::OPTARG, "dfl"), // // -e arg=val // DrtCmdOptDef('e', DrtCmdOptDef::REQARG|DrtCmdOptDef::REQVAL), // // -f arg[=val] // DrtCmdOptDef('f', DrtCmdOptDef::REQARG|DrtCmdOptDef::OPTVAL), // // -g [arg=val] // DrtCmdOptDef('g', DrtCmdOptDef::OPTARG|DrtCmdOptDef::REQVAL), // // -h [arg[=val]] // DrtCmdOptDef('h', DrtCmdOptDef::OPTARG|DrtCmdOptDef::OPTVAL), // // Sentinel (last member) // DrtCmdOptDef(DrtCmdOptDef::END) // }; // // Next we establish a command parsing object, upon which we will iterate. // We pass it the array of option objects (above) as well as the command // argument count and string array (upon which it will iterate): // DrtCmdParser cmd(opts, argc, argv); // // Note that the 'argv' variable may require a cast: // DrtCmdParser cmd(opts, argc, (const char *const *)argv); // Or: // DrtCmdParser cmd(opts, argc, (const wchar_t *const *)argv); // // Next we provide the main loop, which iterates over the command line // arguments, parsing and testing one option at a time: // while (cmd.hasMore()) // { // DrtCmdOpt * opt = null; // // // Retrieve and parse the next command option // opt = cmd.getNext(); // // if (opt->error() != DrtCmdOpt::E_OKAY) // ...error, bad option... // // switch (opt->optChar()) // { // case 'a': // -a // ... // break; // // case 'b': // -b arg // ... // break; // // case 'c': // -c [arg] // ... // break; // // case 'd': // -d [arg] // ... // break; // } // // delete opt; // Clean up // } // // For simple options with no argument, we can simply set a flag (or do // whatever is appropriate: // bool opt_a; // // case 'a': // -a // opt_a = true; // break; // // For options with required arguments, we can access and save the // argument string: // const DrtChar * opt_b; // // case 'b': // -b arg // opt_b = opt->takeArg(); // Gets the 'arg' // break; // // For options with optional arguments without a default setting, we can // access the argument, which will be null if no argument was given. // We can also test for the absence of the argument: // const char * opt_c; // // case 'c': // -c [arg] // if (opt->hasArg()) // opt_c = opt->takeArg(); // Gets the 'arg' // else // ...No arg present, take other action... // // For options with optional arguments with a default setting, we can // access the argument, which will have the default setting if an option // argument was not given. // const DrtChar * opt_d; // // case 'd': // -d [arg] // opt_d = opt->takeArg(); // Gets the 'arg' // // For options with arguments expecting values, we can access both the // argument and its value: // const DrtChar * opt_e; // const DrtChar * val_e; // // case 'e': // -e arg=val // opt_e = opt->takeArg(); // Gets the 'arg' // val_e = opt->takeArgVal(); // Gets the 'val' // // We can also push back an option, for situations where we want to look // ahead at the next option, for instance: // DrtCmdOpt * la_opt = null; // // opt = cmd.getNext(); // ...examine the option // cmd.unget(opt); // // When the last command line option has been parsed, the cmd.hasMore() // function returns false, and the while-loop (above) terminates. // // History // 0.01, 1996-06-11, David R Tribble. // First cut. // // 0.02, 1998-10-24, David R Tribble. // Added 'REQVAL' et al flags. // // 0.03, 1999-02-21, David R Tribble. // MOve from scm/ to drt/sys/. // // Copyright ©1996-1999, by David R. Tribble, all rights reserved. // See "drt/sys/copyr.txt" for more information. //----------------------------------------------------------------------------- #ifndef drt_sys_scmdargs_hpp #define drt_sys_scmdargs_hpp 1 // Identification #ifndef NO_H_IDENT static const char drt_sys_scmdargs_hpp_id[] = "@(#)drt/sys/scmdargs.hpp 0.03"; #endif // Special includes #ifndef drt_sys_sdefs_hpp #include "sdefs.hpp" #endif // Local includes #ifndef drt_sys_schar_hpp #include "schar.hpp" #endif #ifndef drt_sys_sdebug_hpp #include "sdebug.hpp" #endif #ifndef drt_sys_smagic_hpp #include "smagic.hpp" #endif // Local wrappers #include "slib1.hpp" drt_namespace_begin // Local forward declarations class DrtCmdOpt; //----------------------------------------------------------------------------- // Class DrtCmdOptDef // Specifies the syntax for a single program command option. // // Usage // (See the "Usage" description at the top of this file.) // // History // 100, 1998-06-11, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtCmdOptDef_VS 100 // Class version class DRTEXPORT DrtCmdOptDef: public DrtMagic { public: // Shared constants static const int VS; // Class version static const unsigned int MAGIC; // Class magic number public: // Constants #define DrtCmdOptDef_Type_VS 100 // Enum version enum Type // Option types { NOARG = 0x0001, // Flag option, no args: '-o' REQARG = 0x0002, // Req'd arg: '-o a' OPTARG = 0x0003, // Opt'l arg: '-o [a]' REQVAL = 0x0010, // Req'd arg value: '-o a=v' OPTVAL = 0x0020, // Opt'l arg value: '-o a[=v]' PARM = 0x0100, // Non-option parameter: 'x' END = 0x0800 // End of the list }; public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Functions /*void*/ ~DrtCmdOptDef(); // Destructor /*void*/ DrtCmdOptDef(Type t); // Constructor /*void*/ DrtCmdOptDef(const char *ch, int t); // Constructor /*void*/ DrtCmdOptDef(const char *ch, int t, const char *dfl); // Constructor /*void*/ DrtCmdOptDef(const wchar_t *ch, int t); // Constructor /*void*/ DrtCmdOptDef(const wchar_t *ch, int t, const wchar_t *dfl); // Constructor bool isValid() const; // Check this object void dump() const; // Dump contents private: // Constants #define DrtCmdOptDef_Mask_VS 100 // Enum version enum Mask // Option type masks { M_ARG = 0x000F, // Option argument mask M_VAL = 0x00F0, // Option argument value mask M_PARM = 0x0F00 // Non-option parameter mask }; #define DrtCmdOptDef_Flags_VS 100 // Enum version enum Flags // Control bitflags { F_ARG = 0x000F, // Option arg mask F_ARG_NONE = 0x0001, // Option has no arg: '-a' F_ARG_REQ = 0x0002, // Option expects an arg: '-a x' F_ARG_OPT = 0x0003, // Arg is optional: '-a [x]' F_ARG_DFL = 0x0004, // Arg has a default setting F_ARG_PLUS = 0x0008, // Arg takes a leading '-' or '+' F_VAL = 0x00F0, // Option arg value mask F_VAL_NONE = 0x0010, // Arg has no value: '-a' F_VAL_REQ = 0x0020, // Arg expects a value: '-a x=v' F_VAL_OPT = 0x0030, // Arg value is optional: '-a x[=v]' F_VAL_DFL = 0x0040, // Arg value has a default value F_PARM = 0x0F00, // Non-flag parameter mask F_PARM_NF = 0x0100, // Non-flag parameter: 'x' F_END = 0x0800, // End of the list F_DFL = F_ARG_NONE // Default flags }; private: // Variables Flags m_flags; // Control flags DrtChar m_ch; // Option char const DrtChar * m_dflArg; // Default arg setting const DrtChar * m_dflVal; // Default arg value private: // Functions // Constructors and destructors not provided /*void*/ DrtCmdOptDef(); // Default constructor /*void*/ DrtCmdOptDef(const DrtCmdOptDef &r); // Copy constructor const DrtCmdOptDef & operator =(const DrtCmdOptDef &r); // Assignment operator }; //----------------------------------------------------------------------------- // Class DrtCmdParser // This class manages the parsing of command line options, iterating over // them one option at a time. // // Usage // (See the "Usage" description at the top of this file.) // // History // 100, 1998-06-11, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtCmdParser_VS 100 // Class version class DRTEXPORT DrtCmdParser: public DrtMagic { friend class DrtCmdOpt; public: // Shared constants static const int VS; // Class version static const unsigned int MAGIC; // Class magic number public: // Constants #define DrtCmdParser_State_VS 100 // Enum version enum State // State codes { ST_INIT, // Initializing ST_START, // Starting ST_MORE, // More command line args remain ST_AT_ARG, // At a command line arg ST_AT_JARGVAL, // At a joined command line arg value ST_AT_SARGVAL, // At a separate command line arg value ST_NO_MORE, // No more command line args remain ST_END, // Parsing completed ST__MAX }; public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Functions /*void*/ ~DrtCmdParser(); // Destructor /*void*/ DrtCmdParser(const DrtCmdOptDef *opts, int argc, const char *const *argv); // Constructor /*void*/ DrtCmdParser(const DrtCmdOptDef *opts, int argc, const wchar_t *const *argv); // Constructor bool isValid() const; // Check this object void dump() const; // Dump contents bool hasMore() const; // More options remain int numOpts() const; // Number of options DrtCmdOpt * getNext(); // Parse next command option bool unget(DrtCmdOpt *opt); // Push back a command option private: // Constants #define DrtCmdParser_Flags_VS 100 // Enum version enum Flags // Control flags { F_WCHAR = 0x0001, // Command line args are 'wchar_t*' F_DFL = 0x0000 // Default }; private: // Variables const void *const m_argv; // Command arg strings int m_argc; // Remaining arg count DrtCmdOpt * m_opts; // List of undeleted options int m_optc; // Option counter Flags m_flags; // Control flags State m_state; // Current state private: // Functions // Constructors and destructors not provided /*void*/ DrtCmdParser(); // Default constructor /*void*/ DrtCmdParser(const DrtCmdParser &r); // Copy constructor const DrtCmdParser & operator =(const DrtCmdParser &r); // Assignment operator void save(DrtCmdOpt *opt); // Remember an undeleted opt void forget(DrtCmdOpt *opt); // Forget a deleted option }; //----------------------------------------------------------------------------- // Class DrtCmdOpt // This is the result returned when a single program command option has // been parsed. // // Usage // (See the "Usage" description at the top of this file.) // // History // 100, 1998-06-11, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtCmdOpt_VS 100 // Class version class DRTEXPORT DrtCmdOpt: public DrtMagic { friend class DrtCmdParser; public: // Shared constants static const int VS; // Class version static const unsigned int MAGIC; // Class magic number public: // Constants #define DrtCmdOpt_Type_VS 100 // Enum version enum Type // Option types { OPT, // Option: '-o [arg[=val]]' PARM // Non-option parameter: 'x' }; #define DrtCmdOpt_Error_VS 100 // Enum version enum Error // Error codes { E_OKAY = 0, // Okay, no error E_BAD_OPT, // Invalid/unknown option char E_NO_ARG, // Missing req'd option argument E__MAX }; public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Functions /*void*/ ~DrtCmdOpt(); // Destructor /*void*/ DrtCmdOpt(); // Default constructor bool isValid() const; // Check this object void dump() const; // Dump contents int type() const; // Get the option type int optChar() const; // Get the option char const DrtChar * takeArg(); // Steal the option argument const DrtChar * takeArgVal(); // Steal the option arg value private: // Variables DrtCmdParser * m_cmd; // Parent command parser const DrtCmdOptDef * m_opt; // Syntax info const DrtChar * m_arg; // Option argument const DrtChar * m_val; // Option argument value DrtCmdOpt * m_prev; // Previous undeleted option Error m_err; // Last error private: // Functions // Constructors and destructors not provided /*void*/ DrtCmdOpt(const DrtCmdOpt &r); // Copy constructor const DrtCmdOpt & operator =(const DrtCmdOpt &r); // Assignment operator void append(DrtCmdOpt *opt); // Append an undeleted opt void unhook(); // Unlink this deleted opt }; #include "slib2.hpp" drt_namespace_end #endif // drt_sys_scmdargs_hpp // End drt/sys/scmdargs.hpp