first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / 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"
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. */
94
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. */
101
102   virtual ~command_line();
103
104   DEFINE_CLASS_NAME("command_line");
105
106   filesystem::filename program_name() const;
107     //!< Returns the program name found in the command line.
108
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. */
119
120   int entries() const;
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. */
124
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. */
129
130   bool zap(int field);
131     //!< eats the entry at position "field".
132     /*!< this is useful for cleaning out entries that have already been dealt
133     with. */
134
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.
138
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.
147
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
155     "Linkage". */
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.
159
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. */
174
175   basis::astring text_form() const;
176     //!< returns a string with all the information we have for the command line.
177
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
182     object. */
183
184 private:
185   internal_cmd_line_array_of_parms *_implementation;  //!< held parameters.
186   filesystem::filename *_program_name;  //!< the name of this program.
187
188   void parse_string_array(const structures::string_array &to_parse);
189     //!< pulls all the strings in "to_parse" into the command_parameter list.
190
191   // forbidden:
192   command_line(const command_line &to_copy);
193   command_line &operator =(const command_line &to_copy);
194
195   static const command_parameter &cmdline_blank_parm();
196 };
197
198 //////////////
199
200 // this declares a program-wide command-line argument storage area.
201
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
206
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; \
211 }
212
213 } //namespace.
214
215 #endif
216