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