/class/Getopt.php
PHP | 331 lines | 262 code | 12 blank | 57 comment | 18 complexity | 248f0d3a2f201f2c72eba4bf5a3b3c32 MD5 | raw file
Possible License(s): BSD-3-Clause
- <?php
- // vim: foldmethod=marker
- /**
- * Getopt.php
- *
- * @author Yoshinari Takaoka <takaoka@beatcraft.com>
- * @license Public Domain
- * @package Ethna
- * @version $Id: adb71f2ff53da8464732977145d8d6d2e7da9d28 $
- */
- if (!defined('ETHNA_OPTVALUE_IS_DISABLED')) {
- define('ETHNA_OPTVALUE_IS_DISABLED', 1);
- }
- if (!defined('ETHNA_OPTVALUE_IS_REQUIRED')) {
- define('ETHNA_OPTVALUE_IS_REQUIRED', 2);
- }
- if (!defined('ETHNA_OPTVALUE_IS_OPTIONAL')) {
- define('ETHNA_OPTVALUE_IS_OPTIONAL', 3);
- }
- // {{{ Ethna_Getopt
- /**
- * ?????????????????
- * PEAR ???????????? Console_Getopt ???????????
- *
- * @author Yoshinari Takaoka <takaoka@beatcraft.com>
- * @access public
- * @package Ethna
- * @see http://pear.php.net/manual/en/package.console.console-getopt.php
- */
- class Ethna_Getopt
- {
- /**
- * PHP ????????$argv ????????
- * ini ????????? register_argc_argv ???????
- *
- * ??? PHP 4.2.0 ?????$argv ???????
- * register_globals ? ON ?????????
- * ??????Ethna ? ?????off????
- * ?????????????????????
- * ????????
- *
- * @return array - ?????????????????
- * ???? Ethna_Error
- */
- public function readPHPArgv()
- {
- global $argv;
- if (ini_get('register_argc_argv') == false) {
- return Ethna::raiseError(
- 'Could not read cmd args (register_argc_argv=Off?'
- );
- }
- return $argv;
- }
- /**
- * ??????????????????????????
- *
- * @param array $args - ????????????
- * @param string $shortoptions - ?????????????????????
- * @param array $longoptions - ?????????????????????
- *
- * @return array - ????????????????????????????
- * ? 2??????????????? Ethna_Error ?
- */
- public function getopt($args, $shortoptions, $longoptions = NULL)
- {
- $shortopts = $this->_parseShortOption($shortoptions);
- if (Ethna::isError($shortopts)) {
- return $shortopts;
- }
- $longopts = $this->_parseLongOption($longoptions);
- if (Ethna::isError($longopts)) {
- return $longopts;
- }
- $parsed_arguments = array();
- $nonparsed_arguments = array();
- for ($pos = 0; $pos < count($args); $pos++) {
- $arg = $args[$pos];
- $next_arg = isset($args[$pos + 1]) ? $args[$pos + 1] : NULL;
- $is_nextarg_is_value = false;
- $required = false;
- if (strpos($arg, '--') === 0) { // long option
- //
- // GNU getopt(3) ??????????????????
- // ?????????????????? --foo, --fuji
- // ????????????????? --fo ? --fu ?
- // ??????????????????
- //
- // PEAR ? Console_Getopt ??????????????
- // ??????????????? Ethna ???????
- // ???????????
- //
- // ????????????
- $lopt = str_replace('--', '', $arg);
- $opt_and_value = explode('=', $lopt);
- $opt = $opt_and_value[0];
- if (!array_key_exists($opt, $longopts)) {
- return Ethna::raiseError("unrecognized option --$opt");
- }
- // ????????????
- $required = $longopts[$opt];
- $value = NULL;
- if (count($opt_and_value) == 2) {
- $value = $opt_and_value[1]; // --foo=bar
- } elseif (strpos('-', $next_arg) !== 0
- && $required == ETHNA_OPTVALUE_IS_REQUIRED) {
- if (!empty($next_arg)) { // --foo bar
- // ?? $argv ???????
- // == ??????????????????????
- $value = $next_arg;
- $pos++;
- }
- }
- // ???????????
- switch ($required) {
- case ETHNA_OPTVALUE_IS_REQUIRED:
- if ($value === NULL) {
- return Ethna::raiseError(
- "option --$opt requires an argument"
- );
- }
- break;
- case ETHNA_OPTVALUE_IS_DISABLED:
- if ($value !== NULL) {
- return Ethna::raiseError(
- "option --$opt doesn't allow an argument"
- );
- }
- break;
- }
- // ????????????-- ??????????????
- // Console_Getopt ????????
- $parsed_arguments[] = array("--$opt", $value);
- } elseif (strpos($arg, '-') === 0) { // short option
- //
- // -abcd ????????????????
- // ?????????????????????????
- // ????????GNU getopt(3) ??????
- //
- // 1. abcd ?1?????????a, b, c, d ???
- //
- // 2. ':' (???) ?????????????????????
- // ??????????????????argv????????
- // ???????????????? argv ?????????
- // ???????????
- // 3. '::'(????) ????????????????????
- // ?????????????????????????argv?
- // ???????????
- //
- // 4. ???(?????)???????????????????
- // ?????????argv??????????
- //
- // @see LANG=C; man 3 getopt (??????????????????)
- // @see http://www.gnu.org/software/libtool/manual/libc/Using-Getopt.html
- //
- // TODO: ambiguous ?????????????????
- //
- $sopt = str_replace('-', '', $arg);
- $sopt_len = strlen($sopt);
- for ($sopt_pos = 0; $sopt_pos < $sopt_len; $sopt_pos++) {
- // ??????????
- $opt = $sopt[$sopt_pos];
- $value = NULL;
- $do_next_arg = false;
- $required = isset($shortopts[$opt]) ? $shortopts[$opt] : NULL;
- switch ($required) {
- case ETHNA_OPTVALUE_IS_REQUIRED:
- case ETHNA_OPTVALUE_IS_OPTIONAL:
- if ($sopt_len == 1
- && $required == ETHNA_OPTVALUE_IS_REQUIRED) {
- if ($next_arg[0] != '-') { // -a hoge
- // ?? $argv ???????
- // ???:: ?????????
- $value = $next_arg;
- $pos++;
- }
- } else {
- // ????????????
- $value = substr($sopt, $sopt_pos + 1);
- $value = (empty($value)) ? NULL : $value;
- }
- if ($required == ETHNA_OPTVALUE_IS_REQUIRED
- && empty($value)) {
- return Ethna::raiseError(
- "option -$opt requires an argument"
- );
- }
- // ':' ??? '::' ??????????????
- // ??????????????????argv???
- // ?????
- $do_next_arg = true;
- break;
- case ETHNA_OPTVALUE_IS_DISABLED:
- // ?????????????????????
- // ????????????????
- break;
- default:
- return Ethna::raiseError("unrecognized option -$opt");
- break;
- }
- // ????????????- ?????????????????
- // Console_Getopt ????????
- $parsed_arguments[] = array($opt, $value);
- if ($do_next_arg === true) {
- break;
- }
- }
- } else { // ??????????????
- // non-parsed ????????????
- // ??????????????
- // ???????????????????
- //
- // ??? POSIX_CORRECT ???????
- // GNU Getopt ????????????
- // Console_Getopt ??????????
- // ????????
- $nonparsed_arguments = array_slice($args, $pos);
- break;
- }
- }
- return array($parsed_arguments, $nonparsed_arguments);
- }
- /**
- * ????????????????
- *
- * @param string $sopts ?????????
- * @return array ???????????????
- * ??????? Ethna_Error
- * @access protected
- */
- protected function _parseShortOption($sopts)
- {
- if (empty($sopts)) {
- return array();
- }
- if (!preg_match('/^[A-Za-z:]+$/', $sopts)) {
- return Ethna::raiseError('invalid short options.');
- }
- $analyze_result = array();
- for ($pos = 0; $pos < strlen($sopts); $pos++) {
- $char = $sopts[$pos];
- $next_char = (isset($sopts[$pos + 1]))
- ? $sopts[$pos + 1]
- : NULL;
- $next2_char = (isset($sopts[$pos + 2]))
- ? $sopts[$pos + 2]
- : NULL;
- if ($char == ':') {
- continue;
- }
- // $sopts[$pos] is character.
- if ($next_char == ':' && $next2_char == ':') {
- $analyze_result[$char] = ETHNA_OPTVALUE_IS_OPTIONAL; // ????
- } elseif ($next_char == ':' && $next2_char != ':') {
- $analyze_result[$char] = ETHNA_OPTVALUE_IS_REQUIRED; // ????
- } else {
- $analyze_result[$char] = ETHNA_OPTVALUE_IS_DISABLED; // ????
- }
- }
- return $analyze_result;
- }
- /**
- * ????????????????
- *
- * @param array $lopts ?????????
- * @return array ???????????????
- * ??????? Ethna_Error
- * @access protected
- */
- protected function _parseLongOption($lopts)
- {
- if (empty($lopts)) {
- return array();
- }
- if (!is_array($lopts)) {
- return Ethna::raiseError('invalid long options.');
- }
- $analyze_result = array();
- foreach ($lopts as $opt) {
- if (preg_match('/==$/', $opt) > 0) {
- $opt = substr($opt, 0, -2);
- $analyze_result[$opt] = ETHNA_OPTVALUE_IS_OPTIONAL; // ????
- } elseif (preg_match('/=$/', $opt) > 0) {
- $opt = substr($opt, 0, -1);
- $analyze_result[$opt] = ETHNA_OPTVALUE_IS_REQUIRED; // ????
- } else {
- $analyze_result[$opt] = ETHNA_OPTVALUE_IS_DISABLED; // ????
- }
- }
- return $analyze_result;
- }
- }
- // }}}