Class it:

/**
 * Parse command line options with Usage given as template and return assoc array.
 * @param $usage Usage parsed to determine options, example see below.
 * @param $p['optbeforearg'] Stop parsing options when first argument is encountered
 * @param $p['noexit'] Just return false in case of help or bad usage
 * @return Associative array of options, key 'args' for optional non-option args
 *
 * Usage: myprogram.php [OPTIONS] PATTERN [MOREARGS]
 *  -s, --short      Use short ouput
 *  -f, --file=FILE  Use FILE for input [foo.txt]
 *  -x EXTENSION     Ignore EXTENSION
 * Mandatory arguments from the Usage: line are returned under their (lowercased!) name.
 * Option text must be indented; if long and short option present, value is stored in long one.
 * For long opts with arguments, = is mandatory in usage. Defaults in [ ] at end of line
 * Two or more blanks must be in front of option explanation
 * Options without arguments store true or false under their key
 * Option --help or -h prints de-indented usage and exits (needs not be in usage)
 * Option --debug foo-bar will store bar in EDC('foo'). (needs not be in usage)
 * Option --verbose sets debug variable verbose for EDC('verbose', $bar). (must be in usage)
 */
static function getopt($usage$p = array())
{
    
$GLOBALS['it_stdin'] = array(
        
'fd' => null,
        
'args' => array(),
        
'filename' => "",
        
'line' => 0,
    );

    
$result = array('args' => array());

    if (
$indentation it::match('^\s+'$usage))
        
$usage it::replace(array($indentation => "\n"), $usage);

    foreach(
explode("\n"trim($usage)) as $usageline)
    {
        
$shortoptname $shortoptarg $longoptname $longoptarg "";
        foreach (
explode(','$usageline) as $optdesc)
        {
            
$optdesc trim($optdesc);
            if (
$matches = (array)it::match('^--(\w[\w-]*)(=[A-Z])?'$optdesc))
                list(
$longoptname$longoptarg) = $matches;
            else if (
$matches = (array)it::match('^-(\w)( [A-Z])?'$optdesc))
                list(
$shortoptname$shortoptarg) = $matches;
        }

        if ((
$default it::match('\[(.*)\]\s*$'$usageline)) !== null)
        {
            if (
$longoptarg || $shortoptarg)
                
$defaults[$longoptname $longoptname $shortoptname] = it::replace(array('^default:\s*' => ""), trim($default));
            else if ((
$longoptname || $shortoptname) && it::match('^\w+$'$default))
                
it::error('defaults for boolean arguments not supported!');
        }

        if (
$longoptname || $shortoptname)
        {
            if (
$longoptname && ($shortoptname || $shortoptname === "0"))
            {
                if (
$alias[$shortoptname])
                    
it::error("getopt: short option -$shortoptname is used twice: --{$alias[$shortoptname]} and --$longoptname!");
                
$alias[$shortoptname] = $longoptname;
            }

            
$witharg[$longoptname $longoptname $shortoptname] = $longoptarg || $shortoptarg;
        }
    }
    
$witharg['debug'] = true;

    
$argsdesc trim(it::replace(array("\n.*" => """^\S+\s+\S+\s*" => ""), trim($usage)));
    
$mandatoryargs it::match('\S+'it::replace(['\[.*?\]' => ''], $argsdesc), ['all' => true]);
    
$optionalargs it::match('\[((?!OPTIONS\]).*?)\]'$argsdesc, ['all' => true]);
    if (
$mandatoryargs && !it::match("Usage:"$usage))
        
it::error("Usage string must contain 'Usage:'");

    foreach (
array_slice($_SERVER['argv'], 1) as $arg)
    {
        if (
$eat)
            
$result[array_shift($eat)] = $arg;
        else if (
$arg == "--")
            
$noopts true;
        else if (!
$noopts && ($matches = (array)it::match('^--(\w[\w-]*)(=.*)?'$arg)))
        {
            list(
$optname$val) = $matches;
            if (!isset(
$witharg[$optname]) || isset($val) && !$witharg[$optname])
                
$err true;
            else if(
$witharg[$optname] && !$val)
                
$eat[] = $optname;
            else
                
$result[$optname] = $val substr($val1) : true;
        }
        else if (!
$noopts && (($letters it::match('^-(\w+)'$arg)) || $letters === "0"))
        {
            foreach (
explode("\n"trim(chunk_split($letters1"\n"))) as $letter)
            {
                
$optname $alias[$letter] ? $alias[$letter] : $letter;
                if (
$witharg[$optname] && it::match('='$arg))
                    
$result[$optname] = it::match('=(.*)'$arg);
                else if (
$witharg[$optname])
                    
$eat[] = $optname;
                else if (!isset(
$witharg[$optname]))
                    
$err true;
                else
                    
$result[$optname] = true;
            }
        }
        else if(
$mandatoryargs)
            
$result[strtolower(array_shift($mandatoryargs))] = $seenarg $arg;
        else
            
$result['args'][] = $seenarg $arg;

        if (
$p['optbeforearg'] && $seenarg)
            
$noopts true;
    }

    if (
$err || $eat || $result['h'] || $result['help'] || $mandatoryargs || (!$optionalargs && $result['args']))
    {
        if (
is_resource($out $result['h'] || $result['help'] ? STDOUT STDERR))
            
fputs($outtrim($usage) . "\n");
        return 
$p['noexit'] ? false : exit(1);
    }

    if (
$result['debug'])
        
it_debug::set($result['debug']);

    
$GLOBALS['it_stdin']['args'] = $result['args'] ? $result['args'] : array("-");

    if (
$result['verbose'])
        
$GLOBALS['debug_verbose']++;

    return 
$result + (array)$defaults;
}