File Coverage

File:lib/Parrot/Configure/Options.pm
Coverage:99.1%

linestmtbrancondsubcode
1# Copyright (C) 2001-2011, Parrot Foundation.
2
3package Parrot::Configure::Options;
4
5
103
103
103
use strict;
6
103
103
103
use warnings;
7
103
103
103
use base qw( Exporter );
8our @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
17sub 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
51sub _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
78sub _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
1031;
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: