Home | History | Annotate | Line # | Download | only in Config
      1  1.1  christos # Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
      2  1.1  christos #
      3  1.1  christos # Licensed under the Apache License 2.0 (the "License").  You may not use
      4  1.1  christos # this file except in compliance with the License.  You can obtain a copy
      5  1.1  christos # in the file LICENSE in the source distribution or at
      6  1.1  christos # https://www.openssl.org/source/license.html
      7  1.1  christos 
      8  1.1  christos package OpenSSL::Config::Query;
      9  1.1  christos 
     10  1.1  christos use 5.10.0;
     11  1.1  christos use strict;
     12  1.1  christos use warnings;
     13  1.1  christos use Carp;
     14  1.1  christos 
     15  1.1  christos =head1 NAME
     16  1.1  christos 
     17  1.1  christos OpenSSL::Config::Query - Query OpenSSL configuration info
     18  1.1  christos 
     19  1.1  christos =head1 SYNOPSIS
     20  1.1  christos 
     21  1.1  christos     use OpenSSL::Config::Info;
     22  1.1  christos 
     23  1.1  christos     my $query = OpenSSL::Config::Query->new(info => \%unified_info);
     24  1.1  christos 
     25  1.1  christos     # Query for something that's expected to give a scalar back
     26  1.1  christos     my $variable = $query->method(... args ...);
     27  1.1  christos 
     28  1.1  christos     # Query for something that's expected to give a list back
     29  1.1  christos     my @variable = $query->method(... args ...);
     30  1.1  christos 
     31  1.1  christos =head1 DESCRIPTION
     32  1.1  christos 
     33  1.1  christos The unified info structure, commonly known as the %unified_info table, has
     34  1.1  christos become quite complex, and a bit overwhelming to look through directly.  This
     35  1.1  christos module makes querying this structure simpler, through diverse methods.
     36  1.1  christos 
     37  1.1  christos =head2 Constructor
     38  1.1  christos 
     39  1.1  christos =over 4
     40  1.1  christos 
     41  1.1  christos =item B<new> I<%options>
     42  1.1  christos 
     43  1.1  christos Creates an instance of the B<OpenSSL::Config::Query> class.  It takes options
     44  1.1  christos in keyed pair form, i.e. a series of C<< key => value >> pairs.  Available
     45  1.1  christos options are:
     46  1.1  christos 
     47  1.1  christos =over 4
     48  1.1  christos 
     49  1.1  christos =item B<info> =E<gt> I<HASHREF>
     50  1.1  christos 
     51  1.1  christos A reference to a unified information hash table, most commonly known as
     52  1.1  christos %unified_info.
     53  1.1  christos 
     54  1.1  christos =item B<config> =E<gt> I<HASHREF>
     55  1.1  christos 
     56  1.1  christos A reference to a config information hash table, most commonly known as
     57  1.1  christos %config.
     58  1.1  christos 
     59  1.1  christos =back
     60  1.1  christos 
     61  1.1  christos Example:
     62  1.1  christos 
     63  1.1  christos     my $info = OpenSSL::Config::Info->new(info => \%unified_info);
     64  1.1  christos 
     65  1.1  christos =back
     66  1.1  christos 
     67  1.1  christos =cut
     68  1.1  christos 
     69  1.1  christos sub new {
     70  1.1  christos     my $class = shift;
     71  1.1  christos     my %opts = @_;
     72  1.1  christos 
     73  1.1  christos     my @messages = _check_accepted_options(\%opts,
     74  1.1  christos                                            info => 'HASH',
     75  1.1  christos                                            config => 'HASH');
     76  1.1  christos     croak $messages[0] if @messages;
     77  1.1  christos 
     78  1.1  christos     # We make a shallow copy of the input structure.  We might make
     79  1.1  christos     # a different choice in the future...
     80  1.1  christos     my $instance = { info => $opts{info} // {},
     81  1.1  christos                      config => $opts{config} // {} };
     82  1.1  christos     bless $instance, $class;
     83  1.1  christos 
     84  1.1  christos     return $instance;
     85  1.1  christos }
     86  1.1  christos 
     87  1.1  christos =head2 Query methods
     88  1.1  christos 
     89  1.1  christos =over 4
     90  1.1  christos 
     91  1.1  christos =item B<get_sources> I<LIST>
     92  1.1  christos 
     93  1.1  christos LIST is expected to be the collection of names of end products, such as
     94  1.1  christos programs, modules, libraries.
     95  1.1  christos 
     96  1.1  christos The returned result is a hash table reference, with each key being one of
     97  1.1  christos these end product names, and its value being a reference to an array of
     98  1.1  christos source file names that constitutes everything that will or may become part
     99  1.1  christos of that end product.
    100  1.1  christos 
    101  1.1  christos =cut
    102  1.1  christos 
    103  1.1  christos sub get_sources {
    104  1.1  christos     my $self = shift;
    105  1.1  christos 
    106  1.1  christos     my $result = {};
    107  1.1  christos     foreach (@_) {
    108  1.1  christos         my @sources = @{$self->{info}->{sources}->{$_} // []};
    109  1.1  christos         my @staticlibs =
    110  1.1  christos             grep { $_ =~ m|\.a$| } @{$self->{info}->{depends}->{$_} // []};
    111  1.1  christos 
    112  1.1  christos         my %parts = ( %{$self->get_sources(@sources)},
    113  1.1  christos                       %{$self->get_sources(@staticlibs)} );
    114  1.1  christos         my @parts = map { @{$_} } values %parts;
    115  1.1  christos 
    116  1.1  christos         my @generator =
    117  1.1  christos             ( ( $self->{info}->{generate}->{$_} // [] ) -> [0] // () );
    118  1.1  christos         my %generator_parts = %{$self->get_sources(@generator)};
    119  1.1  christos         # if there are any generator parts, we ignore it, because that means
    120  1.1  christos         # it's a compiled program and thus NOT part of the source that's
    121  1.1  christos         # queried.
    122  1.1  christos         @generator = () if %generator_parts;
    123  1.1  christos 
    124  1.1  christos         my @partial_result =
    125  1.1  christos             ( ( map { @{$_} } values %parts ),
    126  1.1  christos               ( grep { !defined($parts{$_}) } @sources, @generator ) );
    127  1.1  christos 
    128  1.1  christos         # Push conditionally, to avoid creating $result->{$_} with an empty
    129  1.1  christos         # value
    130  1.1  christos         push @{$result->{$_}}, @partial_result if @partial_result;
    131  1.1  christos     }
    132  1.1  christos 
    133  1.1  christos     return $result;
    134  1.1  christos }
    135  1.1  christos 
    136  1.1  christos =item B<get_config> I<LIST>
    137  1.1  christos 
    138  1.1  christos LIST is expected to be the collection of names of configuration data, such
    139  1.1  christos as build_infos, sourcedir, ...
    140  1.1  christos 
    141  1.1  christos The returned result is a hash table reference, with each key being one of
    142  1.1  christos these configuration data names, and its value being a reference to the value
    143  1.1  christos corresponding to that name.
    144  1.1  christos 
    145  1.1  christos =cut
    146  1.1  christos 
    147  1.1  christos sub get_config {
    148  1.1  christos     my $self = shift;
    149  1.1  christos 
    150  1.1  christos     return { map { $_ => $self->{config}->{$_} } @_ };
    151  1.1  christos }
    152  1.1  christos 
    153  1.1  christos ########
    154  1.1  christos #
    155  1.1  christos #  Helper functions
    156  1.1  christos #
    157  1.1  christos 
    158  1.1  christos sub _check_accepted_options {
    159  1.1  christos     my $opts = shift;           # HASH reference (hopefully)
    160  1.1  christos     my %conds = @_;             # key => type
    161  1.1  christos 
    162  1.1  christos     my @messages;
    163  1.1  christos     my %optnames = map { $_ => 1 } keys %$opts;
    164  1.1  christos     foreach (keys %conds) {
    165  1.1  christos         delete $optnames{$_};
    166  1.1  christos     }
    167  1.1  christos     push @messages, "Unknown options: " . join(', ', sort keys %optnames)
    168  1.1  christos         if keys %optnames;
    169  1.1  christos     foreach (sort keys %conds) {
    170  1.1  christos         push @messages, "'$_' value not a $conds{$_} reference"
    171  1.1  christos             if (defined $conds{$_} && defined $opts->{$_}
    172  1.1  christos                 && ref $opts->{$_} ne $conds{$_});
    173  1.1  christos     }
    174  1.1  christos     return @messages;
    175  1.1  christos }
    176  1.1  christos 
    177  1.1  christos 1;
    178