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