PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/script/lib/Console/Getopt.php

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