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