File Coverage

blib/lib/Getopt/Euclid.pm
Criterion Covered Total %
statement 614 652 94.1
branch 231 274 84.3
condition 61 80 76.2
subroutine 59 61 96.7
pod 7 7 100.0
total 972 1074 90.5


line stmt bran cond sub pod time code
1             package Getopt::Euclid;
2              
3 66     66   10053185 use version; our $VERSION = version->declare('0.4.5');
  66         84242  
  66         491  
4              
5 66     66   14864 use warnings;
  66         158  
  66         4678  
6 66     66   717 use strict;
  66         209  
  66         1957  
7 66     66   1132 use 5.005000; # perl 5.5.0
  66         516  
8 66     66   375 use Carp;
  66         146  
  66         6270  
9 66     66   38265 use Symbol ();
  66         91872  
  66         2477  
10 66     66   531 use re 'eval'; # for matcher regex
  66         199  
  66         4071  
11 66     66   38351 use Pod::Select;
  66         186802  
  66         9765  
12 66     66   40077 use Pod::PlainText;
  66         404370  
  66         5203  
13 66     66   579 use File::Basename;
  66         122  
  66         7113  
14 66     66   32632 use File::Spec::Functions qw(splitpath catpath catfile);
  66         58293  
  66         6685  
15 66     66   521 use List::Util qw( first );
  66         156  
  66         7763  
16 66     66   57143 use Text::Balanced qw(extract_multiple extract_bracketed extract_variable extract_delimited);
  66         943714  
  66         191310  
