File Coverage

blib/lib/Getopt/Tabular.pm
Criterion Covered Total %
statement 104 273 38.1
branch 43 174 24.7
condition 5 67 7.4
subroutine 13 30 43.3
pod 0 26 0.0
total 165 570 28.9


line stmt bran cond sub pod time code
1             package Getopt::Tabular;
2              
3             #
4             # Getopt/Tabular.pm
5             #
6             # Perl module for table-driven argument parsing, somewhat like Tk's
7             # ParseArgv. To use the package, you just have to set up an argument table
8             # (a list of array references), and call &GetOptions (the name is exported
9             # from the module). &GetOptions takes two or three arguments; a reference
10             # to your argument table (which is not modified), a reference to the list
11             # of command line arguments, e.g. @ARGV (or a copy of it), and (optionally)
12             # a reference to a new empty array. In the two argument form, the second
13             # argument is modified in place to remove all options and their arguments.
14             # In the three argument form, the second argument is unmodified, and the
15             # third argument is set to a copy of it with options removed.
16             #
17             # The argument table consists of one element per valid command-line option;
18             # each element should be a reference to a list of the form:
19             #
20             # ( option_name, type, num_values, option_data, help_string, arg_desc )
21             #
22             # See Getopt/Tabular.pod for complete information.
23             #
24             # originally by Greg Ward 1995/07/06-07/09 as ParseArgs.pm
25             # renamed to Getopt::Tabular and somewhat reorganized/reworked,
26             # 1996/11/08-11/10
27             #
28             # $Id: Tabular.pm,v 1.8 1999/04/08 01:11:24 greg Exp $
29              
30             # Copyright (c) 1995-98 Greg Ward. All rights reserved. This package is
31             # free software; you can redistribute it and/or modify it under the same
32             # terms as Perl itself.
33              
34             require Exporter;
35 1     1   1061 use Carp;
  1         2  
  1         182  
36              
37 1     1   5 use strict;
  1         2  
  1         30  
38 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         4  
  1         84  
39 1         7025 use vars qw/%Patterns %OptionHandlers %TypeDescriptions @OptionPatterns
40             %SpoofCode $OptionTerminator $HelpOption
41 1     1   4 $LongHelp $Usage $ErrorClass $ErrorMessage/;
  1         2  
