📄 long.pm
字号:
# GetOpt::Long.pm -- Universal options parsing
package Getopt::Long;
# RCS Status : $Id: GetoptLong.pl,v 2.18 1998-06-14 15:02:19+02 jv Exp $
# Author : Johan Vromans
# Created On : Tue Sep 11 15:00:12 1990
# Last Modified By: Johan Vromans
# Last Modified On: Sun Jun 14 13:17:22 1998
# Update Count : 705
# Status : Released
################ Copyright ################
# This program is Copyright 1990,1998 by Johan Vromans.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# If you do not have a copy of the GNU General Public License write to
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
# MA 02139, USA.
################ Module Preamble ################
use strict;
BEGIN {
require 5.004;
use Exporter ();
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
$VERSION = "2.17";
@ISA = qw(Exporter);
@EXPORT = qw(&GetOptions $REQUIRE_ORDER $PERMUTE $RETURN_IN_ORDER);
%EXPORT_TAGS = qw();
@EXPORT_OK = qw();
use AutoLoader qw(AUTOLOAD);
}
# User visible variables.
use vars @EXPORT, @EXPORT_OK;
use vars qw($error $debug $major_version $minor_version);
# Deprecated visible variables.
use vars qw($autoabbrev $getopt_compat $ignorecase $bundling $order
$passthrough);
# Official invisible variables.
use vars qw($genprefix);
# Public subroutines.
sub Configure (@);
sub config (@); # deprecated name
sub GetOptions;
# Private subroutines.
sub ConfigDefaults ();
sub FindOption ($$$$$$$);
sub Croak (@); # demand loading the real Croak
################ Local Variables ################
################ Resident subroutines ################
sub ConfigDefaults () {
# Handle POSIX compliancy.
if ( defined $ENV{"POSIXLY_CORRECT"} ) {
$genprefix = "(--|-)";
$autoabbrev = 0; # no automatic abbrev of options
$bundling = 0; # no bundling of single letter switches
$getopt_compat = 0; # disallow '+' to start options
$order = $REQUIRE_ORDER;
}
else {
$genprefix = "(--|-|\\+)";
$autoabbrev = 1; # automatic abbrev of options
$bundling = 0; # bundling off by default
$getopt_compat = 1; # allow '+' to start options
$order = $PERMUTE;
}
# Other configurable settings.
$debug = 0; # for debugging
$error = 0; # error tally
$ignorecase = 1; # ignore case when matching options
$passthrough = 0; # leave unrecognized options alone
}
################ Initialization ################
# Values for $order. See GNU getopt.c for details.
($REQUIRE_ORDER, $PERMUTE, $RETURN_IN_ORDER) = (0..2);
# Version major/minor numbers.
($major_version, $minor_version) = $VERSION =~ /^(\d+)\.(\d+)/;
# Set defaults.
ConfigDefaults ();
################ Package return ################
1;
__END__
################ AutoLoading subroutines ################
# RCS Status : $Id: GetoptLongAl.pl,v 2.20 1998-06-14 15:02:19+02 jv Exp $
# Author : Johan Vromans
# Created On : Fri Mar 27 11:50:30 1998
# Last Modified By: Johan Vromans
# Last Modified On: Sun Jun 14 13:54:35 1998
# Update Count : 24
# Status : Released
sub GetOptions {
my @optionlist = @_; # local copy of the option descriptions
my $argend = '--'; # option list terminator
my %opctl = (); # table of arg.specs (long and abbrevs)
my %bopctl = (); # table of arg.specs (bundles)
my $pkg = (caller)[0]; # current context
# Needed if linkage is omitted.
my %aliases= (); # alias table
my @ret = (); # accum for non-options
my %linkage; # linkage
my $userlinkage; # user supplied HASH
my $opt; # current option
my $genprefix = $genprefix; # so we can call the same module many times
my @opctl; # the possible long option names
$error = '';
print STDERR ("GetOpt::Long $Getopt::Long::VERSION ",
"called from package \"$pkg\".",
"\n ",
'GetOptionsAl $Revision: 2.20 $ ',
"\n ",
"ARGV: (@ARGV)",
"\n ",
"autoabbrev=$autoabbrev,".
"bundling=$bundling,",
"getopt_compat=$getopt_compat,",
"order=$order,",
"\n ",
"ignorecase=$ignorecase,",
"passthrough=$passthrough,",
"genprefix=\"$genprefix\".",
"\n")
if $debug;
# Check for ref HASH as first argument.
# First argument may be an object. It's OK to use this as long
# as it is really a hash underneath.
$userlinkage = undef;
if ( ref($optionlist[0]) and
"$optionlist[0]" =~ /^(?:.*\=)?HASH\([^\(]*\)$/ ) {
$userlinkage = shift (@optionlist);
print STDERR ("=> user linkage: $userlinkage\n") if $debug;
}
# See if the first element of the optionlist contains option
# starter characters.
if ( $optionlist[0] =~ /^\W+$/ ) {
$genprefix = shift (@optionlist);
# Turn into regexp. Needs to be parenthesized!
$genprefix =~ s/(\W)/\\$1/g;
$genprefix = "([" . $genprefix . "])";
}
# Verify correctness of optionlist.
%opctl = ();
%bopctl = ();
while ( @optionlist > 0 ) {
my $opt = shift (@optionlist);
# Strip leading prefix so people can specify "--foo=i" if they like.
$opt = $+ if $opt =~ /^$genprefix+(.*)$/s;
if ( $opt eq '<>' ) {
if ( (defined $userlinkage)
&& !(@optionlist > 0 && ref($optionlist[0]))
&& (exists $userlinkage->{$opt})
&& ref($userlinkage->{$opt}) ) {
unshift (@optionlist, $userlinkage->{$opt});
}
unless ( @optionlist > 0
&& ref($optionlist[0]) && ref($optionlist[0]) eq 'CODE' ) {
$error .= "Option spec <> requires a reference to a subroutine\n";
next;
}
$linkage{'<>'} = shift (@optionlist);
next;
}
# Match option spec. Allow '?' as an alias.
if ( $opt !~ /^((\w+[-\w]*)(\|(\?|\w[-\w]*)?)*)?([!~+]|[=:][infse][@%]?)?$/ ) {
$error .= "Error in option spec: \"$opt\"\n";
next;
}
my ($o, $c, $a) = ($1, $5);
$c = '' unless defined $c;
if ( ! defined $o ) {
# empty -> '-' option
$opctl{$o = ''} = $c;
}
else {
# Handle alias names
my @o = split (/\|/, $o);
my $linko = $o = $o[0];
# Force an alias if the option name is not locase.
$a = $o unless $o eq lc($o);
$o = lc ($o)
if $ignorecase > 1
|| ($ignorecase
&& ($bundling ? length($o) > 1 : 1));
foreach ( @o ) {
if ( $bundling && length($_) == 1 ) {
$_ = lc ($_) if $ignorecase > 1;
if ( $c eq '!' ) {
$opctl{"no$_"} = $c;
warn ("Ignoring '!' modifier for short option $_\n");
$c = '';
}
$opctl{$_} = $bopctl{$_} = $c;
}
else {
$_ = lc ($_) if $ignorecase;
if ( $c eq '!' ) {
$opctl{"no$_"} = $c;
$c = '';
}
$opctl{$_} = $c;
}
if ( defined $a ) {
# Note alias.
$aliases{$_} = $a;
}
else {
# Set primary name.
$a = $_;
}
}
$o = $linko;
}
# If no linkage is supplied in the @optionlist, copy it from
# the userlinkage if available.
if ( defined $userlinkage ) {
unless ( @optionlist > 0 && ref($optionlist[0]) ) {
if ( exists $userlinkage->{$o} && ref($userlinkage->{$o}) ) {
print STDERR ("=> found userlinkage for \"$o\": ",
"$userlinkage->{$o}\n")
if $debug;
unshift (@optionlist, $userlinkage->{$o});
}
else {
# Do nothing. Being undefined will be handled later.
next;
}
}
}
# Copy the linkage. If omitted, link to global variable.
if ( @optionlist > 0 && ref($optionlist[0]) ) {
print STDERR ("=> link \"$o\" to $optionlist[0]\n")
if $debug;
if ( ref($optionlist[0]) =~ /^(SCALAR|CODE)$/ ) {
$linkage{$o} = shift (@optionlist);
}
elsif ( ref($optionlist[0]) =~ /^(ARRAY)$/ ) {
$linkage{$o} = shift (@optionlist);
$opctl{$o} .= '@'
if $opctl{$o} ne '' and $opctl{$o} !~ /\@$/;
$bopctl{$o} .= '@'
if $bundling and defined $bopctl{$o} and
$bopctl{$o} ne '' and $bopctl{$o} !~ /\@$/;
}
elsif ( ref($optionlist[0]) =~ /^(HASH)$/ ) {
$linkage{$o} = shift (@optionlist);
$opctl{$o} .= '%'
if $opctl{$o} ne '' and $opctl{$o} !~ /\%$/;
$bopctl{$o} .= '%'
if $bundling and defined $bopctl{$o} and
$bopctl{$o} ne '' and $bopctl{$o} !~ /\%$/;
}
else {
$error .= "Invalid option linkage for \"$opt\"\n";
}
}
else {
# Link to global $opt_XXX variable.
# Make sure a valid perl identifier results.
my $ov = $o;
$ov =~ s/\W/_/g;
if ( $c =~ /@/ ) {
print STDERR ("=> link \"$o\" to \@$pkg","::opt_$ov\n")
if $debug;
eval ("\$linkage{\$o} = \\\@".$pkg."::opt_$ov;");
}
elsif ( $c =~ /%/ ) {
print STDERR ("=> link \"$o\" to \%$pkg","::opt_$ov\n")
if $debug;
eval ("\$linkage{\$o} = \\\%".$pkg."::opt_$ov;");
}
else {
print STDERR ("=> link \"$o\" to \$$pkg","::opt_$ov\n")
if $debug;
eval ("\$linkage{\$o} = \\\$".$pkg."::opt_$ov;");
}
}
}
# Bail out if errors found.
die ($error) if $error;
$error = 0;
# Sort the possible long option names.
@opctl = sort(keys (%opctl)) if $autoabbrev;
# Show the options tables if debugging.
if ( $debug ) {
my ($arrow, $k, $v);
$arrow = "=> ";
while ( ($k,$v) = each(%opctl) ) {
print STDERR ($arrow, "\$opctl{\"$k\"} = \"$v\"\n");
$arrow = " ";
}
$arrow = "=> ";
while ( ($k,$v) = each(%bopctl) ) {
print STDERR ($arrow, "\$bopctl{\"$k\"} = \"$v\"\n");
$arrow = " ";
}
}
# Process argument list
while ( @ARGV > 0 ) {
#### Get next argument ####
$opt = shift (@ARGV);
print STDERR ("=> option \"", $opt, "\"\n") if $debug;
#### Determine what we have ####
# Double dash is option list terminator.
if ( $opt eq $argend ) {
# Finish. Push back accumulated arguments and return.
unshift (@ARGV, @ret)
if $order == $PERMUTE;
return ($error == 0);
}
my $tryopt = $opt;
my $found; # success status
my $dsttype; # destination type ('@' or '%')
my $incr; # destination increment
my $key; # key (if hash type)
my $arg; # option argument
($found, $opt, $arg, $dsttype, $incr, $key) =
FindOption ($genprefix, $argend, $opt,
\%opctl, \%bopctl, \@opctl, \%aliases);
if ( $found ) {
# FindOption undefines $opt in case of errors.
next unless defined $opt;
if ( defined $arg ) {
$opt = $aliases{$opt} if defined $aliases{$opt};
if ( defined $linkage{$opt} ) {
print STDERR ("=> ref(\$L{$opt}) -> ",
ref($linkage{$opt}), "\n") if $debug;
if ( ref($linkage{$opt}) eq 'SCALAR' ) {
if ( $incr ) {
print STDERR ("=> \$\$L{$opt} += \"$arg\"\n")
if $debug;
if ( defined ${$linkage{$opt}} ) {
${$linkage{$opt}} += $arg;
}
else {
${$linkage{$opt}} = $arg;
}
}
else {
print STDERR ("=> \$\$L{$opt} = \"$arg\"\n")
if $debug;
${$linkage{$opt}} = $arg;
}
}
elsif ( ref($linkage{$opt}) eq 'ARRAY' ) {
print STDERR ("=> push(\@{\$L{$opt}, \"$arg\")\n")
if $debug;
push (@{$linkage{$opt}}, $arg);
}
elsif ( ref($linkage{$opt}) eq 'HASH' ) {
print STDERR ("=> \$\$L{$opt}->{$key} = \"$arg\"\n")
if $debug;
$linkage{$opt}->{$key} = $arg;
}
elsif ( ref($linkage{$opt}) eq 'CODE' ) {
print STDERR ("=> &L{$opt}(\"$opt\", \"$arg\")\n")
if $debug;
&{$linkage{$opt}}($opt, $arg);
}
else {
print STDERR ("Invalid REF type \"", ref($linkage{$opt}),
"\" in linkage\n");
Croak ("Getopt::Long -- internal error!\n");
}
}
# No entry in linkage means entry in userlinkage.
elsif ( $dsttype eq '@' ) {
if ( defined $userlinkage->{$opt} ) {
print STDERR ("=> push(\@{\$L{$opt}}, \"$arg\")\n")
if $debug;
push (@{$userlinkage->{$opt}}, $arg);
}
else {
print STDERR ("=>\$L{$opt} = [\"$arg\"]\n")
if $debug;
$userlinkage->{$opt} = [$arg];
}
}
elsif ( $dsttype eq '%' ) {
if ( defined $userlinkage->{$opt} ) {
print STDERR ("=> \$L{$opt}->{$key} = \"$arg\"\n")
if $debug;
$userlinkage->{$opt}->{$key} = $arg;
}
else {
print STDERR ("=>\$L{$opt} = {$key => \"$arg\"}\n")
if $debug;
$userlinkage->{$opt} = {$key => $arg};
}
}
else {
if ( $incr ) {
print STDERR ("=> \$L{$opt} += \"$arg\"\n")
if $debug;
if ( defined $userlinkage->{$opt} ) {
$userlinkage->{$opt} += $arg;
}
else {
$userlinkage->{$opt} = $arg;
}
}
else {
print STDERR ("=>\$L{$opt} = \"$arg\"\n") if $debug;
$userlinkage->{$opt} = $arg;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -