LCOV - code coverage report
Current view: directory - js/src/shell - jsoptparse.h (source / functions) Found Hit Coverage
Test: app.info Lines: 52 44 84.6 %
Date: 2012-06-02 Functions: 37 27 73.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is SpiderMonkey JavaScript shell.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Mozilla Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Christopher D. Leary <cdleary@mozilla.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #ifndef jsoptparse_h__
      42                 : #define jsoptparse_h__
      43                 : 
      44                 : #include <stdio.h>
      45                 : 
      46                 : #include "js/Vector.h"
      47                 : #include "jsalloc.h"
      48                 : 
      49                 : namespace js {
      50                 : namespace cli {
      51                 : 
      52                 : namespace detail {
      53                 : 
      54                 : struct BoolOption;
      55                 : struct MultiStringOption;
      56                 : struct ValuedOption;
      57                 : struct StringOption;
      58                 : struct IntOption;
      59                 : 
      60                 : enum OptionKind
      61                 : {
      62                 :     OptionKindBool,
      63                 :     OptionKindString,
      64                 :     OptionKindInt,
      65                 :     OptionKindMultiString,
      66                 :     OptionKindInvalid
      67                 : };
      68                 : 
      69                 : struct Option
      70                 : {
      71                 :     const char  *longflag;
      72                 :     const char  *help;
      73                 :     OptionKind  kind;
      74                 :     char        shortflag;
      75                 :     bool        terminatesOptions;
      76                 : 
      77          312885 :     Option(OptionKind kind, char shortflag, const char *longflag, const char *help)
      78          312885 :       : longflag(longflag), help(help), kind(kind), shortflag(shortflag), terminatesOptions(false)
      79          312885 :     {}
      80                 : 
      81                 :     virtual ~Option() = 0;
      82                 : 
      83           18405 :     void setTerminatesOptions(bool enabled) { terminatesOptions = enabled; }
      84           94584 :     bool getTerminatesOptions() const { return terminatesOptions; }
      85                 : 
      86               0 :     virtual bool isValued() const { return false; }
      87                 : 
      88                 :     /* Only some valued options are variadic (like MultiStringOptions). */
      89           18405 :     virtual bool isVariadic() const { return false; }
      90                 : 
      91                 :     /* 
      92                 :      * For arguments, the shortflag field is used to indicate whether the
      93                 :      * argument is optional.
      94                 :      */
      95                 :     bool isOptional() { return shortflag; }
      96                 : 
      97               0 :     void setFlagInfo(char shortflag, const char *longflag, const char *help) {
      98               0 :         this->shortflag = shortflag;
      99               0 :         this->longflag = longflag;
     100               0 :         this->help = help;
     101               0 :     }
     102                 : 
     103                 :     ValuedOption *asValued();
     104                 :     const ValuedOption *asValued() const;
     105                 : 
     106                 : #define OPTION_CONVERT_DECL(__cls) \
     107                 :     bool is##__cls##Option() const; \
     108                 :     __cls##Option *as##__cls##Option(); \
     109                 :     const __cls##Option *as##__cls##Option() const;
     110                 : 
     111                 :     OPTION_CONVERT_DECL(Bool)
     112                 :     OPTION_CONVERT_DECL(String)
     113                 :     OPTION_CONVERT_DECL(Int)
     114                 :     OPTION_CONVERT_DECL(MultiString)
     115                 : };
     116                 : 
     117          312885 : inline Option::~Option() {}
     118                 : 
     119                 : struct BoolOption : public Option
     120                 : {
     121                 :     size_t  argno;
     122                 :     bool    value;
     123                 : 
     124          202455 :     BoolOption(char shortflag, const char *longflag, const char *help)
     125          202455 :       : Option(OptionKindBool, shortflag, longflag, help), value(false)
     126          202455 :     {}
     127                 : 
     128          202455 :     virtual ~BoolOption() {}
     129                 : };
     130                 : 
     131                 : struct ValuedOption : public Option
     132                 : {
     133                 :     const char *metavar;
     134                 : 
     135          110430 :     ValuedOption(OptionKind kind, char shortflag, const char *longflag, const char *help,
     136                 :                  const char *metavar)
     137          110430 :       : Option(kind, shortflag, longflag, help), metavar(metavar)
     138          110430 :     {}
     139                 : 
     140                 :     virtual ~ValuedOption() = 0;
     141               0 :     virtual bool isValued() const { return true; }
     142                 : };
     143                 : 
     144          110430 : inline ValuedOption::~ValuedOption() {}
     145                 : 
     146                 : struct StringOption : public ValuedOption
     147                 : {
     148                 :     const char *value;
     149                 : 
     150           36810 :     StringOption(char shortflag, const char *longflag, const char *help, const char *metavar)
     151           36810 :       : ValuedOption(OptionKindString, shortflag, longflag, help, metavar), value(NULL)
     152           36810 :     {}
     153                 : 
     154           36810 :     virtual ~StringOption() {}
     155                 : };
     156                 : 
     157                 : struct IntOption : public ValuedOption
     158                 : {
     159                 :     int value;
     160                 : 
     161           18405 :     IntOption(char shortflag, const char *longflag, const char *help, const char *metavar,
     162                 :               int defaultValue)
     163           18405 :       : ValuedOption(OptionKindInt, shortflag, longflag, help, metavar), value(defaultValue)
     164           18405 :     {}
     165                 : 
     166           18405 :     virtual ~IntOption() {}
     167                 : };
     168                 : 
     169                 : struct StringArg
     170           73620 : {
     171                 :     char    *value;
     172                 :     size_t  argno;
     173                 : 
     174           55215 :     StringArg(char *value, size_t argno) : value(value), argno(argno) {}
     175                 : };
     176                 : 
     177                 : struct MultiStringOption : public ValuedOption
     178                 : {
     179                 :     Vector<StringArg, 0, SystemAllocPolicy> strings;
     180                 : 
     181           55215 :     MultiStringOption(char shortflag, const char *longflag, const char *help, const char *metavar)
     182           55215 :       : ValuedOption(OptionKindMultiString, shortflag, longflag, help, metavar)
     183           55215 :     {}
     184                 : 
     185           55215 :     virtual ~MultiStringOption() {}
     186                 : 
     187               0 :     virtual bool isVariadic() const { return true; }
     188                 : };
     189                 : 
     190                 : } /* namespace detail */
     191                 : 
     192                 : class MultiStringRange
     193                 : {
     194                 :     typedef detail::StringArg StringArg;
     195                 :     const StringArg *cur;
     196                 :     const StringArg *end;
     197                 : 
     198                 :   public:
     199           55215 :     explicit MultiStringRange(const StringArg *cur, const StringArg *end)
     200           55215 :       : cur(cur), end(end) {
     201           55215 :         JS_ASSERT(end - cur >= 0);
     202           55215 :     }
     203                 : 
     204          420804 :     bool empty() const { return cur == end; }
     205           54378 :     void popFront() { JS_ASSERT(!empty()); ++cur; }
     206           55215 :     char *front() const { JS_ASSERT(!empty()); return cur->value; }
     207           73620 :     size_t argno() const { JS_ASSERT(!empty()); return cur->argno; }
     208                 : };
     209                 : 
     210                 : /* 
     211                 :  * Builder for describing a command line interface and parsing the resulting
     212                 :  * specification.
     213                 :  *
     214                 :  * - A multi-option is an option that can appear multiple times and still
     215                 :  *   parse as valid command line arguments.
     216                 :  * - An "optional argument" is supported for backwards compatibility with prior
     217                 :  *   command line interface usage. Once one optional argument has been added,
     218                 :  *   *only* optional arguments may be added.
     219                 :  */
     220                 : class OptionParser
     221                 : {
     222                 :   public:
     223                 :     enum Result
     224                 :     {
     225                 :         Okay = 0,
     226                 :         Fail,       /* As in, allocation fail. */
     227                 :         ParseError, /* Successfully parsed but with an error. */
     228                 :         ParseHelp   /* Aborted on help flag. */
     229                 :     };
     230                 : 
     231                 :   private:
     232                 :     typedef Vector<detail::Option *, 0, SystemAllocPolicy> Options;
     233                 :     typedef detail::Option Option;
     234                 :     typedef detail::BoolOption BoolOption;
     235                 : 
     236                 :     Options     options;
     237                 :     Options     arguments;
     238                 :     BoolOption  helpOption;
     239                 :     const char  *usage;
     240                 :     const char  *ver;
     241                 :     const char  *descr;
     242                 :     size_t      descrWidth;
     243                 :     size_t      helpWidth;
     244                 :     size_t      nextArgument;
     245                 : 
     246                 :     static const char prognameMeta[];
     247                 : 
     248                 :     Option *findOption(char shortflag);
     249                 :     const Option *findOption(char shortflag) const;
     250                 :     Option *findOption(const char *longflag);
     251                 :     const Option *findOption(const char *longflag) const;
     252                 :     Option *findArgument(const char *name);
     253                 :     const Option *findArgument(const char *name) const;
     254                 : 
     255                 :     Result error(const char *fmt, ...);
     256                 :     Result extractValue(size_t argc, char **argv, size_t *i, char **value);
     257                 :     Result handleArg(size_t argc, char **argv, size_t *i, bool *optsAllowed);
     258                 :     Result handleOption(Option *opt, size_t argc, char **argv, size_t *i, bool *optsAllowed);
     259                 : 
     260                 :   public:
     261           18405 :     explicit OptionParser(const char *usage)
     262                 :       : helpOption('h', "help", "Display help information"),
     263           18405 :         usage(usage), ver(NULL), descr(NULL), descrWidth(80), helpWidth(80), nextArgument(0)
     264           18405 :     {}
     265                 : 
     266                 :     ~OptionParser();
     267                 : 
     268                 :     Result parseArgs(int argc, char **argv);
     269                 :     Result printHelp(const char *progname);
     270                 : 
     271                 :     /* Metadata */
     272                 : 
     273           18405 :     void setVersion(const char *version) { ver = version; }
     274           18405 :     void setHelpWidth(size_t width) { helpWidth = width; }
     275           18405 :     void setDescriptionWidth(size_t width) { descrWidth = width; }
     276           18405 :     void setDescription(const char *description) { descr = description; }
     277                 :     void setHelpOption(char shortflag, const char *longflag, const char *help);
     278                 :     void setArgTerminatesOptions(const char *name, bool enabled);
     279                 : 
     280                 :     /* Arguments: no further arguments may be added after a variadic argument. */
     281                 : 
     282                 :     bool addOptionalStringArg(const char *name, const char *help);
     283                 :     bool addOptionalMultiStringArg(const char *name, const char *help);
     284                 : 
     285                 :     const char *getStringArg(const char *name) const;
     286                 :     MultiStringRange getMultiStringArg(const char *name) const;
     287                 : 
     288                 :     /* Options */
     289                 : 
     290                 :     bool addBoolOption(char shortflag, const char *longflag, const char *help);
     291                 :     bool addStringOption(char shortflag, const char *longflag, const char *help,
     292                 :                          const char *metavar);
     293                 :     bool addIntOption(char shortflag, const char *longflag, const char *help,
     294                 :                       const char *metavar, int defaultValue);
     295                 :     bool addMultiStringOption(char shortflag, const char *longflag, const char *help,
     296                 :                               const char *metavar);
     297                 :     bool addOptionalVariadicArg(const char *name);
     298                 : 
     299                 :     int getIntOption(char shortflag) const;
     300                 :     int getIntOption(const char *longflag) const;
     301                 :     const char *getStringOption(char shortflag) const;
     302                 :     const char *getStringOption(const char *longflag) const;
     303                 :     bool getBoolOption(char shortflag) const;
     304                 :     bool getBoolOption(const char *longflag) const;
     305                 :     MultiStringRange getMultiStringOption(char shortflag) const;
     306                 :     MultiStringRange getMultiStringOption(const char *longflag) const;
     307                 : 
     308                 :     /* 
     309                 :      * Return whether the help option was present (and thus help was already
     310                 :      * displayed during parse_args).
     311                 :      */
     312                 :     bool getHelpOption() const;
     313                 : };
     314                 : 
     315                 : } /* namespace cli */
     316                 : } /* namespace js */
     317                 : 
     318                 : #endif /* jsoptparse_h__ */

Generated by: LCOV version 1.7