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"
92 string (element zero) is ignored because it is assumed that it is the program name.
93 these become available in the global variables _global_argc and _global_argv. */
95 command_line(const basis::astring &to_parse);
96 //!< takes a string form of the command line.
97 /*!< this is the form rendered by GetCommandLine() in Win32. on certain
98 win32 platforms, this may not return a full path for the program_name()
99 method. this uses the separate_command_line() method to pick out the
100 relevant pieces and supports embedded, escaped quotes. */
102 virtual ~command_line();
104 DEFINE_CLASS_NAME("command_line");
106 filesystem::filename program_name() const;
107 //!< Returns the program name found in the command line.
109 static void separate_command_line(const basis::astring &cmd_line, basis::astring &app,
110 basis::astring &parms);
111 //!< breaks apart a command line in "cmd_line" into "app" and "parms".
112 /*!< when given a full command line, where the application to run is the
113 first chunk and its parameters (if any) are subsequent chunks, this will
114 store the application name in "app" and the rest of the parameters in
115 "parms". this expects any paths in the "cmd_line" that contain spaces
116 to be surrounded by quotes. if there are any quote characters that are
117 escaped, they are considered to be embedded in the parameter string; they
118 will not be considered as matching any pending closing quotes. */
121 //!< Returns the number of fields found on the command line.
122 /*!< This does not include the program name found; that's only
123 accessible through the program_name() method. */
125 const command_parameter &get(int field) const;
126 //!< Returns the parameter at the "field" specified.
127 /*!< The "field" ranges from zero through "entries() - 1" inclusive. if
128 an invalid index is used, then the type will be BOGUS_ITEM. */
131 //!< eats the entry at position "field".
132 /*!< this is useful for cleaning out entries that have already been dealt
135 // note: in the following, if "case_sense" is true, then the searches are
136 // case-sensitive. otherwise, case of the flags is not a concern.
137 // the returned values always retain the original case.
139 bool find(char option_character, int &index, bool case_sense = true) const;
140 //!< Returns true if the "option_character" is found in the parameters.
141 /*!< The search starts at the "index" specified, and if the item is found,
142 its location is returned in "index" and the function returns true.
143 Otherwise false is returned and the "index" is not modified. */
144 bool find(const basis::astring &option_string, int &index,
145 bool case_sense = true) const;
146 //!< Returns true if the "option_string" is found in the parameters.
148 bool get_value(char option_character, basis::astring &value,
149 bool case_sense = true) const;
150 //!< retrieves the "value" found for the option flag specified.
151 /*!< this is useful for command lines with standard spacing. for example,
152 if the command line is "-Q query.bop --Linkage plorgs.txt", then this
153 function would return "query.bop" for a search on 'Q' and the find()
154 method below would return "plorgs.txt" for the string flag search on
156 bool get_value(const basis::astring &option_string, basis::astring &value,
157 bool case_sense = true) const;
158 //!< retrieves the "value" found for the "option_string" specified.
160 //is this useful? it's kind of like what we need for special flags (like
161 // -fgob.h, where gob.h is a value parameter) but needs to terminate
162 //differently for that to work.
163 basis::astring gather(int &index) const;
164 //!< coalesces parameters together until the next option flag.
165 /*!< Returns a string constructed from the concatenation of the strings
166 for the parameters at all indices in the list starting at "index" until
167 an option character is found. Note that this means an empty string
168 will be returned if the parameter at "index" has an option character,
169 or if "index" is greater than or equal to "elements()".
170 After gather, "index" is set to the last location included in the
171 string. "index" is set to the last index in the list if "index" was
172 past the end to begin with or if strings are gathered up to the last
173 index. otherwise, "index" is unchanged if nothing was gathered. */
175 basis::astring text_form() const;
176 //!< returns a string with all the information we have for the command line.
178 static structures::string_array get_command_line();
179 //!< returns the command line passed to the program as a list of strings.
180 /*!< the string at index zero is the program name. this is just a useful
181 helper function and is not normally needed by users of the command_line
185 internal_cmd_line_array_of_parms *_implementation; //!< held parameters.
186 filesystem::filename *_program_name; //!< the name of this program.
188 void parse_string_array(const structures::string_array &to_parse);
189 //!< pulls all the strings in "to_parse" into the command_parameter list.
192 command_line(const command_line &to_copy);
193 command_line &operator =(const command_line &to_copy);
195 static const command_parameter &cmdline_blank_parm();
200 // this declares a program-wide command-line argument storage area.
202 extern int _global_argc;
203 extern char **_global_argv;
204 //! this macro allocates space for the command-line storage areas.
205 #define DEFINE_ARGC_AND_ARGV int _global_argc = 0; char **_global_argv = NIL
207 //! this macro assigns our command-line parameters for this program.
208 #define SET_ARGC_ARGV(argc, argv) { \
209 application::_global_argc = argc; \
210 application::_global_argv = argv; \