📄 long.pm
字号:
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 ) { if ( defined $aliases{$opt} ) { print STDERR ("=> alias \"$opt\" -> \"$aliases{$opt}\"\n") if $debug; $opt = $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; local ($@); eval { &{$linkage{$opt}}($opt, $arg); }; print STDERR ("=> die($@)\n") if $debug && $@ ne ''; if ( $@ =~ /^!/ ) { if ( $@ =~ /^!FINISH\b/ ) { $goon = 0; } } elsif ( $@ ne '' ) { warn ($@); $error++; } } 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; } } } } # Not an option. Save it if we $PERMUTE and don't have a <>. elsif ( $order == $PERMUTE ) { # Try non-options call-back. my $cb; if ( (defined ($cb = $linkage{'<>'})) ) { local ($@); eval { &$cb ($tryopt); }; print STDERR ("=> die($@)\n") if $debug && $@ ne ''; if ( $@ =~ /^!/ ) { if ( $@ =~ /^!FINISH\b/ ) { $goon = 0; } } elsif ( $@ ne '' ) { warn ($@); $error++; } } else { print STDERR ("=> saving \"$tryopt\" ", "(not an option, may permute)\n") if $debug; push (@ret, $tryopt); } next; } # ...otherwise, terminate. else { # Push this one back and exit. unshift (@ARGV, $tryopt); return ($error == 0); } } # Finish. if ( $order == $PERMUTE ) { # Push back accumulated arguments print STDERR ("=> restoring \"", join('" "', @ret), "\"\n") if $debug && @ret > 0; unshift (@ARGV, @ret) if @ret > 0; } return ($error == 0);}# Option lookup.sub FindOption ($$$$$$$) { # returns (1, $opt, $arg, $dsttype, $incr, $key) if okay, # returns (0) otherwise. my ($prefix, $argend, $opt, $opctl, $bopctl, $names, $aliases) = @_; my $key; # hash key for a hash option my $arg; print STDERR ("=> find \"$opt\", prefix=\"$prefix\"\n") if $debug; return 0 unless $opt =~ /^$prefix(.*)$/s; return 0 if $opt eq "-" && !defined $opctl->{""}; $opt = $+; my ($starter) = $1; print STDERR ("=> split \"$starter\"+\"$opt\"\n") if $debug; my $optarg = undef; # value supplied with --opt=value my $rest = undef; # remainder from unbundling # If it is a long option, it may include the value. if (($starter eq "--" || ($getopt_compat && !$bundling)) && $opt =~ /^([^=]+)=(.*)$/s ) { $opt = $1; $optarg = $2; print STDERR ("=> option \"", $opt, "\", optarg = \"$optarg\"\n") if $debug; } #### Look it up ### my $tryopt = $opt; # option to try my $optbl = $opctl; # table to look it up (long names) my $type; my $dsttype = ''; my $incr = 0; if ( $bundling && $starter eq '-' ) { # 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 ''; $optbl = $bopctl; # look it up in the short names table # If bundling == 2, long options can override bundles. if ( $bundling == 2 and defined ($rest) and defined ($type = $opctl->{$tryopt.$rest}) ) { print STDERR ("=> $starter$tryopt rebundled to ", "$starter$tryopt$rest\n") if $debug; $tryopt .= $rest; undef $rest; } } # Try auto-abbreviation. elsif ( $autoabbrev ) { # Downcase if allowed. $tryopt = $opt = lc ($opt) if $ignorecase; # 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 ) { $_ = $aliases->{$_} if defined $aliases->{$_}; $hit{$_} = 1; } # Now see if it really is ambiguous. unless ( keys(%hit) == 1 ) { return (0) if $passthrough; warn ("Option ", $opt, " is ambiguous (", join(", ", @hits), ")\n"); $error++; undef $opt; return (1, $opt,$arg,$dsttype,$incr,$key); } @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. $type = $optbl->{$tryopt} unless defined $type; unless ( defined $type ) { return (0) if $passthrough; warn ("Unknown option: ", $opt, "\n"); $error++; return (1, $opt,$arg,$dsttype,$incr,$key); } # Apparently valid. $opt = $tryopt; print STDERR ("=> found \"$type\" for \"", $opt, "\"\n") if $debug; #### Determine argument status #### # If it is an option w/o argument, we're almost finished with it. 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 '+' ) { $arg = 1; # supply explicit value $incr = $type eq '+'; } else { substr ($opt, 0, 2) = ''; # strip NO prefix $arg = 0; # supply explicit value } unshift (@ARGV, $starter.$rest) if defined $rest; return (1, $opt,$arg,$dsttype,$incr,$key); } # Get mandatory status and type info. my $mand; ($mand, $type, $dsttype, $key) = $type =~ /^(.)(.)([@%]?)$/; # Check if there is an option argument available. if ( $gnu_compat ) { return (1, $opt, $optarg, $dsttype, $incr, $key) if defined $optarg; return (1, $opt, $type eq "s" ? '' : 0, $dsttype, $incr, $key) if $mand eq ':'; } # 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 eq "=" ) { return (0) if $passthrough; warn ("Option ", $opt, " requires an argument\n"); $error++; undef $opt; } return (1, $opt, $type eq "s" ? '' : 0, $dsttype, $incr, $key); } # 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. $key = undef; if ($dsttype eq '%' && defined $arg) { ($key, $arg) = ($arg =~ /^([^=]*)=(.*)$/s) ? ($1, $2) : ($arg, 1); } #### Check if the argument is valid for this option #### if ( $type eq "s" ) { # string # A mandatory string takes anything. return (1, $opt,$arg,$dsttype,$incr,$key) if $mand eq "="; # An optional string takes almost anything. return (1, $opt,$arg,$dsttype,$incr,$key) if defined $optarg || defined $rest; return (1, $opt,$arg,$dsttype,$incr,$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 "n" || $type eq "i" ) { # numeric/integer if ( $bundling && defined $rest && $rest =~ /^([-+]?[0-9]+)(.*)$/s ) { $arg = $1; $rest = $2; unshift (@ARGV, $starter.$rest) if defined $rest && $rest ne ''; } elsif ( $arg !~ /^[-+]?[0-9]+$/ ) { if ( defined $optarg || $mand eq "=" ) { if ( $passthrough ) { unshift (@ARGV, defined $rest ? $starter.$rest : $arg) unless defined $optarg; return (0); } warn ("Value \"", $arg, "\" invalid for option ", $opt, " (number expected)\n"); $error++; undef $opt; # Push back. unshift (@ARGV, $starter.$rest) if defined $rest; } else { # Push back. unshift (@ARGV, defined $rest ? $starter.$rest : $arg); # Supply default value. $arg = 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 =~ /^([-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)(.*)$/s ) { $arg = $1; $rest = $+; unshift (@ARGV, $starter.$rest) if defined $rest && $rest ne ''; } elsif ( $arg !~ /^[-+]?[0-9.]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/ ) { if ( defined $optarg || $mand eq "=" ) { 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++; undef $opt; # Push back. unshift (@ARGV, $starter.$rest) if defined $rest; } else { # Push back. unshift (@ARGV, defined $rest ? $starter.$rest : $arg); # Supply default value. $arg = 0.0; } } } else { Croak ("GetOpt::Long internal error (Can't happen)\n"); } return (1, $opt, $arg, $dsttype, $incr, $key);}# 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 ]; if ( ref($options[0]) eq 'ARRAY' ) { ( $error, $debug, $major_version, $minor_version, $autoabbrev, $getopt_compat, $ignorecase, $bundling, $order, $gnu_compat, $passthrough, $genprefix ) = @{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') ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -