comparison vendor/pear/console_getopt/Console/Getopt.php @ 0:1e000243b222

vanilla 1.3.3 distro, I hope
author Charlie Root
date Thu, 04 Jan 2018 15:50:29 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e000243b222
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 * @category Console
17 * @package Console_Getopt
18 * @author Andrei Zmievski <andrei@php.net>
19 * @license http://www.php.net/license/3_0.txt PHP 3.0
20 * @version CVS: $Id$
21 * @link http://pear.php.net/package/Console_Getopt
22 */
23
24 require_once 'PEAR.php';
25
26 /**
27 * Command-line options parsing class.
28 *
29 * @category Console
30 * @package Console_Getopt
31 * @author Andrei Zmievski <andrei@php.net>
32 * @license http://www.php.net/license/3_0.txt PHP 3.0
33 * @link http://pear.php.net/package/Console_Getopt
34 */
35 class Console_Getopt
36 {
37
38 /**
39 * Parses the command-line options.
40 *
41 * The first parameter to this function should be the list of command-line
42 * arguments without the leading reference to the running program.
43 *
44 * The second parameter is a string of allowed short options. Each of the
45 * option letters can be followed by a colon ':' to specify that the option
46 * requires an argument, or a double colon '::' to specify that the option
47 * takes an optional argument.
48 *
49 * The third argument is an optional array of allowed long options. The
50 * leading '--' should not be included in the option name. Options that
51 * require an argument should be followed by '=', and options that take an
52 * option argument should be followed by '=='.
53 *
54 * The return value is an array of two elements: the list of parsed
55 * options and the list of non-option command-line arguments. Each entry in
56 * the list of parsed options is a pair of elements - the first one
57 * specifies the option, and the second one specifies the option argument,
58 * if there was one.
59 *
60 * Long and short options can be mixed.
61 *
62 * Most of the semantics of this function are based on GNU getopt_long().
63 *
64 * @param array $args an array of command-line arguments
65 * @param string $short_options specifies the list of allowed short options
66 * @param array $long_options specifies the list of allowed long options
67 * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
68 *
69 * @return array two-element array containing the list of parsed options and
70 * the non-option arguments
71 */
72 public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
73 {
74 return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
75 }
76
77 /**
78 * This function expects $args to start with the script name (POSIX-style).
79 * Preserved for backwards compatibility.
80 *
81 * @param array $args an array of command-line arguments
82 * @param string $short_options specifies the list of allowed short options
83 * @param array $long_options specifies the list of allowed long options
84 *
85 * @see getopt2()
86 * @return array two-element array containing the list of parsed options and
87 * the non-option arguments
88 */
89 public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
90 {
91 return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
92 }
93
94 /**
95 * The actual implementation of the argument parsing code.
96 *
97 * @param int $version Version to use
98 * @param array $args an array of command-line arguments
99 * @param string $short_options specifies the list of allowed short options
100 * @param array $long_options specifies the list of allowed long options
101 * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
102 *
103 * @return array
104 */
105 public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
106 {
107 // in case you pass directly readPHPArgv() as the first arg
108 if (PEAR::isError($args)) {
109 return $args;
110 }
111
112 if (empty($args)) {
113 return array(array(), array());
114 }
115
116 $non_opts = $opts = array();
117
118 settype($args, 'array');
119
120 if ($long_options) {
121 sort($long_options);
122 }
123
124 /*
125 * Preserve backwards compatibility with callers that relied on
126 * erroneous POSIX fix.
127 */
128 if ($version < 2) {
129 if (isset($args[0]{0}) && $args[0]{0} != '-') {
130 array_shift($args);
131 }
132 }
133
134 reset($args);
135 while (list($i, $arg) = each($args)) {
136 /* The special element '--' means explicit end of
137 options. Treat the rest of the arguments as non-options
138 and end the loop. */
139 if ($arg == '--') {
140 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
141 break;
142 }
143
144 if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
145 $non_opts = array_merge($non_opts, array_slice($args, $i));
146 break;
147 } elseif (strlen($arg) > 1 && $arg{1} == '-') {
148 $error = Console_Getopt::_parseLongOption(substr($arg, 2),
149 $long_options,
150 $opts,
151 $args,
152 $skip_unknown);
153 if (PEAR::isError($error)) {
154 return $error;
155 }
156 } elseif ($arg == '-') {
157 // - is stdin
158 $non_opts = array_merge($non_opts, array_slice($args, $i));
159 break;
160 } else {
161 $error = Console_Getopt::_parseShortOption(substr($arg, 1),
162 $short_options,
163 $opts,
164 $args,
165 $skip_unknown);
166 if (PEAR::isError($error)) {
167 return $error;
168 }
169 }
170 }
171
172 return array($opts, $non_opts);
173 }
174
175 /**
176 * Parse short option
177 *
178 * @param string $arg Argument
179 * @param string[] $short_options Available short options
180 * @param string[][] &$opts
181 * @param string[] &$args
182 * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
183 *
184 * @return void
185 */
186 protected static function _parseShortOption($arg, $short_options, &$opts, &$args, $skip_unknown)
187 {
188 for ($i = 0; $i < strlen($arg); $i++) {
189 $opt = $arg{$i};
190 $opt_arg = null;
191
192 /* Try to find the short option in the specifier string. */
193 if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') {
194 if ($skip_unknown === true) {
195 break;
196 }
197
198 $msg = "Console_Getopt: unrecognized option -- $opt";
199 return PEAR::raiseError($msg);
200 }
201
202 if (strlen($spec) > 1 && $spec{1} == ':') {
203 if (strlen($spec) > 2 && $spec{2} == ':') {
204 if ($i + 1 < strlen($arg)) {
205 /* Option takes an optional argument. Use the remainder of
206 the arg string if there is anything left. */
207 $opts[] = array($opt, substr($arg, $i + 1));
208 break;
209 }
210 } else {
211 /* Option requires an argument. Use the remainder of the arg
212 string if there is anything left. */
213 if ($i + 1 < strlen($arg)) {
214 $opts[] = array($opt, substr($arg, $i + 1));
215 break;
216 } else if (list(, $opt_arg) = each($args)) {
217 /* Else use the next argument. */;
218 if (Console_Getopt::_isShortOpt($opt_arg)
219 || Console_Getopt::_isLongOpt($opt_arg)) {
220 $msg = "option requires an argument --$opt";
221 return PEAR::raiseError("Console_Getopt: " . $msg);
222 }
223 } else {
224 $msg = "option requires an argument --$opt";
225 return PEAR::raiseError("Console_Getopt: " . $msg);
226 }
227 }
228 }
229
230 $opts[] = array($opt, $opt_arg);
231 }
232 }
233
234 /**
235 * Checks if an argument is a short option
236 *
237 * @param string $arg Argument to check
238 *
239 * @return bool
240 */
241 protected static function _isShortOpt($arg)
242 {
243 return strlen($arg) == 2 && $arg[0] == '-'
244 && preg_match('/[a-zA-Z]/', $arg[1]);
245 }
246
247 /**
248 * Checks if an argument is a long option
249 *
250 * @param string $arg Argument to check
251 *
252 * @return bool
253 */
254 protected static function _isLongOpt($arg)
255 {
256 return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
257 preg_match('/[a-zA-Z]+$/', substr($arg, 2));
258 }
259
260 /**
261 * Parse long option
262 *
263 * @param string $arg Argument
264 * @param string[] $long_options Available long options
265 * @param string[][] &$opts
266 * @param string[] &$args
267 *
268 * @return void|PEAR_Error
269 */
270 protected static function _parseLongOption($arg, $long_options, &$opts, &$args, $skip_unknown)
271 {
272 @list($opt, $opt_arg) = explode('=', $arg, 2);
273
274 $opt_len = strlen($opt);
275
276 for ($i = 0; $i < count($long_options); $i++) {
277 $long_opt = $long_options[$i];
278 $opt_start = substr($long_opt, 0, $opt_len);
279
280 $long_opt_name = str_replace('=', '', $long_opt);
281
282 /* Option doesn't match. Go on to the next one. */
283 if ($long_opt_name != $opt) {
284 continue;
285 }
286
287 $opt_rest = substr($long_opt, $opt_len);
288
289 /* Check that the options uniquely matches one of the allowed
290 options. */
291 if ($i + 1 < count($long_options)) {
292 $next_option_rest = substr($long_options[$i + 1], $opt_len);
293 } else {
294 $next_option_rest = '';
295 }
296
297 if ($opt_rest != '' && $opt{0} != '=' &&
298 $i + 1 < count($long_options) &&
299 $opt == substr($long_options[$i+1], 0, $opt_len) &&
300 $next_option_rest != '' &&
301 $next_option_rest{0} != '=') {
302
303 $msg = "Console_Getopt: option --$opt is ambiguous";
304 return PEAR::raiseError($msg);
305 }
306
307 if (substr($long_opt, -1) == '=') {
308 if (substr($long_opt, -2) != '==') {
309 /* Long option requires an argument.
310 Take the next argument if one wasn't specified. */;
311 if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
312 $msg = "Console_Getopt: option requires an argument --$opt";
313 return PEAR::raiseError($msg);
314 }
315
316 if (Console_Getopt::_isShortOpt($opt_arg)
317 || Console_Getopt::_isLongOpt($opt_arg)) {
318 $msg = "Console_Getopt: option requires an argument --$opt";
319 return PEAR::raiseError($msg);
320 }
321 }
322 } else if ($opt_arg) {
323 $msg = "Console_Getopt: option --$opt doesn't allow an argument";
324 return PEAR::raiseError($msg);
325 }
326
327 $opts[] = array('--' . $opt, $opt_arg);
328 return;
329 }
330
331 if ($skip_unknown === true) {
332 return;
333 }
334
335 return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
336 }
337
338 /**
339 * Safely read the $argv PHP array across different PHP configurations.
340 * Will take care on register_globals and register_argc_argv ini directives
341 *
342 * @return mixed the $argv PHP array or PEAR error if not registered
343 */
344 public static function readPHPArgv()
345 {
346 global $argv;
347 if (!is_array($argv)) {
348 if (!@is_array($_SERVER['argv'])) {
349 if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
350 $msg = "Could not read cmd args (register_argc_argv=Off?)";
351 return PEAR::raiseError("Console_Getopt: " . $msg);
352 }
353 return $GLOBALS['HTTP_SERVER_VARS']['argv'];
354 }
355 return $_SERVER['argv'];
356 }
357 return $argv;
358 }
359
360 }