source: branches/version-2_13-dev/data/module/Console/Getopt.php @ 23125

Revision 23125, 10.7 KB checked in by kimoto, 11 years ago (diff)

#2275 PEAR更新
不要なrequire_onceの削除
レガシーなPEARモジュールは使わない
SearchReplace?.phpのパスが間違っているので修正

Line 
1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------+
4// | PHP Version 5                                                        |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1997-2004 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// +----------------------------------------------------------------------+
18//
19// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $
20
21require_once 'PEAR.php';
22
23/**
24 * Command-line options parsing class.
25 *
26 * @author Andrei Zmievski <andrei@php.net>
27 *
28 */
29class Console_Getopt {
30    /**
31     * Parses the command-line options.
32     *
33     * The first parameter to this function should be the list of command-line
34     * arguments without the leading reference to the running program.
35     *
36     * The second parameter is a string of allowed short options. Each of the
37     * option letters can be followed by a colon ':' to specify that the option
38     * requires an argument, or a double colon '::' to specify that the option
39     * takes an optional argument.
40     *
41     * The third argument is an optional array of allowed long options. The
42     * leading '--' should not be included in the option name. Options that
43     * require an argument should be followed by '=', and options that take an
44     * option argument should be followed by '=='.
45     *
46     * The return value is an array of two elements: the list of parsed
47     * options and the list of non-option command-line arguments. Each entry in
48     * the list of parsed options is a pair of elements - the first one
49     * specifies the option, and the second one specifies the option argument,
50     * if there was one.
51     *
52     * Long and short options can be mixed.
53     *
54     * Most of the semantics of this function are based on GNU getopt_long().
55     *
56     * @param array  $args           an array of command-line arguments
57     * @param string $short_options  specifies the list of allowed short options
58     * @param array  $long_options   specifies the list of allowed long options
59     *
60     * @return array two-element array containing the list of parsed options and
61     * the non-option arguments
62     *
63     * @access public
64     *
65     */
66    function getopt2($args, $short_options, $long_options = null)
67    {
68        return Console_Getopt::doGetopt(2, $args, $short_options, $long_options);
69    }
70
71    /**
72     * This function expects $args to start with the script name (POSIX-style).
73     * Preserved for backwards compatibility.
74     * @see getopt2()
75     */   
76    function getopt($args, $short_options, $long_options = null)
77    {
78        return Console_Getopt::doGetopt(1, $args, $short_options, $long_options);
79    }
80
81    /**
82     * The actual implementation of the argument parsing code.
83     */
84    function doGetopt($version, $args, $short_options, $long_options = null)
85    {
86        // in case you pass directly readPHPArgv() as the first arg
87        if (PEAR::isError($args)) {
88            return $args;
89        }
90        if (empty($args)) {
91            return array(array(), array());
92        }
93        $opts     = array();
94        $non_opts = array();
95
96        settype($args, 'array');
97
98        if ($long_options) {
99            sort($long_options);
100        }
101
102        /*
103         * Preserve backwards compatibility with callers that relied on
104         * erroneous POSIX fix.
105         */
106        if ($version < 2) {
107            if (isset($args[0]{0}) && $args[0]{0} != '-') {
108                array_shift($args);
109            }
110        }
111
112        reset($args);
113        while (list($i, $arg) = each($args)) {
114
115            /* The special element '--' means explicit end of
116               options. Treat the rest of the arguments as non-options
117               and end the loop. */
118            if ($arg == '--') {
119                $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
120                break;
121            }
122
123            if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
124                $non_opts = array_merge($non_opts, array_slice($args, $i));
125                break;
126            } elseif (strlen($arg) > 1 && $arg{1} == '-') {
127                $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
128                if (PEAR::isError($error))
129                    return $error;
130            } elseif ($arg == '-') {
131                // - is stdin
132                $non_opts = array_merge($non_opts, array_slice($args, $i));
133                break;
134            } else {
135                $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
136                if (PEAR::isError($error))
137                    return $error;
138            }
139        }
140
141        return array($opts, $non_opts);
142    }
143
144    /**
145     * @access private
146     *
147     */
148    function _parseShortOption($arg, $short_options, &$opts, &$args)
149    {
150        for ($i = 0; $i < strlen($arg); $i++) {
151            $opt = $arg{$i};
152            $opt_arg = null;
153
154            /* Try to find the short option in the specifier string. */
155            if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
156            {
157                return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt");
158            }
159
160            if (strlen($spec) > 1 && $spec{1} == ':') {
161                if (strlen($spec) > 2 && $spec{2} == ':') {
162                    if ($i + 1 < strlen($arg)) {
163                        /* Option takes an optional argument. Use the remainder of
164                           the arg string if there is anything left. */
165                        $opts[] = array($opt, substr($arg, $i + 1));
166                        break;
167                    }
168                } else {
169                    /* Option requires an argument. Use the remainder of the arg
170                       string if there is anything left. */
171                    if ($i + 1 < strlen($arg)) {
172                        $opts[] = array($opt,  substr($arg, $i + 1));
173                        break;
174                    } else if (list(, $opt_arg) = each($args)) {
175                        /* Else use the next argument. */;
176                        if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) {
177                            return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt");
178                        }
179                    } else {
180                        return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt");
181                    }
182                }
183            }
184
185            $opts[] = array($opt, $opt_arg);
186        }
187    }
188
189    /**
190     * @access private
191     *
192     */
193    function _isShortOpt($arg)
194    {
195        return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]);
196    }
197
198    /**
199     * @access private
200     *
201     */
202    function _isLongOpt($arg)
203    {
204        return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
205            preg_match('/[a-zA-Z]+$/', substr($arg, 2));
206    }
207
208    /**
209     * @access private
210     *
211     */
212    function _parseLongOption($arg, $long_options, &$opts, &$args)
213    {
214        @list($opt, $opt_arg) = explode('=', $arg, 2);
215        $opt_len = strlen($opt);
216
217        for ($i = 0; $i < count($long_options); $i++) {
218            $long_opt  = $long_options[$i];
219            $opt_start = substr($long_opt, 0, $opt_len);
220            $long_opt_name = str_replace('=', '', $long_opt);
221
222            /* Option doesn't match. Go on to the next one. */
223            if ($long_opt_name != $opt) {
224                continue;
225            }
226
227            $opt_rest  = substr($long_opt, $opt_len);
228
229            /* Check that the options uniquely matches one of the allowed
230               options. */
231            if ($i + 1 < count($long_options)) {
232                $next_option_rest = substr($long_options[$i + 1], $opt_len);
233            } else {
234                $next_option_rest = '';
235            }
236            if ($opt_rest != '' && $opt{0} != '=' &&
237                $i + 1 < count($long_options) &&
238                $opt == substr($long_options[$i+1], 0, $opt_len) &&
239                $next_option_rest != '' &&
240                $next_option_rest{0} != '=') {
241                return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous");
242            }
243
244            if (substr($long_opt, -1) == '=') {
245                if (substr($long_opt, -2) != '==') {
246                    /* Long option requires an argument.
247                       Take the next argument if one wasn't specified. */;
248                    if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
249                        return PEAR::raiseError("Console_Getopt: option --$opt requires an argument");
250                    }
251                    if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) {
252                        return PEAR::raiseError("Console_Getopt: option requires an argument --$opt");
253                    }
254                }
255            } else if ($opt_arg) {
256                return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument");
257            }
258
259            $opts[] = array('--' . $opt, $opt_arg);
260            return;
261        }
262
263        return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
264    }
265
266    /**
267    * Safely read the $argv PHP array across different PHP configurations.
268    * Will take care on register_globals and register_argc_argv ini directives
269    *
270    * @access public
271    * @return mixed the $argv PHP array or PEAR error if not registered
272    */
273    function readPHPArgv()
274    {
275        global $argv;
276        if (!is_array($argv)) {
277            if (!@is_array($_SERVER['argv'])) {
278                if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
279                    return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)");
280                }
281                return $GLOBALS['HTTP_SERVER_VARS']['argv'];
282            }
283            return $_SERVER['argv'];
284        }
285        return $argv;
286    }
287
288}
289
290?>
Note: See TracBrowser for help on using the repository browser.