17              
18              
19             # Set some module variables
20             my $skip_keyword = 'Getopt::Euclid'; # Ignore files with a first line containing this keyword.
21             my $pod_file_msg = "# This file was generated dynamically by $skip_keyword. Do not edit it.";
22              
23             my $has_run = 0;
24             my $has_processed_pod = 0;
25             my $export_lvl = 1;
26             my @pod_names;
27             my $minimal_keys;
28             my $vars_prefix;
29             my $defer = 0;
30             my $matcher;
31             my %requireds;
32             my %options;
33             my %longnames;
34             our $man; # --man message
35             my $help; # --help message
36             my $usage; # --usage message
37             my $version; # --version message
38              
39             my $optional_re;
40             $optional_re = qr{ \[ [^[]* (?: (??{$optional_re}) [^[]* )* \] }xms;
41              
42              
43             # Global variables
44             our $SCRIPT_NAME;
45             our $SCRIPT_VERSION; # for ticket # 55259
46              
47              
48             # Convert arg specification syntax to Perl regex syntax
49              
50             my %std_matcher_for = (
51             integer => '[+-]?\\d+(?:[eE][+]?\d+)?',
52             number => '[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\d+)?',
53             input => '\S+',
54             output => '\S+',
55             string => '\S+',
56             q{} => '\S+',
57             );
58              
59             _make_equivalent(
60             \%std_matcher_for,
61             integer => [qw( int i +int +i 0+int 0+i +integer 0+integer )],
62             number => [qw( num n +num +n 0+num 0+n +number 0+number )],
63             input => [qw( readable in )],
64             output => [qw( writable writeable out )],
65             string => [qw( str s )],
66             );
67              
68             my %std_constraint_for = (
69             'string' => sub { 1 }, # Always okay (matcher ensures this)
70             'integer' => sub { 1 }, # Always okay (matcher ensures this)
71             '+integer' => sub { $_[0] > 0 },
72             '0+integer' => sub { $_[0] >= 0 },
73             'number' => sub { 1 }, # Always okay (matcher ensures this)
74             '+number' => sub { $_[0] > 0 },
75             '0+number' => sub { $_[0] >= 0 },
76             'input' => sub { $_[0] eq '-' || -r $_[0] },
77             'output' => sub {
78             my ( $vol, $dir ) = splitpath( $_[0] );
79             $dir = ($vol && $dir) ? catpath($vol, $dir) : '.';
80             $_[0] eq '-' ? 1 : -e $_[0] ? -w $_[0] : -w $dir;
81             },
82             );
83              
84             _make_equivalent(
85             \%std_constraint_for,
86             'integer' => [qw( int i )],
87             '+integer' => [qw( +int +i )],
88             '0+integer' => [qw( 0+int 0+i )],
89             'number' => [qw( num n )],
90             '+number' => [qw( +num +n )],
91             '0+number' => [qw( 0+num 0+n )],
92             'string' => [qw( str s )],
93             'input' => [qw( in readable )],
94             'output' => [qw( out writable writeable )],
95             );
96              
97              
98             sub Getopt::Euclid::Importer::DESTROY {
99 0 0 0 0   0 return if $has_run || $^C; # No errors when only compiling
100 0         0 croak '.pm file cannot define an explicit import() when using Getopt::Euclid';
101             }
102              
103              
104             sub import {
105 69     69   1904 shift @_;
106 69   100     208 @_ = grep { !( /:minimal_keys/ and $minimal_keys = 1 ) } @_;
  11         104  
107 69   66     2350 @_ = grep { !( /:vars(?:<(\w+)>)?/ and $vars_prefix = $1 || 'ARGV_' ) } @_;
  6         58  
108 69   100     173 @_ = grep { !( /:defer/ and $defer = 1 ) } @_;
  4         35  
109 69         437 croak "Unknown mode ('$_')" for @_;
110 68 100       2017 $export_lvl++ if not $defer;
111              
112             # No POD parsing and argument processing in Perl compile mode (ticket 34195)
113 68 100       389 return if $^C;
114              
115             # Get name of caller program and its modules in @pod_names
116 67 100       269 return unless _get_pod_names();
117              
118             # Extract POD of given files
119 63         705 __PACKAGE__->process_pods( [reverse @pod_names] );
120 63         190 undef @pod_names;
121 63         164 $has_run = 1;
122              
123             # Parse POD + parse and export arguments
124              
125             ######
126             #use Data::Dumper; print "ARGV: ".Dumper(\@ARGV);
127             ######
128              
129 63 100       670 __PACKAGE__->process_args( \@ARGV ) unless $defer;
130              
131 36         6248 return 1;
132             }
133              
134              
135             sub process_pods {
136             # Extract POD content from list of Perl scripts (.pl) and modules (.pm) and
137             # their corresponding .pod file if available. When given the argument
138             # {-strict => 1}, do not look for .pod files.
139 64     64 1 308898 my ($self, $perl_files, $args) = @_;
140              
141 64         206 my $pod_string = '';
142 64 50       1250 open my $pod_fh, '>', \$pod_string
143             or croak "Could not open filehandle to variable because $!";
144 64         251 for my $perl_file (@$perl_files) {
145              
146 67         143 my $got_pod_file = 0;
147              
148 67 50       285 if ( not $args->{-strict} ) {
149              
150             # Find corresponding .pod file
151 67         6436 my ($name_re, $path, $suffix) = fileparse($perl_file, qr/\.[^.]*/);
152 67         916 my $pod_file = catfile( $path, $name_re.'.pod' );
153              
154             # Get POD either from .pod file (preferably) or from Perl file
155 67 100       3881 if ( -e $pod_file ) {
156             # Get .pod file content
157 6 50       261 open my $in, '<', $pod_file
158             or croak "Could not open file $pod_file because $!";
159 6         179 my $first_line = <$in>;
160 6         22 chomp $first_line;
161 6 100       113 if ( not ($first_line =~ m/$skip_keyword/) ) {
162             # Skip G::E auto-generated files since they lack important data
163 4         26 print $pod_fh "$first_line\n";
164 4         163 print $pod_fh $_ while <$in>;
165 4         12 $got_pod_file = 1;
166             }
167 6         94 close $in;
168             }
169             }
170              
171 67 100       315 if (not $got_pod_file) {
172             # Parse POD content of Perl file
173 63         619 podselect( {-output => $pod_fh}, $perl_file );
174             }
175 67 100       192472 print $pod_fh "\n" if $pod_string;
176              
177             }
178 64         198 close $pod_fh;
179 64         220 $man = $pod_string;
180 64         279 return 1;
181             }
182              
183              
184             sub process_args {
185             # First, parse the POD specifications. Then, parse the given array of
186             # arguments (\@ARGV or other) and populate %ARGV (or export specific
187             # variable names).
188 70     70 1 1217416 my ($self, $args, $options) = @_;
189              
190             # Parse POD
191 70 100       277 if (not $has_processed_pod) {
192 64         291 _parse_pod();
193 51         184 $has_processed_pod = 1;
194             }
195              
196             # Set options for argument parsing
197 57 100       287 if (defined $options) {
198 2 100       11 if (exists $options->{-minimal_keys}) {
199 1         3 $minimal_keys = 1;
200             }
201 2 100       8 if (exists $options->{-vars}) {
202 1         5 $vars_prefix = $options->{-vars};
203             }
204             }
205              
206 57         218 %ARGV = ();
207              
208             # Handle standard args...
209 57 50   629   912 if ( first { $_ eq '--man' } @$args ) {
  629 50       1428  
    50          
    50          
    50          
210 0         0 _print_pod( __PACKAGE__->man(), 'paged' );
211 0         0 exit;
212 629     629   1155 } elsif ( first { $_ eq '--usage' } @$args ) {
213 0         0 print __PACKAGE__->usage();
214 0         0 exit;
215 629     629   1238 } elsif ( first { $_ eq '--help' } @$args ) {
216 0         0 _print_pod( __PACKAGE__->help(), 'paged' );
217 0         0 exit;
218 629     629   1151 } elsif ( first { $_ eq '--version' } @$args ) {
219 0         0 print __PACKAGE__->version();
220 0         0 exit;
221 629     629   987 } elsif ( first { $_ eq '--podfile' } @$args ) {
222             # Option meant for authors
223 0         0 my $podfile = podfile( );
224 0         0 print "Wrote POD manual in file $podfile\n";
225 0         0 exit;
226             }
227              
228             # Subroutine to report problems during parsing...
229             *_bad_arglist = sub {
230 16     16   52 my (@msg) = @_;
231 16         58 my $msg = join q{}, @msg;
232 16         53 $msg = _rectify_arg($msg);
233 16         126 $msg =~ s/\n?\z/\n/xms;
234 16         171 warn "$msg\nTry this for usage help: $SCRIPT_NAME --help\n".
235             "Or this for full manual: $SCRIPT_NAME --man\n\n";
236 16         126 exit 2; # Traditional "bad arg list" value
237 57         898 };
238              
239             # Run matcher...
240 57         221 my $argv = join( q{ }, map { $_ = _escape_arg($_) } @$args );
  629         1141  
241 57         640 my $all_args_ref = { %options, %requireds };
242 57 100       419 if ( my $error = _doesnt_match( $matcher, $argv, $all_args_ref ) ) {
243 7         34 _bad_arglist($error);
244             }
245              
246             # Check that all requireds have been found...
247 50         120 my @missing;
248 50         281 while ( my ($req) = each %requireds ) {
249 101 100       389 push @missing, "\t$req\n" if !exists $ARGV{$req};
250             }
251             _bad_arglist(
252 50 50       171 'Missing required argument',
    100          
253             ( @missing == 1 ? q{} : q{s} ),
254             ":\n", @missing
255             ) if @missing;
256              
257             # Back-translate \0-quoted spaces and \1-quoted tabs...
258 49         255 _rectify_all_args();
259              
260             # Check exclusive variables, variable constraints and fill in defaults...
261 49         255 _verify_args($all_args_ref);
262              
263             # Clean up @$args since everything must have been parsed
264 41         198 @$args = ();
265              
266             # Clean up %ARGV
267 41         158 for my $arg_name ( keys %ARGV ) {
268              
269             # Flatten non-repeatables...
270 260         552 my $vals = delete $ARGV{$arg_name};
271 260         713 my $repeatable = $all_args_ref->{$arg_name}{is_repeatable};
272 260 100       611 if ($repeatable) {
273 4         7 pop @{$vals};
  4         9  
274             }
275              
276 260         397 for my $val ( @{$vals} ) {
  260         548  
277 261         362 my $var_count = keys %{$val};
  261         486  
278             $val = $var_count == 0
279             ? 1 # Boolean -> true
280             : $var_count == 1
281 261 100       853 ? ( values %{$val} )[0] # Single var -> var's val
  215 50       596  
282             : $val # Otherwise keep hash
283             ;
284 261         685 my $false_vals = $all_args_ref->{$arg_name}{false_vals};
285 261         434 my %vars_opt_vals;
286              
287 261         639 for my $arg_flag ( _get_variants($arg_name) ) {
288 481         830 my $variant_val = $val;
289 481 100 100     1539 if ( $false_vals && $arg_flag =~ m{\A $false_vals \z}xms ) {
290 14 100       44 $variant_val = $variant_val ? 0 : 1;
291             }
292              
293 481 100       1041 if ($repeatable) {
294 25         27 push @{ $ARGV{$arg_flag} }, $variant_val;
  25         80  
295             } else {
296 456         1077 $ARGV{$arg_flag} = $variant_val;
297             }
298 481 100       1121 $vars_opt_vals{$arg_flag} = $ARGV{$arg_flag} if $vars_prefix;
299             }
300              
301 261 100       974 if ($vars_prefix) {
302 28         124 _minimize_entries_of( \%vars_opt_vals );
303 28         85 my $maximal = _longestname( keys %vars_opt_vals );
304 28         106 _export_var( $vars_prefix, $maximal, $vars_opt_vals{$maximal} );
305 28         147 delete $longnames{$maximal};
306             }
307             }
308             }
309              
310 41 100       232 if ($vars_prefix) {
311              
312             # Export any unspecified options to keep use strict happy
313 3         18 while ( my ($opt_name, $arg_name) = each %longnames ) {
314 17         36 my $arg_info = $all_args_ref->{$arg_name};
315 17         45 my $val;
316 17 100 100     82 if ( $arg_info->{is_repeatable} or $arg_name =~ />\.\.\./ ) {
317             # Empty arrayref for repeatable options
318 3         7 $val = [];
319             } else {
320 14 100       26 if (keys %{ $arg_info->{var} } > 1) {
  14         72  
321             # Empty hashref for non-repeatable options with multiple placeholders
322 1         3 $val = {};
323             }
324             }
325 17         63 _export_var( $vars_prefix, $opt_name, $val );
326             }
327             }
328              
329              
330 41 100       144 if ($minimal_keys) {
331 6         23 _minimize_entries_of( \%ARGV );
332             }
333              
334 41         261 return 1;
335             }
336              
337              
338             sub podfile {
339             # Write the given POD doc into a .pod file, overwriting any existing .pod file
340 1 50   1 1 1356 return if not -e $0;
341 1         58 my ($name_re, $path, $suffix) = fileparse($0, qr/\.[^.]*/);
342 1         14 my $pod_file = catfile( $path, $name_re.'.pod' );
343 1 50       363 open my $out_fh, '>', $pod_file or croak "Could not write file $pod_file because $!";
344 1         11 print $out_fh $pod_file_msg."\n\n".__PACKAGE__->man();
345 1         62 close $out_fh;
346 1         13 return $pod_file;
347             }
348              
349              
350             sub man {
351 6     6 1 1596380 return $man;
352             }
353              
354              
355             sub usage {
356 1     1 1 3776 return $usage;
357             }
358              
359              
360             sub help {
361 2     2 1 379656 return $help;
362             }
363              
364              
365             sub version {
366 1     1 1 1358 return $version;
367             }
368              
369              
370             # # # # # # # # Utility subs # # # # # # # #
371              
372             # Recursively remove decorations on %ARGV keys
373              
374             sub AUTOLOAD {
375 9     9   21 our $AUTOLOAD;
376 9         59 $AUTOLOAD =~ s{.*::}{main::}xms;
377 66     66   752 no strict 'refs';
  66         135  
  66         660532  
378 9         99 goto &$AUTOLOAD;
379             }
380              
381              
382             sub _parse_pod {
383             # Set up parsing rules...
384 64     64   332 my $space_re = qr{ [^\S\n]* }xms;
385 64         204 my $head_start_re = qr{ ^=head1 }xms;
386 64         1781 my $head_end_re = qr{ (?= $head_start_re | \z) }xms;
387 64         339 my $pod_cmd_re = qr{ = [^\W\d]\w+ [^\n]* (?= \n\n )}xms;
388 64         2826 my $pod_cut_re = qr{ (?! \n\n ) = cut $space_re (?= \n\n )}xms;
389              
390 64         4021 my $name_re = qr{ $space_re NAME $space_re \n }xms;
391 64         3482 my $vers_re = qr{ $space_re VERSION $space_re \n }xms;
392 64         3586 my $usage_re = qr{ $space_re USAGE $space_re \n }xms;
393              
394 64         281 my $std_re = qr{ STANDARD | STD | PROGRAM | SCRIPT | CLI | COMMAND(?:-|\s)?LINE }xms;
395 64         3660 my $arg_re = qr{ $space_re (?:PARAM(?:ETER)?|ARG(?:UMENT)?)S? }xms;
396              
397 64         11165 my $options_re = qr{ $space_re $std_re? $space_re OPTION(?:AL|S)? $arg_re? $space_re \n }xms;
398 64         10759 my $required_re = qr{ $space_re $std_re? $space_re (?:REQUIRED|MANDATORY) $arg_re? $space_re \n }xms;
399              
400 64         389 my $euclid_arg = qr{ ^=item \s* ([^\n]*?) \s* \n\s*\n
401             (
402             .*?
403             (?:
404             ^=for \s* (?i: Euclid) .*? \n\s*\n
405             | (?= ^=[^\W\d]\w* | \z)
406             )
407             )
408             }xms;
409              
410             # Clean up line delimiters
411 64         2912 $man =~ s{ [\n\r] }{\n}gx;
412              
413             # Clean up significant entities...
414 64         344 $man =~ s{ E }{<}gxms;
415 64         210 $man =~ s{ E }{>}gxms;
416              
417             # Put program name in man
418 64 100       2120 $SCRIPT_NAME = (-e $0) ? (splitpath $0)[-1] : 'one-liner';
419 64         7636 $man =~ s{ ($head_start_re $name_re \s*) .*? (- .*)? $head_end_re }
420 52 100       1378 {$1.$SCRIPT_NAME.($2 ? " $2" : "\n\n")}xems;
421              
422             # Put version number in man
423 64         6571 ($SCRIPT_VERSION) =
424             $man =~ m/$head_start_re $vers_re .*? (\d+(?:[._]\d+)+) .*? $head_end_re /xms;
425 64 100       415 if ( !defined $SCRIPT_VERSION ) {
426 14         44 $SCRIPT_VERSION = $main::VERSION;
427             }
428 64 100       581 if ( !defined $SCRIPT_VERSION ) {
429 14 100       765 $SCRIPT_VERSION = (-e $0) ? localtime((stat $0)[9]) : 'one-liner';
430             }
431 64         7113 $man =~ s{ ($head_start_re $vers_re \s*) .*? (\s*) $head_end_re }
432             {$1This document refers to $SCRIPT_NAME version $SCRIPT_VERSION $2}xms;
433              
434             # Extra info from PODs
435 64         311 my ($options, $opt_name, $required, $req_name, $licence);
436 64         13660 while ($man =~ m/$head_start_re ($required_re) (.*?) $head_end_re /gxms) {
437             # Required arguments
438 51         461 my ( $more_req_name, $more_required ) = ($1, $2);
439 51 50       228 $req_name = $more_req_name if not defined $req_name;
440 51   50     1192 $required = ( $more_required || q{} ) . ( $required || q{} );
      50        
441             }
442 64         15404 while ($man =~ m/$head_start_re ($options_re) (.*?) $head_end_re /gxms) {
443             # Optional arguments
444 55         516 my ( $more_opt_name, $more_options ) = ($1, $2);
445 55 50       275 $opt_name = $more_opt_name if not defined $opt_name;
446 55   50     1001 $options = ( $more_options || q{} ) . ( $options || q{} );
      50        
447             }
448 64         9537 while ($man =~ m/$head_start_re [^\n]+ (?i: licen[sc]e | copyright ) .*? \n \s* (.*?) \s* $head_end_re /gxms) {
449             # License information
450 47         294 my ($more_licence) = ($1, $2);
451 47   50     612 $licence = ( $more_licence || q{} ) . ( $licence || q{} );
      50        
452             }
453              
454             # Clean up interface titles...
455 64         238 for my $name_re ( $opt_name, $req_name ) {
456 128 100       1145 next if !defined $name_re;
457 106         856 $name_re =~ s{\A \s+ | \s+ \z}{}gxms;
458             }
459              
460             # Extract the actual interface and store each arg entry into a hash of specifications...
461 64         152 my $seq = 0;
462 64         169 my $seen = {};
463 64   100     17921 while ( ( $required || q{} ) =~ m{ $euclid_arg }gxms ) {
464 120         589 $seen = _register_specs( $1, $2, $seq, \%requireds, \%longnames, $seen );
465 120         1611 $seq++;
466             }
467 64   100     12652 while ( ( $options || q{} ) =~ m{ $euclid_arg }gxms ) {
468 418         1328 $seen = _register_specs( $1, $2, $seq, \%options, \%longnames, $seen );
469 417         6661 $seq++;
470             }
471 63         255 undef $seen;
472 63         344 _minimize_entries_of( \%longnames );
473              
474             # Extract Euclid information...
475 63         453 my $all_specs = {%requireds, %options};
476 63         331 _process_euclid_specs( $all_specs );
477              
478             # Insert default values (if any) in the program's documentation
479 52         247 $required = _insert_default_values(\%requireds);
480 51         189 $options = _insert_default_values(\%options );
481              
482             # One-line representation of interface...
483             my $arg_summary = join ' ', (sort
484 51         312 { $requireds{$a}{'seq'} <=> $requireds{$b}{'seq'} }
  142         447  
485             (keys %requireds));
486              
487 51         576 1 while $arg_summary =~ s/\[ [^][]* \]//gxms;
488              
489 51 100       230 if ($opt_name) {
490 42 100       169 $arg_summary .= ' ' if $arg_summary;
491 42         180 $arg_summary .= lc "[$opt_name]";
492             }
493 51         348 $arg_summary =~ s/\s+/ /gxms;
494              
495             # Manual message
496 51         7040 $man =~ s{ ($head_start_re $usage_re \s*) .*? (\s*) $head_end_re } {$1$SCRIPT_NAME $arg_summary$2}xms;
497 51         14903 $man =~ s{ ($head_start_re $required_re \s*) .*? (\s*) $head_end_re } {$1$required$2}xms;
498 51         17467 $man =~ s{ ($head_start_re $options_re \s*) .*? (\s*) $head_end_re } {$1$options$2}xms;
499              
500             # Usage message
501 51         274 $usage = " $SCRIPT_NAME $arg_summary\n";
502 51         150 $usage .= " $SCRIPT_NAME --help\n";
503 51         246 $usage .= " $SCRIPT_NAME --man\n";
504 51         415 $usage .= " $SCRIPT_NAME --usage\n";
505 51         166 $usage .= " $SCRIPT_NAME --version\n";
506              
507             # Help message
508 51         242 $help = "=head1 \L\uUsage:\E\n\n$usage\n";
509 51 100 100     608 $help .= "=head1 \L\u$req_name:\E\n\n$required\n\n"
510             if ( $req_name || q{} ) =~ /\S/;
511 51 100 100     581 $help .= "=head1 \L\u$opt_name:\E\n\n$options\n\n"
512             if ( $opt_name || q{} ) =~ /\S/;
513              
514 51         137 $usage = "Usage:\n".$usage;
515              
516             # Version message
517 51         146 $version = "This is $SCRIPT_NAME version $SCRIPT_VERSION\n";
518 51 100       212 $version .= "\n$licence\n" if $licence;
519              
520             # Convert arg specifications to regexes...
521 51         292 _convert_to_regex( $all_specs );
522              
523             # Build matcher...
524 51         253 my @arg_list = ( values(%requireds), values(%options) );
525 435         1583 $matcher = join '|', map { $_->{matcher} }
526 1017         1852 sort( { $b->{name} cmp $a->{name} } grep { $_->{name} =~ /^[^<]/ } @arg_list ),
  435         1268  
527 51         202 sort( { $a->{seq} <=> $b->{seq} } grep { $_->{name} =~ /^[<]/ } @arg_list );
  1         4  
  435         909  
528 51         399 $matcher .= '|(?> (.+)) (?{ push @errors, $^N }) (?!)';
529 51         153 $matcher = '(?:' . $matcher . ')';
530              
531 51         13680 return 1;
532             }
533              
534              
535             sub _register_specs {
536 538     538   2172 my ($name_re, $spec, $seq, $storage, $longnames, $seen) = @_;
537 538         1274 my @variants = _get_variants($name_re);
538 538         3203 $storage->{$name_re} = {
539             seq => $seq,
540             src => $spec,
541             name => $name_re,
542             variants => \@variants,
543             };
544 538 100       1282 if ($minimal_keys) {
545 41         84 my $minimal = _minimize_name($name_re);
546             croak "Internal error: minimalist mode caused arguments ".
547             "'$name_re' and '".$seen->{$minimal}."' to clash"
548 41 100       285 if $seen->{$minimal};
549 40         97 $seen->{$minimal} = $name_re;
550             }
551 537         1340 $longnames->{ _longestname(@variants) } = $name_re;
552 537         1543 return $seen;
553             }
554              
555              
556             sub _process_euclid_specs {
557 63     63   149 my ($args) = @_;
558 63         171 my %all_var_list;
559             my %excluded_by_def;
560              
561             ARG:
562 63         386 while ( (undef, my $arg) = each %$args ) {
563              
564             # Validate and record variable names seen here...
565 483         1299 my $var_list = _validate_name( $arg->{name} );
566 481         1794 while (my ($var_name, undef) = each %$var_list) {
567 375         1359 $all_var_list{$var_name} = undef;
568             }
569              
570             # Process arguments with a Euclid specification further
571 481 100       3131 $arg->{src} =~ s{^ =for \s+ Euclid\b [^\n]* \s* (.*) \z}{}ixms
572             or next ARG;
573 238         661 my $info = $1;
574              
575 238         756 $arg->{is_repeatable} = $info =~ s{^ \s* repeatable \s*? $}{}xms;
576              
577 238         380 my @false_vals;
578 238         888 while ( $info =~ s{^ \s* false \s*[:=] \s* ([^\n]*)}{}xms ) {
579 10         26 my $regex = $1;
580 10         61 1 while $regex =~ s/ \[ ([^]]*) \] /(?:$1)?/gxms;
581 10         45 $regex =~ s/ (\s+) /$1.'[\\s\\0\\1]*'/egxms;
  0         0  
582 10         36 push @false_vals, $regex;
583             }
584 238 100       574 if (@false_vals) {
585 8         35 $arg->{false_vals} = '(?:' . join( '|', @false_vals ) . ')';
586             }
587              
588 238         1366 while (
589             $info =~ m{\G \s* (([^.]+)\.([^:=\s]+) \s*[:=]\s* ([^\n]*)) }gcxms )
590             {
591 405         2023 my ( $spec, $var, $field, $val ) = ( $1, $2, $3, $4 );
592              
593             # Check for misplaced fields...
594 405 100       6171 if ( $arg->{name} !~ m{\Q<$var>}xms ) {
595 1         8 _fail( "Invalid constraint: $spec\n(No <$var> placeholder in ".
596             "argument: $arg->{name})" );
597             }
598              
599             # Decode...
600 404 100 100     1839 if ( $field eq 'type.error' ) {
    100          
    100          
    100          
    100          
601 2         11 $arg->{var}{$var}{type_error} = $val;
602             } elsif ( $field eq 'type' ) {
603 239         607 $val = _qualify_variables_fully( $val );
604 239         1414 my ( $matchtype, $comma, $constraint ) =
605             $val =~ m{(/(?:\.|.)+/ | [^,\s]+)\s*(?:(,))?\s*(.*)}xms;
606 239         1061 $arg->{var}{$var}{type} = $matchtype;
607 239 100 66     960 if ( $comma && length $constraint ) {
    100          
608 18         1039 ( $arg->{var}{$var}{constraint_desc} = $constraint ) =~
609             s/\s*\b\Q$var\E\b\s*//g;
610 18         289 $constraint =~ s/\b\Q$var\E\b/\$_[0]/g;
611 18 50       2360 $arg->{var}{$var}{constraint} = eval "sub{ $constraint }"
612             or _fail("Invalid .type constraint: $spec\n($@)");
613             } elsif ( length $constraint ) {
614 40         143 $arg->{var}{$var}{constraint_desc} = $constraint;
615             $arg->{var}{$var}{constraint} =
616 40 50       4760 eval "sub{ \$_[0] $constraint }"
617             or _fail("Invalid .type constraint: $spec\n($@)");
618             } else {
619 181         408 $arg->{var}{$var}{constraint_desc} = $matchtype;
620             $arg->{var}{$var}{constraint} =
621             $matchtype =~ m{\A\s*/.*/\s*\z}xms
622 4     4   11 ? sub { 1 }
623 181 100       1444 : $std_constraint_for{$matchtype}
    100          
624             or _fail("Unknown .type constraint: $spec");
625             }
626              
627             } elsif ( ($field eq 'default') || ($field eq 'opt_default') ) {
628 155         366 $val = _qualify_variables_fully( $val );
629 155 100       14144 eval "\$val = $val; 1"
630             or _fail("Invalid .$field value: $spec\n($@)");
631 154         947 $arg->{var}{$var}{$field} = $val;
632 154         348 my $has_field = 'has_'.$field;
633             $arg->{$has_field} = exists $arg->{$has_field} ?
634 154 100       595 $arg->{$has_field}++ :
635             1;
636              
637 154 100       784 if ($field eq 'opt_default') {
638             # Check that placeholders with optional defaults have a flagged argument
639 8 100       29 if ( $arg->{name} =~ m{^<}xms ) {
640 1         5 _fail( "Invalid .$field constraint: $spec\nParameter ".
641             "$arg->{name} must have a flag" );
642             }
643             # Check that placeholders with optional defaults is optional
644 7 100       121 if ( $arg->{name} !~ m{\Q[<$var>]}xms ) {
645 1         7 _fail( "Invalid .$field constraint: $spec\nPlaceholder".
646             " <$var> must be optional, i.e. [<$var>], to have ".
647             "an optional default in argument: $arg->{name}" );
648             }
649             }
650              
651             } elsif ( $field eq 'excludes.error' ) {
652 1         3 $arg->{var}{$var}{excludes_error} = $val;
653             } elsif ( $field eq 'excludes' ) {
654 6         44 $arg->{var}{$var}{excludes} = [ split '\s*,\s*', $val ];
655 6         15 for my $excl_var (@{$arg->{var}{$var}{excludes}}) {
  6         26  
656 8 100       38 if ($var eq $excl_var) {
657 1         6 _fail( "Invalid .excludes value for variable <$var>: ".
658             "<$excl_var> cannot exclude itself." );
659             }
660             }
661             } else {
662 1         5 _fail("Unknown specification: $spec");
663             }
664             }
665             # Record variables excluded by another that has a default
666 231         477 while (my ($var_name, $var_data) = each %{$arg->{var}}) {
  488         1760  
667 257         371 for my $excl_var (@{$arg->{var}{$var_name}{excludes}}) {
  257         1553  
668 7 100       32 $excluded_by_def{$excl_var}{default}{$var_name} = 1 if $arg->{has_default};
669 7 50       21 $excluded_by_def{$excl_var}{opt_default}{$var_name} = 1 if $arg->{has_opt_default};
670             }
671             }
672 231 100       2975 if ( $info =~ m{\G \s* ([^\s\0\1] [^\n]*) }gcxms ) {
673 1         6 _fail("Unknown specification: $1");
674             }
675             }
676              
677             # Validate and complete .excludes specs
678              
679 53         285 while ( (undef, my $arg) = each %$args ) {
680 448         627 while ( my ($var, $var_specs) = each %{$arg->{var}} ) {
  690         2399  
681             # Check for invalid placeholder name in .excludes specifications
682 243         353 for my $excl_var (@{$var_specs->{excludes}}) {
  243         539  
683 7 100       23 if (not exists $all_var_list{$excl_var}) {
684 1         7 _fail( "Invalid .excludes value for variable <$var>: ".
685             "<$excl_var> does not exist\n" );
686             }
687             }
688             # Remove default for placeholders excluded by others that have a default
689 242         385 for my $type ( 'default', 'opt_default' ) {
690 484 100 100     1547 if ( (exists $arg->{var}->{$var}->{$type}) && (exists $excluded_by_def{$var}{$type}) ) {
691 3         7 delete $arg->{var}->{$var}->{$type};
692 3         8 $arg->{"has_$type"}--;
693 3 100       9 if ($arg->{"has_$type"} == 0) {
694 2         6 delete $arg->{"has_$type"};
695             }
696             }
697             }
698             }
699             }
700              
701 52         241 return 1;
702             }
703              
704              
705             sub _qualify_variables_fully {
706             # Restore fully-qualified name to variables:
707             # $x becomes $main::x
708             # $::x becomes $main::x
709             # $Package::x stays as $Package::x
710             # /^asdf$/ stays as /^asdf$/
711             # '$10' stays as '$10'
712             # Note: perlvar indicates that ' can also be used instead of ::
713 394     394   743 my ($val) = @_;
714 394 100       1023 if ($val =~ m/[\$\@\%]/) { # Avoid expensive Text::Balanced operations when there are no variables
715 9         19 my $new_val;
716 9     295   74 for my $s (extract_multiple($val,[{Quoted=>sub{extract_delimited($_[0])}}],undef,0)) {
  295         32298  
717 10 100       1075 if (not ref $s) {
718             # A non-quoted section... may contain variables to fix
719 9         17 for my $var_name ( @{_get_variable_names($s)} ) {
  9         29  
720             # Skip fully qualified names, such as '$Package::x'
721 11 100       40 next if $var_name =~ m/main(?:'|::)/;
722             # Remove sigils from beginning of variable name: $ @ % {
723 10         40 $var_name =~ s/^[\$\@\%\{]+//;
724             # Substitute non-fully qualified vars, e.g. '$x' or '$::x', by '$main::x'
725 10         39 my $new_name = Symbol::qualify($var_name, 'main');
726 10 100       197 next if $new_name eq $var_name;
727 9         24 $var_name = quotemeta( $var_name );
728 9         207 $s =~ s/$var_name/$new_name/;
729             }
730 9         38 $new_val .= $s;
731             } else {
732             # A quoted section, to keep as-is
733 1         2 $new_val .= $$s;
734             }
735             }
736 9         71 return $new_val;
737             } else {
738 385         945 return $val;
739             }
740             }
741              
742              
743             sub _get_variable_names {
744             # Get an arrayref of the variables names found in the provided string.
745             # This function is a hack, needed only because of Text::Balanced ticket #78855:
746             # https://rt.cpan.org/Public/Bug/Display.html?id=78855
747 9     9   51 my ($str) = @_;
748 9         17 my $vars = [];
749 9     172   66 for my $var (extract_multiple($str,[sub{extract_variable($_[0],'')}],undef,1)) {
  172         16396  
750             # Name must start with underscore or a letter, e.g. $t $$h{a} ${$h}{a} $h->{a} @_
751             # Skip special or invalid names, e.g. $/ $1
752 13         1681 my $tmp = $var;
753 13         58 $tmp =~ s/(?:{|})//g;
754 13 100       60 next if not $tmp =~ m/^[\$\@\%]+[_a-z]/i;
755 11         32 push @$vars, $var;
756             }
757 9         167 return $vars;
758             }
759              
760              
761             sub _minimize_name {
762 701     701   1193 my ($name_re) = @_;
763 701         1188 $name_re =~ s{[][]}{}gxms; # remove all square brackets
764 701         2245 $name_re =~ s{\A \W+ ([\w-]*) .* \z}{$1}gxms;
765 701         1180 $name_re =~ s{-}{_}gxms;
766 701         1228 return $name_re;
767             }
768              
769              
770             sub _minimize_entries_of {
771 97     97   330 my ($arg_ref) = @_;
772 97 50       451 return if ref $arg_ref ne 'HASH';
773              
774 97         381 for my $old_key (keys %$arg_ref) {
775 660         1164 my $new_key = _minimize_name($old_key);
776 660         1782 $arg_ref->{$new_key} = delete $arg_ref->{$old_key};
777             }
778              
779 97         280 return 1;
780             }
781              
782              
783             # Do match, recursively trying to expand cuddles...
784             sub _doesnt_match {
785 62     62   649 my ( $matcher, $argv, $arg_specs_ref ) = @_;
786              
787 62         186 our @errors; # 'our' instead of 'my' because it is needed for the re pragma
788 62         219 local @errors = ();
789 62         179 %ARGV = ();
790              
791             # Match arguments, populate %ARGV and @errors
792             # Note that the matcher needs the pragma: use re 'eval';
793 62         119066 $argv =~ m{\A (?: \s* $matcher )* \s* \z}xms;
794              
795             # Report errors in passed arguments
796 62         623 for my $error (@errors) {
797 12 100       76 if ( $error =~ m/\A ((\W) (\w) (\w+))/xms ) {
798 5         33 my ( $bundle, $marker, $firstchar, $chars ) = ( $1, $2, $3, $4 );
799 5         72 $argv =~ s{\Q$bundle\E}{$marker$firstchar $marker$chars}xms;
800 5 100       29 return if !_doesnt_match( $matcher, $argv, $arg_specs_ref );
801             }
802             ARG:
803 10         22 for my $arg_spec_ref ( values %{$arg_specs_ref} ) {
  10         35  
804 56         130 our $bad_type;
805 56         79 local $bad_type;
806             next ARG
807 56 100 100     9603 if $error !~ m/\A [\s\0\1]* ($arg_spec_ref->{generic_matcher})/xms
808             || !$bad_type;
809            
810             my $msg = _type_error( $bad_type->{arg}, $bad_type->{var},
811 4         30 $bad_type->{val}, $bad_type->{type}, $bad_type->{type_error} );
812 4         36 return $msg;
813             }
814 6         48 return "Unknown argument: $error";
815             }
816              
817 50         336 return 0; # No error
818             }
819              
820              
821             sub _escape_arg {
822 629     629   1023 my $arg = shift;
823 629         1070 my ($num_replaced) = ($arg =~ tr/ \t/\0\1/);
824 629         1759 return $arg;
825             }
826              
827              
828             sub _rectify_arg {
829 428     428   676 my $arg = shift;
830 428         729 my ($num_replaced) = ($arg =~ tr/\0\1/ \t/);
831 428         5766 return $arg;
832             }
833              
834              
835             sub _rectify_all_args {
836 49     49   250 while ( my (undef, $arg_list) = each %ARGV ) {
837 275         411 for my $arg ( @{$arg_list} ) {
  275         482  
838 286 50       634 if ( ref $arg eq 'HASH' ) {
839 286         399 for my $var ( values %{$arg} ) {
  286         684  
840 312 100       597 if ( ref $var eq 'ARRAY' ) {
841 35         30 $var = [ map { _rectify_arg($_) } @{$var} ];
  135         140  
  35         39  
842             } else {
843 277         568 $var = _rectify_arg($var);
844             }
845             }
846             } else {
847 0 0       0 if ( ref $arg eq 'ARRAY' ) {
848 0         0 $arg = [ map { _rectify_arg($_) } @{$arg} ];
  0         0  
  0         0  
849             } else {
850 0         0 $arg = _rectify_arg($arg);
851             }
852             }
853             }
854             }
855 49         106 return 1;
856             }
857              
858              
859             sub _verify_args {
860 49     49   138 my ($arg_specs_ref) = @_;
861             # Check exclusive variables, variable constraints and fill in defaults...
862             # Handle mutually exclusive arguments
863 49         101 my %seen_vars;
864 49         263 while ( my ($arg_name, $arg_elems) = each %ARGV ) {
865 275         374 for my $elem (@{$arg_elems}) {
  275         438  
866 286         417 while ( my ($var_name) = each (%{$elem}) ) {
  598         1746  
867 312 100       879 $seen_vars{$var_name} = $arg_name if $var_name;
868             }
869             }
870             }
871              
872 49         109 while ( my ($arg_name, $arg) = each %{$arg_specs_ref} ) {
  484         1235  
873 438         2152 while ( my ($var_name, $var) = each %{$arg->{var}} ) {
  774         2159  
874             # Enforce placeholders that cannot be specified with others
875 339         458 for my $excluded_var ( @{$var->{excludes}} ) {
  339         834  
876 11 50 66     44 if (exists $seen_vars{$var_name} &&
877             exists $seen_vars{$excluded_var}) {
878 3         7 my $excl_arg = $seen_vars{$excluded_var};
879 3         5 my $msg;
880 3 100       24 if (exists $var->{excludes_error}) {
881 1         3 $msg = $var->{excludes_error};
882             } else {
883 2         14 $msg =
884             qq{Invalid "$excl_arg" argument.\n<$excluded_var> }.
885             qq{cannot be specified with <$var_name> because }.
886             qq{argument "$arg_name" excludes <$excluded_var>};
887             }
888 3         10 _bad_arglist($msg);
889             }
890             }
891             }
892             }
893              
894             # Enforce constraints and fill in defaults...
895             ARG:
896 46         156 while (my ($arg_name, $arg_specs) = each %{$arg_specs_ref} ) {
  447         1304  
897              
898             # Skip non-existent/non-defaulting/non-optional-defaulting arguments
899             next ARG
900             if !exists $ARGV{$arg_name}
901             && !( $arg_specs->{has_default}
902 406 100 100     1455 || $arg_specs->{has_opt_default} );
      100        
903              
904             # Ensure all vars exist within arg...
905 283         394 my @vars = keys %{$arg_specs->{placeholders}};
  283         864  
906 283         422 for my $index ( 0 .. $#{ $ARGV{$arg_name} } ) {
  283         796  
907 259         452 my $entry = $ARGV{$arg_name}[$index];
908 259         393 @{$entry}{@vars} = @{$entry}{@vars};
  259         466  
  259         501  
909              
910             # Get arg specs...
911             VAR:
912 259         508 for my $var (@vars) {
913              
914 259         477 my $arg_vars = $arg_specs->{var}->{$var};
915              
916             # Check constraints on vars...
917 259 50       586 if ( exists $ARGV{$arg_name} ) {
918              
919 259 100 66     1269 if ( ref $entry eq 'HASH' && defined $entry->{$var} ) {
    50 33        
920             # Named vars...
921 230 100       619 for my $val (
922             ref $entry->{$var} eq 'ARRAY'
923 35         48 ? @{ $entry->{$var} }
924             : $entry->{$var}
925             )
926             {
927 330 100 100     2603 if ( $arg_vars->{constraint} &&
928             !$arg_vars->{constraint}->($val) ) {
929             _bad_arglist( _type_error($arg_name, $var, $val,
930             $arg_vars->{constraint_desc},
931 5         31 $arg_vars->{type_error}) );
932             }
933             }
934 225         926 next VAR;
935             } elsif ( ref $entry ne 'HASH' && defined $entry ) {
936             # Unnamed vars...
937 0 0       0 for my $val (
938             ref $entry eq 'ARRAY'
939 0         0 ? @{$entry}
940             : $entry
941             )
942             {
943 0 0 0     0 if ( $arg_vars->{constraint} &&
944             !$arg_vars->{constraint}->($val) ) {
945             _bad_arglist( _type_error( $arg_name, $var, $val,
946             $arg_vars->{constraint_desc},
947 0         0 $arg_vars->{type_error}) );
948             }
949             $entry->{$var} = ''
950 0 0       0 unless defined( $ARGV{$arg_name} );
951             }
952 0         0 next VAR;
953             }
954             }
955              
956             # Assign placeholder defaults (if necessary)...
957             next ARG
958             if !exists $arg_vars->{default}
959 29 100 100     265 && !exists $arg_vars->{opt_default};
960              
961             $entry->{$var} = exists $arg_vars->{opt_default} ?
962             $arg_vars->{opt_default} :
963 17 100       90 $arg_vars->{default};
964             }
965             }
966              
967             # Handle defaults for missing args...
968 266 100       456 if ( !@{ $ARGV{$arg_name} } ) {
  266         888  
969 35         76 for my $var (@vars) {
970             # Assign defaults (if necessary)...
971 37         86 my $arg_vars = $arg_specs->{var}->{$var};
972             next ARG
973 37 100       124 if !exists $arg_vars->{default}; # no default specified
974              
975             # Omit default if it conflicts with a specified parameter
976 32         56 for my $excl_var ( @{$arg_specs->{var}->{$var}->{excludes}} ) {
  32         119  
977 5 100       16 if (exists $seen_vars{$excl_var}) {
978 3         11 next ARG;
979             }
980             }
981              
982 29         136 $ARGV{$arg_name}[0]{$var} = $arg_vars->{default};
983             }
984             }
985             }
986 41         173 return 1;
987             }
988              
989              
990             sub _type_error {
991 9     9   48 my ($arg_name, $var_name, $var_val, $var_constraint, $var_error) = @_;
992 9         24 my $msg = qq{Invalid "$arg_name" argument.\n};
993 9         43 $var_name =~ s{\W+}{}gxms;
994 9 100       36 if ( $var_error ) {
995 3         7 $msg = $var_error;
996 3         79 $msg =~ s{(?)}{$var_val}gxms;
997             } else {
998 6         28 $msg = qq{<$var_name> must be $var_constraint but the supplied value }.
999             qq{("$var_val") is not.};
1000             }
1001 9         37 return $msg;
1002             }
1003              
1004              
1005             sub _convert_to_regex {
1006 51     51   194 my ($args_ref) = @_;
1007              
1008             # Regexp to capture the start of a new argument
1009 51         249 my $no_esc_ws = '(?!\0)'; # no escaped whitespaces
1010              
1011 51         119 my @arg_variants;
1012 51         120 while ( my ($arg_name, $arg_specs) = each %{$args_ref} ) {
  486         1414  
1013 435         3939 push @arg_variants, @{$arg_specs->{variants}};
  435         1380  
1014             }
1015              
1016 51         302 my $no_match = join('|',@arg_variants);
1017 51         264 $no_match = _escape_specials($no_match);
1018 51         199 $no_match = '(?!(?:'.$no_match.')'.$no_esc_ws.')';
1019              
1020 51         202 while ( my ($arg_name, $arg) = each %{$args_ref} ) {
  486         1597  
1021 435         756 my $regex = $arg_name;
1022              
1023             # Quotemeta specials...
1024 435         1021 $regex = _escape_specials($regex);
1025 435         982 $regex = "(?:$regex)";
1026              
1027             # Convert optionals...
1028 435         2699 1 while $regex =~ s/ \[ ([^]]*) \] /(?:$1)?/gxms;
1029 435         1239 $regex =~ s/ (\s+) /$1.'\s*'.$no_esc_ws/egxms;
  321         1487  
1030 435         920 my $generic = $regex;
1031              
1032             # Set the matcher
1033             $regex =~
1034             s{ < (.*?) >(\.\.\.|) }
1035 347         1054 { my ($var_name, $var_rep) = ($1, $2);
1036 347         550 $var_name =~ s/(\s+)\[\\s\\0\\1]\*/$1/gxms;
1037 347   100     1488 my $type = $arg->{var}{$var_name}{type} || q{};
1038 347         1094 $arg->{placeholders}->{$var_name} = undef;
1039             my $matcher =
1040             $type =~ m{\A\s*/.*/\s*\z}xms
1041             ? eval "qr$type"
1042 347 100       1771 : $std_matcher_for{ $type }
    50          
1043             or _fail("Unknown type ($type) in specification: $arg_name");
1044 347 100       2187 $var_rep ?
1045             "(?:[\\s\\0\\1]*$no_match($matcher)(?{push \@{(\$ARGV{q{$arg_name}}||=[{}])->[-1]{q{$var_name}}}, \$^N}))+"
1046             :
1047             "(?:$no_match($matcher)(?{(\$ARGV{q{$arg_name}}||=[{}])->[-1]{q{$var_name}} = \$^N}))";
1048             }gexms
1049 435 100       1500 or do {
1050 167         427 $regex .= "(?{(\$ARGV{q{$arg_name}}||=[{}])->[-1]{q{}} = 1})";
1051             };
1052              
1053 435 100       1184 if ( $arg->{is_repeatable} ) {
1054 6         17 $arg->{matcher} = "$regex (?:(?
1055             } else {
1056             $arg->{matcher} = "(??{exists\$ARGV{q{$arg_name}}?'(?!)':''}) "
1057             . (
1058             $arg->{false_vals}
1059 429 100       2172 ? "(?:$arg->{false_vals} (?:(? 0 }] }) | $regex (?:(? 1}] }))"
1060             : "$regex (?:(?
1061             );
1062             }
1063              
1064             # Set the generic matcher
1065 435         1451 $generic =~
1066             s{ < (.*?) > }
1067 347         735 { my $var_name = $1;
1068 347         588 $var_name =~ s/(\s+)\[\\s\\0\\1]\*/$1/gxms;
1069 347   100     1299 my $type = $arg->{var}{$var_name}{type} || q{};
1070 347   100     1329 my $type_error = $arg->{var}{$var_name}{type_error} || q{};
1071             my $matcher = $type =~ m{\A\s*/.*/\s*\z}xms
1072             ? eval "qr$type"
1073 347 100       1314 : $std_matcher_for{ $type };
1074 347         1679 "(?:($matcher|([^\\s\\0\\1]+)"
1075             . "(?{\$bad_type ||= "
1076             . "{arg=>q{$arg_name},type=>q{$type},type_error=>q{$type_error}, var=>q{<$var_name>},val=>\$^N};})))"
1077             }gexms;
1078 435         1455 $arg->{generic_matcher} = $generic;
1079             }
1080 51         295 return 1;
1081             }
1082              
1083              
1084             sub _escape_specials {
1085             # Escape quotemeta special characters
1086 486     486   892 my $arg = shift;
1087 486         2242 $arg =~ s{([@#\$^*()+{}?])}{\\$1}gxms;
1088 486         963 return $arg;
1089             }
1090              
1091              
1092             sub _print_pod {
1093 0     0   0 my ( $pod, $paged ) = @_;
1094              
1095 0 0       0 if ($paged) {
1096             # Page output
1097 0 0       0 eval { require IO::Pager::Page } or eval { require IO::Page };
  0         0  
  0         0  
1098             }
1099            
1100             # Convert POD to plaintext, wrapping the lines at 76 chars and print to STDOUT
1101 0 0       0 open my $parser_in, '<', \$pod or croak "Could not read from variable because $!";
1102 0         0 Pod::PlainText->new()->parse_from_filehandle($parser_in);
1103 0         0 close $parser_in;
1104              
1105 0         0 return 1;
1106             }
1107              
1108              
1109             sub _validate_name {
1110             # Check that the argument name only has pairs of < > brackets (ticket 34199)
1111             # Return the name of the variables that this argument specifies
1112 483     483   1154 my ($name) = @_;
1113 483 100       1486 if ($name =~ m/[<>]/) { # skip expensive Text::Balance functions if possible
1114 301         475 my %var_names;
1115 301         482 my $pos = 0;
1116 301     3431   2080 for my $s (extract_multiple($name,[sub{extract_bracketed($_[0],'<>')}],undef,0)) {
  3431         312866  
1117 836 100       47623 next if not $s =~ m/[<>]/;
1118 390         2092 $s =~ s/^<(.*)>$/$1/;
1119 390 100       1125 if ( $s =~ m/[<>]/ ) {
1120 2         8 _fail( 'Invalid argument specification: '.$name );
1121             }
1122 388         576 $pos++;
1123 388 100       1413 $var_names{$s} = $pos if not exists $var_names{$s};
1124             }
1125 299         1924 return \%var_names;
1126             } else {
1127 182         408 return {};
1128             }
1129             }
1130              
1131              
1132             sub _get_variants {
1133 799     799   47454 my @arg_desc = shift =~ m{ [^[|]+ (?: $optional_re [^[|]* )* }gmxs;
1134              
1135 799         2629 for (@arg_desc) {
1136 824         4954 s{^ \s+ | \s+ $}{}gxms;
1137             }
1138              
1139             # Only consider first "word"...
1140 799 100       3108 return $1 if $arg_desc[0] =~ m/\A (< [^>]+ >)/xms;
1141              
1142 762         3951 $arg_desc[0] =~ s/\A ([^\s<]+) \s* (?: < .*)? \z/$1/xms;
1143              
1144             # Variants are all those with and without each optional component...
1145 762         1371 my %variants;
1146 762         1632 while (@arg_desc) {
1147 3054         4857 my $arg_desc_with = shift @arg_desc;
1148 3054         4755 my $arg_desc_without = $arg_desc_with;
1149              
1150 3054 100       8303 if ( $arg_desc_without =~ s/ \[ [^][]* \] //xms ) {
1151 1167         2135 push @arg_desc, $arg_desc_without;
1152             }
1153 3054 100       7507 if ( $arg_desc_with =~ m/ [[(] ([^][()]*) [])] /xms ) {
1154 1167         2319 my $option = $1;
1155 1167         2736 for my $alternative ( split /\|/, $option ) {
1156 1100         1602 my $arg_desc = $arg_desc_with;
1157 1100         2989 $arg_desc =~ s{[[(] [^][()]* [])]}{$alternative}xms;
1158 1100         2655 push @arg_desc, $arg_desc;
1159             }
1160             }
1161              
1162 3054         7494 $arg_desc_with =~ s/[][]//gxms;
1163 3054         8180 $arg_desc_with =~ s/\b[^-\w] .* \z//xms;
1164 3054         8234 $variants{$arg_desc_with} = 1;
1165             }
1166              
1167 762         2982 return keys %variants;
1168             }
1169              
1170              
1171             sub _longestname {
1172 565 50   565   2047 return ( sort { length $a <=> length $b || $a cmp $b } @_ )[-1];
  540         1677  
1173             }
1174              
1175              
1176             sub _export_var {
1177 45     45   111 my ( $prefix, $key, $value ) = @_;
1178 45         88 my $export_as = $prefix . $key;
1179 45         98 $export_as =~ s{\W}{_}gxms; # mainly for '-'
1180 45   50     226 my $callpkg = caller( $export_lvl + ($Exporter::ExportLevel || 0) );
1181 66     66   1092 no strict 'refs';
  66         285  
  66         22507  
1182 45 100       114 *{"$callpkg\::$export_as"} = ( ref $value ) ? $value : \$value;
  45         310  
1183 45         143 return 1;
1184             }
1185              
1186              
1187             # Utility sub to factor out hash key aliasing...
1188             sub _make_equivalent {
1189 132     132   1234 my ( $hash_ref, %alias_hash ) = @_;
1190              
1191 132         666 while ( my ( $name_re, $aliases ) = each %alias_hash ) {
1192 924         1607 for my $alias (@$aliases) {
1193 2772         9310 $hash_ref->{$alias} = $hash_ref->{$name_re};
1194             }
1195             }
1196              
1197 132         417 return 1;
1198             }
1199              
1200              
1201             # Report problems in specification and die
1202             sub _fail {
1203 12     12   36 my (@msg) = @_;
1204 12         2834 croak "Getopt::Euclid: @msg";
1205             }
1206              
1207              
1208             sub _get_pod_names {
1209             # Parse the POD of the caller program and its modules.
1210 67     67   596 my @caller = caller(1);
1211              
1212             # Sanity check
1213 67 50       412 if ($has_run) {
1214 0         0 carp 'Getopt::Euclid loaded a second time';
1215 0         0 warn "Second attempt to parse command-line was ignored\n";
1216 0         0 return 0;
1217             }
1218              
1219             # Handle calls from .pm files
1220 67 100       432 if ( $caller[1] =~ m/[.]pm \z/xms ) {
1221 4         21 my @caller = caller(1); # at import()'s level
1222 4         12 push @pod_names, $caller[1];
1223             # Install this import() sub as module's import sub...
1224 66     66   1288 no strict 'refs';
  66         141  
  66         58370  
1225             croak '.pm file cannot define an explicit import() when using Getopt::Euclid'
1226 4 50       12 if *{"$caller[0]::import"}{CODE};
  4         51  
1227 4         10 my $lambda; # Needed so the anon sub is generated at run-time
1228 4         20 *{"$caller[0]::import"}
1229 4     4   74 = bless sub { $lambda = 1; goto &Getopt::Euclid::import },
  4         25  
1230 4         30 'Getopt::Euclid::Importer';
1231              
1232 4         232 return 0;
1233             }
1234              
1235             # Add name of caller program
1236 63 100       2291 push @pod_names, $0 if (-e $0); # When calling perl -e '...', $0 is '-e', i.e. not a actual file
1237              
1238 63         437 return 1;
1239             }
1240              
1241              
1242             sub _insert_default_values {
1243 103     103   236 my ($args) = @_;
1244 103         203 my $pod_string = '';
1245             # Retrieve item names in sequential order
1246 103         562 for my $item_name ( sort { $args->{$a}->{'seq'} <=> $args->{$b}->{'seq'} } (keys %$args) ) {
  877         1720  
1247 436         895 my $item_spec = $args->{$item_name}->{'src'};
1248 436         776 $item_spec =~ s/=for(.*)//ms;
1249 436         777 $pod_string .= "=item $item_name\n\n";
1250             # Get list of variable for this argument
1251 436         660 while ( my ($var_name, $var) = each %{$args->{$item_name}->{var}} ) {
  672         2209  
1252             # Get default for this variable
1253 236         446 for my $default_type ( 'default', 'opt_default' ) {
1254 472         806 my $var_default;
1255 472 100       1003 if (exists $var->{$default_type}) {
1256 132 100       544 if (ref($var->{$default_type}) eq 'ARRAY') {
    50          
1257 1         3 $var_default = join(' ', @{$var->{$default_type}});
  1         10  
1258             } elsif (ref($var->{$default_type}) eq '') {
1259 131         264 $var_default = $var->{$default_type};
1260             } else {
1261 0         0 carp 'Getopt::Euclid found an unexpected default value type';
1262             }
1263             } else {
1264 340         504 $var_default = 'none';
1265             }
1266 472         4993 $item_spec =~ s/$var_name\.$default_type/$var_default/g;
1267             }
1268             }
1269 436 100       1258 if ($item_spec =~ m/(\S+(\.(?:opt_)?default))/) {
1270 1         3 my ($reference, $default_type) = ($1, $2);
1271 1         6 _fail( "Invalid reference to field $reference in argument ".
1272             "description:\n$item_spec" );
1273             }
1274 435         891 $pod_string .= $item_spec;
1275             }
1276 102         273 $pod_string = "=over\n\n".$pod_string."=back\n\n";
1277 102         423 return $pod_string;
1278             }
1279              
1280              
1281             1; # Magic true value required at end of module
1282              
1283              
1284             =head1 NAME
1285              
1286             Getopt::Euclid - Executable Uniform Command-Line Interface Descriptions
1287              
1288             =head1 VERSION
1289              
1290             This document describes Getopt::Euclid version 0.4.5
1291              
1292             =head1 SYNOPSIS
1293              
1294             use Getopt::Euclid;
1295              
1296             if ($ARGV{-i}) {
1297             print "Interactive mode...\n";
1298             }
1299              
1300             for my $x (0..$ARGV{-size}{h}-1) {
1301             for my $y (0..$ARGV{-size}{w}-1) {
1302             do_something_with($x, $y);
1303             }
1304             }
1305              
1306             __END__
1307              
1308             =head1 NAME
1309              
1310             yourprog - Your program here
1311              
1312             =head1 VERSION
1313              
1314             This documentation refers to yourprog version 1.9.4
1315              
1316             =head1 USAGE
1317              
1318             yourprog [options] -s[ize]=x -o[ut][file]
1319              
1320             =head1 REQUIRED ARGUMENTS
1321              
1322             =over
1323              
1324             =item -s[ize]=x
1325              
1326             Specify size of simulation
1327              
1328             =for Euclid:
1329             h.type: int > 0
1330             h.default: 24
1331             w.type: int >= 10
1332             w.default: 80
1333              
1334             =item -o[ut][file]
1335              
1336             Specify output file
1337              
1338             =for Euclid:
1339             file.type: writable
1340             file.default: '-'
1341              
1342             =back
1343              
1344             =head1 OPTIONS
1345              
1346             =over
1347              
1348             =item -i
1349              
1350             Specify interactive simulation
1351              
1352             =item -l[[en][gth]]
1353              
1354             Length of simulation. The default is l.default
1355              
1356             =for Euclid:
1357             l.type: int > 0
1358             l.default: 99
1359              
1360             =item --debug []
1361              
1362             Set the log level. Default is log_level.default but if you provide --debug,
1363             then it is log_level.opt_default.
1364              
1365             =for Euclid:
1366             log_level.type: int
1367             log_level.default: 0
1368             log_level.opt_default: 1
1369              
1370             =item --version
1371              
1372             =item --usage
1373              
1374             =item --help
1375              
1376             =item --man
1377              
1378             Print the usual program information
1379              
1380             =back
1381              
1382             Remainder of documentation starts here...
1383              
1384             =head1 AUTHOR
1385              
1386             Damian Conway (DCONWAY@CPAN.org)
1387              
1388             =head1 BUGS
1389              
1390             There are undoubtedly serious bugs lurking somewhere in this code.
1391             Bug reports and other feedback are most welcome.
1392              
1393             =head1 COPYRIGHT
1394              
1395             Copyright (c) 2005, Damian Conway. All Rights Reserved.
1396             This module is free software. It may be used, redistributed
1397             and/or modified under the terms of the Perl Artistic License
1398             (see http://www.perl.com/perl/misc/Artistic.html)
1399              
1400              
1401             =head1 DESCRIPTION
1402              
1403             Getopt::Euclid uses your program's own POD documentation to create a powerful
1404             command-line argument parser. This ensures that your program's documented interface
1405             and its actual interface always agree.
1406              
1407             The created command-line argument parser includes many features such as argument
1408             type checking, required arguments, exclusive arguments, optional arguments with
1409             default values, automatic usage message, ...
1410              
1411             To use the module, simply write the following at the top of your program:
1412              
1413             use Getopt::Euclid;
1414              
1415             This will cause Getopt::Euclid to be require'd and its import method will be
1416             called. It is important that the import method be allowed to run, so do not
1417             invoke Getopt::Euclid in the following manner:
1418              
1419             # Will not work
1420             use Getopt::Euclid ();
1421              
1422             When the module is loaded within a regular Perl program, it will:
1423              
1424             =over
1425              
1426             =item 1.
1427              
1428             locate any POD in the same *.pl file or its associated *.pod file.
1429              
1430             =item 2.
1431              
1432             extract information from that POD, most especially from
1433             the C<=head1 REQUIRED ARGUMENTS> and C<=head1 OPTIONS> sections,
1434              
1435             =item 3.
1436              
1437             build a parser that parses the arguments and options the POD specifies,
1438              
1439             =item 4.
1440              
1441             remove the command-line arguments from C<@ARGV> and parse them, and
1442              
1443             =item 5.
1444              
1445             put the results in the global C<%ARGV> variable (or into specifically named
1446             optional variables, if you request that -- see L).
1447              
1448             =back
1449              
1450             As a special case, if the module is loaded within some other module
1451             (i.e. from within a C<.pm> file), it still locates and extracts POD
1452             information, but instead of parsing C<@ARGV> immediately, it caches that
1453             information and installs an C subroutine in the caller module.
1454             This new C acts just like Getopt::Euclid's own import, except
1455             that it adds the POD from the caller module to the POD of the callee.
1456              
1457             All of which just means you can put some or all of your CLI specification
1458             in a module, rather than in the application's source file.
1459             See L for more details.
1460              
1461             =head1 INTERFACE
1462              
1463             =head2 Program interface
1464              
1465             You write:
1466              
1467             use Getopt::Euclid;
1468              
1469             and your command-line is parsed automagically.
1470              
1471             =head2 Module interface
1472              
1473             =over
1474              
1475             =item import()
1476              
1477             You write:
1478              
1479             use Getopt::Euclid;
1480              
1481             and your module will then act just like Getopt::Euclid (i.e. you can use
1482             your module I of Getopt::Euclid>, except that your module's POD
1483             will also be prepended to the POD of any module that loads yours. In
1484             other words, you can use Getopt::Euclid in a module to create a standard
1485             set of CLI arguments, which can then be added to any application simply
1486             by loading your module.
1487              
1488             To accomplish this trick Getopt::Euclid installs an C
1489             subroutine in your module. If your module already has an C
1490             subroutine defined, terrible things happen. So do not do that.
1491              
1492             You may also short-circuit the import method within your calling program to
1493             have the POD from several modules included for argument parsing.
1494              
1495             use Module1::Getopt (); # No argument parsing
1496             use Module2::Getopt (); # No argument parsing
1497             use Getopt::Euclid; # Arguments parsed
1498              
1499             =item process_args()
1500              
1501             Alternatively, to parse arguments from a source different from C<@ARGV>, use the
1502             C subroutine.
1503              
1504             use Getopt::Euclid qw(:defer);
1505             my @args = ( '-in', 'file.txt', '-out', 'results.txt' );
1506             Getopt::Euclid->process_args(\@args);
1507              
1508             If you want to use the :minimal or :vars mode in this type of scenario, you can
1509             pass extra options to C:
1510              
1511             use Getopt::Euclid qw(:defer);
1512             my @args = ( '-in', 'file.txt', '-out', 'results.txt' );
1513             Getopt::Euclid->process_args(\@args, {-minimal => 1, -vars => 'prefix_'});
1514              
1515             This is particularly when you plan on processing POD manually.
1516              
1517             =item process_pods()
1518              
1519             Similarly, to parse argument specifications from a source different than the
1520             current script (and its dependencies), use the C subroutine.
1521              
1522             use Getopt::Euclid ();
1523             my @pods = ( 'script.pl', 'Module.pm' );
1524             $Getopt::Euclid::MAN = Getopt::Euclid->process_pods(\@pods, {-strict => 1});
1525             my @args = ( '-in', 'file.txt', '-out', 'results.txt' );
1526             Getopt::Euclid->process_args(\@args);
1527              
1528             By default, this method will look for .pod files associated with the given .pl
1529             and .pm files and use these .pod files preferentially when available. Set
1530             -strict to 1 to only use the given files.
1531              
1532             =back
1533              
1534             =head2 POD interface
1535              
1536             This is where all the action is. POD markup can be placed in a .pod file that
1537             has the same prefix as the corresponding Perl file. Alternatively, POD can be
1538             inserted anywhere in the Perl code, but is typically added either after an
1539             __END__ statement (like in the L), or interspersed in the code: