| File: | lib/Parrot/Configure/Options.pm |
| Coverage: | 99.1% |
| line | stmt | bran | cond | sub | code |
|---|---|---|---|---|---|
| 1 | # Copyright (C) 2001-2011, Parrot Foundation. | ||||
| 2 | |||||
| 3 | package Parrot::Configure::Options; | ||||
| 4 | |||||
| 5 | 103 103 103 | use strict; | |||
| 6 | 103 103 103 | use warnings; | |||
| 7 | 103 103 103 | use base qw( Exporter ); | |||
| 8 | our @EXPORT_OK = qw( | ||||
| 9 | process_options | ||||
| 10 | ); | ||||
| 11 | 103 103 103 | use Carp; | |||
| 12 | 103 103 103 | use lib qw( lib ); | |||
| 13 | 103 103 103 | use Parrot::Configure::Options::Conf::CLI (); | |||
| 14 | 103 103 103 | use Parrot::Configure::Options::Conf::File (); | |||
| 15 | 103 103 103 | use Parrot::Configure::Options::Reconf (); | |||
| 16 | |||||
| 17 | sub process_options { | ||||
| 18 | 252 | my $argsref = shift; | |||
| 19 | |||||
| 20 | 252 | croak "'mode' argument not provided to process_options()" | |||
| 21 | unless defined $argsref->{mode}; | ||||
| 22 | |||||
| 23 | 250 | my ($options_components, $script); | |||
| 24 | 250 | ($argsref, $options_components, $script) = | |||
| 25 | _process_options_components($argsref); | ||||
| 26 | |||||
| 27 | 248 | my ($data, $short_circuits_seen_ref) = | |||
| 28 | _initial_pass($argsref, $options_components, $script); | ||||
| 29 | |||||
| 30 | 243 243 | if (@{ $short_circuits_seen_ref }) { | |||
| 31 | # run all the short circuits | ||||
| 32 | 5 5 | foreach my $sc (@{ $short_circuits_seen_ref }) { | |||
| 33 | 5 5 | &{ $options_components->{short_circuits}{$sc} }; | |||
| 34 | } | ||||
| 35 | 5 | return; | |||
| 36 | } | ||||
| 37 | else { | ||||
| 38 | 238 | if ($argsref->{mode} eq 'file' or $argsref->{mode} eq 'configure') { | |||
| 39 | 228 | my $steps_list_ref; | |||
| 40 | 228 | ($data, $steps_list_ref) = | |||
| 41 | 228 | &{ $options_components->{conditionals} }($data); | |||
| 42 | 224 | return ($data, $steps_list_ref); | |||
| 43 | } | ||||
| 44 | else { | ||||
| 45 | 10 10 | $data = &{ $options_components->{conditionals} }($data); | |||
| 46 | 10 | return $data; | |||
| 47 | } | ||||
| 48 | } | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | sub _process_options_components { | ||||
| 52 | 255 | my $argsref = shift; | |||
| 53 | 255 | my %options_components; | |||
| 54 | 255 | if ( $argsref->{mode} =~ m/^reconfigure$/i ) { | |||
| 55 | 15 | %options_components = | |||
| 56 | %Parrot::Configure::Options::Reconf::options_components; | ||||
| 57 | } | ||||
| 58 | elsif ( $argsref->{mode} =~ m/^file$/i ) { | ||||
| 59 | 8 | %options_components = | |||
| 60 | %Parrot::Configure::Options::Conf::File::options_components; | ||||
| 61 | } | ||||
| 62 | elsif ( $argsref->{mode} =~ m/^configure$/i ) { | ||||
| 63 | 230 | %options_components = | |||
| 64 | %Parrot::Configure::Options::Conf::CLI::options_components; | ||||
| 65 | } | ||||
| 66 | else { | ||||
| 67 | 2 | croak "Invalid value for 'mode' argument to process_options()"; | |||
| 68 | } | ||||
| 69 | 253 | $argsref->{argv} = [] unless defined $argsref->{argv}; | |||
| 70 | |||||
| 71 | 253 | my $script = | |||
| 72 | $options_components{script} | ||||
| 73 | ? $options_components{script} | ||||
| 74 | : croak "Must provide value for 'script'"; | ||||
| 75 | 253 | return ($argsref, \%options_components, $script); | |||
| 76 | } | ||||
| 77 | |||||
| 78 | sub _initial_pass { | ||||
| 79 | 250 | my ($argsref, $options_components, $script) = @_; | |||
| 80 | 17558 | my %valid_opts = | |||
| 81 | 250 250 | map { $_, 1 } @{ $options_components->{valid_options} }; | |||
| 82 | 250 | my $data = {}; | |||
| 83 | 250 | my @short_circuits_seen = (); | |||
| 84 | 250 250 | for my $el ( @{ $argsref->{argv} } ) { | |||
| 85 | 199 | my ( $key, $value ); | |||
| 86 | 199 | if ($el =~ m/--([-\w]+)(?:=(.*))?/) { | |||
| 87 | 197 | ( $key, $value ) = ($1, $2); | |||
| 88 | } | ||||
| 89 | 199 | $key = 'help' unless defined $key; | |||
| 90 | 199 | $value = 1 unless defined $value; | |||
| 91 | |||||
| 92 | 199 | unless ( $valid_opts{$key} ) { | |||
| 93 | 5 | die qq/Invalid option "$key". See "perl $script --help" for valid options\n/; | |||
| 94 | } | ||||
| 95 | 194 | if ( $options_components->{short_circuits}{$key} ) { | |||
| 96 | 6 | push @short_circuits_seen, $key; | |||
| 97 | } | ||||
| 98 | 194 | $data->{$key} = $value; | |||
| 99 | } | ||||
| 100 | 245 | return ($data, \@short_circuits_seen); | |||
| 101 | } | ||||
| 102 | |||||
| 103 | 1; | ||||
| 104 | |||||
| 105 | #################### DOCUMENTATION #################### | ||||
| 106 | |||||
| 107 - 210 | =head1 NAME
Parrot::Configure::Options - Process command-line options to F<Configure.pl>
=head1 SYNOPSIS
use Parrot::Configure::Options qw( process_options );
$args = process_options( {
mode => q{configure},
argv => [@ARGV],
} );
=head1 DESCRIPTION
Parrot::Configure::Options exports on demand the subroutine
C<process_options()>, which processes the command-line options provided to
F<Configure.pl> or to F<tools/dev/reconfigure.pl>.
If you provide F<Configure.pl> with either C<--help> or C<--version>,
C<process_options()> will print out the appropriate message and perform a
bare C<return>, I<i.e.>, the return value will be C<undef>. The calling
script -- whether F<Configure.pl> or a test file -- can then check for the
definedness of C<process_options()>'s return value and proceed appropriately.
An array of valid command-line option names stored internally is consulted;
the program will die if an invalid option is called.
=head1 SUBROUTINES
=head2 C<process_options()>
=over 4
=item * Purpose
Process command-line options provided to F<Configure.pl> and proceed
appropriately.
=item * Arguments
One argument: Reference to a hash holding the following key-value pairs:
mode : 'configure', 'reconfigure' or 'file'
argv : reference to @ARGV; defaults to []
=item * Return Value
=over 4
=item * C<--version> or C<--help> options
Bare return (C<undef>).
=item * All other options
Reference to a hash of option names and values.
=back
=item * Comment
The C<mode> element in the argument to C<process_options()> should be set
according to the following rules:
=over 4
=item * C<configure>
Command-Line Interface: Initial Parrot configuration with zero or more
command-line options (other than the C<--file> option). This is the most
typical case. See F<Configure.pl> or any test file simulating the
functionality of F<Configure.pl> in the F<t/configure/> or F<t/steps/>
directories.
=item * C<file>
Configuration-File Interface: Initial Parrot configuration where the options
are stored in a configuration file whose location is the value of the sole
command-line option C<--file>.
=item * C<reconfigure>
After F<Configure.pl> has completed, some Parrot developers need to rerun a
particular configuration step (typically, C<gen::makefiles>) to debug
revisions. F<tools/dev/reconfigure.pl> with the F<--step=step::class> option
does this and internally calls C<process_options()> in C<reconfigure> mode.
=back
=back
=head1 NOTES
The functionality in this package originally appeared in F<Configure.pl>. It
was transferred here and refactored by James E Keenan.
=head1 SEE ALSO
F<Configure.pl>. Parrot::Configure::Options::Conf.
Parrot::Configure::Options::Reconf. Parrot::Configure::Options::Conf::CLI.
Parrot::Configure::Options::Conf::File.
=cut | ||||
| 211 | |||||
| 212 | # Local Variables: | ||||
| 213 | # mode: cperl | ||||
| 214 | # cperl-indent-level: 4 | ||||
| 215 | # fill-column: 100 | ||||
| 216 | # End: | ||||
| 217 | # vim: expandtab shiftwidth=4: | ||||