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