1 #ifndef COMMAND_LINE_CLASS
2 #define COMMAND_LINE_CLASS
4 /*****************************************************************************\
6 * Name : command_line *
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 1992-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
18 #include <basis/contracts.h>
19 #include <filesystem/filename.h>
21 namespace application {
23 //! This class parses the command line passed to the main() function.
25 The main function might be called WinMain or be implemented by CWinApp in MS-Windows, but all
26 of these types of applications will still have flags passed to them. This class constructs a
27 list of parameters from the command line provided by the OS. A parameter is either a command
28 flag or a value string. Flag characters take the form of "-l" or "-Q" or "-als" (which has
29 three flags). Value strings are other strings found on the command line that do not start with
30 the separator character (usually '-'). Flag characters are all broken up into separate entries.
31 A special kind of flag uses a double separator to allow multiple character flag names (e.g.,
32 the string "--follow" where the flag name is "follow"), as in GNU software.
33 This class knows about the convention of a paramter of just '--' being used to
34 indicate that the rest of the line is all normal parameters and has no intentional flags
35 in them. This allows passing of character strings that would otherwise be misinterpreted
36 as flags rather than literal input.
39 A special feature is provided to allow parsing of flag characters followed
40 directly by the value (as in "-fbroiler.h", where the flag character is 'f'
41 and the value is "broiler.h".
45 // forward declarations.
46 class internal_cmd_line_array_of_parms;
48 class command_parameter : public virtual basis::root_object
51 enum parameter_types { VALUE, CHAR_FLAG, STRING_FLAG, BOGUS_ITEM };
53 command_parameter(parameter_types type = BOGUS_ITEM);
54 //!< default constructor initializes to mostly blank state.
56 command_parameter(parameter_types type, const basis::astring &text);
57 //!< constructs a parameter of "type" where the value is "text".
58 /*!< if the "type" is CHAR_FLAG, then this should be a string of
59 one character. for STRING_FLAG, the length is arbitrary. */
61 command_parameter(const command_parameter &to_copy);
65 DEFINE_CLASS_NAME("command_parameter");
67 command_parameter &operator =(const command_parameter &to_copy);
69 parameter_types type() const { return _type; }
70 //!< observes the type of the parameter.
71 void type(parameter_types new_type) { _type = new_type; }
72 //!< modifies the type of the parameter.
74 const basis::astring &text() const;
75 //!< observes the string contents.
76 void text(const basis::astring &new_text);
77 //!< modifies the string contents.
80 parameter_types _type;
81 basis::astring *_text;
89 command_line(int argc, char *argv[]);
90 //!< takes command line parameters in the form of "argc" and "argv".
91 /*!< this is suitable for most C++ main programs. the first "argv" string (element zero) is
92 ignored because it is assumed that it is the program name. that means that the array of
93 command parameters here will be (argc - 1) in length, and that index zero of our array has
94 the first "real" parameter that was passed to the program (i.e., not it's name).
95 note that the unaltered command parameters of argc and argv become available in the global
96 variables _global_argc and _global_argv. */
98 command_line(const basis::astring &to_parse);
99 //!< takes a string form of the command line.
100 /*!< this is the form rendered by GetCommandLine() in Win32. on certain
101 win32 platforms, this may not return a full path for the program_name()
102 method. this uses the separate_command_line() method to pick out the
103 relevant pieces and supports embedded, escaped quotes. */
105 virtual ~command_line();
107 DEFINE_CLASS_NAME("command_line");
109 filesystem::filename program_name() const;
110 //!< Returns the program name found in the command line.
112 static void separate_command_line(const basis::astring &cmd_line, basis::astring &app,
113 basis::astring &parms);
114 //!< breaks apart a command line in "cmd_line" into "app" and "parms".
115 /*!< when given a full command line, where the application to run is the
116 first chunk and its parameters (if any) are subsequent chunks, this will
117 store the application name in "app" and the rest of the parameters in
118 "parms". this expects any paths in the "cmd_line" that contain spaces
119 to be surrounded by quotes. if there are any quote characters that are
120 escaped, they are considered to be embedded in the parameter string; they
121 will not be considered as matching any pending closing quotes. */
124 //!< Returns the number of fields found on the command line.
125 /*!< This does not include the program name found; that's only
126 accessible through the program_name() method. */
128 const command_parameter &get(int field) const;
129 //!< Returns the parameter at the "field" specified.
130 /*!< The "field" ranges from zero through "entries() - 1" inclusive. if
131 an invalid index is used, then the type will be BOGUS_ITEM. */
134 //!< eats the entry at position "field".
135 /*!< this is useful for cleaning out entries that have already been dealt
138 // note: in the following, if "case_sense" is true, then the searches are
139 // case-sensitive. otherwise, case of the flags is not a concern.
140 // the returned values always retain the original case.
142 bool find(char option_character, int &index, bool case_sense = true) const;
143 //!< Returns true if the "option_character" is found in the parameters.
144 /*!< The search starts at the "index" specified, and if the item is found,
145 its location is returned in "index" and the function returns true.
146 Otherwise false is returned and the "index" is not modified. */
147 bool find(const basis::astring &option_string, int &index,
148 bool case_sense = true) const;
149 //!< Returns true if the "option_string" is found in the parameters.
151 bool get_value(char option_character, basis::astring &value,
152 bool case_sense = true) const;
153 //!< retrieves the "value" found for the option flag specified.
154 /*!< this is useful for command lines with standard spacing. for example,
155 if the command line is "-Q query.bop --Linkage plorgs.txt", then this
156 function would return "query.bop" for a search on 'Q' and the find()
157 method below would return "plorgs.txt" for the string flag search on
159 bool get_value(const basis::astring &option_string, basis::astring &value,
160 bool case_sense = true) const;
161 //!< retrieves the "value" found for the "option_string" specified.
163 //is this useful? it's kind of like what we need for special flags (like
164 // -fgob.h, where gob.h is a value parameter) but needs to terminate
165 //differently for that to work.
166 basis::astring gather(int &index) const;
167 //!< coalesces parameters together until the next option flag.
168 /*!< Returns a string constructed from the concatenation of the strings
169 for the parameters at all indices in the list starting at "index" until
170 an option character is found. Note that this means an empty string
171 will be returned if the parameter at "index" has an option character,
172 or if "index" is greater than or equal to "elements()".
173 After gather, "index" is set to the last location included in the
174 string. "index" is set to the last index in the list if "index" was
175 past the end to begin with or if strings are gathered up to the last
176 index. otherwise, "index" is unchanged if nothing was gathered. */
178 basis::astring text_form() const;
179 //!< returns a string with all the information we have for the command line.
181 static structures::string_array get_command_line();
182 //!< returns the command line passed to the program as a list of strings.
183 /*!< the string at index zero is the program name. this is just a useful
184 helper function and is not normally needed by users of the command_line
188 internal_cmd_line_array_of_parms *_implementation; //!< held parameters.
189 filesystem::filename *_program_name; //!< the name of this program.
191 void parse_string_array(const structures::string_array &to_parse);
192 //!< pulls all the strings in "to_parse" into the command_parameter list.
195 command_line(const command_line &to_copy);
196 command_line &operator =(const command_line &to_copy);
198 static const command_parameter &cmdline_blank_parm();
203 // this declares a program-wide command-line argument storage area.
205 extern int _global_argc;
206 extern char **_global_argv;
207 //! this macro allocates space for the command-line storage areas.
208 #define DEFINE_ARGC_AND_ARGV int _global_argc = 0; char **_global_argv = NULL_POINTER
210 //! this macro assigns our command-line parameters for this program.
211 #define SET_ARGC_ARGV(argc, argv) { \
212 application::_global_argc = argc; \
213 application::_global_argv = argv; \