📄 long.pm
字号:
# Getopt::Long.pm -- Universal options parsingpackage Getopt::Long;# RCS Status : $Id: Long.pm,v 2.74 2007/09/29 13:40:13 jv Exp $# Author : Johan Vromans# Created On : Tue Sep 11 15:00:12 1990# Last Modified By: Johan Vromans# Last Modified On: Sat Sep 29 15:38:55 2007# Update Count : 1571# Status : Released################ Copyright ################# This program is Copyright 1990,2007 by Johan Vromans.# This program is free software; you can redistribute it and/or# modify it under the terms of the Perl Artistic License or 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 5.004;use strict;use vars qw($VERSION);$VERSION = 2.37;# For testing versions only.use vars qw($VERSION_STRING);$VERSION_STRING = "2.37";use Exporter;use vars qw(@ISA @EXPORT @EXPORT_OK);@ISA = qw(Exporter);# Exported subroutines.sub GetOptions(@); # alwayssub GetOptionsFromArray($@); # on demandsub GetOptionsFromString($@); # on demandsub Configure(@); # on demandsub HelpMessage(@); # on demandsub VersionMessage(@); # in demandBEGIN { # Init immediately so their contents can be used in the 'use vars' below. @EXPORT = qw(&GetOptions $REQUIRE_ORDER $PERMUTE $RETURN_IN_ORDER); @EXPORT_OK = qw(&HelpMessage &VersionMessage &Configure &GetOptionsFromArray &GetOptionsFromString);}# 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 $caller $gnu_compat $auto_help $auto_version $longprefix);# Public subroutines.sub config(@); # deprecated name# Private subroutines.sub ConfigDefaults();sub ParseOptionSpec($$);sub OptCtl($);sub FindOption($$$$$);sub ValidValue ($$$$$);################ Local Variables ################# $requested_version holds the version that was mentioned in the 'use'# or 'require', if any. It can be used to enable or disable specific# features.my $requested_version = 0;################ 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 $gnu_compat = 0; # require --opt=val if value is optional $longprefix = "(--)"; # what does a long prefix look like}# Override import.sub import { my $pkg = shift; # package my @syms = (); # symbols to import my @config = (); # configuration my $dest = \@syms; # symbols first for ( @_ ) { if ( $_ eq ':config' ) { $dest = \@config; # config next next; } push(@$dest, $_); # push } # Hide one level and call super. local $Exporter::ExportLevel = 1; push(@syms, qw(&GetOptions)) if @syms; # always export GetOptions $pkg->SUPER::import(@syms); # And configure. Configure(@config) if @config;}################ 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+)/;ConfigDefaults();################ OO Interface ################package Getopt::Long::Parser;# Store a copy of the default configuration. Since ConfigDefaults has# just been called, what we get from Configure is the default.my $default_config = do { Getopt::Long::Configure ()};sub new { my $that = shift; my $class = ref($that) || $that; my %atts = @_; # Register the callers package. my $self = { caller_pkg => (caller)[0] }; bless ($self, $class); # Process config attributes. if ( defined $atts{config} ) { my $save = Getopt::Long::Configure ($default_config, @{$atts{config}}); $self->{settings} = Getopt::Long::Configure ($save); delete ($atts{config}); } # Else use default config. else { $self->{settings} = $default_config; } if ( %atts ) { # Oops die(__PACKAGE__.": unhandled attributes: ". join(" ", sort(keys(%atts)))."\n"); } $self;}sub configure { my ($self) = shift; # Restore settings, merge new settings in. my $save = Getopt::Long::Configure ($self->{settings}, @_); # Restore orig config and save the new config. $self->{settings} = Getopt::Long::Configure ($save);}sub getoptions { my ($self) = shift; # Restore config settings. my $save = Getopt::Long::Configure ($self->{settings}); # Call main routine. my $ret = 0; $Getopt::Long::caller = $self->{caller_pkg}; eval { # Locally set exception handler to default, otherwise it will # be called implicitly here, and again explicitly when we try # to deliver the messages. local ($SIG{__DIE__}) = '__DEFAULT__'; $ret = Getopt::Long::GetOptions (@_); }; # Restore saved settings. Getopt::Long::Configure ($save); # Handle errors and return value. die ($@) if $@; return $ret;}package Getopt::Long;################ Back to Normal ################# Indices in option control info.# Note that ParseOptions uses the fields directly. Search for 'hard-wired'.use constant CTL_TYPE => 0;#use constant CTL_TYPE_FLAG => '';#use constant CTL_TYPE_NEG => '!';#use constant CTL_TYPE_INCR => '+';#use constant CTL_TYPE_INT => 'i';#use constant CTL_TYPE_INTINC => 'I';#use constant CTL_TYPE_XINT => 'o';#use constant CTL_TYPE_FLOAT => 'f';#use constant CTL_TYPE_STRING => 's';use constant CTL_CNAME => 1;use constant CTL_DEFAULT => 2;use constant CTL_DEST => 3; use constant CTL_DEST_SCALAR => 0; use constant CTL_DEST_ARRAY => 1; use constant CTL_DEST_HASH => 2; use constant CTL_DEST_CODE => 3;use constant CTL_AMIN => 4;use constant CTL_AMAX => 5;# FFU.#use constant CTL_RANGE => ;#use constant CTL_REPEAT => ;# Rather liberal patterns to match numbers.use constant PAT_INT => "[-+]?_*[0-9][0-9_]*";use constant PAT_XINT => "(?:". "[-+]?_*[1-9][0-9_]*". "|". "0x_*[0-9a-f][0-9a-f_]*". "|". "0b_*[01][01_]*". "|". "0[0-7_]*". ")";use constant PAT_FLOAT => "[-+]?[0-9._]+(\.[0-9_]+)?([eE][-+]?[0-9_]+)?";sub GetOptions(@) { # Shift in default array. unshift(@_, \@ARGV); # Try to keep caller() and Carp consitent. goto &GetOptionsFromArray;}sub GetOptionsFromString($@) { my ($string) = shift; require Text::ParseWords; my $args = [ Text::ParseWords::shellwords($string) ]; $caller ||= (caller)[0]; # current context my $ret = GetOptionsFromArray($args, @_); return ( $ret, $args ) if wantarray; if ( @$args ) { $ret = 0; warn("GetOptionsFromString: Excess data \"@$args\" in string \"$string\"\n"); } $ret;}sub GetOptionsFromArray($@) { my ($argv, @optionlist) = @_; # local copy of the option descriptions my $argend = '--'; # option list terminator my %opctl = (); # table of option specs my $pkg = $caller || (caller)[0]; # current context # Needed if linkage is omitted. my @ret = (); # accum for non-options my %linkage; # linkage my $userlinkage; # user supplied HASH my $opt; # current option my $prefix = $genprefix; # current prefix $error = ''; if ( $debug ) { # Avoid some warnings if debugging. local ($^W) = 0; print STDERR ("Getopt::Long $Getopt::Long::VERSION (", '$Revision: 2.74 $', ") ", "called from package \"$pkg\".", "\n ", "argv: (@$argv)", "\n ", "autoabbrev=$autoabbrev,". "bundling=$bundling,", "getopt_compat=$getopt_compat,", "gnu_compat=$gnu_compat,", "order=$order,", "\n ", "ignorecase=$ignorecase,", "requested_version=$requested_version,", "passthrough=$passthrough,", "genprefix=\"$genprefix\",", "longprefix=\"$longprefix\".", "\n"); } # 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 ( @optionlist && ref($optionlist[0]) and UNIVERSAL::isa($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. # Be careful not to interpret '<>' as option starters. if ( @optionlist && $optionlist[0] =~ /^\W+$/ && !($optionlist[0] eq '<>' && @optionlist > 0 && ref($optionlist[1])) ) { $prefix = shift (@optionlist); # Turn into regexp. Needs to be parenthesized! $prefix =~ s/(\W)/\\$1/g; $prefix = "([" . $prefix . "])"; print STDERR ("=> prefix=\"$prefix\"\n") if $debug; } # Verify correctness of optionlist. %opctl = (); while ( @optionlist ) { my $opt = shift (@optionlist); unless ( defined($opt) ) { $error .= "Undefined argument in option spec\n"; next; } # Strip leading prefix so people can specify "--foo=i" if they like. $opt = $+ if $opt =~ /^$prefix+(.*)$/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"; # Kill the linkage (to avoid another error). shift (@optionlist) if @optionlist && ref($optionlist[0]); next; } $linkage{'<>'} = shift (@optionlist); next; } # Parse option spec. my ($name, $orig) = ParseOptionSpec ($opt, \%opctl); unless ( defined $name ) { # Failed. $orig contains the error message. Sorry for the abuse. $error .= $orig; # Kill the linkage (to avoid another error). shift (@optionlist) if @optionlist && ref($optionlist[0]); next; } # 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->{$orig} && ref($userlinkage->{$orig}) ) { print STDERR ("=> found userlinkage for \"$orig\": ", "$userlinkage->{$orig}\n") if $debug; unshift (@optionlist, $userlinkage->{$orig}); } 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 \"$orig\" to $optionlist[0]\n") if $debug; my $rl = ref($linkage{$orig} = shift (@optionlist)); if ( $rl eq "ARRAY" ) { $opctl{$name}[CTL_DEST] = CTL_DEST_ARRAY; } elsif ( $rl eq "HASH" ) { $opctl{$name}[CTL_DEST] = CTL_DEST_HASH; } elsif ( $rl eq "SCALAR" || $rl eq "REF" ) {# if ( $opctl{$name}[CTL_DEST] == CTL_DEST_ARRAY ) {# my $t = $linkage{$orig};# $$t = $linkage{$orig} = [];# }# elsif ( $opctl{$name}[CTL_DEST] == CTL_DEST_HASH ) {# }# else { # Ok.# } } elsif ( $rl eq "CODE" ) { # Ok. } else { $error .= "Invalid option linkage for \"$opt\"\n"; } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -