home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / Console / Getopt.php
PHP Script  |  2001-03-12  |  8KB  |  203 lines

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  4. // +----------------------------------------------------------------------+
  5. // | PHP version 4.0                                                      |
  6. // +----------------------------------------------------------------------+
  7. // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
  8. // +----------------------------------------------------------------------+
  9. // | This source file is subject to version 2.0 of the PHP license,       |
  10. // | that is bundled with this package in the file LICENSE, and is        |
  11. // | available at through the world-wide-web at                           |
  12. // | http://www.php.net/license/2_02.txt.                                 |
  13. // | If you did not receive a copy of the PHP license and are unable to   |
  14. // | obtain it through the world-wide-web, please send a note to          |
  15. // | license@php.net so we can mail you a copy immediately.               |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: Andrei Zmievski <andrei@ispi.net>                           |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Getopt.php,v 1.2 2001/03/12 03:05:04 andrei Exp $
  21.  
  22. require_once 'PEAR.php';
  23.  
  24. /**
  25.  * Command-line options parsing class.
  26.  *
  27.  * @author Andrei Zmievski <andrei@ispi.net>
  28.  *
  29.  */
  30. class Console_Getopt {
  31.     /**
  32.      * Parses the command-line options.
  33.      *
  34.      * The first parameter to this function should be the list of command-line
  35.      * arguments without the leading reference to the running program.
  36.      *
  37.      * The second parameter is a string of allowed short options. Each of the
  38.      * option letters can be followed by a colon ':' to specify that the option
  39.      * requires an argument, or a double colon '::' to specify that the option
  40.      * takes an optional argument.
  41.      *
  42.      * The third argument is an optional array of allowed long options. The
  43.      * leading '--' should not be included in the option name. Options that
  44.      * require an argument should be followed by '=', and options that take an
  45.      * option argument should be followed by '=='.
  46.      *
  47.      * The return value is an array of two elements: the list of parsed
  48.      * options and the list of non-option command-line arguments. Each entry in
  49.      * the list of parsed options is a pair of elements - the first one
  50.      * specifies the option, and the second one specifies the option argument,
  51.      * if there was one.
  52.      *
  53.      * Long and short options can be mixed.
  54.      *
  55.      * Most of the semantics of this function are based on GNU getopt_long().
  56.      * 
  57.      * @param $args array an array of command-line arguments
  58.      * @param $short_options string specifies the list of allowed short options
  59.      * @param $long_options array specifies the list of allowed long options
  60.      *
  61.      * @return array two-element array containing the list of parsed options and
  62.      * the non-option arguments
  63.      *
  64.      * @access public
  65.      *
  66.      */
  67.     function getopt($args, $short_options, $long_options = null)
  68.     {
  69.         $opts     = array();
  70.         $non_opts = array();
  71.  
  72.         settype($args, 'array');
  73.  
  74.         if ($long_options)
  75.             sort($long_options);
  76.  
  77.         reset($args);
  78.         while (list(, $arg) = each($args)) {
  79.  
  80.             /* The special element '--' means explicit end of options. Treat the
  81.                rest of the arguments as non-options and end the loop. */
  82.             if ($arg == '--') {
  83.                 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
  84.                 break;
  85.             }
  86.  
  87.             if ($arg{0} != '-' || ($arg{1} == '-' && !$long_options)) {
  88.                 $non_opts[] = $arg;
  89.             } else if ($arg{1} == '-') {
  90.                 $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
  91.                 if (PEAR::isError($error))
  92.                     return $error;
  93.             } else {
  94.                 $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
  95.                 if (PEAR::isError($error))
  96.                     return $error;
  97.             }
  98.         }
  99.  
  100.         return array($opts, $non_opts);
  101.     }
  102.  
  103.     /**
  104.      * @access private
  105.      *
  106.      */
  107.     function _parseShortOption($arg, $short_options, &$opts, &$args)
  108.     {
  109.         for ($i = 0; $i < strlen($arg); $i++) {
  110.             $opt = $arg{$i};
  111.             $opt_arg = null;
  112.  
  113.             /* Try to find the short option in the specifier string. */
  114.             if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
  115.             {
  116.                 return new Getopt_Error("unrecognized option -- $opt\n");
  117.             }
  118.  
  119.             if ($spec{1} == ':') {
  120.                 if ($spec{2} == ':') {
  121.                     if ($i + 1 < strlen($arg)) {
  122.                         /* Option takes an optional argument. Use the remainder of
  123.                            the arg string if there is anything left. */
  124.                         $opts[] = array($opt, substr($arg, $i + 1));
  125.                         break;
  126.                     }
  127.                 } else {
  128.                     /* Option requires an argument. Use the remainder of the arg
  129.                        string if there is anything left. */
  130.                     if ($i + 1 < strlen($arg)) {
  131.                         $opts[] = array($opt,  substr($arg, $i + 1));
  132.                         break;
  133.                     } else if (list(, $opt_arg) = each($args))
  134.                         /* Else use the next argument. */;
  135.                     else
  136.                         return new Getopt_Error("option requires an argument -- $opt\n");
  137.                 }
  138.             }
  139.  
  140.             $opts[] = array($opt, $opt_arg);
  141.         }
  142.     }
  143.  
  144.     /**
  145.      * @access private
  146.      *
  147.      */
  148.     function _parseLongOption($arg, $long_options, &$opts, &$args)
  149.     {
  150.         list($opt, $opt_arg) = explode('=', $arg);
  151.         $opt_len = strlen($opt);
  152.  
  153.         for ($i = 0; $i < count($long_options); $i++) {
  154.             $long_opt  = $long_options[$i];
  155.             $opt_start = substr($long_opt, 0, $opt_len);
  156.             
  157.             /* Option doesn't match. Go on to the next one. */
  158.             if ($opt_start != $opt)
  159.                 continue;
  160.  
  161.             $opt_rest  = substr($long_opt, $opt_len);
  162.  
  163.             /* Check that the options uniquely matches one of the allowed
  164.                options. */
  165.             if ($opt_rest != '' && $opt{0} != '=' &&
  166.                 $i + 1 < count($long_options) &&
  167.                 $opt == substr($long_options[$i+1], 0, $opt_len)) {
  168.                 return new Getopt_Error("option --$opt is ambiguous\n");
  169.             }
  170.  
  171.             if (substr($long_opt, -1) == '=') {
  172.                 if (substr($long_opt, -2) != '==') {
  173.                     /* Long option requires an argument.
  174.                        Take the next argument if one wasn't specified. */;
  175.                     if (!$opt_arg && !(list(, $opt_arg) = each($args))) {
  176.                         return new Getopt_Error("option --$opt requires an argument\n");
  177.                     }
  178.                 }
  179.             } else if ($opt_arg) {
  180.                 return new Getopt_Error("option --$opt doesn't allow an argument\n");
  181.             }
  182.  
  183.             $opts[] = array('--' . substr($long_opt, 0, strpos($long_opt, '=')), $opt_arg);
  184.             return;
  185.         }
  186.  
  187.         return new Getopt_Error("unrecognized option --$opt\n");
  188.     }
  189. }
  190.  
  191.  
  192. class Getopt_Error extends PEAR_Error {
  193.     var $classname             = 'Getopt';
  194.     var $error_message_prepend = 'Error in Getopt';
  195.  
  196.     function Getopt_Error($message, $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
  197.     {
  198.         $this->PEAR_Error($message, $code, $mode, $level);
  199.     }
  200. }
  201.  
  202. ?>
  203.