1 /*
2  * args.h
3  *
4  * Program Argument Parsing class
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25  * All Rights Reserved.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Revision: 24177 $
30  * $Author: rjongbloed $
31  * $Date: 2010-04-05 06:52:04 -0500 (Mon, 05 Apr 2010) $
32  */
33 
34 #ifndef PTLIB_ARGLIST_H
35 #define PTLIB_ARGLIST_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 /** This class allows the parsing of a set of program arguments. This translates
42    the standard argc/argv style variables passed into the main() function into
43    a set of options (preceded by a '-' character) and parameters.
44 */
45 class PArgList : public PObject
46 {
47   PCLASSINFO(PArgList, PObject);
48 
49   public:
50   /**@name Construction */
51   //@{
52     /** Create an argument list.
53         An argument list is created given the standard arguments and a
54        specification for options. The program arguments are parsed from this
55        into options and parameters.
56 
57        The specification string consists of case significant letters for each
58        option. If the letter is followed by the ':' character then the option
59        has an associated string. This string must be in the argument or in the
60        next argument.
61      */
62     PArgList(
63       const char * theArgPtr = NULL,        ///< A string constituting the arguments
64       const char * argumentSpecPtr = NULL,  ///< The specification C string for argument options. See description for details.
65       PBoolean optionsBeforeParams = true       ///< Parse options only before parameters
66     );
67     /** Create an argument list. */
68     PArgList(
69       const PString & theArgStr,             ///< A string constituting the arguments
70       const char * argumentSpecPtr = NULL,   ///< The specification C string for argument options. See description for details.
71       PBoolean optionsBeforeParams = true        ///< Parse options only before parameters
72     );
73     /** Create an argument list. */
74     PArgList(
75       const PString & theArgStr,             ///< A string constituting the arguments
76       const PString & argumentSpecStr,       ///< The specification string for argument options. See description for details.
77       PBoolean optionsBeforeParams = true        ///< Parse options only before parameters
78     );
79     /** Create an argument list. */
80     PArgList(
81       int theArgc,                           ///< Count of argument strings in theArgv
82       char ** theArgv,                       ///< An array of strings constituting the arguments
83       const char * argumentSpecPtr = NULL,   ///< The specification C string for argument options. See description for details.
84       PBoolean optionsBeforeParams = true        ///< Parse options only before parameters
85     );
86     /** Create an argument list. */
87     PArgList(
88       int theArgc,                           ///< Count of argument strings in theArgv
89       char ** theArgv,                       ///< An array of strings constituting the arguments
90       const PString & argumentSpecStr,       ///< The specification string for argument options. See description for details.
91       PBoolean optionsBeforeParams = true        ///< Parse options only before parameters
92     );
93   //@}
94 
95   /**@name Overrides from class PObject */
96   //@{
97     /**Output the string to the specified stream.
98      */
99     virtual void PrintOn(
100       ostream & strm  ///< I/O stream to output to.
101     ) const;
102 
103     /**Input the string from the specified stream. This will read all
104        characters until a end of line is reached, then parsing the arguments.
105      */
106     virtual void ReadFrom(
107       istream & strm  ///< I/O stream to input from.
108     );
109   //@}
110 
111   /**@name Setting & Parsing */
112   //@{
113     /** Set the internal copy of the program arguments.
114     */
115     void SetArgs(
116       const PString & theArgStr ///< A string constituting the arguments
117     );
118     /** Set the internal copy of the program arguments. */
119     void SetArgs(
120       int theArgc,     ///< Count of argument strings in theArgv
121       char ** theArgv  ///< An array of strings constituting the arguments
122     );
123     /** Set the internal copy of the program arguments. */
124     void SetArgs(
125       const PStringArray & theArgs ///< A string array constituting the arguments
126     );
127 
128     /** Parse the arguments.
129        Parse the standard C program arguments into an argument of options and
130        parameters. Consecutive calls with <code>optionsBeforeParams</code> set
131        to true will parse out different options and parameters. If SetArgs()
132        function is called then the Parse() function will restart from the
133        beginning of the argument list.
134 
135        The specification string consists of case significant letters for each
136        option. If the letter is followed by a '-' character then a long name
137        version of the option is present. This is terminated either by a '.' or
138        a ':' character. If the single letter or long name is followed by the
139        ':' character then the option has may have an associated string. This
140        string must be within the argument or in the next argument. If a single
141        letter option is followed by a ';' character, then the option may have
142        an associated string but this MUST follow the letter immediately, if
143        it is present at all.
144 
145        For example, "ab:c" allows for "-a -b arg -barg -c" and
146        "a-an-arg.b-option:c;" allows for "-a --an-arg --option arg -c -copt".
147 
148        @return true if there is at least one parameter after parsing.
149      */
150     virtual PBoolean Parse(
151       const char * theArgumentSpec,    ///< The specification string for argument options. See description for details.
152       PBoolean optionsBeforeParams = true  ///< Parse options only before parameters
153     );
154     /** Parse the arguments. */
155     virtual PBoolean Parse(
156       const PString & theArgumentStr,  ///< The specification string for argument options. See description for details.
157       PBoolean optionsBeforeParams = true  ///< Parse options only before parameters
158     );
159   //@}
160 
161   /**@name Getting parsed arguments */
162   //@{
163     /** Get the count of the number of times the option was specified on the
164        command line.
165 
166        @return option repeat count.
167      */
168     virtual PINDEX GetOptionCount(
169       char optionChar        ///< Character letter code for the option
170     ) const;
171     /** Get the count of option */
172     virtual PINDEX GetOptionCount(
173       const char * optionStr ///< String code for the option
174     ) const;
175     /** Get the count of option */
176     virtual PINDEX GetOptionCount(
177       const PString & optionName ///< String code for the option
178     ) const;
179 
180     /** Get if option present.
181       Determines whether the option was specified on the command line.
182 
183        @return true if the option was present.
184      */
185     PBoolean HasOption(
186       char optionChar             ///< Character letter code for the option
187     ) const;
188     /** Get if option present. */
189     PBoolean HasOption(
190       const char * optionStr     ///< String letter code for the option
191     ) const;
192     /** Get if option present. */
193     PBoolean HasOption(
194       const PString & optionName ///<  String code for the option
195     ) const;
196 
197     /** Get option string.
198        Gets the string associated with an option e.g. -ofile or -o file
199        would return the string "file". An option may have an associated string
200        if it had a ':' character folowing it in the specification string passed
201        to the Parse() function.
202 
203        @return the options associated string.
204      */
205     virtual PString GetOptionString(
206       char optionChar,          ///< Character letter code for the option
207       const char * dflt = NULL  ///< Default value of the option string
208     ) const;
209     /** Get option string. */
210     virtual PString GetOptionString(
211       const char * optionStr,   ///< String letter code for the option
212       const char * dflt = NULL  ///<Default value of the option string
213     ) const;
214     /** Get option string. */
215     virtual PString GetOptionString(
216       const PString & optionName, ///< String code for the option
217       const char * dflt = NULL    ///< Default value of the option string
218     ) const;
219 
220     /** Get the argument count.
221        Get the number of parameters that may be obtained via the
222        <code>GetParameter()</code> function. Note that this does not include options
223        and option strings.
224 
225        @return count of parameters.
226      */
227     PINDEX GetCount() const;
228 
229     /** Get the parameters that were parsed in the argument list.
230 
231        @return array of parameter strings at the specified index range.
232      */
233     PStringArray GetParameters(
234       PINDEX first = 0,
235       PINDEX last = P_MAX_INDEX
236     ) const;
237 
238     /** Get the parameter that was parsed in the argument list.
239 
240        @return parameter string at the specified index.
241      */
242     PString GetParameter(
243       PINDEX num   ///< Number of the parameter to retrieve.
244     ) const;
245 
246     /** Get the parameter that was parsed in the argument list. The argument
247        list object can thus be treated as an "array" of parameters.
248 
249        @return parameter string at the specified index.
250      */
251     PString operator[](
252       PINDEX num   ///< Number of the parameter to retrieve.
253     ) const;
254 
255     /** Shift the parameters by the specified amount. This allows the parameters
256        to be parsed at the same position in the argument list "array".
257      */
258     void Shift(
259       int sh ///< Number of parameters to shift forward through list
260     );
261 
262     /** Shift the parameters by the specified amount. This allows the parameters
263        to be parsed at the same position in the argument list "array".
264      */
265     PArgList & operator<<(
266       int sh ///< Number of parameters to shift forward through list
267     );
268 
269     /** Shift the parameters by the specified amount. This allows the parameters
270        to be parsed at the same position in the argument list "array".
271      */
272     PArgList & operator>>(
273       int sh ///< Number of parameters to shift backward through list
274     );
275   //@}
276 
277   /**@name Errors */
278   //@{
279     /** This function is called when access to illegal parameter index is made
280        in the GetParameter function. The default behaviour is to output a
281        message to the standard <code>PError</code> stream.
282      */
283     virtual void IllegalArgumentIndex(
284       PINDEX idx ///< Number of the parameter that was accessed.
285     ) const;
286 
287     /** This function is called when an unknown option was specified on the
288        command line. The default behaviour is to output a message to the
289        standard <code>PError</code> stream.
290      */
291     virtual void UnknownOption(
292       const PString & option   ///< Option that was illegally placed on command line.
293     ) const;
294 
295     /** This function is called when an option that requires an associated
296        string was specified on the command line but no associated string was
297        provided. The default behaviour is to output a message to the standard
298        <code>PError</code> stream.
299      */
300     virtual void MissingArgument(
301       const PString & option  ///< Option for which the associated string was missing.
302     ) const;
303   //@}
304 
305   protected:
306     /// The original program arguments.
307     PStringArray argumentArray;
308     /// The specification letters for options
309     PString      optionLetters;
310     /// The specification strings for options
311     PStringArray optionNames;
312     /// The count of the number of times an option appeared in the command line.
313     PIntArray    optionCount;
314     /// The array of associated strings to options.
315     PStringArray optionString;
316     /// The index of each .
317     PIntArray    parameterIndex;
318     /// Shift count for the parameters in the argument list.
319     int          shift;
320 
321   private:
322     PBoolean ParseOption(PINDEX idx, PINDEX offset, PINDEX & arg, const PIntArray & canHaveOptionString);
323     PINDEX GetOptionCountByIndex(PINDEX idx) const;
324     PString GetOptionStringByIndex(PINDEX idx, const char * dflt) const;
325     int m_argsParsed;
326 };
327 
328 
329 #ifdef P_CONFIG_FILE
330 
331 /**This class parse command line arguments with the ability to override them
332    from a PConfig file/registry.
333   */
334 class PConfigArgs : public PArgList
335 {
336     PCLASSINFO(PConfigArgs, PArgList);
337   public:
338   /**@name Construction */
339   //@{
340     PConfigArgs(
341       const PArgList & args   ///< Raw argument list.
342     );
343   //@}
344 
345   /**@name Overrides from class PArgList */
346   //@{
347     /** Get the count of the number of times the option was specified on the
348        command line.
349 
350        @return option repeat count.
351      */
352     virtual PINDEX GetOptionCount(
353       char optionChar  ///< Character letter code for the option
354     ) const;
355     /** Get the count of option */
356     virtual PINDEX GetOptionCount(
357       const char * optionStr ///< String code for the option
358     ) const;
359     /** Get the count of option */
360     virtual PINDEX GetOptionCount(
361       const PString & optionName ///< String code for the option
362     ) const;
363 
364     /** Get option string.
365        Gets the string associated with an option e.g. -ofile or -o file
366        would return the string "file". An option may have an associated string
367        if it had a ':' character folowing it in the specification string passed
368        to the Parse() function.
369 
370        @return the options associated string.
371      */
372     virtual PString GetOptionString(
373       char optionChar,          ///< Character letter code for the option
374       const char * dflt = NULL  ///< Default value of the option string
375     ) const;
376 
377     /** Get option string. */
378     virtual PString GetOptionString(
379       const char * optionStr,   ///< String letter code for the option
380       const char * dflt = NULL  ///< Default value of the option string
381     ) const;
382 
383     /** Get option string. */
384     virtual PString GetOptionString(
385       const PString & optionName, ///< String code for the option
386       const char * dflt = NULL    ///< Default value of the option string
387     ) const;
388   //@}
389 
390   /**@name Overrides from class PArgList */
391   //@{
392     /**Save the current options to the PConfig.
393        This function will check to see if the option name is present and if
394        so, save to the PConfig all of the arguments present in the currently
395        parsed list. Note that the optionName for saving is not saved to the
396        PConfig itself as this would cause the data to be saved always!
397       */
398     void Save(
399       const PString & optionName   ///< Option name for saving.
400     );
401 
402     /**Set the PConfig section name for options.
403       */
SetSectionName(const PString & section)404     void SetSectionName(
405       const PString & section ///< New section name
406     ) { sectionName = section; }
407 
408     /**Get the PConfig section name for options.
409       */
GetSectionName()410     const PString & GetSectionName() const { return sectionName; }
411 
412     /**Set the prefix for option negation.
413        The default is "no-".
414       */
SetNegationPrefix(const PString & prefix)415     void SetNegationPrefix(
416       const PString & prefix ///< New prefix string
417     ) { negationPrefix = prefix; }
418 
419     /**Get the prefix for option negation.
420        The default is "no-".
421       */
GetNegationPrefix()422     const PString & GetNegationPrefix() const { return negationPrefix; }
423   //@}
424 
425 
426   protected:
427     PString CharToString(char ch) const;
428     PConfig config;
429     PString sectionName;
430     PString negationPrefix;
431 };
432 
433 #endif // P_CONFIG_FILE
434 
435 
436 #endif // PTLIB_ARGLIST_H
437 
438 
439 // End Of File ///////////////////////////////////////////////////////////////
440