new home directory
[feisty_meow.git] / nucleus / library / application / command_line.h
1 #ifndef COMMAND_LINE_CLASS
2 #define COMMAND_LINE_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 * Name   : command_line                                                       *
7 * Author : Chris Koeritz                                                      *
8 *                                                                             *
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 \*****************************************************************************/
17
18 #include <basis/contracts.h>
19 #include <filesystem/filename.h>
20
21 namespace application {
22
23 //! This class parses the command line passed to the main() function.
24 /*!
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.
37
38 (not implemented)
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".
42 (not implemented)
43 */
44
45 // forward declarations.
46 class internal_cmd_line_array_of_parms;
47
48 class command_parameter : public virtual basis::root_object
49 {
50 public:
51   enum parameter_types { VALUE, CHAR_FLAG, STRING_FLAG, BOGUS_ITEM };
52
53   command_parameter(parameter_types type = BOGUS_ITEM);
54     //!< default constructor initializes to mostly blank state.
55
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. */
60
61   command_parameter(const command_parameter &to_copy);
62
63   ~command_parameter();
64
65   DEFINE_CLASS_NAME("command_parameter");
66
67   command_parameter &operator =(const command_parameter &to_copy);
68
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.
73
74   const basis::astring &text() const;
75     //!< observes the string contents.
76   void text(const basis::astring &new_text);
77     //!< modifies the string contents.
78
79 private:
80   parameter_types _type;
81   basis::astring *_text;
82 };
83
84 //////////////
85
86 class command_line
87 {
88 public:
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. */
97
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. */
104
105   virtual ~command_line();
106
107   DEFINE_CLASS_NAME("command_line");
108
109   filesystem::filename program_name() const;
110     //!< Returns the program name found in the command line.
111
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. */
122
123   int entries() const;
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. */
127
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. */
132
133   bool zap(int field);
134     //!< eats the entry at position "field".
135     /*!< this is useful for cleaning out entries that have already been dealt
136     with. */
137
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.
141
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.
150
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
158     "Linkage". */
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.
162
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. */
177
178   basis::astring text_form() const;
179     //!< returns a string with all the information we have for the command line.
180
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
185     object. */
186
187 private:
188   internal_cmd_line_array_of_parms *_implementation;  //!< held parameters.
189   filesystem::filename *_program_name;  //!< the name of this program.
190
191   void parse_string_array(const structures::string_array &to_parse);
192     //!< pulls all the strings in "to_parse" into the command_parameter list.
193
194   // forbidden:
195   command_line(const command_line &to_copy);
196   command_line &operator =(const command_line &to_copy);
197
198   static const command_parameter &cmdline_blank_parm();
199 };
200
201 //////////////
202
203 // this declares a program-wide command-line argument storage area.
204
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
209
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; \
214 }
215
216 } //namespace.
217
218 #endif
219