📄 long.pm
字号:
my $tryopt = $opt; # option to try if ( $bundling && $starter eq '-' ) { # To try overrides, obey case ignore. $tryopt = $ignorecase ? lc($opt) : $opt; # If bundling == 2, long options can override bundles. if ( $bundling == 2 && length($tryopt) > 1 && defined ($opctl->{$tryopt}) ) { print STDERR ("=> $starter$tryopt overrides unbundling\n") if $debug; } else { $tryopt = $opt; # Unbundle single letter option. $rest = length ($tryopt) > 0 ? substr ($tryopt, 1) : ''; $tryopt = substr ($tryopt, 0, 1); $tryopt = lc ($tryopt) if $ignorecase > 1; print STDERR ("=> $starter$tryopt unbundled from ", "$starter$tryopt$rest\n") if $debug; $rest = undef unless $rest ne ''; } } # Try auto-abbreviation. elsif ( $autoabbrev ) { # Sort the possible long option names. my @names = sort(keys (%$opctl)); # Downcase if allowed. $opt = lc ($opt) if $ignorecase; $tryopt = $opt; # Turn option name into pattern. my $pat = quotemeta ($opt); # Look up in option names. my @hits = grep (/^$pat/, @names); print STDERR ("=> ", scalar(@hits), " hits (@hits) with \"$pat\" ", "out of ", scalar(@names), "\n") if $debug; # Check for ambiguous results. unless ( (@hits <= 1) || (grep ($_ eq $opt, @hits) == 1) ) { # See if all matches are for the same option. my %hit; foreach ( @hits ) { my $hit = $_; $hit = $opctl->{$hit}->[CTL_CNAME] if defined $opctl->{$hit}->[CTL_CNAME]; $hit{$hit} = 1; } # Remove auto-supplied options (version, help). if ( keys(%hit) == 2 ) { if ( $auto_version && exists($hit{version}) ) { delete $hit{version}; } elsif ( $auto_help && exists($hit{help}) ) { delete $hit{help}; } } # Now see if it really is ambiguous. unless ( keys(%hit) == 1 ) { return (0) if $passthrough; warn ("Option ", $opt, " is ambiguous (", join(", ", @hits), ")\n"); $error++; return (1, undef); } @hits = keys(%hit); } # Complete the option name, if appropriate. if ( @hits == 1 && $hits[0] ne $opt ) { $tryopt = $hits[0]; $tryopt = lc ($tryopt) if $ignorecase; print STDERR ("=> option \"$opt\" -> \"$tryopt\"\n") if $debug; } } # Map to all lowercase if ignoring case. elsif ( $ignorecase ) { $tryopt = lc ($opt); } # Check validity by fetching the info. my $ctl = $opctl->{$tryopt}; unless ( defined $ctl ) { return (0) if $passthrough; # Pretend one char when bundling. if ( $bundling == 1 && length($starter) == 1 ) { $opt = substr($opt,0,1); unshift (@ARGV, $starter.$rest) if defined $rest; } warn ("Unknown option: ", $opt, "\n"); $error++; return (1, undef); } # Apparently valid. $opt = $tryopt; print STDERR ("=> found ", OptCtl($ctl), " for \"", $opt, "\"\n") if $debug; #### Determine argument status #### # If it is an option w/o argument, we're almost finished with it. my $type = $ctl->[CTL_TYPE]; my $arg; if ( $type eq '' || $type eq '!' || $type eq '+' ) { if ( defined $optarg ) { return (0) if $passthrough; warn ("Option ", $opt, " does not take an argument\n"); $error++; undef $opt; } elsif ( $type eq '' || $type eq '+' ) { # Supply explicit value. $arg = 1; } else { $opt =~ s/^no-?//i; # strip NO prefix $arg = 0; # supply explicit value } unshift (@ARGV, $starter.$rest) if defined $rest; return (1, $opt, $ctl, $arg); } # Get mandatory status and type info. my $mand = $ctl->[CTL_AMIN]; # Check if there is an option argument available. if ( $gnu_compat && defined $optarg && $optarg eq '' ) { return (1, $opt, $ctl, $type eq 's' ? '' : 0) unless $mand; $optarg = 0 unless $type eq 's'; } # Check if there is an option argument available. if ( defined $optarg ? ($optarg eq '') : !(defined $rest || @ARGV > 0) ) { # Complain if this option needs an argument. if ( $mand ) { return (0) if $passthrough; warn ("Option ", $opt, " requires an argument\n"); $error++; return (1, undef); } if ( $type eq 'I' ) { # Fake incremental type. my @c = @$ctl; $c[CTL_TYPE] = '+'; return (1, $opt, \@c, 1); } return (1, $opt, $ctl, defined($ctl->[CTL_DEFAULT]) ? $ctl->[CTL_DEFAULT] : $type eq 's' ? '' : 0); } # Get (possibly optional) argument. $arg = (defined $rest ? $rest : (defined $optarg ? $optarg : shift (@ARGV))); # Get key if this is a "name=value" pair for a hash option. my $key; if ($ctl->[CTL_DEST] == CTL_DEST_HASH && defined $arg) { ($key, $arg) = ($arg =~ /^([^=]*)=(.*)$/s) ? ($1, $2) : ($arg, defined($ctl->[CTL_DEFAULT]) ? $ctl->[CTL_DEFAULT] : ($mand ? undef : ($type eq 's' ? "" : 1))); if (! defined $arg) { warn ("Option $opt, key \"$key\", requires a value\n"); $error++; # Push back. unshift (@ARGV, $starter.$rest) if defined $rest; return (1, undef); } } #### Check if the argument is valid for this option #### my $key_valid = $ctl->[CTL_DEST] == CTL_DEST_HASH ? "[^=]+=" : ""; if ( $type eq 's' ) { # string # A mandatory string takes anything. return (1, $opt, $ctl, $arg, $key) if $mand; # An optional string takes almost anything. return (1, $opt, $ctl, $arg, $key) if defined $optarg || defined $rest; return (1, $opt, $ctl, $arg, $key) if $arg eq "-"; # ?? # Check for option or option list terminator. if ($arg eq $argend || $arg =~ /^$prefix.+/) { # Push back. unshift (@ARGV, $arg); # Supply empty value. $arg = ''; } } elsif ( $type eq 'i' # numeric/integer || $type eq 'I' # numeric/integer w/ incr default || $type eq 'o' ) { # dec/oct/hex/bin value my $o_valid = $type eq 'o' ? "[-+]?[1-9][0-9]*|0x[0-9a-f]+|0b[01]+|0[0-7]*" : "[-+]?[0-9]+"; if ( $bundling && defined $rest && $rest =~ /^($key_valid)($o_valid)(.*)$/si ) { ($key, $arg, $rest) = ($1, $2, $+); chop($key) if $key; $arg = ($type eq 'o' && $arg =~ /^0/) ? oct($arg) : 0+$arg; unshift (@ARGV, $starter.$rest) if defined $rest && $rest ne ''; } elsif ( $arg =~ /^($o_valid)$/si ) { $arg = ($type eq 'o' && $arg =~ /^0/) ? oct($arg) : 0+$arg; } else { if ( defined $optarg || $mand ) { if ( $passthrough ) { unshift (@ARGV, defined $rest ? $starter.$rest : $arg) unless defined $optarg; return (0); } warn ("Value \"", $arg, "\" invalid for option ", $opt, " (", $type eq 'o' ? "extended " : '', "number expected)\n"); $error++; # Push back. unshift (@ARGV, $starter.$rest) if defined $rest; return (1, undef); } else { # Push back. unshift (@ARGV, defined $rest ? $starter.$rest : $arg); if ( $type eq 'I' ) { # Fake incremental type. my @c = @$ctl; $c[CTL_TYPE] = '+'; return (1, $opt, \@c, 1); } # Supply default value. $arg = defined($ctl->[CTL_DEFAULT]) ? $ctl->[CTL_DEFAULT] : 0; } } } elsif ( $type eq 'f' ) { # real number, int is also ok # We require at least one digit before a point or 'e', # and at least one digit following the point and 'e'. # [-]NN[.NN][eNN] if ( $bundling && defined $rest && $rest =~ /^($key_valid)([-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)(.*)$/s ) { ($key, $arg, $rest) = ($1, $2, $+); chop($key) if $key; unshift (@ARGV, $starter.$rest) if defined $rest && $rest ne ''; } elsif ( $arg !~ /^[-+]?[0-9.]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/ ) { if ( defined $optarg || $mand ) { if ( $passthrough ) { unshift (@ARGV, defined $rest ? $starter.$rest : $arg) unless defined $optarg; return (0); } warn ("Value \"", $arg, "\" invalid for option ", $opt, " (real number expected)\n"); $error++; # Push back. unshift (@ARGV, $starter.$rest) if defined $rest; return (1, undef); } else { # Push back. unshift (@ARGV, defined $rest ? $starter.$rest : $arg); # Supply default value. $arg = 0.0; } } } else { die("Getopt::Long internal error (Can't happen)\n"); } return (1, $opt, $ctl, $arg, $key);}sub ValidValue ($$$$$) { my ($ctl, $arg, $mand, $argend, $prefix) = @_; if ( $ctl->[CTL_DEST] == CTL_DEST_HASH ) { return 0 unless $arg =~ /[^=]+=(.*)/; $arg = $1; } my $type = $ctl->[CTL_TYPE]; if ( $type eq 's' ) { # string # A mandatory string takes anything. return (1) if $mand; return (1) if $arg eq "-"; # Check for option or option list terminator. return 0 if $arg eq $argend || $arg =~ /^$prefix.+/; return 1; } elsif ( $type eq 'i' # numeric/integer || $type eq 'I' # numeric/integer w/ incr default || $type eq 'o' ) { # dec/oct/hex/bin value my $o_valid = $type eq 'o' ? "[-+]?[1-9][0-9]*|0x[0-9a-f]+|0b[01]+|0[0-7]*" : "[-+]?[0-9]+"; return $arg =~ /^$o_valid$/si; } elsif ( $type eq 'f' ) { # real number, int is also ok # We require at least one digit before a point or 'e', # and at least one digit following the point and 'e'. # [-]NN[.NN][eNN] return $arg =~ /^[-+]?[0-9.]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/; } die("ValidValue: Cannot happen\n");}# Getopt::Long Configuration.sub Configure (@) { my (@options) = @_; my $prevconfig = [ $error, $debug, $major_version, $minor_version, $autoabbrev, $getopt_compat, $ignorecase, $bundling, $order, $gnu_compat, $passthrough, $genprefix, $auto_version, $auto_help, $longprefix ]; if ( ref($options[0]) eq 'ARRAY' ) { ( $error, $debug, $major_version, $minor_version, $autoabbrev, $getopt_compat, $ignorecase, $bundling, $order, $gnu_compat, $passthrough, $genprefix, $auto_version, $auto_help, $longprefix ) = @{shift(@options)}; } my $opt; foreach $opt ( @options ) { my $try = lc ($opt); my $action = 1; if ( $try =~ /^no_?(.*)$/s ) { $action = 0; $try = $+; } if ( ($try eq 'default' or $try eq 'defaults') && $action ) { ConfigDefaults (); } elsif ( ($try eq 'posix_default' or $try eq 'posix_defaults') ) { local $ENV{POSIXLY_CORRECT}; $ENV{POSIXLY_CORRECT} = 1 if $action; ConfigDefaults (); } elsif ( $try eq 'auto_abbrev' or $try eq 'autoabbrev' ) { $autoabbrev = $action; } elsif ( $try eq 'getopt_compat' ) { $getopt_compat = $action; } elsif ( $try eq 'gnu_getopt' ) { if ( $action ) { $gnu_compat = 1; $bundling = 1; $getopt_compat = 0; $order = $PERMUTE; } } elsif ( $try eq 'gnu_compat' ) { $gnu_compat = $action; } elsif ( $try =~ /^(auto_?)?version$/ ) { $auto_version = $action; } elsif ( $try =~ /^(auto_?)?help$/ ) { $auto_help = $action; } elsif ( $try eq 'ignorecase' or $try eq 'ignore_case' ) { $ignorecase = $action; } elsif ( $try eq 'ignore_case_always' ) { $ignorecase = $action ? 2 : 0; } elsif ( $try eq 'bundling' ) { $bundling = $action; } elsif ( $try eq 'bundling_override' ) { $bundling = $action ? 2 : 0; } elsif ( $try eq 'require_order' ) { $order = $action ? $REQUIRE_ORDER : $PERMUTE; } elsif ( $try eq 'permute' ) { $order = $action ? $PERMUTE : $REQUIRE_ORDER; } elsif ( $try eq 'pass_through' or $try eq 'passthrough' ) { $passthrough = $action; } elsif ( $try =~ /^prefix=(.+)$/ && $action ) { $genprefix = $1; # Turn into regexp. Needs to be parenthesized! $genprefix = "(" . quotemeta($genprefix) . ")"; eval { '' =~ /$genprefix/; }; die("Getopt::Long: invalid pattern \"$genprefix\"") if $@; } elsif ( $try =~ /^prefix_pattern=(.+)$/ && $action ) { $genprefix = $1; # Parenthesize if needed. $genprefix = "(" . $genprefix . ")" unless $genprefix =~ /^\(.*\)$/; eval { '' =~ m"$genprefix"; }; die("Getopt::Long: invalid pattern \"$genprefix\"") if $@; } elsif ( $try =~ /^long_prefix_pattern=(.+)$/ && $action ) { $longprefix = $1; # Parenthesize if needed. $longprefix = "(" . $longprefix . ")" unless $longprefix =~ /^\(.*\)$/; eval { '' =~ m"$longprefix"; }; die("Getopt::Long: invalid long prefix pattern \"$longprefix\"") if $@; } elsif ( $try eq 'debug' ) { $debug = $action; } else { die("Getopt::Long: unknown config parameter \"$opt\"") } } $prevconfig;}# Deprecated name.sub config (@) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -