File Coverage

blib/lib/Getopt/Declare.pm
Criterion Covered Total %
statement 391 547 71.4
branch 147 288 51.0
condition 69 151 45.7
subroutine 50 74 67.5
pod 6 10 60.0
total 663 1070 61.9


line stmt bran cond sub pod time code
1             package Getopt::Declare;
2              
3 5     5   149715 use strict;
  5         12  
  5         227  
4 5     5   25 use vars qw($VERSION);
  5         10  
  5         237  
5 5     5   24 use Carp;
  5         12  
  5         963  
6              
7             $VERSION = '1.14';
8              
9             sub import {
10 5     5   57 my ($class, $defn) = @_;
11 5 50 33     118 return if @_<2 || ! length $defn;
12 0         0 $_[2] = Getopt::Declare->new($defn);
13 0 0       0 exit(0) unless $_[2];
14 0         0 delete $_[2]{_internal};
15             }
16              
17             sub AUTOLOAD {
18 5     5   24 use vars '$AUTOLOAD';
  5         7  
  5         6997  
19 0 0   0   0 return if $AUTOLOAD =~ /::DESTROY$/ ;
20 0         0 $AUTOLOAD =~ s/.*::/main::/;
21 0         0 goto &$AUTOLOAD;
22             }
23              
24             package Getopt::Declare::StartOpt;
25              
26 0     0   0 sub new { bless {} }
27 0     0   0 sub matcher { '(?:()' }
28 0     0   0 sub code { '' }
29 0     0   0 sub cachecode { '' }
30 0     0   0 sub trailer { undef }
31 0     0   0 sub ows { return $_[1]; }
32              
33             package Getopt::Declare::EndOpt;
34              
35 0     0   0 sub new { bless {} }
36 0     0   0 sub matcher { '())?' }
37 0     0   0 sub code { '' }
38 0     0   0 sub cachecode { '' }
39 0     0   0 sub trailer { undef }
40 0     0   0 sub ows { return $_[1]; }
41              
42             package Getopt::Declare::ScalarArg;
43              
44             my %stdtype = ();
45              
46             sub _reset_stdtype
47             {
48 13     13   463 %stdtype =
49             (
50             ':i' => { pattern => '(?:(?:%T[+-]?)%D+)' },
51             ':n' => { pattern => '(?:(?:%T[+-]?)(?:%D+(?:%T\.%D*)?(?:%T[eE][+-]?%D+)?|%T\.%D+(?:%T[eE][+-]?%D+)?))' },
52             ':s' => { pattern => '(?:%T(?:\S|\0))+' },
53             ':qs' => { pattern => q{(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|(?:%T(?:\S|\0))+)} },
54             ':id' => { pattern => '%T[a-zA-Z_](?:%T\w)*' },
55             ':if' => { pattern => '(?:%T(?:\S|\0))+',
56             action => '{reject (!defined $_VAL_ || $_VAL_ ne "-" && ! -r $_VAL_, "in parameter \'$_PARAM_\' (file \"$_VAL_\" is not readable)")}' },
57             ':of' => { pattern => '(?:%T(?:\S|\0))+',
58             action => '{reject (!defined $_VAL_ || $_VAL_ ne "-" && -e $_VAL_ && ! -w $_VAL_ , "in parameter \'$_PARAM_\' (file \"$_VAL_\" is not writable)")}' },
59             '' => { pattern => ':s', ind => 1 },
60             ':+i' => { pattern => ':i',
61             action => '{reject (!defined $_VAL_ || $_VAL_<=0, "in parameter \'$_PARAM_\' ($_VAR_ must be an integer greater than zero)")}',
62             ind => 1},
63             ':+n' => { pattern => ':n',
64             action => '{reject (!defined $_VAL_ || $_VAL_<=0, "in parameter \'$_PARAM_\' ($_VAR_ must be a number greater than zero)")}',
65             ind => 1},
66             ':0+i' => { pattern => ':i',
67             action => '{reject (!defined $_VAL_ || $_VAL_<0, "in parameter \'$_PARAM_\' ($_VAR_ must be an positive integer)")}',
68             ind => 1},
69             ':0+n' => { pattern => ':n',
70             action => '{reject (!defined $_VAL_ || $_VAL_<0, "in parameter \'$_PARAM_\' ($_VAR_ must be a positive number)")}',
71             ind => 1},
72             );
73             }
74              
75             sub stdtype # ($typename)
76             {
77 38     38   84 my $name = shift;
78 38         58 my %seen = ();
79 38   33     296 while (!$seen{$name} && $stdtype{$name} && $stdtype{$name}->{ind})
      66        
80             {
81 32         52 $seen{$name} = 1;
82 32         226 $name = $stdtype{$name}->{pattern}
83             }
84              
85 38 50 33     186 return undef if $seen{$name} || !$stdtype{$name};
86 38         115 return $stdtype{$name}->{pattern};
87             }
88              
89             sub stdactions # ($typename)
90             {
91 36     36   47 my $name = shift;
92 36         56 my %seen = ();
93 36         47 my @actions = ();
94 36   33     459 while (!$seen{$name} && $stdtype{$name} && $stdtype{$name}->{ind})
      66        
95             {
96 30         52 $seen{$name} = 1;
97 30 100       82 push @actions, $stdtype{$name}->{action}
98             if $stdtype{$name}->{action};
99 30         260 $name = $stdtype{$name}->{pattern}
100             }
101 36 100       95 push @actions, $stdtype{$name}->{action}
102             if $stdtype{$name}->{action};
103              
104 36         76 return @actions;
105             }
106              
107             sub addtype # ($abbrev, $pattern, $action, $ref)
108             {
109 3     3   8 my $typeid = ":$_[0]";
110 3 50       13 unless ($_[1] =~ /\S/) { $_[1] = ":s" , $_[3] = 1; }
  0         0  
111 3         8 $stdtype{$typeid} = {};
112 3 50 33     37 $stdtype{$typeid}->{pattern} = "(?:$_[1])" if $_[1] && !$_[3];
113 3 50 33     24 $stdtype{$typeid}->{pattern} = ":$_[1]" if $_[1] && $_[3];
114 3 100       10 $stdtype{$typeid}->{action} = $_[2] if $_[2];
115 3         10 $stdtype{$typeid}->{ind} = $_[3];
116             }
117              
118             sub new # ($self, $name, $type, $nows)
119             {
120 34   33 34   280 bless
121             { name => $_[1],
122             type => $_[2],
123             nows => $_[3],
124             }, ref($_[0])||$_[0];
125             }
126              
127             sub matcher # ($self, $trailing)
128             {
129 36     36   70 my ($self, $trailing) = @_;
130              
131             #WAS: $trailing = $trailing ? '(?!\Q'.$trailing.'\E)' : '';
132 36 100       88 $trailing = $trailing ? '(?!'.quotemeta($trailing).')' : '';
133 36         128 my $stdtype = stdtype($self->{type});
134 36 50 33     115 if (!$stdtype && $self->{type} =~ m#\A:/([^/]+)/\Z#) { $stdtype = $1; }
  0         0  
135 36 50       71 if (!$stdtype)
136             {
137 0         0 die "Error: bad type in Getopt::Declare parameter variable specification near '<$self->{name}$self->{type}>'\n";
138             }
139 36         74 $stdtype =~ s/\%D/(?:$trailing\\d)/g;
140 36         118 $stdtype =~ s/\%T/$trailing/g;
141 36 50       88 unless ($stdtype =~ s/\%F//)
142             {
143 36         64 $stdtype = Getopt::Declare::Arg::negflagpat().$stdtype;
144             }
145 36         73 $stdtype = Getopt::Declare::Arg::negflagpat().$stdtype;
146              
147 36         138 return "(?:$stdtype)";
148             }
149              
150             sub code # ($self, $pos, $package)
151             {
152 34     34   127 my $code = '
153             $_VAR_ = q|<' . $_[0]->{name} . '>|;
154             $_VAL_ = defined $' . ($_[1]+1) . '? $' . ($_[1]+1) . ': undef;
155             $_VAL_ =~ tr/\0/ / if $_VAL_;';
156              
157 34         83 my @actions = stdactions($_[0]->{type});
158 34         69 foreach ( @actions )
159             {
160 2         15 s/(\s*\{)/$1 package $_[2]; /;
161 2         6 $code .= "\n\t\tdo $_;";
162             }
163              
164 34         94 $code .= '
165             my $' . $_[0]->{name} . ' = $_VAL_;';
166              
167 34         97 return $code;
168             }
169              
170             sub cachecode # ($self, $ownerflag, $itemcount)
171             {
172 34 100   34   207 return "\t\t\$self->{'$_[1]'}{'<$_[0]->{name}>'} = \$$_[0]->{name};\n"
173             if $_[2] > 1;
174 11         112 return "\t\t\$self->{'$_[1]'} = \$$_[0]->{name};\n";
175             }
176              
177 12     12   38 sub trailer { '' }; # MEANS TRAILING PARAMETER VARIABLE
178              
179             sub ows
180             {
181 36 100   36   193 return '[\s\0]*('.$_[1].')' unless $_[0]->{nows};
182 4         16 return '('.$_[1].')';
183             }
184              
185              
186             package Getopt::Declare::ArrayArg;
187              
188 5     5   130 use base qw( Getopt::Declare::ScalarArg );
  5         6  
  5         7204  
189              
190             sub matcher # ($self, $trailing)
191             {
192 2     2   6 my ($self, $trailing) = @_;
193 2 50 33     7 my $suffix = (defined $trailing && !$trailing) ? '([\s\0]+)' : '';
194 2         10 my $scalar = $self->SUPER::matcher($trailing);
195 2         14 return $scalar.'(?:[\s\0]+'.$scalar.')*'.$suffix;
196             }
197              
198             sub code # ($self, $pos, $package)
199             {
200 2     2   9 my $code = '
201             $_VAR_ = q|<' . $_[0]->{name} . '>|;
202             $_VAL_ = undef;
203             my @' . $_[0]->{name} . ' = map { tr/\0/ /; $_ } split " ", $'.($_[1]+1)."||'';\n";
204              
205 2         5 my @actions = Getopt::Declare::ScalarArg::stdactions($_[0]->{type});
206 2 100       4 if (@actions)
207             {
208 1         7 $code .= '
209             foreach $_VAL_ ( @' . $_[0]->{name} . ' )
210             {';
211 1         3 foreach ( @actions )
212             {
213 1         14 s/(\s*\{)/$1 package $_[2]; /;
214 1         9 $code .= "\n\t\t\tdo $_;\n";
215             }
216 1         2 $code .= '
217             }';
218             }
219 2         6 return $code;
220             }
221              
222             sub cachecode # ($self, $ownerflag, $itemcount)
223             {
224 2 50   2   5 return "\t\t\$self->{'$_[1]'}{'<$_[0]->{name}>'} = []
225             unless \$self->{'$_[1]'}{'<$_[0]->{name}>'};
226             push \@{\$self->{'$_[1]'}{'<$_[0]->{name}>'}}, \@$_[0]->{name};\n"
227             if $_[2] > 1;
228 2         11 return "\t\t\$self->{'$_[1]'} = []
229             unless \$self->{'$_[1]'};
230             push \@{\$self->{'$_[1]'}}, \@$_[0]->{name};\n";
231             }
232              
233              
234             package Getopt::Declare::Punctuator;
235              
236             sub new # ($self, $text, $nows)
237             {
238 12     12   55 bless { text => $_[1], nows => $_[2] }
239             }
240              
241             sub matcher # ($self, $trailing)
242             {
243             #WAS: Getopt::Declare::Arg::negflagpat() . '\Q' . $_[0]->{text} . '\E';
244 12     12   30 Getopt::Declare::Arg::negflagpat() . quotemeta($_[0]->{text});
245             }
246              
247             sub code # ($self, $pos)
248             {
249 12     12   49 "
250             \$_PUNCT_{'" . $_[0]->{text} . "'" . '} = $' . ($_[1]+1) . ";\n";
251             }
252              
253             sub cachecode # ($self, $ownerflag, $itemcount)
254             {
255 12 50   12   65 return "\t\t\$self->{'$_[1]'}{'$_[0]->{text}'} = \$_PUNCT_{'$_[0]->{text}'};\n"
256             if $_[2] > 1;
257 0         0 return "\t\t\$self->{'$_[1]'} = \$_PUNCT_{'$_[0]->{text}'};\n";
258             }
259              
260 12     12   49 sub trailer { $_[0]->{text} };
261              
262             sub ows
263             {
264 12 100   12   58 return '[\s\0]*('.$_[1].')' unless $_[0]->{nows};
265 3         14 return '('.$_[1].')';
266             }
267              
268              
269             package Getopt::Declare::Arg;
270              
271 5     5   7790 use Text::Balanced qw( extract_bracketed );
  5         120575  
  5         20244  
272              
273             my $nextID = 0;
274              
275             my @helpcmd = qw( -help --help -Help --Help -HELP --HELP -h -H );
276             my %helpcmd = map { $_ => 1 } @helpcmd;
277              
278 18 50   18   37 sub besthelp { foreach ( @helpcmd ) { return $_ if exists $helpcmd{$_}; } }
  18         24957  
279 13     13   100 sub helppat { return join '|', keys %helpcmd; }
280              
281             my @versioncmd = qw( -version --version -Version --Version
282             -VERSION --VERSION -v -V );
283             my %versioncmd = map { $_ => 1 } @versioncmd;
284              
285 3 50   3   8 sub bestversion {foreach (@versioncmd) { return $_ if exists $versioncmd{$_}; }}
  3         14  
286 13     13   309 sub versionpat { return join '|', keys %versioncmd; }
287              
288             my @flags;
289             my $posflagpat = '';
290             my $negflagpat = '';
291             sub negflagpat
292             {
293 99 100 100 99   266 $negflagpat = join '', map { "(?!".quotemeta($_).")" } @flags
  14         46  
294             if !$negflagpat && @flags;
295 99         294 return $negflagpat;
296             }
297              
298             sub posflagpat
299             {
300 15 100 100 15   63 $posflagpat = '(?:'.join('|', map { quotemeta($_) } @flags).')'
  14         26  
301             if !$posflagpat && @flags;
302 15         100 return $posflagpat;
303             }
304              
305             sub new # ($class, $spec, $desc, $dittoflag)
306             {
307 25     25   53 my ($class,$spec,$desc,$ditto) = @_;
308 25         39 my $first = 1;
309 25         33 my $arg;
310             my $nows;
311              
312 25         250 my $self =
313             {
314             flag => '',
315             flagid => '',
316             args => [],
317             actions => [],
318             ditto => $ditto,
319             required => 0,
320             requires => '',
321             ID => $nextID++,
322             desc => $spec,
323             items => 0,
324             };
325              
326 25         244 $self->{desc} =~ s/\A\s*(.*?)\s*\Z/$1/;
327              
328 25         42 my $ws_seen = "";
329              
330 25         69 while ($spec)
331             {
332             # OPTIONAL
333 69 50       247 if ($spec =~ s/\A(\s*)\[/$1/)
    50          
334             {
335 0         0 push @{$self->{args}}, Getopt::Declare::StartOpt->new;
  0         0  
336 0         0 next;
337             }
338             elsif ($spec =~ s/\A\s*\]//)
339             {
340 0         0 push @{$self->{args}}, Getopt::Declare::EndOpt->new;
  0         0  
341 0         0 next;
342             }
343              
344             # ARG
345 69         192 ($arg,$spec,$nows) = extract_bracketed($spec,'<>');
346 69 100       5441 if ($arg)
    50          
347             {
348 34 50       202 $arg =~ m/\A(\s*)(<)([a-zA-Z]\w*)(:[^>]+|)>/ or
349             die "Error: bad Getopt::Declare parameter variable specification near '$arg'\n";
350              
351 34   100     232 my @details = ( $3, $4, !$first && !length($nows) ); # NAME,TYPE,NOWS
352              
353 34 100       91 if ($spec =~ s/\A\.\.\.//) # ARRAY ARG
354             {
355 2         3 push @{$self->{args}},
  2         15  
356             Getopt::Declare::ArrayArg->new(@details);
357             }
358             else # SCALAR ARG
359             {
360 32         37 push @{$self->{args}},
  32         184  
361             Getopt::Declare::ScalarArg->new(@details);
362             }
363 34         67 $self->{items}++;
364 34         86 next;
365             }
366              
367             # PUNCTUATION
368             elsif ( $spec =~ s/\A(\s*)((\\.|[^] \t\n[<])+)// )
369             {
370 35         80 my ($ows, $punct) = ($1,$2);
371 35         52 $punct =~ s/\\(?!\\)(.)/$1/g;
372 35 100       59 if ($first) {
373 23         57 $spec =~ m/\A(\S+)/;
374 23   50     100 $self->{flagid} = $punct.($1||"");
375 23         44 $self->{flag} = $punct;
376 23         53 push @flags, $punct;
377             }
378              
379 12         16 else { push @{$self->{args}},
  12         87  
380             Getopt::Declare::Punctuator->new($punct,!length($ows));
381 12         29 $self->{items}++; }
382              
383             }
384              
385 0         0 else { last; }
386              
387             }
388             continue
389             {
390 69         172 $first = 0;
391             }
392              
393 25 50       89 delete $helpcmd{$self->{flag}} if exists $helpcmd{$self->{flag}};
394 25 50       64 delete $versioncmd{$self->{flag}} if exists $versioncmd{$self->{flag}};
395              
396 25         69 bless $self;
397             }
398              
399             sub code
400             {
401 27     27   44 my ($self, $owner,$package) = @_;
402              
403 27         38 my $code = "\n";
404 27         42 my $flag = $self->{flag};
405 27         38 my $flagid = $self->{flagid};
406 27         49 my $clump = $owner->{_internal}{clump};
407 27         31 my $i = 0;
408 27 50 33     46 my $nocase = (Getopt::Declare::_nocase() || $self->{nocase} ? 'i' : '');
409              
410 27 100 66     180 $code .= (!$self->{repeatable} && !$owner->{_internal}{all_rep})
411             ? q# param: while (!$_FOUND_{'# . $self->id . q#'}#
412             : q# param: while (1#;
413              
414 27 50 33     197 if ($flag && ($clump==1 && $flag !~ /\A[^a-z0-9]+[a-z0-9]\Z/i
      66        
415             || ($clump<3 && @{$self->{args}} )))
416             {
417 0         0 $code .= q# && !$_lastprefix#;
418             }
419              
420 27         49 $code .= q#)
421             {
422             pos $_args = $_nextpos if defined $_args;
423             %_PUNCT_ = ();#;
424              
425 27 100 50     49 if ($flag)
    50          
426             {
427             #WAS: $_args =~ m/\G[\s\0]*\Q# . $flag . q#\E/g# . $nocase
428 25         75 $code .= q#
429            
430             $_args && $_args =~ m/\G[\s\0]*# . quotemeta($flag) . q#/g# . $nocase
431             . q# or last;
432             $_errormsg = q|incorrect specification of '# . $flag . q#' parameter| unless $_errormsg;
433              
434             #;
435             }
436             elsif ((Getopt::Declare::ScalarArg::stdtype($self->{args}[0]{type})||'') !~ /\%F/)
437             {
438 2         4 $code .= q#
439            
440             last if $_errormsg;
441              
442             #;
443             }
444              
445 27         70 $code .= q#
446             $_PARAM_ = '# . $self->name . q#';
447             #;
448 27         43 my @trailer;
449 27         59 $#trailer = @{$self->{args}};
  27         92  
450 27         33 for ($i=$#{$self->{args}} ; $i>0 ; $i-- )
  27         92  
451             {
452 24         83 $trailer[$i-1] = $self->{args}[$i]->trailer();
453 24 50       89 $trailer[$i-1] = $trailer[$i] unless defined $trailer[$i-1];
454             }
455              
456 27 100       30 if (@{$self->{args}})
  27         78  
457             {
458 24         40 $code .= "\t\t".'$_args && $_args =~ m/\G';
459 24         36 for ($i=0; $i < @{$self->{args}} ; $i++ )
  72         193  
460             {
461 48         204 $code .= $self->{args}[$i]->ows($self->{args}[$i]->matcher($trailer[$i]));
462             }
463 24         46 $code .= '/gx' . $nocase . ' or last;'
464             }
465              
466              
467 27         41 for ($i=0; $i < @{$self->{args}} ; $i++ )
  75         215  
468             {
469 48         129 $code .= $self->{args}[$i]->code($i,$package); #, $flag ????
470             }
471              
472 27 100       56 if ($flag)
473             {
474 0         0 $code .= q#
475             if (exists $_invalid{'# . $flag . q#'})
476             {
477             $_errormsg = q|parameter '# . $flag
478             . q#' not allowed with parameter '|
479             . $_invalid{'# . $flag . q#'} . q|'|;
480             last;
481             }
482             else
483             {
484             foreach (#
485             . ($owner->{_internal}{mutex}{$flag}
486 25 50       143 ? join(',', map {"'$_'"} @{$owner->{_internal}{mutex}{$flag}})
  0         0  
487             : '()')
488             . q#)
489             {
490             $_invalid{$_} = '# . $flag . q#';
491             }
492             }
493             #
494             }
495              
496 27         36 foreach my $action ( @{$self->{actions}} )
  27         65  
497             {
498 2         15 $action =~ s{(\s*\{)}
499             { $1 package $package; };
500 2         7 $code .= "\n\t\tdo " . $action . ";\n";
501             }
502              
503 27 100 100     125 if ($flag && $self->{items}==0)
504             {
505 3         6 $code .= "\n\t\t\$self->{'$flag'} = '$flag';\n";
506             }
507 27         33 foreach my $subarg ( @{$self->{args}} )
  27         53  
508             {
509 48         106 $code .= $subarg->cachecode($self->name,$self->{items});
510             }
511              
512 27 100       107 if ($flag =~ /\A([^a-z0-9]+)/i) { $code .= '$_lastprefix = "'.quotemeta($1).'";'."\n" }
  24         66  
513 3         6 else { $code .= '$_lastprefix = "";' }
514              
515 27         52 $code .= q#
516             $_FOUND_{'# . $self->name . q#'} = 1;
517             next arg if pos $_args;
518             $_nextpos = length $_args;
519             last arg;
520             }
521              
522             #;
523             }
524              
525             sub name {
526 102     102   118 my $self = shift;
527 102   66     613 return $self->{flag} || "<$self->{args}[0]{name}>";
528             }
529              
530             sub id {
531 26     26   32 my $self = shift;
532 26   66     149 return $self->{flagid} || "<$self->{args}[0]{name}>";
533             }
534              
535              
536             package Getopt::Declare;
537              
538 5     5   51 use Text::Balanced qw( :ALL );
  5         10  
  5         1168  
539 5     5   4640 use Text::Tabs qw( expand );
  5         4184  
  5         27096  
540              
541             # PREDEFINED GRAMMARS
542              
543             my %_predef_grammar =
544             (
545             "-PERL" =>
546             q{ - Set $ to 1 [repeatable]
547             { no strict "refs"; ${"::$varname"} = 1 }
548              
549             },
550            
551             "-AWK" =>
552             q{ = Set $ to [repeatable]
553             {no strict "refs"; ${"::$varname"} = $val }
554             = Set $ to '' [repeatable]
555             {no strict "refs"; ${"::$varname"} = '' }
556              
557             },
558             );
559             my $_predef_grammar = join '|', keys %_predef_grammar;
560              
561             sub _quoteat
562             {
563 0     0   0 my $text = shift;
564 0         0 $text =~ s/\A\@/\\\@/;
565 0         0 $text =~ s/([^\\])\@/$1\\\@/;
566 0         0 $text;
567             }
568              
569             sub new # ($self, $grammar; $source)
570             {
571             # HANDLE SHORT-CIRCUITS
572 13 50 33 13 1 144 return 0 if @_==3 && (!defined($_[2]) || $_[2] eq '-SKIP');
      66        
573              
574             # SET-UP
575 13         33 my ($_class, $_grammar) = @_;
576              
577             # PREDEFINED GRAMMAR?
578 13 50       62 if ($_grammar =~ /\A(-[A-Z]+)+/)
579             {
580 0         0 my $predef = $_grammar;
581 0         0 my %seen = ();
582 0         0 $_grammar = '';
583 0 0       0 $predef =~ s{($_predef_grammar)}{ do {$_grammar .= $_predef_grammar{$1} unless $seen{$1}; $seen{$1} = 1; ""} }ge;
  0         0  
  0         0  
  0         0  
  0         0  
584 0 0 0     0 return undef if $predef || !$_grammar;
585             }
586              
587             # PRESERVE ESCAPED '['s (opening bracket only)
588 13         34 $_grammar =~ s/\\\[/\255/g;
589              
590             # MAKE SURE GRAMMAR ENDS WITH A NEWLINE
591 13         128 $_grammar =~ s/([^\n])\Z/$1\n/;
592              
593             # SET-UP
594 13         36 local $_ = $_grammar;
595 13         27 my @_args = ();
596 13         24 my $_mutex = {};
597 13         22 my $_action;
598 13         19 my $_strict = 0;
599 13         17 my $_all_repeatable = 0;
600 13         22 my $_lastdesc = undef;
601 13         42 _nocase(0);
602 13         42 Getopt::Declare::ScalarArg::_reset_stdtype();
603              
604             # CONSTRUCT GRAMMAR
605 13         62 while (length $_ > 0)
606             {
607             # COMMENT:
608 39 50       100 s/\A[ ]*#.*\n// and next;
609              
610             # TYPE DIRECTIVE:
611 39         107 s{\A(\s*\[\s*pvtype:\s*\S+\s+)/}{$1 qr/};
612 39 100 66     133 if (m/\A\s*\[\s*pvtype:/ and $_action = extract_codeblock($_,'[]'))
613             {
614 3         2104 $_action =~ s/.*?\[\s*pvtype:\s*//;
615 3         10 _typedef($_action);
616 3         11 next;
617             }
618              
619             # ACTION
620 36 100       128 if ($_action = extract_codeblock)
    50          
621             {
622             # WAS: eval q{no strict;my $ref = sub }._quoteat($_action).q{;1}
623 2         871 my $_check_action = $_action;
624 2         17 $_check_action =~ s{(\s*\{)}
625             { $1 sub defer(&); sub finish(;\$); sub reject(;\$\$); };
626 2 50   2   160 eval q{no strict;my $ref = sub }.$_check_action.q{;1}
  2         14  
  2         2  
  2         178  
627             or die "Error: bad action in Getopt::Declare specification:"
628             . "\n\n$_action\n\n$@\n";
629 2 50       9 if ($#_args < 0)
630             {
631 0         0 die "Error: unattached action in Getopt::Declare specification:\n$_action\n"
632             . "\t(did you forget the tab after the preceding parameter specification?)\n"
633             }
634 2         3 push @{$_args[$#_args]->{actions}}, $_action;
  2         5  
635 2         7 next;
636             }
637             elsif (m/\A(\s*[{].*)/)
638             {
639 0         0 die "Error: incomplete action in Getopt::Declare specification:\n$1.....\n"
640             . "\t(did you forget a closing '}'?)\n";
641             }
642              
643             # ARG + DESC:
644 34 100       2512 if ( s/\A(.*?\S.*?)(\t.*\n)// )
645             {
646 25         59 my $spec = $1;
647 25         42 my $desc = $2;
648 25         26 my $ditto;
649 25   33     116 $_strict ||= $desc =~ /\Q[strict]/;
650              
651 25         114 $desc .= $1 while s/\A((?![ ]*({|\n)|.*?\S.*?\t.*?\S).*?\S.*\n)//;
652            
653 25 100 100     98 $_lastdesc and $desc =~ s/\A\s*\[\s*ditto\s*\]/$_lastdesc/
654             and $ditto = 1;
655 25         37 $_lastdesc = $desc;
656              
657 25         108 my $arg = Getopt::Declare::Arg->new($spec,$desc,$ditto) ;
658 25         35 push @_args, $arg;
659              
660 25         63 _infer($desc, $arg, $_mutex);
661 25         74 next;
662             }
663              
664              
665             # OTHERWISE: DECORATION
666 9         35 s/((?:(?!\[\s*pvtype:).)*)(\n|(?=\[\s*pvtype:))//;
667 9         26 my $decorator = $1;
668 9   33     45 $_strict ||= $decorator =~ /\Q[strict]/;
669 9         32 _infer($decorator, undef, $_mutex);
670 9 50       33 $_all_repeatable = 1 if $decorator =~ /\[\s*repeatable\s*\]/;
671             }
672              
673 13         20 my $_lastactions;
674 13         28 foreach ( @_args )
675             {
676 25 100 100     115 if ($_lastactions && $_->{ditto} && !@{$_->{actions}})
  1   66     4  
677 1         3 { $_->{actions} = $_lastactions }
678             else
679 24         68 { $_lastactions = $_->{actions} }
680             }
681              
682             @_args = sort
683 0         0 {
684 13         37 length($b->{flag}) <=> length($a->{flag})
685             or
686 37 0 33     150 $b->{flag} eq $a->{flag} and $#{$b->{args}} <=> $#{$a->{args}}
  0   66     0  
687             or
688             $a->{ID} <=> $b->{ID}
689              
690             } @_args;
691              
692             # CONSTRUCT OBJECT ITSELF
693 13 50       139 my $clump = ($_grammar =~ /\[\s*cluster:\s*none\s*\]/i) ? 0
    50          
    50          
    50          
    50          
694             : ($_grammar =~ /\[\s*cluster:\s*singles?\s*\]/i) ? 1
695             : ($_grammar =~ /\[\s*cluster:\s*flags?\s*\]/i) ? 2
696             : ($_grammar =~ /\[\s*cluster:\s*any\s*\]/i) ? 3
697             : ($_grammar =~ /\[\s*cluster:(.*)\s*\]/i) ?
698             die "Error: unknown clustering mode: [cluster:$1]\n"
699             : 3;
700              
701 13   33     60 my $self = bless
702             {
703             _internal =>
704             {
705             args => [@_args],
706             mutex => $_mutex,
707             usage => $_grammar,
708             helppat => Getopt::Declare::Arg::helppat(),
709             verspat => Getopt::Declare::Arg::versionpat(),
710             strict => $_strict,
711             clump => $clump,
712             source => '',
713             all_rep => $_all_repeatable,
714             'caller' => scalar caller(),
715             }
716             }, ref($_class)||$_class;
717              
718              
719             # VESTIGAL DEBUGGING CODE
720 13 50 0     58 open (CODE, ">.CODE")
      0        
721             and print CODE $self->code($self->{_internal}{'caller'})
722             and close CODE
723             if $::Declare_debug;
724              
725             # DO THE PARSE (IF APPROPRIATE)
726 13 50       33 if (@_==3) { return undef unless defined $self->parse($_[2]) }
  1 100       6  
727 12 50       52 else { return undef unless defined $self->parse(); }
728              
729 13         116 return $self;
730             }
731              
732 0     0   0 sub _get_nextline { scalar <> }
733              
734             sub _load_sources # ( \$_get_nextline, @files )
735             {
736 0     0   0 my $text = '';
737 0         0 my @found = ();
738 0         0 my $gnlref = shift;
739 0         0 foreach ( @_ )
740             {
741 0 0       0 open FILE, $_ or next;
742 0 0       0 if (-t FILE)
743             {
744 0         0 push @found, '';
745 0         0 $$gnlref = \&_get_nextline;
746             }
747             else
748             {
749 0         0 push @found, $_;
750 0         0 $text .= join "\n", ;
751             }
752             }
753 0 0       0 return undef unless @found;
754 0 0       0 $text = unless $text;
755 0         0 return ( $text, join(" or ",@found));
756             }
757              
758              
759             sub parse # ($self;$source)
760             {
761 14     14 1 30 my ( $self, $source ) = @_;
762 14         19 my $_args = ();
763 14     13   59 my $_get_nextline = sub { undef };
  13         270  
764 14 100       39 if (@_>1) # if $source was provided
765             {
766 1 50       13 if (!defined $source)
    50          
    50          
    50          
    50          
767             {
768 0         0 return 0;
769             }
770             elsif ( ref $source eq 'CODE' )
771             {
772 0         0 $_get_nextline = $source;
773 0         0 $_args = &{$_get_nextline}($self);
  0         0  
774 0         0 $source = '[SUB]';
775             }
776             elsif ( ref $source eq 'GLOB' )
777             {
778 0 0       0 if (-t *$source)
779             {
780 0         0 $_get_nextline = \&_get_nextline ;
781 0         0 $_args = ;
782 0         0 $source = '';
783             }
784             else
785             {
786 0         0 $_args = join ' ', (<$source>);
787 0         0 $_args =~ tr/\t\n/ /s;
788 0         0 $source = ref($source);
789             }
790             }
791             elsif ( ref $source eq 'IO::Handle' )
792             {
793 0 0 0     0 if (!($source->fileno) && -t)
794             {
795 0         0 $_get_nextline = \&_get_nextline ;
796 0         0 $_args = ;
797 0         0 $source = '';
798             }
799             else
800             {
801 0         0 $_args = join ' ', (<$source>);
802 0         0 $_args =~ tr/\t\n/ /s;
803 0         0 $source = ref($source);
804             }
805             }
806             elsif ( ref $source eq 'ARRAY' )
807             {
808 0 0 0     0 if (@$source == 1 && (!defined($source->[0])
    0 0        
    0 0        
      0        
809             || $source->[0] eq '-BUILD'
810             || $source->[0] eq '-SKIP') )
811             {
812 0         0 return 0;
813             }
814             elsif (@$source == 1 && $source->[0] eq '-STDIN')
815             {
816 0         0 $_get_nextline = \&_get_nextline ;
817 0         0 $_args = ;
818 0         0 $source = '';
819             }
820             elsif (@$source == 1 && $source->[0] eq '-CONFIG')
821             {
822 0         0 my $progname = "$0rc";
823 0         0 $progname =~ s#.*/##;
824 0         0 ($_args,$source) = _load_sources(\$_get_nextline,"$ENV{HOME}/.$progname", ".$progname");
825             }
826             else
827             {
828 0         0 my $stdin;
829 0         0 ($_args,$source) = _load_sources(\$_get_nextline,@$source);
830             }
831             }
832             else # LITERAL STRING TO PARSE
833             {
834 1         2 $_args = $source;
835 1 50       3 substr($source,7) = '...' if length($source)>7;
836 1         2 $source = "\"$source\"";
837             }
838 1 50       3 return 0 unless defined $_args;
839 1         2 $source = " (in $source)";
840             }
841             else # $source was NOT provided
842             {
843 13         32 foreach (@ARGV) {
844             # Clean entries: remove spaces, tabs and newlines
845 57         97 $_ =~ tr/ \t\n/\0\0\0/;
846             }
847 13         45 $_args = join(' ', @ARGV);
848 13         25 $source = '';
849             }
850              
851 14         51 $self->{_internal}{source} = $source;
852              
853 14 50       64 if (!eval $self->code($self->{_internal}{'caller'}))
854             {
855 0 0       0 die "Error: in generated parser code:\n$@\n" if $@;
856 0         0 return undef;
857             }
858              
859 14         68 return 1;
860             }
861              
862             sub type # ($abbrev, $pattern, $action)
863             {
864 0     0 1 0 &Getopt::Declare::ScalarArg::addtype;
865             }
866              
867             sub _enbool
868             {
869 0     0   0 my $expr = shift;
870 0         0 $expr =~ s/\s*\|\|\s*/ or /g;
871 3         8 $expr =~ s/\s*&&\s*/ and /g;
872 3         16 $expr =~ s/\s*!\s*/ not /g;
873 0         0 return $expr;
874             }
875              
876             sub _enfound
877             {
878 0     0   0 my $expr = shift;
879 0         0 my $original = $expr;
880 0         0 $expr =~ s/((?:&&|\|\|)?\s*(?:[!(]\s*)*)([^ \t\n|&\)]+)/$1\$_FOUND_{'$2'}/gx;
881 0 0       0 die "Error: bad condition in [requires: $original]\n"
882             unless eval 'no strict; my $ref = sub { '.$expr.' }; 1';
883 0         0 return $expr;
884             }
885              
886             my $_nocase = 0;
887              
888             sub _nocase
889             {
890 40 50   40   95 $_nocase = $_[0] if $_[0];
891 40         159 return $_nocase;
892             }
893              
894             sub _infer # ($desc, $arg, $mutex)
895             {
896 34     34   65 my ($desc, $arg, $mutex) = @_;
897              
898 34         96 _mutex($mutex, split(' ',$1))
899             while $desc =~ s/\[\s*mutex:\s*(.*?)\]//i;
900              
901 34 50       84 if ( $desc =~ m/\[\s*no\s*case\s*\]/i)
902             {
903 0 50       0 if ($arg) { $arg->{nocase} = 1 }
  0         0  
904 0         0 else { _nocase(1); }
905             }
906              
907 34 100       69 if (defined $arg)
908             {
909 25 50       66 _exclude($mutex, $arg->name, (split(' ',$1)))
910             if $desc =~ m/.*\[\s*excludes:\s*(.*?)\]/i;
911 25 50       73 $arg->{requires} = $1
912             if $desc =~ m/.*\[\s*requires:\s*(.*?)\]/i;
913              
914 25         79 $arg->{required} = ( $desc =~ m/\[\s*required\s*\]/i );
915 25   66     127 $arg->{repeatable} ||= ( $desc =~ m/\[\s*repeatable\s*\]/i );
916             }
917              
918 34         117 _typedef($desc) while $desc =~ s/.*?\[\s*pvtype:\s*//;
919             }
920              
921             sub _typedef
922             {
923 3     3   8 my $desc = $_[0];
924 3         3 my ($name,$pat,$action,$ind);
925              
926 3         12 ($name,$desc) = (extract_quotelike($desc))[5,1];
927 3 50       136 do { $desc =~ s/\A\s*([^] \t\n]+)// and $name = $1 } unless $name;
  3 50       19  
928 3 50 33     7 die "Error: bad type directive (missing type name): [pvtype: "
929             . substr($desc,0,index($desc,']')||20). "....\n"
930             unless $name;
931              
932 3         11 ($pat,$desc,$ind) = (extract_quotelike($desc,'\s*:?\s*'))[5,1,2];
933 3 0 0     322 do { $desc =~ s/\A\s*(:?)\s*([^] \t\n]+)//
  0 50       0  
934             and $pat = $2 and $ind = $1 } unless $pat;
935 3 50       8 $pat = '' unless $pat;
936 3   100     8 $action = extract_codeblock($desc) || '';
937              
938 3 0       678 die "Error: bad type directive (expected closing ']' but found"
    50          
939             . "'$1' instead): [pvtype: $name " . ($pat?"/$pat/":'')
940             . " $action $1$2....\n" if $desc =~ /\A\s*([^] \t\n])(\S*)/;
941              
942 3         13 Getopt::Declare::ScalarArg::addtype($name,$pat,$action,$ind=~/:/);
943             }
944              
945             sub _ditto # ($originalflag, $orginaldesc, $extra)
946             {
947 2     2   3 my ($originalflag, $originaldesc, $extra) = @_;
948 2 50       7 if ($originaldesc =~ /\n.*\n/)
949             {
950 0         0 $originaldesc = "Same as $originalflag ";
951             }
952             else
953             {
954 2         5 chomp $originaldesc;
955 2         10 $originaldesc =~ s/\S/"/g;
956 2         25 1 while $originaldesc =~ s/"("+)"/ $1 /g;
957 2         5 $originaldesc =~ s/""/" /g;
958             }
959 2         6 return "$originaldesc$extra\n";
960             }
961              
962             sub _mutex # (\%mutex, @list)
963             {
964 0     0   0 my ($mref, @mutexlist) = @_;
965              
966 0         0 foreach my $flag ( @mutexlist )
967             {
968 0 0       0 $mref->{$flag} = [] unless $mref->{$flag};
969 0         0 foreach my $otherflag ( @mutexlist )
970             {
971 0 0       0 next if ($flag eq $otherflag);
972 0         0 push @{$mref->{$flag}}, $otherflag;
  0         0  
973             }
974             }
975             }
976              
977             sub _exclude # (\%mutex, $excluded, @list)
978             {
979 0     0   0 my ($mref, $excluded, @mutexlist) = @_;
980              
981 0         0 foreach my $flag ( @mutexlist )
982             {
983 0 0       0 unless ($flag eq $excluded)
984             {
985 0 0       0 $mref->{$flag} = [] unless $mref->{$flag};
986 0         0 push @{$mref->{$excluded}}, $flag;
  0         0  
987 0         0 push @{$mref->{$flag}}, $excluded;
  0         0  
988             }
989             }
990             }
991              
992             sub version
993             {
994 1     1 1 3 my ($self, $exit_status) = @_;
995             # my $filedate = localtime(time - 86400 * -M $0);
996 1         205 my $filedate = localtime((stat $0)[9]);
997 1 50       5 if ($::VERSION) { print "\n\t$0: version $::VERSION ($filedate)\n\n" }
  0         0  
998 1         55 else { print "\n\t$0: version dated $filedate\n\n" }
999 1 50       5 exit $exit_status if defined $exit_status;
1000 1         5 return 1;
1001             }
1002              
1003             sub usage
1004             {
1005 1     1 1 3 my ($self, $exit_status) = @_;
1006              
1007 1         1 my $use_pager = eval { require IO::Pager };
  1         487  
1008              
1009 1 50       8 if ($use_pager)
1010             {
1011 0         0 new IO::Pager; # use a pager for all print() statements
1012             }
1013              
1014 1         7 print $self->usage_string;
1015              
1016 1 50       5 if ($use_pager)
1017             {
1018 0         0 close; # done using the pager
1019             }
1020              
1021 1 50       3 if (defined $exit_status)
1022             {
1023 0         0 exit $exit_status;
1024             }
1025 1         6 return 1;
1026             }
1027              
1028             sub usage_string
1029             {
1030 3     3 0 6 my $self = shift;
1031              
1032 3         10 local $_ = $self->{_internal}{usage};
1033              
1034 3         5 my $lastflag = undef;
1035 3         6 my $lastdesc = undef;
1036              
1037 3         5 my $usage = '';
1038 3         5 my $uoff;
1039             my $decfirst;
1040 0         0 my $ditto;
1041              
1042 3         12 while (length $_ > 0)
1043             {
1044              
1045             # COMMENT:
1046 43 50       104 s/\A[ ]*#.*\n// and next;
1047              
1048             # TYPE DIRECTIVE:
1049             #WAS: if (m/\A\s*\[\s*pvtype:/ and extract_codeblock($_,'[{}]'))
1050 43 100 66     161 if (m/\A\s*\[\s*pvtype:/ and extract_bracketed($_,'[{}]'))
1051             {
1052 5         1135 next;
1053             }
1054              
1055             # ACTION
1056             #WAS: extract_codeblock and do {
1057 38 100       136 extract_bracketed($_,'[{}]') and do {
1058 3         551 s/\A[ ]*\n//;
1059 3 50       11 $decfirst = 0 unless defined $decfirst;
1060 3         9 next;
1061             };
1062              
1063             # ARG + DESC:
1064 35 100       1794 if ( s/\A(.*?\S.*?\t+)(.*?\n)// )
1065             {
1066 27 100       54 $decfirst = 0 unless defined $decfirst;
1067              
1068 27         60 my ($spec) = expand $1;
1069 27         1285 my ($desc) = expand $2;
1070              
1071 27         455 $desc .= (expand $1)[0]
1072             while s/\A((?![ ]*({|\n)|.*?\S.*?\t.*?\S).*?\S.*\n)//;
1073              
1074             # Skip parameters with the special directive [undocumented]
1075 27 50       145 next if $desc =~ /\[\s*undocumented\s*\]/i;
1076              
1077 27         27 $uoff = 0;
1078 27 50       72 $spec =~ s/(<[a-zA-Z]\w*):([^>]+)>/$uoff+=1+length $2 and "$1>"/ge;
  14         63  
1079              
1080 27         43 $ditto = $desc =~ /\A\s*\[\s*ditto\s*\]/;
1081 27         36 $desc =~ s/^\s*\[.*?\]\s*\n//gm;
1082 27         35 $desc =~ s/\[.*?\]//g;
1083              
1084 27 100       75 if ($ditto)
    50          
1085 2 50       8 { $desc = ($lastdesc? _ditto($lastflag,$lastdesc,$desc) : "" ) }
1086             elsif ($desc =~ /\A\s*\Z/)
1087             # Skip parameters with no description
1088 0         0 { next; }
1089             else
1090 25         31 { $lastdesc = $desc; }
1091 27 50       94 $spec =~ /\A\s*(\S+)/ and $lastflag = $1;
1092              
1093 27         62 $usage .= $spec . ' ' x $uoff . $desc;
1094              
1095 27         66 next;
1096             };
1097              
1098             # OTHERWISE, DECORATION
1099 8 50       49 if (s/((?:(?!\[\s*pvtype:).)*)(\n|(?=\[\s*pvtype:))//)
1100             {
1101 8   50     34 my $desc = $1.($2||'');
1102 8         13 $desc =~ s/^(\s*\[.*?\])+\s*\n//gm;
1103 8         12 $desc =~ s/\[.*?\]//g;
1104 8 50 66     40 $decfirst = 1 unless defined $decfirst
1105             or $desc =~ m/\A\s*\Z/;
1106 8         12 $usage .= $desc;
1107 8         19 next;
1108             }
1109              
1110             # Should never get here if all goes well
1111 0         0 die "Error: internal error\n";
1112             }
1113              
1114 3         5 my $required = '';
1115              
1116 3         5 foreach my $arg ( @{$self->{_internal}{args}} )
  3         11  
1117             {
1118 27 50       55 if ($arg->{required})
1119             {
1120 0         0 $required .= ' ' . $arg->{desc} . ' ';
1121             }
1122             }
1123              
1124             # REINSTATE ESCAPED '['s
1125 3         15 $usage =~ s/\255/[/g;
1126              
1127 3         5 $required =~ s/<([a-zA-Z]\w*):[^>]+>/<$1>/g;
1128              
1129 3         8 my $helpcmd = Getopt::Declare::Arg::besthelp;
1130 3         10 my $versioncmd = Getopt::Declare::Arg::bestversion;
1131              
1132 3         4 my $msg = '';
1133 3 50       11 unless ($self->{_internal}{source})
1134             {
1135 3         11 $msg .= "\nUsage: $0 [options] $required\n";
1136 3 50       14 $msg .= " $0 $helpcmd\n" if $helpcmd;
1137 3 50       12 $msg .= " $0 $versioncmd\n" if $versioncmd;
1138 3 50 33     12 $msg .= "\n" unless $decfirst && $usage =~ /\A[ \t]*\n/;
1139             }
1140 3 50       8 $msg .= "Options:\n" unless $decfirst;
1141 3         5 $msg .= $usage;
1142 3         85 return $msg;
1143             }
1144              
1145             sub unused {
1146 0 0   0 0 0 return @{$_[0]->{_internal}{unused}} if wantarray;
  0         0  
1147 0         0 return join " ", @{$_[0]->{_internal}{unused}};
  0         0  
1148             }
1149              
1150             sub flatten {
1151 0     0 0 0 my ($val, $nested) = @_;
1152 0 0       0 if (ref $val eq 'ARRAY') {
    0          
1153 0         0 return join " ", map {flatten($_,1)} @$val;
  0         0  
1154             }
1155             elsif (ref $val eq 'HASH') {
1156 0 0 0     0 return join " ", map {
1157 0         0 $nested || /^-/ ? ($_, flatten($val->{$_},1))
1158             : (flatten($val->{$_},1))
1159             } keys %$val;
1160             }
1161             else {
1162 0         0 return $val;
1163             }
1164             }
1165              
1166             sub used {
1167 0     0 0 0 my $self = shift;
1168 0 0       0 my @used = map { /^_/ ? () : ($_, $self->{$_}) } keys %$self;
  0         0  
1169 0 0       0 return @used if wantarray;
1170 0         0 return join " ", map { flatten $_ } @used;
  0         0  
1171             }
1172              
1173             sub code
1174             {
1175 15     15 1 27 my $self = shift;
1176 15   100     49 my $package = shift||'main';
1177              
1178 15 50       186 my $code = q#
1179              
1180             do
1181             {
1182             my @_deferred = ();
1183             my @_unused = ();
1184             sub # . $package . q#::defer (&);
1185             {
1186             package # . $package . q#; local $^W;
1187             *defer = sub (&) { push @_deferred, $_[0]; }
1188             }
1189             my %_FOUND_ = ();
1190             my $_errors = 0;
1191             my $_nextpos;
1192             my %_invalid = ();
1193             my $_lastprefix = '';
1194             my $_finished = 0;
1195             my %_PUNCT_;
1196             my $_errormsg;
1197             my $_VAL_;
1198             my $_VAR_;
1199             my $_PARAM_;
1200              
1201             sub # . $package . q#::reject (;$$);
1202             sub # . $package . q#::finish (;$);
1203              
1204             {
1205             package # . $package . q#; local $^W;
1206             *reject = sub (;$$) { local $^W; if (!@_ || $_[0]) { $_errormsg = $_[1] if defined $_[1]; last param; } };
1207             *finish = sub (;$) { if (!@_ || $_[0]) { $_finished = 1; } };
1208             }
1209              
1210             $_nextpos = 0;
1211             arg: while (!$_finished)
1212             {
1213             $_errormsg = '';
1214             # . ( $self->{_internal}{clump} ? q#
1215             while ($_lastprefix)
1216             {
1217             my $substr = substr($_args,$_nextpos);
1218             $substr =~ m/\A(?!\s|\0|\Z)#
1219             . Getopt::Declare::Arg::negflagpat() . q#/
1220             or do { $_lastprefix='';last};
1221             "$_lastprefix$substr" =~ m/\A(#
1222             . Getopt::Declare::Arg::posflagpat()
1223             . q#)/
1224             or do { $_lastprefix='';last};
1225             substr($_args,$_nextpos,0) = $_lastprefix;
1226             last;
1227             }
1228             # : '') . q#
1229             pos $_args = $_nextpos if defined $_args;
1230              
1231             $self->usage(0) if $_args && $_args =~ m/\G(# . $self->{_internal}{helppat} . q#)(\s|\0|\Z)/g;
1232             $self->version(0) if $_args && $_args =~ m/\G(# . $self->{_internal}{verspat} . q#)(\s|\0|\Z)/g;
1233              
1234             #;
1235              
1236 15         29 foreach my $arg ( @{$self->{_internal}{args}} )
  15         45  
1237             {
1238 27         77 $code .= $arg->code($self,$package);
1239             }
1240              
1241 15         49 $code .= q#
1242              
1243             if ($_lastprefix)
1244             {
1245             pos $_args = $_nextpos+length($_lastprefix);
1246             $_lastprefix = '';
1247             next;
1248             }
1249            
1250             pos $_args = $_nextpos;
1251             $_args && $_args =~ m/\G[\s\0]*(\S+)/g or last;
1252             if ($_errormsg) { print STDERR "Error"."$self->{_internal}{source}: $_errormsg\n" }
1253              
1254             else { push @_unused, $1; }
1255             $_errors++ if ($_errormsg);
1256             }
1257             continue
1258             {
1259             $_nextpos = pos $_args if defined $_args;
1260             if (defined $_args and $_args =~ m/\G[\s\0]*\Z/g)
1261             {
1262             $_args = &{$_get_nextline}($self);
1263             last unless defined($_args);
1264             $_nextpos = 0;
1265             $_lastprefix = '';
1266             }
1267             }
1268             #;
1269              
1270 15         20 foreach my $arg ( @{$self->{_internal}{args}} )
  15         1548  
1271             {
1272 27 50       75 next unless $arg->{required};
1273 0         0 $code .= q#
1274             do { print STDERR "Error"."$self->{_internal}{source}".': required parameter # . $arg->name . q# not found.',"\n"; $_errors++ }
1275             unless $_FOUND_{'# . $arg->name . q#'}#;
1276 0 0       0 if ($self->{_internal}{mutex}{$arg->name})
1277             {
1278 0         0 foreach my $mutex (@{$self->{_internal}{mutex}{$arg->name}})
  0         0  
1279             {
1280 0         0 $code .= q# or $_FOUND_{'# . $mutex . q#'}#;
1281             }
1282             }
1283 0         0 $code .= ';';
1284             }
1285            
1286 15         34 foreach my $arg ( @{$self->{_internal}{args}} )
  15         39  
1287             {
1288 27 50       77 if ($arg->{requires})
1289             {
1290 0         0 $code .= q#
1291             do { print STDERR q|Error|.$self->{_internal}{source}.q|: parameter '# . $arg->name
1292             . q#' can only be specified with '# . _enbool($arg->{requires})
1293             . q#'|,"\n"; $_errors++ }
1294             if $_FOUND_{'# . $arg->name . "'} && !(" . _enfound($arg->{requires}) . ');'
1295             }
1296             }
1297              
1298 15         30 $code .= q#
1299             push @_unused, split(' ', substr($_args,$_nextpos))
1300             if $_args && $_nextpos && length($_args) >= $_nextpos;
1301             #;
1302              
1303 15 50       45 if ($self->{_internal}{strict})
1304             {
1305 0         0 $code .= q#
1306             unless ($_nextpos < length($_args||''))
1307             {
1308             foreach (@_unused)
1309             {
1310             tr/\0/ /;
1311             print STDERR "Error"."$self->{_internal}{source}: unrecognizable argument ('$_')\n";
1312             $_errors++;
1313             }
1314             }
1315             #
1316             }
1317              
1318 15         48 $code .= q#
1319              
1320             if ($_errors && !$self->{_internal}{source})
1321             {
1322             print STDERR "\n(try '$0 ".'# . Getopt::Declare::Arg::besthelp
1323             . q#'."' for more information)\n";
1324             }
1325              
1326             $self->{_internal}{unused} = [map { tr/\0/ /; $_ } @_unused];
1327             @ARGV = @{$self->{_internal}{unused}}
1328             unless $self->{_internal}{source};
1329              
1330             unless ($_errors) { foreach (@_deferred) { &$_ } }
1331              
1332             !$_errors;
1333              
1334             }
1335             #;
1336              
1337             }
1338              
1339             1;
1340             __END__