42              
43             $VERSION = 0.3;
44             @ISA = qw/Exporter/;
45             @EXPORT = qw/GetOptions/;
46             @EXPORT_OK = qw/SetHelp SetHelpOption SetError GetError SpoofGetOptions/;
47              
48             # -------------------------------------------------------------------- #
49             # Private global variables #
50             # -------------------------------------------------------------------- #
51              
52              
53             # The regexp for floating point numbers here is a little more permissive
54             # than the C standard -- it recognizes "0", "0.", ".0", and "0.0" (where 0
55             # can be substituted by any string of one or more digits), preceded by an
56             # optional sign, and followed by an optional exponent.
57              
58             %Patterns = ('integer' => '[+-]?\d+',
59             'float' => '[+-]? ( \d+(\.\d*)? | \.\d+ ) ([Ee][+-]?\d+)?',
60             'string' => '.*');
61              
62              
63             # This hash defines the allowable option types, and what to do when we
64             # see an argument of a given type in the argument list. New types
65             # can be added by calling AddType, as long as you supply an option
66             # handler that acts like one of the existing handlers. (Ie. takes
67             # the same three arguments, returns 1 for success and 0 for failure,
68             # and calls SetError appropriately.)
69              
70             %OptionHandlers = ("string", \&process_pattern_option,
71             "integer", \&process_pattern_option,
72             "float", \&process_pattern_option,
73             "boolean", \&process_boolean_option,
74             "const", \&process_constant_option,
75             "copy", \&process_constant_option,
76             "arrayconst",\&process_constant_option,
77             "hashconst", \&process_constant_option,
78             "call", \&process_call_option,
79             "eval", \&process_eval_option,
80             "section", undef);
81              
82             # This hash is used for building error messages for pattern types. A
83             # subtle point is that the description should be such that it can be
84             # pluralized by adding an "s". OK, OK, you can supply an alternate
85             # plural form by making the description a reference to a two-element list,
86             # singular and plural forms. I18N fanatics should be happy.
87              
88             %TypeDescriptions = ("integer" => "integer",
89             "float" => "floating-point number",
90             "string" => "string");
91              
92             @OptionPatterns = ('(-)(\w+)'); # two parts: "prefix" and "body"
93             $OptionTerminator = "--";
94             $HelpOption = "-help";
95              
96             # The %SpoofCode hash is for storing alternate versions of callbacks
97             # for call or eval options. The alternate versions should have no side
98             # effects apart from changing the argument list identically to their
99             # "real" alternatives.
100              
101             %SpoofCode = ();
102              
103             $ErrorClass = ""; # can be "bad_option", "bad_value",
104             # "bad_eval", or "help"
105             $ErrorMessage = ""; # can be anything
106              
107             # -------------------------------------------------------------------- #
108             # Public (but not exported) subroutines used to set options before #
109             # calling GetOptions. #
110             # -------------------------------------------------------------------- #
111              
112             sub SetHelp
113             {
114 0     0 0 0 $LongHelp = shift;
115 0         0 $Usage = shift;
116             }
117              
118             sub SetOptionPatterns
119             {
120 0     0 0 0 @OptionPatterns = @_;
121             }
122              
123             sub SetHelpOption
124             {
125 0     0 0 0 $HelpOption = shift;
126             }
127              
128             sub SetTerminator
129             {
130 0     0 0 0 $OptionTerminator = shift;
131             }
132              
133             sub UnsetTerminator
134             {
135 0     0 0 0 undef $OptionTerminator;
136             }
137              
138             sub AddType
139             {
140 0     0 0 0 my ($type, $handler) = @_;
141 0 0       0 croak "AddType: \$handler must be a code ref"
142             unless ref $handler eq 'CODE';
143 0         0 $OptionHandlers{$type} = $handler;
144             }
145              
146             sub AddPatternType
147             {
148 0     0 0 0 my ($type, $pattern, $description) = @_;
149 0         0 $OptionHandlers{$type} = \&process_pattern_option;
150 0         0 $Patterns{$type} = $pattern;
151 0   0     0 $TypeDescriptions{$type} = ($description || $type);
152             }
153              
154             sub GetPattern
155             {
156 0     0 0 0 my ($type) = @_;
157 0         0 $Patterns{$type};
158             }
159              
160             sub SetSpoofCodes
161             {
162 0     0 0 0 my ($option, $code);
163 0 0 0     0 croak "Even number of arguments required"
164             unless (@_ > 0 && @_ % 2 == 0);
165              
166 0         0 while (@_)
167             {
168 0         0 ($option, $code) = (shift, shift);
169 0         0 $SpoofCode{$option} = $code;
170             }
171             }
172              
173             sub SetError
174             {
175 6     6 0 9 $ErrorClass = shift;
176 6         8 $ErrorMessage = shift;
177             }
178              
179             sub GetError
180             {
181 0     0 0 0 ($ErrorClass, $ErrorMessage);
182             }
183              
184             # --------------------------------------------------------------------
185             # Private utility subroutines:
186             # quote_strings
187             # print_help
188             # scan_table
189             # match_abbreviation
190             # option_error
191             # check_value
192             # split_option
193             # find_calling_package
194             # --------------------------------------------------------------------
195              
196              
197             #
198             # "e_strings
199             #
200             # prepares strings for printing in a list of default values (for the
201             # help text). If a string is empty or contains whitespace, it is quoted;
202             # otherwise, it is left alone. The input list of strings is returned
203             # concatenated into a single space-separated string. This is *not*
204             # rigorous by any stretch; it's just to make the help text look nice.
205             #
206             sub quote_strings
207             {
208 0     0 0 0 my @strings = @_;
209 0         0 my $string;
210 0         0 foreach $string (@strings)
211             {
212 0 0 0     0 $string = qq["$string"] if ($string eq '' || $string =~ /\s/);
213             }
214 0         0 return join (' ', @strings);
215             }
216              
217              
218             #
219             # &print_help
220             #
221             # walks through an argument table and prints out nicely-formatted
222             # option help for all entries that provide it. Also does the Right Thing
223             # (trust me) if you supply "argument description" text after the help.
224             #
225             # Don't read this code if you can possibly avoid it. It's pretty gross.
226             #
227             sub print_help
228             {
229 0 0   0 0 0 confess ("internal error, wrong number of input args to &print_help")
230             if (scalar (@_) != 1);
231 0         0 my ($argtable) = @_;
232 0         0 my ($maxoption, $maxargdesc, $numcols, $opt, $breakers);
233 0         0 my ($textlength, $std_format, $alt_format);
234 0         0 my ($option, $type, $num, $value, $help, $argdesc);
235              
236 0         0 $maxoption = 0;
237 0         0 $maxargdesc = 0;
238              
239             # Loop over all options to determine the length of the longest option name
240 0         0 foreach $opt (@$argtable)
241             {
242 0         0 my ($argdesclen, $neg_option);
243 0         0 my ($option, $type, $help, $argdesc) = @{$opt} [0,1,4,5];
  0         0  
244 0 0 0     0 next if $type eq "section" or ! defined $help;
245              
246             # Boolean options contribute *two* lines to the help: one for the
247             # option, and one for its negative. Other options just contribute
248             # one line, so they're a bit simpler.
249 0 0       0 if ($type eq 'boolean')
250             {
251 0         0 my ($pos, $neg) = &split_option ($opt);
252 0         0 my $pos_len = length ($pos);
253 0         0 my $neg_len = length ($neg);
254 0 0       0 $maxoption = $pos_len if ($pos_len > $maxoption);
255 0 0       0 $maxoption = $neg_len if ($pos_len > $maxoption);
256 0 0       0 carp "Getopt::Tabular: argument descriptions ignored " .
257             "for boolean option \"$option\""
258             if defined $argdesc;
259             }
260             else
261             {
262 0         0 my $optlen = length ($option);
263 0 0       0 $maxoption = $optlen if ($optlen > $maxoption);
264              
265 0 0       0 if (defined $argdesc)
266             {
267 0         0 $argdesclen = length ($argdesc);
268 0 0       0 $maxargdesc = $argdesclen if ($argdesclen > $maxargdesc);
269             }
270             }
271             }
272              
273             # We need to construct and eval code that looks something like this:
274             # format STANDARD =
275             # @<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
276             # $option, $help
277             # ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
278             # $help
279             # .
280             #
281             # with an alternative format like this:
282             # format ALTERNATIVE =
283             # @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
284             # $option, $argdesc
285             # ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
286             # $help
287             # ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
288             # $help
289             # .
290             # in order to nicely print out the help. Can't hardcode a format,
291             # though, because we don't know until now how much space to allocate
292             # for the option (ie. $maxoption).
293              
294 0         0 local $: = " \n";
295 0         0 local $~;
296              
297 0         0 $numcols = 80; # not always accurate, but faster!
298              
299             # width of text = width of terminal, with columns removed as follows:
300             # 3 (for left margin), $maxoption (option names), 2 (gutter between
301             # option names and help text), and 2 (right margin)
302 0         0 $textlength = $numcols - 3 - $maxoption - 2 - 2;
303 0         0 $std_format = "format STANDARD =\n" .
304             " @" . ("<" x $maxoption) . " ^" . ("<" x ($textlength-1)) . "\n".
305             "\$option, \$help\n" .
306             "~~ " . (" " x $maxoption) . " ^" . ("<" x ($textlength-1)) . "\n" .
307             "\$help\n.";
308 0         0 $alt_format = "format ALTERNATIVE =\n" .
309             " @" . ("<" x ($maxoption + $maxargdesc)) . "\n" .
310             "\$option\n" .
311             " " . (" " x $maxoption) . " ^" . ("<" x ($textlength-1)) . "\n" .
312             "\$help\n" .
313             "~~ " . (" " x $maxoption) . " ^" . ("<" x ($textlength-1)) . "\n" .
314             "\$help\n.";
315            
316 0         0 eval $std_format;
317 0 0       0 confess ("internal error with format \"$std_format\": $@") if $@;
318 0         0 eval $alt_format;
319 0 0       0 confess ("internal error with format \"$alt_format\": $@") if $@;
320              
321 0         0 my $show_defaults = 1;
322              
323 0 0       0 print $LongHelp . "\n" if defined $LongHelp;
324 0         0 print "Summary of options:\n";
325 0         0 foreach $opt (@$argtable)
326             {
327 0         0 ($option, $type, $num, $value, $help, $argdesc) = @$opt;
328              
329 0 0       0 if ($type eq "section")
330             {
331 0         0 printf "\n-- %s %s\n", $option, "-" x ($numcols-4-length($option));
332 0         0 next;
333             }
334              
335 0 0       0 next unless defined $help;
336 0 0       0 $argdesc = "" unless defined $argdesc;
337              
338 0   0     0 my $show_default = $show_defaults && $help !~ /\[default/;
339              
340 0         0 $~ = 'STANDARD';
341 0 0       0 if ($type eq 'boolean')
342             {
343 0         0 undef $option; # arg! why is this necessary?
344 0         0 my ($pos, $neg) = &split_option ($opt);
345 0         0 $option = $pos;
346 0 0 0     0 $help .= ' [default]'
      0        
347             if $show_default && defined $$value && $$value;
348 0         0 write;
349 0         0 $help = "opposite of $pos";
350 0 0 0     0 $help .= ' [default]'
      0        
351             if $show_default && defined $$value && ! $$value;
352 0         0 $option = $neg;
353 0         0 write;
354             }
355             else
356             {
357             # If the option type is of the argument-taking variety, then
358             # we'll try to help out by saying what the default value(s)
359             # is/are
360 0 0       0 if ($OptionHandlers{$type} == \&process_pattern_option)
361             {
362 0 0       0 if ($num == 1) # expectes a scalar value
363             {
364 0 0 0     0 $help .= ' [default: ' . quote_strings ($$value) . ']'
365             if ($show_default && defined $$value);
366             }
367             else # expects a vector value
368             {
369 0 0 0     0 $help .= ' [default: ' . quote_strings (@$value) . ']'
      0        
370             if ($show_default &&
371             @$value && ! grep (! defined $_, @$value));
372             }
373             }
374              
375 0 0       0 if ($argdesc)
376             {
377 0 0       0 my $expanded_option = $option . " " . $argdesc if $argdesc;
378 0         0 $option = $expanded_option;
379              
380 0 0       0 if (length ($expanded_option) > $maxoption+1)
381             {
382 0         0 $~ = 'ALTERNATIVE';
383             }
384             }
385 0         0 write;
386             }
387             }
388              
389 0         0 print "\n";
390 0 0       0 print $Usage if defined $Usage;
391             }
392              
393              
394             #
395             # &scan_table
396             #
397             # walks through an argument table, building a hash that lets us quickly
398             # and painlessly look up an option.
399             #
400             sub scan_table
401             {
402 6     6 0 7 my ($argtable, $arghash) = @_;
403 6         6 my ($opt, $option, $type, $value);
404              
405 0         0 my $i;
406 6         14 for $i (0 .. $#$argtable)
407             {
408 36         36 $opt = $argtable->[$i];
409 36         60 ($option, $type, $value) = @$opt;
410 36 50       72 unless (exists $OptionHandlers{$type})
411             {
412 0         0 croak "Unknown option type \"$type\" supplied for option $option";
413             }
414              
415 36 100       94 if ($type eq "boolean")
    50          
416             {
417 6         13 my ($pos,$neg) = &split_option($opt);
418 6         14 $arghash->{$pos} = $i;
419 6 50       16 $arghash->{$neg} = $i if defined $neg;
420             }
421             elsif ($type ne "section")
422             {
423 30         63 $arghash->{$option} = $i;
424             }
425             }
426             }
427              
428              
429             #
430             # &match_abbreviation
431             #
432             # Given a string $s and a list of words @$words, finds the word for which
433             # $s is a non-ambiguous abbreviation. If $s is found to be ambiguous or
434             # doesn't match, a clear and concise error message is printed, using
435             # $err_format as a format for sprintf. Suggested form for $err_format is
436             # "%s option: %s"; the first %s will be substituted with either "ambiguous"
437             # or "unknown" (depending on the problem), and the second will be
438             # substituted with $s. Thus, with this format, the error message will look
439             # something like "unknown option: -foo" or "ambiguous option: -f".
440             #
441             sub match_abbreviation
442             {
443 15     15 0 19 my ($s, $words, $err_format) = @_;
444 15         14 my ($match);
445              
446             my $word;
447 15         20 foreach $word (@$words)
448             {
449             # If $s is a prefix of $word, it's at least an approximate match,
450             # so try to do better
451              
452 46 100       90 next unless ($s eq substr ($word, 0, length ($s)));
453              
454             # We have an exact match, so return it now
455              
456 15 50       47 return $word if ($s eq $word);
457              
458             # We have an approx. match, and already had one before
459              
460 0 0       0 if ($match)
461             {
462 0         0 &SetError ("bad_option", sprintf ("$err_format", "ambiguous", $s));
463 0         0 return 0;
464             }
465              
466 0         0 $match = $word;
467             }
468 0 0       0 &SetError ("bad_option", sprintf ("$err_format", "unknown", $s))
469             if !$match;
470 0         0 $match;
471             }
472              
473              
474             #
475             # &option_error
476             #
477             # Constructs a useful error message to deal with an option that expects
478             # a certain number of values of certain types, but a command-line that
479             # falls short of this mark. $option should be the option that triggers
480             # the situation; $type should be the expected type; $n should be the
481             # number of values expected.
482             #
483             # The error message (returned by the function) will look something like
484             # "-foo option must be followed by an integer" (yes, it does pick "a"
485             # or "an", depending on whether the description of the type starts
486             # with a vowel) or "-bar option must be followed by 3 strings".
487             #
488             # The error message is put in the global $ErrorMessage, as well as returned
489             # by the function. Also, the global $ErrorClass is set to "bad_value".
490             #
491             sub option_error
492             {
493 0     0 0 0 my ($option, $type, $n) = @_;
494 0         0 my ($typedesc, $singular, $plural, $article, $desc);
495              
496 0         0 $typedesc = $TypeDescriptions{$type};
497 0 0       0 ($singular,$plural) = (ref $typedesc eq 'ARRAY')
498             ? @$typedesc
499             : ($typedesc, $typedesc . "s");
500              
501 0 0       0 $article = ($typedesc =~ /^[aeiou]/) ? "an" : "a";
502 0 0       0 $desc = ($n > 1) ?
503             "$n $plural" :
504             "$article $singular";
505 0         0 &SetError ("bad_value", "$option option must be followed by $desc");
506             }
507            
508              
509             #
510             # &check_value
511             #
512             # Verifies that a value (presumably from the command line) satisfies
513             # the requirements for the expected type.
514             #
515             # Calls &option_error (to set $ErrorClass and $ErrorMessage globals) and returns
516             # 0 if the value isn't up to scratch.
517             #
518             sub check_value
519             {
520 14     14 0 16 my ($val, $option, $type, $n) = @_;
521              
522 14 50 33     248 unless (defined $val && $val =~ /^$Patterns{$type}$/x)
523             {
524 0         0 &option_error ($option, $type, $n);
525 0         0 return 0;
526             }
527             }
528              
529              
530             #
531             # &split_option
532             #
533             # Splits a boolean option into positive and negative alternatives. The
534             # two alternatives are returned as a two-element array.
535             #
536             # Croaks if it can't figure out the alternatives, or if there appear to be
537             # more than 2 alternatives specified.
538             #
539             sub split_option
540             {
541 46     46 0 41 my ($opt_desc) = @_;
542 46         34 my ($option, @options);
543              
544 46         44 $option = $opt_desc->[0];
545 46 100       116 return ($option) if $opt_desc->[1] ne "boolean";
546              
547 16         31 @options = split ('\|', $option);
548              
549 16 50       36 if (@options == 2)
    50          
550             {
551 0         0 return @options;
552             }
553             elsif (@options == 1)
554             {
555 16         14 my ($pattern, $prefix, $positive_alt, $negative_alt);
556 16         21 for $pattern (@OptionPatterns)
557             {
558 16         13 my ($prefix, $body);
559 16 50       99 if (($prefix, $body) = $option =~ /^$pattern$/)
560             {
561 16         23 $negative_alt = $prefix . "no" . $body;
562 16         46 return ($option, $negative_alt);
563             }
564             }
565 0         0 croak "Boolean option \"$option\" did not match " .
566             "any option prefixes - unable to guess negative alternative";
567 0         0 return ($option);
568             }
569             else
570             {
571 0         0 croak "Too many alternatives supplied for boolean option \"$option\"";
572             }
573             }
574              
575              
576             #
577             # &find_calling_package
578             #
579             # walks up the call stack until we find a caller in a different package
580             # from the current one. (Handy for `eval' options, when we want to
581             # eval a chunk of code in the package that called GetOptions.)
582             #
583             sub find_calling_package
584             {
585 0     0 0 0 my ($i, $this_pkg, $up_pkg, @caller);
586            
587 0         0 $i = 0;
588 0         0 $this_pkg = (caller(0))[0];
589 0         0 while (@caller = caller($i++))
590             {
591 0         0 $up_pkg = $caller[0];
592 0 0       0 last if $up_pkg ne $this_pkg;
593             }
594 0         0 $up_pkg;
595             }
596              
597              
598             # ----------------------------------------------------------------------
599             # Option-handling routines:
600             # process_constant_option
601             # process_boolean_option
602             # process_call_option
603             # process_eval_option
604             # ----------------------------------------------------------------------
605              
606             # General description of these routines:
607             # * each one is passed exactly four options:
608             # $arg - the argument that triggered this routine, expanded
609             # into unabbreviated form
610             # $arglist - reference to list containing rest of command line
611             # $opt_desc - reference to an option descriptor list
612             # $spoof - flag: if true, then no side effects
613             # * they are called from GetOptions, through code references in the
614             # %OptionHandlers hash
615             # * if they return a false value, then GetOptions immediately returns
616             # 0 to its caller, with no error message -- thus, the option handlers
617             # should print out enough of an error message for the end user to
618             # figure out what went wrong; also, the option handlers should be
619             # careful to explicitly return 1 if everything went well!
620              
621             sub process_constant_option
622             {
623 0     0 0 0 my ($arg, $arglist, $opt_desc, $spoof) = @_;
624 0         0 my ($type, $n, $value) = @$opt_desc[1,2,3];
625              
626 0 0       0 return 1 if $spoof;
627              
628 0 0       0 if ($type eq "const")
    0          
    0          
    0          
629             {
630 0         0 $$value = $n;
631             }
632             elsif ($type eq "copy")
633             {
634 0 0       0 $$value = (defined $n) ? ($n) : ($arg);
635             }
636             elsif ($type eq "arrayconst")
637             {
638 0         0 @$value = @$n;
639             }
640             elsif ($type eq "hashconst")
641             {
642 0         0 %$value = %$n;
643             }
644             else
645             {
646 0         0 confess ("internal error: can't handle option type \"$type\"");
647             }
648              
649 0         0 1;
650             }
651              
652              
653             sub process_boolean_option
654             {
655 4     4 0 5 my ($arg, $arglist, $opt_desc, $spoof) = @_;
656 4         5 my ($value) = $$opt_desc[3];
657            
658 4 50       8 return 1 if $spoof;
659              
660 4         7 my ($pos,$neg) = &split_option ($opt_desc);
661 4 50 66     16 confess ("internal error: option $arg not found in argument hash")
662             if ($arg ne $pos && $arg ne $neg);
663              
664 4 100       6 $$value = ($arg eq $pos) ? 1 : 0;
665 4         16 1;
666             }
667              
668              
669             sub process_call_option
670             {
671 2     2 0 3 my ($arg, $arglist, $opt_desc, $spoof) = @_;
672 2         5 my ($option, $args, $value) = @$opt_desc[0,2,3];
673              
674 2 50       7 croak "Invalid option table entry for option \"$option\" -- \"value\" " .
675             "field must be a code reference"
676             unless (ref $value eq 'CODE');
677              
678             # This will crash 'n burn big time if there is no spoof code for
679             # this option -- but that's why we check %SpoofCode against the
680             # arg table from GetOptions!
681              
682 2 50       5 $value = $SpoofCode{$arg} if ($spoof);
683              
684 2 50       7 my @args = (ref $args eq 'ARRAY') ? (@$args) : ();
685 2         6 my $result = &$value ($arg, $arglist, @args);
686 2 50       29 if (!$result)
687             {
688             # Wouldn't it be neat if we could get the sub name from the code ref?
689 0   0     0 &SetError
      0        
690             ($ErrorClass || "bad_call",
691             $ErrorMessage || "subroutine call from option \"$arg\" failed");
692             }
693              
694 2         8 return $result;
695              
696             } # &process_call_option
697              
698              
699             sub process_eval_option
700             {
701 0     0 0 0 my ($arg, $arglist, $opt_desc, $spoof) = @_;
702 0         0 my ($value) = $$opt_desc[3];
703              
704 0 0       0 $value = $SpoofCode{$arg} if ($spoof);
705              
706 0         0 my $up_pkg = &find_calling_package ();
707             # print "package $up_pkg; $value"; # DEBUG ONLY
708 0         0 my $result = eval "package $up_pkg; no strict; $value";
709              
710 0 0       0 if ($@) # any error string set?
711             {
712 0         0 &SetError ("bad_eval",
713             "error evaluating \"$value\" (from $arg option): $@");
714 0         0 return 0;
715             }
716              
717 0 0       0 if (!$result)
718             {
719 0   0     0 &SetError
      0        
720             ($ErrorClass || "bad_call",
721             $ErrorMessage || "code eval'd for option \"$arg\" failed");
722             }
723              
724 0         0 return $result;
725             }
726              
727              
728             sub process_pattern_option
729             {
730 9     9 0 12 my ($arg, $arglist, $opt_desc, $spoof) = @_;
731 9         14 my ($type, $n, $value) = @$opt_desc[1,2,3];
732 9         8 my ($dummy, @dummies);
733              
734             # This code looks a little more complicated than you might at first
735             # think necessary. But the ugliness is necessary because $value might
736             # reference a scalar or an array, depending on whether $n is 1 (scalar)
737             # or not (array). Thus, we can't just assume that either @$value or
738             # $$value is valid -- we always have to check which of the two it should
739             # be.
740              
741 9 100       13 if ($n == 1) # scalar-valued option (one argument)
742             {
743 4 50       11 croak "GetOptions: \"$arg\" option must be associated with a scalar ref"
744             unless ref $value eq 'SCALAR';
745 4 50       6 $value = \$dummy if $spoof;
746 4         7 $$value = shift @$arglist;
747 4 50       7 return 0 unless &check_value ($$value, $arg, $type, $n);
748             }
749             else # it's a "vector-valued" option
750             { # (fixed number of arguments)
751 5 50       15 croak "GetOptions: \"$arg\" option must be associated with an array ref"
752             unless ref $value eq 'ARRAY';
753 5 50       9 $value = \@dummies if $spoof;
754 5         12 @$value = splice (@$arglist, 0, $n);
755 5 50       9 if (scalar @$value != $n)
756             {
757 0         0 &option_error ($arg, $type, $n);
758 0         0 return 0;
759             }
760              
761 5         5 my $val;
762 5         6 foreach $val (@$value)
763             {
764 10 50       18 return 0 unless &check_value ($val, $arg, $type, $n);
765             }
766             } # else
767              
768 9         41 return 1;
769              
770             } # &process_pattern_option
771              
772              
773             # --------------------------------------------------------------------
774             # The main public subroutine: GetOptions
775             # --------------------------------------------------------------------
776              
777             sub GetOptions
778             {
779 6     6 0 905 my ($opt_table, $arglist, $new_arglist, $spoof) = @_;
780 6         7 my (%argpos, $arg, $pos, $opt_ref);
781 0         0 my ($option_re, @option_list);
782              
783 6 50       13 $new_arglist = $arglist if !defined $new_arglist;
784 6         14 &SetError ("", "");
785              
786             # Build a hash mapping option -> position in option table
787              
788 6         12 &scan_table ($opt_table, \%argpos);
789              
790             # Regexp to let us recognize options on the command line
791              
792 6         13 $option_re = join ("|", @OptionPatterns);
793              
794             # Build a list of all acceptable options -- used to match abbreviations
795              
796 6         6 my $opt_desc;
797 6         7 foreach $opt_desc (@$opt_table)
798             {
799 36 50       82 push (@option_list, &split_option ($opt_desc))
800             unless $opt_desc->[1] eq "section";
801             }
802 6 50       15 push (@option_list, $HelpOption) if $HelpOption;
803              
804             # If in spoof mode: make sure we have spoof code for all call/eval options
805              
806 6 50       11 if ($spoof)
807             {
808 0         0 my ($opt, $type, $spoof);
809              
810 0         0 foreach $opt_desc (@$opt_table)
811             {
812 0         0 $opt = $opt_desc->[0];
813 0         0 $type = $opt_desc->[1];
814 0         0 $spoof = $SpoofCode{$opt};
815              
816 0 0 0     0 next unless $type eq 'call' || $type eq 'eval';
817 0 0       0 croak "No alternate code supplied for option $opt in spoof mode"
818             unless defined $spoof;
819 0 0 0     0 croak "Alternate code must be a CODE ref for option $opt"
820             if ($type eq 'call' && ref $spoof ne 'CODE');
821 0 0 0     0 croak "Alternate code must be a string for option $opt"
822             if ($type eq 'eval' && ref $spoof);
823             }
824             }
825              
826             # Now walk over the argument list
827              
828 6         14 my @tmp_arglist = @$arglist;
829 6         7 @$new_arglist = ();
830 6         13 while (defined ($arg = shift @tmp_arglist))
831             {
832             # print "arg: $arg\n";
833              
834             # If this argument is the option terminator (usually "--") then
835             # transfer all remaining arguments to the new arg list and stop
836             # processing immediately.
837              
838 27 50 33     108 if (defined $OptionTerminator && $arg eq $OptionTerminator)
839             {
840 0         0 push (@$new_arglist, @tmp_arglist);
841 0         0 last;
842             }
843              
844             # If this argument isn't an option at all, just append it to
845             # @$new_arglist and go to the next one.
846              
847 27 100       70 if ($arg !~ /^($option_re)/o)
848             {
849 12         19 push (@$new_arglist, $arg);
850 12         24 next;
851             }
852              
853             # We know we have something that looks like an option; see if it
854             # matches or is an abbreviation for one of the strings in
855             # @option_list
856              
857 15         28 $arg = &match_abbreviation ($arg, \@option_list, "%s option: %s");
858 15 50       24 if (! $arg)
859             {
860 0 0       0 warn $Usage if defined $Usage;
861 0         0 warn "$ErrorMessage\n";
862 0         0 return 0;
863             }
864              
865             # If it's the help option, print out the help and return
866             # (even if in spoof mode!)
867              
868 15 50       24 if ($arg eq $HelpOption)
869             {
870 0         0 &print_help ($opt_table);
871 0         0 &SetError ("help", "");
872 0         0 return 0;
873             }
874              
875             # Now we know it's a valid option, and it's not the help option --
876             # so it must be in the caller's option table. Look up its
877             # entry there, and use that for the actual option processing.
878              
879 15         22 $pos = $argpos{$arg};
880 15 50       22 confess ("internal error: didn't find arg in arg hash even " .
881             "after resolving abbreviation")
882             unless defined $pos;
883              
884 15         16 my $opt_desc = $opt_table->[$pos];
885 15         17 my $type = $opt_desc->[1];
886 15         18 my $handler = $OptionHandlers{$type};
887              
888 15 50 33     55 if (defined $handler && ref ($handler) eq 'CODE')
889             {
890 15 50       31 if (! &$handler ($arg, \@tmp_arglist, $opt_desc, $spoof))
891             {
892 0 0       0 warn $Usage if defined $Usage;
893 0         0 warn "$ErrorMessage\n";
894 0         0 return 0;
895             }
896             }
897             else
898             {
899 0         0 croak "Unknown option type \"$type\" (found for arg $arg)";
900             }
901             } # while ($arg = shift @$arglist)
902              
903 6         37 return 1;
904              
905             } # GetOptions
906              
907              
908             sub SpoofGetOptions
909             {
910 0     0 0   &GetOptions (@_[0..2], 1);
911             }
912              
913             1;