[ Index ]

PHP Cross Reference of phool

title

Body

[close]

/Phool/Options/ -> Getopt.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4: */
   3  // +----------------------------------------------------------------------+
   4  // | PHP Version 5                                                        |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997-2003 The PHP Group                                |
   7  // +----------------------------------------------------------------------+
   8  // | This source file is subject to version 3.0 of the PHP license,       |
   9  // | that is bundled with this package in the file LICENSE, and is        |
  10  // | available through the world-wide-web at the following url:           |
  11  // | http://www.php.net/license/3_0.txt.                                  |
  12  // | If you did not receive a copy of the PHP license and are unable to   |
  13  // | obtain it through the world-wide-web, please send a note to          |
  14  // | license@php.net so we can mail you a copy immediately.               |
  15  // +----------------------------------------------------------------------+
  16  // | Author: Andrei Zmievski <andrei@php.net>                             |
  17  // | Modified by Francois Laupretre <francois@tekwire.net>                |
  18  // +----------------------------------------------------------------------+
  19  /**
  20  * @copyright Francois Laupretre <phool@tekwire.net>
  21  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0
  22  * @category phool
  23  * @package phool
  24  */
  25  //============================================================================
  26  
  27  //-------------------------------------------------------------------------
  28  // Changes from original version: see class description
  29  //-------------------------------------------------------------------------
  30  
  31  namespace Phool\Options;
  32  
  33  /**
  34   * Command-line options parsing class.
  35   *
  36   * @author Andrei Zmievski <andrei@php.net>
  37   *
  38   */
  39  class Getopt {
  40      /**
  41       * Parses the command-line options.
  42       *
  43       * The first parameter to this function should be the list of command-line
  44       * arguments without the leading reference to the running program.
  45       *
  46       * The second parameter is a string of allowed short options. Each of the
  47       * option letters can be followed by a colon ':' to specify that the option
  48       * requires an argument, or a double colon '::' to specify that the option
  49       * takes an optional argument.
  50       *
  51       * The third argument is an optional array of allowed long options. The
  52       * leading '--' should not be included in the option name. Options that
  53       * require an argument should be followed by '=', and options that take an
  54       * option argument should be followed by '=='.
  55       *
  56       * The return value is an array of two elements: the list of parsed
  57       * options and the list of non-option command-line arguments. Each entry in
  58       * the list of parsed options is a pair of elements - the first one
  59       * specifies the option, and the second one specifies the option argument,
  60       * if there was one.
  61       *
  62       * Long and short options can be mixed.
  63       *
  64       * Most of the semantics of this function are based on GNU getopt_long().
  65       *
  66       * Changes from original version:
  67       *        - switch to PHP 5 object syntax
  68       *        - make independant from PEAR error handling using exceptions
  69       *
  70       * @param array  $args           an array of command-line arguments
  71       * @param string $short_options  specifies the list of allowed short options
  72       * @param array  $long_options   specifies the list of allowed long options
  73       *
  74       * @return array two-element array containing the list of parsed options and
  75       * the non-option arguments
  76       *
  77       * @throws Exception
  78       *
  79       */
  80      public static function getopt2($args, $short_options, $long_options = null)
  81      {
  82          return self::doGetopt(2, $args, $short_options, $long_options);
  83      }
  84  
  85      /**
  86       * This function expects $args to start with the script name (POSIX-style).
  87       * Preserved for backwards compatibility.
  88       * @see getopt2()
  89       */    
  90      public static function getopt($args, $short_options, $long_options = null)
  91      {
  92          return self::doGetopt(1, $args, $short_options, $long_options);
  93      }
  94  
  95      /**
  96       * The actual implementation of the argument parsing code.
  97       */
  98      private static function doGetopt($version, $args, $short_options, $long_options = null)
  99      {
 100          if (empty($args)) {
 101              return array(array(), array());
 102          }
 103          $opts     = array();
 104          $non_opts = array();
 105  
 106          settype($args, 'array');
 107  
 108          if ($long_options) {
 109              sort($long_options);
 110          }
 111  
 112          /*
 113           * Preserve backwards compatibility with callers that relied on
 114           * erroneous POSIX fix.
 115           */
 116          if ($version < 2) {
 117              if (isset($args[0]{0}) && $args[0]{0} != '-') {
 118                  array_shift($args);
 119              }
 120          }
 121  
 122          reset($args);
 123          while (list($i, $arg) = each($args)) {
 124  
 125              /* The special element '--' means explicit end of
 126                 options. Treat the rest of the arguments as non-options
 127                 and end the loop. */
 128              if ($arg == '--') {
 129                  $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
 130                  break;
 131              }
 132  
 133              if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
 134                  $non_opts = array_merge($non_opts, array_slice($args, $i));
 135                  break;
 136              } elseif (strlen($arg) > 1 && $arg{1} == '-') {
 137                  self::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
 138              } else {
 139                  self::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
 140              }
 141          }
 142  
 143          return array($opts, $non_opts);
 144      }
 145  
 146      private static function _parseShortOption($arg, $short_options, &$opts, &$args)
 147      {
 148          for ($i = 0; $i < strlen($arg); $i++) {
 149              $opt = $arg{$i};
 150              $opt_arg = null;
 151  
 152              /* Try to find the short option in the specifier string. */
 153              if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
 154              {
 155                  throw new \Exception(__CLASS__.": unrecognized option -- $opt");
 156              }
 157  
 158              if (strlen($spec) > 1 && $spec{1} == ':') {
 159                  if (strlen($spec) > 2 && $spec{2} == ':') {
 160                      if ($i + 1 < strlen($arg)) {
 161                          /* Option takes an optional argument. Use the remainder of
 162                             the arg string if there is anything left. */
 163                          $opts[] = array($opt, substr($arg, $i + 1));
 164                          break;
 165                      }
 166                  } else {
 167                      /* Option requires an argument. Use the remainder of the arg
 168                         string if there is anything left. */
 169                      if ($i + 1 < strlen($arg)) {
 170                          $opts[] = array($opt,  substr($arg, $i + 1));
 171                          break;
 172                      } else if (list(, $opt_arg) = each($args))
 173                          /* Else use the next argument. */;
 174                      else
 175                          throw new \Exception(__CLASS__.": option requires an argument -- $opt");
 176                  }
 177              }
 178  
 179              $opts[] = array($opt, $opt_arg);
 180          }
 181      }
 182  
 183      private static function _parseLongOption($arg, $long_options, &$opts, &$args)
 184      {
 185          @list($opt, $opt_arg) = explode('=', $arg);
 186          $opt_len = strlen($opt);
 187  
 188          for ($i = 0; $i < count($long_options); $i++) {
 189              $long_opt  = $long_options[$i];
 190              $opt_start = substr($long_opt, 0, $opt_len);
 191  
 192              /* Option doesn't match. Go on to the next one. */
 193              if ($opt_start != $opt)
 194                  continue;
 195  
 196              $opt_rest  = substr($long_opt, $opt_len);
 197  
 198              /* Check that the options uniquely matches one of the allowed
 199                 options. */
 200              if ($opt_rest != '' && $opt{0} != '=' &&
 201                  $i + 1 < count($long_options) &&
 202                  $opt == substr($long_options[$i+1], 0, $opt_len)) {
 203                  throw new \Exception(__CLASS__.": option --$opt is ambiguous");
 204              }
 205  
 206              if (substr($long_opt, -1) == '=') {
 207                  if (substr($long_opt, -2) != '==') {
 208                      /* Long option requires an argument.
 209                         Take the next argument if one wasn't specified. */;
 210                      if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
 211                          throw new \Exception(__CLASS__.": option --$opt requires an argument");
 212                      }
 213                  }
 214              } else if ($opt_arg) {
 215                  throw new \Exception(__CLASS__.": option --$opt doesn't allow an argument");
 216              }
 217  
 218              $opts[] = array('--' . $opt, $opt_arg);
 219              return;
 220          }
 221  
 222          throw new \Exception(__CLASS__.": unrecognized option --$opt");
 223      }
 224  
 225      /**
 226      * Safely read the $argv PHP array across different PHP configurations.
 227      * Will take care on register_globals and register_argc_argv ini directives
 228      *
 229      * @return array the $argv PHP array
 230      * @throws Exception if not registered
 231      */
 232      public static function readPHPArgv()
 233      {
 234          global $argv;
 235          if (!is_array($argv)) {
 236              if (!@is_array($_SERVER['argv'])) {
 237                  if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
 238                      throw new \Exception(__CLASS__.": Could not read cmd args (register_argc_argv=Off?)");
 239                  }
 240                  return $GLOBALS['HTTP_SERVER_VARS']['argv'];
 241              }
 242              return $_SERVER['argv'];
 243          }
 244          return $argv;
 245      }
 246  
 247  }
 248  
 249  ?>


Generated: Thu Jun 4 19:17:11 2015 Cross-referenced by PHPXref 0.7.1