Home | History | Annotate | Line # | Download | only in dist
Configure revision 1.24.2.3
      1 #! /usr/bin/env perl
      2 # -*- mode: perl; -*-
      3 # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
      4 #
      5 # Licensed under the OpenSSL license (the "License").  You may not use
      6 # this file except in compliance with the License.  You can obtain a copy
      7 # in the file LICENSE in the source distribution or at
      8 # https://www.openssl.org/source/license.html
      9 
     10 ##  Configure -- OpenSSL source tree configuration script
     11 
     12 use 5.10.0;
     13 use strict;
     14 use Config;
     15 use FindBin;
     16 use lib "$FindBin::Bin/util/perl";
     17 use File::Basename;
     18 use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
     19 use File::Path qw/mkpath/;
     20 use OpenSSL::Glob;
     21 
     22 # see INSTALL for instructions.
     23 
     24 my $orig_death_handler = $SIG{__DIE__};
     25 $SIG{__DIE__} = \&death_handler;
     26 
     27 my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
     28 
     29 # Options:
     30 #
     31 # --config      add the given configuration file, which will be read after
     32 #               any "Configurations*" files that are found in the same
     33 #               directory as this script.
     34 # --prefix      prefix for the OpenSSL installation, which includes the
     35 #               directories bin, lib, include, share/man, share/doc/openssl
     36 #               This becomes the value of INSTALLTOP in Makefile
     37 #               (Default: /usr/local)
     38 # --openssldir  OpenSSL data area, such as openssl.cnf, certificates and keys.
     39 #               If it's a relative directory, it will be added on the directory
     40 #               given with --prefix.
     41 #               This becomes the value of OPENSSLDIR in Makefile and in C.
     42 #               (Default: PREFIX/ssl)
     43 #
     44 # --cross-compile-prefix Add specified prefix to binutils components.
     45 #
     46 # --api         One of 0.9.8, 1.0.0 or 1.1.0.  Do not compile support for
     47 #               interfaces deprecated as of the specified OpenSSL version.
     48 #
     49 # no-hw-xxx     do not compile support for specific crypto hardware.
     50 #               Generic OpenSSL-style methods relating to this support
     51 #               are always compiled but return NULL if the hardware
     52 #               support isn't compiled.
     53 # no-hw         do not compile support for any crypto hardware.
     54 # [no-]threads  [don't] try to create a library that is suitable for
     55 #               multithreaded applications (default is "threads" if we
     56 #               know how to do it)
     57 # [no-]shared   [don't] try to create shared libraries when supported.
     58 # [no-]pic      [don't] try to build position independent code when supported.
     59 #               If disabled, it also disables shared and dynamic-engine.
     60 # no-asm        do not use assembler
     61 # no-egd        do not compile support for the entropy-gathering daemon APIs
     62 # [no-]zlib     [don't] compile support for zlib compression.
     63 # zlib-dynamic  Like "zlib", but the zlib library is expected to be a shared
     64 #               library and will be loaded in run-time by the OpenSSL library.
     65 # sctp          include SCTP support
     66 # enable-weak-ssl-ciphers
     67 #               Enable weak ciphers that are disabled by default.
     68 # 386           generate 80386 code in assembly modules
     69 # no-sse2       disables IA-32 SSE2 code in assembly modules, the above
     70 #               mentioned '386' option implies this one
     71 # no-<cipher>   build without specified algorithm (rsa, idea, rc5, ...)
     72 # -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
     73 # /<xxx>        passed through to the compiler. Unix-style options beginning
     74 #               with a '-' or '+' are recognized, as well as Windows-style
     75 #               options beginning with a '/'. If the option contains arguments
     76 #               separated by spaces, then the URL-style notation %20 can be
     77 #               used for the space character in order to avoid having to quote
     78 #               the option. For example, -opt%20arg gets expanded to -opt arg.
     79 #               In fact, any ASCII character can be encoded as %xx using its
     80 #               hexadecimal encoding.
     81 # -static       while -static is also a pass-through compiler option (and
     82 #               as such is limited to environments where it's actually
     83 #               meaningful), it triggers a number configuration options,
     84 #               namely no-pic, no-shared and no-threads. It is
     85 #               argued that the only reason to produce statically linked
     86 #               binaries (and in context it means executables linked with
     87 #               -static flag, and not just executables linked with static
     88 #               libcrypto.a) is to eliminate dependency on specific run-time,
     89 #               a.k.a. libc version. The mentioned config options are meant
     90 #               to achieve just that. Unfortunately on Linux it's impossible
     91 #               to eliminate the dependency completely for openssl executable
     92 #               because of getaddrinfo and gethostbyname calls, which can
     93 #               invoke dynamically loadable library facility anyway to meet
     94 #               the lookup requests. For this reason on Linux statically
     95 #               linked openssl executable has rather debugging value than
     96 #               production quality.
     97 #
     98 # BN_LLONG      use the type 'long long' in crypto/bn/bn.h
     99 # RC4_CHAR      use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
    100 # Following are set automatically by this script
    101 #
    102 # MD5_ASM       use some extra md5 assembler,
    103 # SHA1_ASM      use some extra sha1 assembler, must define L_ENDIAN for x86
    104 # RMD160_ASM    use some extra ripemd160 assembler,
    105 # SHA256_ASM    sha256_block is implemented in assembler
    106 # SHA512_ASM    sha512_block is implemented in assembler
    107 # AES_ASM       AES_[en|de]crypt is implemented in assembler
    108 
    109 # Minimum warning options... any contributions to OpenSSL should at least
    110 # get past these.  Note that we only use these with C compilers, not with
    111 # C++ compilers.
    112 
    113 # DEBUG_UNUSED enables __owur (warn unused result) checks.
    114 # -DPEDANTIC complements -pedantic and is meant to mask code that
    115 # is not strictly standard-compliant and/or implementation-specific,
    116 # e.g. inline assembly, disregards to alignment requirements, such
    117 # that -pedantic would complain about. Incidentally -DPEDANTIC has
    118 # to be used even in sanitized builds, because sanitizer too is
    119 # supposed to and does take notice of non-standard behaviour. Then
    120 # -pedantic with pre-C9x compiler would also complain about 'long
    121 # long' not being supported. As 64-bit algorithms are common now,
    122 # it grew impossible to resolve this without sizeable additional
    123 # code, so we just tell compiler to be pedantic about everything
    124 # but 'long long' type.
    125 
    126 my @gcc_devteam_warn = qw(
    127     -DDEBUG_UNUSED
    128     -DPEDANTIC -pedantic -Wno-long-long
    129     -Wall
    130     -Wextra
    131     -Wno-unused-parameter
    132     -Wno-missing-field-initializers
    133     -Wswitch
    134     -Wsign-compare
    135     -Wshadow
    136     -Wformat
    137     -Wtype-limits
    138     -Wundef
    139     -Werror
    140     -Wmissing-prototypes
    141     -Wstrict-prototypes
    142 );
    143 
    144 # These are used in addition to $gcc_devteam_warn when the compiler is clang.
    145 # TODO(openssl-team): fix problems and investigate if (at least) the
    146 # following warnings can also be enabled:
    147 #       -Wcast-align
    148 #       -Wunreachable-code -- no, too ugly/compiler-specific
    149 #       -Wlanguage-extension-token -- no, we use asm()
    150 #       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
    151 #       -Wextended-offsetof -- no, needed in CMS ASN1 code
    152 my @clang_devteam_warn = qw(
    153     -Wno-unknown-warning-option
    154     -Wswitch-default
    155     -Wno-parentheses-equality
    156     -Wno-language-extension-token
    157     -Wno-extended-offsetof
    158     -Wconditional-uninitialized
    159     -Wincompatible-pointer-types-discards-qualifiers
    160     -Wmissing-variable-declarations
    161 );
    162 
    163 my @cl_devteam_warn = qw(
    164     /WX
    165 );
    166 
    167 # This adds backtrace information to the memory leak info.  Is only used
    168 # when crypto-mdebug-backtrace is enabled.
    169 my $memleak_devteam_backtrace = "-rdynamic";
    170 
    171 my $strict_warnings = 0;
    172 
    173 # As for $BSDthreads. Idea is to maintain "collective" set of flags,
    174 # which would cover all BSD flavors. -pthread applies to them all,
    175 # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
    176 # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
    177 # which has to be accompanied by explicit -D_THREAD_SAFE and
    178 # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
    179 # seems to be sufficient?
    180 our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
    181 
    182 #
    183 # API compatibility name to version number mapping.
    184 #
    185 my $maxapi = "1.1.0";           # API for "no-deprecated" builds
    186 my $apitable = {
    187     "1.1.0" => "0x10100000L",
    188     "1.0.0" => "0x10000000L",
    189     "0.9.8" => "0x00908000L",
    190 };
    191 
    192 our %table = ();
    193 our %config = ();
    194 our %withargs = ();
    195 our $now_printing;      # set to current entry's name in print_table_entry
    196                         # (todo: right thing would be to encapsulate name
    197                         # into %target [class] and make print_table_entry
    198                         # a method)
    199 
    200 # Forward declarations ###############################################
    201 
    202 # read_config(filename)
    203 #
    204 # Reads a configuration file and populates %table with the contents
    205 # (which the configuration file places in %targets).
    206 sub read_config;
    207 
    208 # resolve_config(target)
    209 #
    210 # Resolves all the late evaluations, inheritances and so on for the
    211 # chosen target and any target it inherits from.
    212 sub resolve_config;
    213 
    214 
    215 # Information collection #############################################
    216 
    217 # Unified build supports separate build dir
    218 my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
    219 my $blddir = catdir(absolutedir("."));         # catdir ensures local syntax
    220 
    221 # File::Spec::Unix doesn't detect case insensitivity, so we make sure to
    222 # check if the source and build directory are really the same, and make
    223 # them so.  This avoids all kinds of confusion later on.
    224 # We must check @File::Spec::ISA rather than using File::Spec->isa() to
    225 # know if File::Spec ended up loading File::Spec::Unix.
    226 $srcdir = $blddir
    227     if (grep(/::Unix$/, @File::Spec::ISA)
    228         && samedir($srcdir, $blddir));
    229 
    230 my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
    231 
    232 my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
    233 
    234 $config{sourcedir} = abs2rel($srcdir, $blddir);
    235 $config{builddir} = abs2rel($blddir, $blddir);
    236 
    237 # Collect reconfiguration information if needed
    238 my @argvcopy=@ARGV;
    239 
    240 if (grep /^reconf(igure)?$/, @argvcopy) {
    241     die "reconfiguring with other arguments present isn't supported"
    242         if scalar @argvcopy > 1;
    243     if (-f "./configdata.pm") {
    244         my $file = "./configdata.pm";
    245         unless (my $return = do $file) {
    246             die "couldn't parse $file: $@" if $@;
    247             die "couldn't do $file: $!"    unless defined $return;
    248             die "couldn't run $file"       unless $return;
    249         }
    250 
    251         @argvcopy = defined($configdata::config{perlargv}) ?
    252             @{$configdata::config{perlargv}} : ();
    253         die "Incorrect data to reconfigure, please do a normal configuration\n"
    254             if (grep(/^reconf/,@argvcopy));
    255         $config{perlenv} = $configdata::config{perlenv} // {};
    256     } else {
    257         die "Insufficient data to reconfigure, please do a normal configuration\n";
    258     }
    259 }
    260 
    261 $config{perlargv} = [ @argvcopy ];
    262 
    263 # Collect version numbers
    264 $config{version} = "unknown";
    265 $config{version_num} = "unknown";
    266 $config{shlib_version_number} = "unknown";
    267 $config{shlib_version_history} = "unknown";
    268 
    269 collect_information(
    270     collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
    271     qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
    272     qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/      => sub { $config{version_num}=$1 },
    273     qr/SHLIB_VERSION_NUMBER *"([^"]+)"/      => sub { $config{shlib_version_number}=$1 },
    274     qr/SHLIB_VERSION_HISTORY *"([^"]*)"/     => sub { $config{shlib_version_history}=$1 }
    275     );
    276 if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
    277 
    278 ($config{major}, $config{minor})
    279     = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
    280 ($config{shlib_major}, $config{shlib_minor})
    281     = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
    282 die "erroneous version information in opensslv.h: ",
    283     "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
    284     if ($config{major} eq "" || $config{minor} eq ""
    285         || $config{shlib_major} eq "" ||  $config{shlib_minor} eq "");
    286 
    287 # Collect target configurations
    288 
    289 my $pattern = catfile(dirname($0), "Configurations", "*.conf");
    290 foreach (sort glob($pattern)) {
    291     &read_config($_);
    292 }
    293 
    294 if (defined env($local_config_envname)) {
    295     if ($^O eq 'VMS') {
    296         # VMS environment variables are logical names,
    297         # which can be used as is
    298         $pattern = $local_config_envname . ':' . '*.conf';
    299     } else {
    300         $pattern = catfile(env($local_config_envname), '*.conf');
    301     }
    302 
    303     foreach (sort glob($pattern)) {
    304         &read_config($_);
    305     }
    306 }
    307 
    308 # Save away perl command information
    309 $config{perl_cmd} = $^X;
    310 $config{perl_version} = $Config{version};
    311 $config{perl_archname} = $Config{archname};
    312 
    313 $config{prefix}="";
    314 $config{openssldir}="";
    315 $config{processor}="";
    316 $config{libdir}="";
    317 my $auto_threads=1;    # enable threads automatically? true by default
    318 my $default_ranlib;
    319 
    320 # Top level directories to build
    321 $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
    322 # crypto/ subdirectories to build
    323 $config{sdirs} = [
    324     "objects",
    325     "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
    326     "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
    327     "bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine",
    328     "buffer", "bio", "stack", "lhash", "rand", "err",
    329     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
    330     "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
    331     ];
    332 # test/ subdirectories to build
    333 $config{tdirs} = [ "ossl_shim" ];
    334 
    335 # Known TLS and DTLS protocols
    336 my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
    337 my @dtls = qw(dtls1 dtls1_2);
    338 
    339 # Explicitly known options that are possible to disable.  They can
    340 # be regexps, and will be used like this: /^no-${option}$/
    341 # For developers: keep it sorted alphabetically
    342 
    343 my @disablables = (
    344     "afalgeng",
    345     "aria",
    346     "asan",
    347     "asm",
    348     "async",
    349     "autoalginit",
    350     "autoerrinit",
    351     "autoload-config",
    352     "bf",
    353     "blake2",
    354     "buildtest-c\\+\\+",
    355     "camellia",
    356     "capieng",
    357     "cast",
    358     "chacha",
    359     "cmac",
    360     "cms",
    361     "comp",
    362     "crypto-mdebug",
    363     "crypto-mdebug-backtrace",
    364     "ct",
    365     "deprecated",
    366     "des",
    367     "devcryptoeng",
    368     "dgram",
    369     "dh",
    370     "dsa",
    371     "dso",
    372     "dtls",
    373     "dynamic-engine",
    374     "ec",
    375     "ec2m",
    376     "ecdh",
    377     "ecdsa",
    378     "ec_nistp_64_gcc_128",
    379     "egd",
    380     "engine",
    381     "err",
    382     "external-tests",
    383     "filenames",
    384     "fuzz-libfuzzer",
    385     "fuzz-afl",
    386     "gost",
    387     "heartbeats",
    388     "hw(-.+)?",
    389     "idea",
    390     "makedepend",
    391     "md2",
    392     "md4",
    393     "mdc2",
    394     "msan",
    395     "multiblock",
    396     "nextprotoneg",
    397     "pinshared",
    398     "ocb",
    399     "ocsp",
    400     "pic",
    401     "poly1305",
    402     "posix-io",
    403     "psk",
    404     "rc2",
    405     "rc4",
    406     "rc5",
    407     "rdrand",
    408     "rfc3779",
    409     "rmd160",
    410     "scrypt",
    411     "sctp",
    412     "seed",
    413     "shared",
    414     "siphash",
    415     "sm2",
    416     "sm3",
    417     "sm4",
    418     "sock",
    419     "srp",
    420     "srtp",
    421     "sse2",
    422     "ssl",
    423     "ssl-trace",
    424     "static-engine",
    425     "stdio",
    426     "tests",
    427     "threads",
    428     "tls",
    429     "ts",
    430     "ubsan",
    431     "ui-console",
    432     "unit-test",
    433     "whirlpool",
    434     "weak-ssl-ciphers",
    435     "zlib",
    436     "zlib-dynamic",
    437     );
    438 foreach my $proto ((@tls, @dtls))
    439         {
    440         push(@disablables, $proto);
    441         push(@disablables, "$proto-method") unless $proto eq "tls1_3";
    442         }
    443 
    444 my %deprecated_disablables = (
    445     "ssl2" => undef,
    446     "buf-freelists" => undef,
    447     "ripemd" => "rmd160",
    448     "ui" => "ui-console",
    449     );
    450 
    451 # All of the following are disabled by default:
    452 
    453 our %disabled = ( # "what"         => "comment"
    454                   "asan"                => "default",
    455                   "buildtest-c++"       => "default",
    456                   "crypto-mdebug"       => "default",
    457                   "crypto-mdebug-backtrace" => "default",
    458                   "devcryptoeng"        => "default",
    459                   "ec_nistp_64_gcc_128" => "default",
    460                   "egd"                 => "default",
    461                   "external-tests"      => "default",
    462                   "fuzz-libfuzzer"      => "default",
    463                   "fuzz-afl"            => "default",
    464                   "heartbeats"          => "default",
    465                   "md2"                 => "default",
    466                   "msan"                => "default",
    467                   "rc5"                 => "default",
    468                   "sctp"                => "default",
    469                   "ssl-trace"           => "default",
    470                   "ssl3"                => "default",
    471                   "ssl3-method"         => "default",
    472                   "ubsan"               => "default",
    473                   "unit-test"           => "default",
    474                   "weak-ssl-ciphers"    => "default",
    475                   "zlib"                => "default",
    476                   "zlib-dynamic"        => "default",
    477                 );
    478 
    479 # Note: => pair form used for aesthetics, not to truly make a hash table
    480 my @disable_cascades = (
    481     # "what"            => [ "cascade", ... ]
    482     sub { $config{processor} eq "386" }
    483                         => [ "sse2" ],
    484     "ssl"               => [ "ssl3" ],
    485     "ssl3-method"       => [ "ssl3" ],
    486     "zlib"              => [ "zlib-dynamic" ],
    487     "des"               => [ "mdc2" ],
    488     "ec"                => [ "ecdsa", "ecdh" ],
    489 
    490     "dgram"             => [ "dtls", "sctp" ],
    491     "sock"              => [ "dgram" ],
    492     "dtls"              => [ @dtls ],
    493     sub { 0 == scalar grep { !$disabled{$_} } @dtls }
    494                         => [ "dtls" ],
    495 
    496     "tls"               => [ @tls ],
    497     sub { 0 == scalar grep { !$disabled{$_} } @tls }
    498                         => [ "tls" ],
    499 
    500     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
    501 
    502     # Without position independent code, there can be no shared libraries or DSOs
    503     "pic"               => [ "shared" ],
    504     "shared"            => [ "dynamic-engine" ],
    505     "dso"               => [ "dynamic-engine" ],
    506     "engine"            => [ "afalgeng", "devcryptoeng" ],
    507 
    508     # no-autoalginit is only useful when building non-shared
    509     "autoalginit"       => [ "shared", "apps" ],
    510 
    511     "stdio"             => [ "apps", "capieng", "egd" ],
    512     "apps"              => [ "tests" ],
    513     "tests"             => [ "external-tests" ],
    514     "comp"              => [ "zlib" ],
    515     "ec"                => [ "tls1_3", "sm2" ],
    516     "sm3"               => [ "sm2" ],
    517     sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
    518 
    519     sub { !$disabled{"msan"} } => [ "asm" ],
    520     );
    521 
    522 # Avoid protocol support holes.  Also disable all versions below N, if version
    523 # N is disabled while N+1 is enabled.
    524 #
    525 my @list = (reverse @tls);
    526 while ((my $first, my $second) = (shift @list, shift @list)) {
    527     last unless @list;
    528     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
    529                               => [ @list ] );
    530     unshift @list, $second;
    531 }
    532 my @list = (reverse @dtls);
    533 while ((my $first, my $second) = (shift @list, shift @list)) {
    534     last unless @list;
    535     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
    536                               => [ @list ] );
    537     unshift @list, $second;
    538 }
    539 
    540 # Explicit "no-..." options will be collected in %disabled along with the defaults.
    541 # To remove something from %disabled, use "enable-foo".
    542 # For symmetry, "disable-foo" is a synonym for "no-foo".
    543 
    544 &usage if ($#ARGV < 0);
    545 
    546 # For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
    547 # platform specific list separators.  Users from those platforms should
    548 # recognise those separators from how you set up the PATH to find executables.
    549 # The default is the Unix like separator, :, but as an exception, we also
    550 # support the space as separator.
    551 my $list_separator_re =
    552     { VMS           => qr/(?<!\^),/,
    553       MSWin32       => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/;
    554 # All the "make variables" we support
    555 # Some get pre-populated for the sake of backward compatibility
    556 # (we supported those before the change to "make variable" support.
    557 my %user = (
    558     AR          => env('AR'),
    559     ARFLAGS     => [],
    560     AS          => undef,
    561     ASFLAGS     => [],
    562     CC          => env('CC'),
    563     CFLAGS      => [ env('CFLAGS') || () ],
    564     CXX         => env('CXX'),
    565     CXXFLAGS    => [ env('CXXFLAGS') || () ],
    566     CPP         => undef,
    567     CPPFLAGS    => [ env('CPPFLAGS') || () ],  # -D, -I, -Wp,
    568     CPPDEFINES  => [],  # Alternative for -D
    569     CPPINCLUDES => [],  # Alternative for -I
    570     CROSS_COMPILE => env('CROSS_COMPILE'),
    571     HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'),
    572     LD          => undef,
    573     LDFLAGS     => [ env('LDFLAGS') || () ],  # -L, -Wl,
    574     LDLIBS      => [ env('LDLIBS') || () ],  # -l
    575     MT          => undef,
    576     MTFLAGS     => [],
    577     PERL        => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
    578     RANLIB      => env('RANLIB'),
    579     RC          => env('RC') || env('WINDRES'),
    580     RCFLAGS     => [ env('RCFLAGS') || () ],
    581     RM          => undef,
    582    );
    583 # Info about what "make variables" may be prefixed with the cross compiler
    584 # prefix.  This should NEVER mention any such variable with a list for value.
    585 my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC );
    586 # The same but for flags given as Configure options.  These are *additional*
    587 # input, as opposed to the VAR=string option that override the corresponding
    588 # config target attributes
    589 my %useradd = (
    590     CPPDEFINES  => [],
    591     CPPINCLUDES => [],
    592     CPPFLAGS    => [],
    593     CFLAGS      => [],
    594     CXXFLAGS    => [],
    595     LDFLAGS     => [],
    596     LDLIBS      => [],
    597     RCFLAGS     => [],
    598    );
    599 
    600 my %user_synonyms = (
    601     HASHBANGPERL=> 'PERL',
    602     RC          => 'WINDRES',
    603    );
    604 
    605 # Some target attributes have been renamed, this is the translation table
    606 my %target_attr_translate =(
    607     ar          => 'AR',
    608     as          => 'AS',
    609     cc          => 'CC',
    610     cxx         => 'CXX',
    611     cpp         => 'CPP',
    612     hashbangperl => 'HASHBANGPERL',
    613     ld          => 'LD',
    614     mt          => 'MT',
    615     ranlib      => 'RANLIB',
    616     rc          => 'RC',
    617     rm          => 'RM',
    618    );
    619 
    620 # Initialisers coming from 'config' scripts
    621 $config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ];
    622 $config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ];
    623 $config{cppflags} = [ env('__CNF_CPPFLAGS') || () ];
    624 $config{cflags} = [ env('__CNF_CFLAGS') || () ];
    625 $config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ];
    626 $config{lflags} = [ env('__CNF_LDFLAGS') || () ];
    627 $config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
    628 
    629 $config{openssl_api_defines}=[];
    630 $config{openssl_algorithm_defines}=[];
    631 $config{openssl_thread_defines}=[];
    632 $config{openssl_sys_defines}=[];
    633 $config{openssl_other_defines}=[];
    634 $config{options}="";
    635 $config{build_type} = "release";
    636 my $target="";
    637 
    638 my %cmdvars = ();               # Stores FOO='blah' type arguments
    639 my %unsupported_options = ();
    640 my %deprecated_options = ();
    641 # If you change this, update apps/version.c
    642 my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
    643 my @seed_sources = ();
    644 while (@argvcopy)
    645         {
    646         $_ = shift @argvcopy;
    647 
    648         # Support env variable assignments among the options
    649         if (m|^(\w+)=(.+)?$|)
    650                 {
    651                 $cmdvars{$1} = $2;
    652                 # Every time a variable is given as a configuration argument,
    653                 # it acts as a reset if the variable.
    654                 if (exists $user{$1})
    655                         {
    656                         $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
    657                         }
    658                 #if (exists $useradd{$1})
    659                 #       {
    660                 #       $useradd{$1} = [];
    661                 #       }
    662                 next;
    663                 }
    664 
    665         # VMS is a case insensitive environment, and depending on settings
    666         # out of our control, we may receive options uppercased.  Let's
    667         # downcase at least the part before any equal sign.
    668         if ($^O eq "VMS")
    669                 {
    670                 s/^([^=]*)/lc($1)/e;
    671                 }
    672 
    673         # some people just can't read the instructions, clang people have to...
    674         s/^-no-(?!integrated-as)/no-/;
    675 
    676         # rewrite some options in "enable-..." form
    677         s /^-?-?shared$/enable-shared/;
    678         s /^sctp$/enable-sctp/;
    679         s /^threads$/enable-threads/;
    680         s /^zlib$/enable-zlib/;
    681         s /^zlib-dynamic$/enable-zlib-dynamic/;
    682 
    683         if (/^(no|disable|enable)-(.+)$/)
    684                 {
    685                 my $word = $2;
    686                 if (!exists $deprecated_disablables{$word}
    687                         && !grep { $word =~ /^${_}$/ } @disablables)
    688                         {
    689                         $unsupported_options{$_} = 1;
    690                         next;
    691                         }
    692                 }
    693         if (/^no-(.+)$/ || /^disable-(.+)$/)
    694                 {
    695                 foreach my $proto ((@tls, @dtls))
    696                         {
    697                         if ($1 eq "$proto-method")
    698                                 {
    699                                 $disabled{"$proto"} = "option($proto-method)";
    700                                 last;
    701                                 }
    702                         }
    703                 if ($1 eq "dtls")
    704                         {
    705                         foreach my $proto (@dtls)
    706                                 {
    707                                 $disabled{$proto} = "option(dtls)";
    708                                 }
    709                         $disabled{"dtls"} = "option(dtls)";
    710                         }
    711                 elsif ($1 eq "ssl")
    712                         {
    713                         # Last one of its kind
    714                         $disabled{"ssl3"} = "option(ssl)";
    715                         }
    716                 elsif ($1 eq "tls")
    717                         {
    718                         # XXX: Tests will fail if all SSL/TLS
    719                         # protocols are disabled.
    720                         foreach my $proto (@tls)
    721                                 {
    722                                 $disabled{$proto} = "option(tls)";
    723                                 }
    724                         }
    725                 elsif ($1 eq "static-engine")
    726                         {
    727                         delete $disabled{"dynamic-engine"};
    728                         }
    729                 elsif ($1 eq "dynamic-engine")
    730                         {
    731                         $disabled{"dynamic-engine"} = "option";
    732                         }
    733                 elsif (exists $deprecated_disablables{$1})
    734                         {
    735                         if ($deprecated_disablables{$1} ne "")
    736                                 {
    737                                 $deprecated_options{$_} = 1;
    738                                 if (defined $deprecated_disablables{$1})
    739                                         {
    740                                         $disabled{$deprecated_disablables{$1}} = "option";
    741                                         }
    742                                 }
    743                         }
    744                 else
    745                         {
    746                         $disabled{$1} = "option";
    747                         }
    748                 # No longer an automatic choice
    749                 $auto_threads = 0 if ($1 eq "threads");
    750                 }
    751         elsif (/^enable-(.+)$/)
    752                 {
    753                 if ($1 eq "static-engine")
    754                         {
    755                         $disabled{"dynamic-engine"} = "option";
    756                         }
    757                 elsif ($1 eq "dynamic-engine")
    758                         {
    759                         delete $disabled{"dynamic-engine"};
    760                         }
    761                 elsif ($1 eq "zlib-dynamic")
    762                         {
    763                         delete $disabled{"zlib"};
    764                         }
    765                 my $algo = $1;
    766                 delete $disabled{$algo};
    767 
    768                 # No longer an automatic choice
    769                 $auto_threads = 0 if ($1 eq "threads");
    770                 }
    771         elsif (/^--strict-warnings$/)
    772                 {
    773                 # Pretend that our strict flags is a C flag, and replace it
    774                 # with the proper flags later on
    775                 push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
    776                 $strict_warnings=1;
    777                 }
    778         elsif (/^--debug$/)
    779                 {
    780                 $config{build_type} = "debug";
    781                 }
    782         elsif (/^--release$/)
    783                 {
    784                 $config{build_type} = "release";
    785                 }
    786         elsif (/^386$/)
    787                 { $config{processor}=386; }
    788         elsif (/^fips$/)
    789                 {
    790                 die "FIPS mode not supported\n";
    791                 }
    792         elsif (/^rsaref$/)
    793                 {
    794                 # No RSAref support any more since it's not needed.
    795                 # The check for the option is there so scripts aren't
    796                 # broken
    797                 }
    798         elsif (/^nofipscanistercheck$/)
    799                 {
    800                 die "FIPS mode not supported\n";
    801                 }
    802         elsif (m|^[-+/]|)
    803                 {
    804                 if (/^--prefix=(.*)$/)
    805                         {
    806                         $config{prefix}=$1;
    807                         die "Directory given with --prefix MUST be absolute\n"
    808                                 unless file_name_is_absolute($config{prefix});
    809                         }
    810                 elsif (/^--api=(.*)$/)
    811                         {
    812                         $config{api}=$1;
    813                         }
    814                 elsif (/^--libdir=(.*)$/)
    815                         {
    816                         $config{libdir}=$1;
    817                         }
    818                 elsif (/^--openssldir=(.*)$/)
    819                         {
    820                         $config{openssldir}=$1;
    821                         }
    822                 elsif (/^--with-zlib-lib=(.*)$/)
    823                         {
    824                         $withargs{zlib_lib}=$1;
    825                         }
    826                 elsif (/^--with-zlib-include=(.*)$/)
    827                         {
    828                         $withargs{zlib_include}=$1;
    829                         }
    830                 elsif (/^--with-fuzzer-lib=(.*)$/)
    831                         {
    832                         $withargs{fuzzer_lib}=$1;
    833                         }
    834                 elsif (/^--with-fuzzer-include=(.*)$/)
    835                         {
    836                         $withargs{fuzzer_include}=$1;
    837                         }
    838                 elsif (/^--with-rand-seed=(.*)$/)
    839                         {
    840                         foreach my $x (split(m|,|, $1))
    841                             {
    842                             die "Unknown --with-rand-seed choice $x\n"
    843                                 if ! grep { $x eq $_ } @known_seed_sources;
    844                             push @seed_sources, $x;
    845                             }
    846                         }
    847                 elsif (/^--cross-compile-prefix=(.*)$/)
    848                         {
    849                         $user{CROSS_COMPILE}=$1;
    850                         }
    851                 elsif (/^--config=(.*)$/)
    852                         {
    853                         read_config $1;
    854                         }
    855                 elsif (/^-l(.*)$/)
    856                         {
    857                         push @{$useradd{LDLIBS}}, $_;
    858                         }
    859                 elsif (/^-framework$/)
    860                         {
    861                         push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
    862                         }
    863                 elsif (/^-L(.*)$/ or /^-Wl,/)
    864                         {
    865                         push @{$useradd{LDFLAGS}}, $_;
    866                         }
    867                 elsif (/^-rpath$/ or /^-R$/)
    868                         # -rpath is the OSF1 rpath flag
    869                         # -R is the old Solaris rpath flag
    870                         {
    871                         my $rpath = shift(@argvcopy) || "";
    872                         $rpath .= " " if $rpath ne "";
    873                         push @{$useradd{LDFLAGS}}, $_, $rpath;
    874                         }
    875                 elsif (/^-static$/)
    876                         {
    877                         push @{$useradd{LDFLAGS}}, $_;
    878                         }
    879                 elsif (m|^[-/]D(.*)$|)
    880                         {
    881                         push @{$useradd{CPPDEFINES}}, $1;
    882                         }
    883                 elsif (m|^[-/]I(.*)$|)
    884                         {
    885                         push @{$useradd{CPPINCLUDES}}, $1;
    886                         }
    887                 elsif (/^-Wp,$/)
    888                         {
    889                         push @{$useradd{CPPFLAGS}}, $1;
    890                         }
    891                 else    # common if (/^[-+]/), just pass down...
    892                         {
    893                         # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
    894                         # This provides a simple way to pass options with arguments separated
    895                         # by spaces without quoting (e.g. -opt%20arg translates to -opt arg).
    896                         $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
    897                         push @{$useradd{CFLAGS}}, $_;
    898                         push @{$useradd{CXXFLAGS}}, $_;
    899                         }
    900                 }
    901         elsif (m|^/|)
    902                 {
    903                 # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
    904                 # This provides a simple way to pass options with arguments separated
    905                 # by spaces without quoting (e.g. /opt%20arg translates to /opt arg).
    906                 $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
    907                 push @{$useradd{CFLAGS}}, $_;
    908                 push @{$useradd{CXXFLAGS}}, $_;
    909                 }
    910         else
    911                 {
    912                 die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
    913                 $target=$_;
    914                 }
    915         unless ($_ eq $target || /^no-/ || /^disable-/)
    916                 {
    917                 # "no-..." follows later after implied deactivations
    918                 # have been derived.  (Don't take this too seriously,
    919                 # we really only write OPTIONS to the Makefile out of
    920                 # nostalgia.)
    921 
    922                 if ($config{options} eq "")
    923                         { $config{options} = $_; }
    924                 else
    925                         { $config{options} .= " ".$_; }
    926                 }
    927         }
    928 
    929 if (defined($config{api}) && !exists $apitable->{$config{api}}) {
    930         die "***** Unsupported api compatibility level: $config{api}\n",
    931 }
    932 
    933 if (keys %deprecated_options)
    934         {
    935         warn "***** Deprecated options: ",
    936                 join(", ", keys %deprecated_options), "\n";
    937         }
    938 if (keys %unsupported_options)
    939         {
    940         die "***** Unsupported options: ",
    941                 join(", ", keys %unsupported_options), "\n";
    942         }
    943 
    944 # If any %useradd entry has been set, we must check that the "make
    945 # variables" haven't been set.  We start by checking of any %useradd entry
    946 # is set.
    947 if (grep { scalar @$_ > 0 } values %useradd) {
    948     # Hash of env / make variables names.  The possible values are:
    949     # 1 - "make vars"
    950     # 2 - %useradd entry set
    951     # 3 - both set
    952     my %detected_vars =
    953         map { my $v = 0;
    954               $v += 1 if $cmdvars{$_};
    955               $v += 2 if @{$useradd{$_}};
    956               $_ => $v }
    957         keys %useradd;
    958 
    959     # If any of the corresponding "make variables" is set, we error
    960     if (grep { $_ & 1 } values %detected_vars) {
    961         my $names = join(', ', grep { $detected_vars{$_} > 0 }
    962                                sort keys %detected_vars);
    963         die <<"_____";
    964 ***** Mixing make variables and additional compiler/linker flags as
    965 ***** configure command line option is not permitted.
    966 ***** Affected make variables: $names
    967 _____
    968     }
    969 }
    970 
    971 # Check through all supported command line variables to see if any of them
    972 # were set, and canonicalise the values we got.  If no compiler or linker
    973 # flag or anything else that affects %useradd was set, we also check the
    974 # environment for values.
    975 my $anyuseradd =
    976     grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
    977 foreach (keys %user) {
    978     my $value = $cmdvars{$_};
    979     $value //= env($_) unless $anyuseradd;
    980     $value //=
    981         defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
    982     $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
    983         unless $anyuseradd;
    984 
    985     if (defined $value) {
    986         if (ref $user{$_} eq 'ARRAY') {
    987             if ($_ eq 'CPPDEFINES' || $_ eq 'CPPINCLUDES') {
    988                 $user{$_} = [ split /$list_separator_re/, $value ];
    989             } else {
    990                 $user{$_} = [ $value ];
    991             }
    992         } elsif (!defined $user{$_}) {
    993             $user{$_} = $value;
    994         }
    995     }
    996 }
    997 
    998 if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
    999     && !$disabled{shared}
   1000     && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
   1001     die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
   1002         "***** any of asan, msan or ubsan\n";
   1003 }
   1004 
   1005 sub disable {
   1006     my $disable_type = shift;
   1007 
   1008     for (@_) {
   1009         $disabled{$_} = $disable_type;
   1010     }
   1011 
   1012     my @tocheckfor = (@_ ? @_ : keys %disabled);
   1013     while (@tocheckfor) {
   1014         my %new_tocheckfor = ();
   1015         my @cascade_copy = (@disable_cascades);
   1016         while (@cascade_copy) {
   1017             my ($test, $descendents) =
   1018                 (shift @cascade_copy, shift @cascade_copy);
   1019             if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
   1020                 foreach (grep { !defined($disabled{$_}) } @$descendents) {
   1021                     $new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
   1022                 }
   1023             }
   1024         }
   1025         @tocheckfor = (keys %new_tocheckfor);
   1026     }
   1027 }
   1028 disable();                     # First cascade run
   1029 
   1030 our $die = sub { die @_; };
   1031 if ($target eq "TABLE") {
   1032     local $die = sub { warn @_; };
   1033     foreach (sort keys %table) {
   1034         print_table_entry($_, "TABLE");
   1035     }
   1036     exit 0;
   1037 }
   1038 
   1039 if ($target eq "LIST") {
   1040     foreach (sort keys %table) {
   1041         print $_,"\n" unless $table{$_}->{template};
   1042     }
   1043     exit 0;
   1044 }
   1045 
   1046 if ($target eq "HASH") {
   1047     local $die = sub { warn @_; };
   1048     print "%table = (\n";
   1049     foreach (sort keys %table) {
   1050         print_table_entry($_, "HASH");
   1051     }
   1052     exit 0;
   1053 }
   1054 
   1055 print "Configuring OpenSSL version $config{version} ($config{version_num}) ";
   1056 print "for $target\n";
   1057 
   1058 if (scalar(@seed_sources) == 0) {
   1059     print "Using os-specific seed configuration\n";
   1060     push @seed_sources, 'os';
   1061 }
   1062 if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) {
   1063     delete $disabled{'egd'};
   1064 }
   1065 if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
   1066     die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
   1067     warn <<_____ if scalar(@seed_sources) == 1;
   1068 
   1069 ============================== WARNING ===============================
   1070 You have selected the --with-rand-seed=none option, which effectively
   1071 disables automatic reseeding of the OpenSSL random generator.
   1072 All operations depending on the random generator such as creating keys
   1073 will not work unless the random generator is seeded manually by the
   1074 application.
   1075 
   1076 Please read the 'Note on random number generation' section in the
   1077 INSTALL instructions and the RAND_DRBG(7) manual page for more details.
   1078 ============================== WARNING ===============================
   1079 
   1080 _____
   1081 }
   1082 push @{$config{openssl_other_defines}},
   1083      map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
   1084         @seed_sources;
   1085 
   1086 # Backward compatibility?
   1087 if ($target =~ m/^CygWin32(-.*)$/) {
   1088     $target = "Cygwin".$1;
   1089 }
   1090 
   1091 # Support for legacy targets having a name starting with 'debug-'
   1092 my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
   1093 if ($d) {
   1094     $config{build_type} = "debug";
   1095 
   1096     # If we do not find debug-foo in the table, the target is set to foo.
   1097     if (!$table{$target}) {
   1098         $target = $t;
   1099     }
   1100 }
   1101 
   1102 &usage if !$table{$target} || $table{$target}->{template};
   1103 
   1104 $config{target} = $target;
   1105 my %target = resolve_config($target);
   1106 
   1107 foreach (keys %target_attr_translate) {
   1108     $target{$target_attr_translate{$_}} = $target{$_}
   1109         if $target{$_};
   1110     delete $target{$_};
   1111 }
   1112 
   1113 %target = ( %{$table{DEFAULTS}}, %target );
   1114 
   1115 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
   1116 $config{conf_files} = [ sort keys %conf_files ];
   1117 
   1118 # Using sub disable within these loops may prove fragile, so we run
   1119 # a cascade afterwards
   1120 foreach my $feature (@{$target{disable}}) {
   1121     if (exists $deprecated_disablables{$feature}) {
   1122         warn "***** config $target disables deprecated feature $feature\n";
   1123     } elsif (!grep { $feature eq $_ } @disablables) {
   1124         die "***** config $target disables unknown feature $feature\n";
   1125     }
   1126     $disabled{$feature} = 'config';
   1127 }
   1128 foreach my $feature (@{$target{enable}}) {
   1129     if ("default" eq ($disabled{$feature} // "")) {
   1130         if (exists $deprecated_disablables{$feature}) {
   1131             warn "***** config $target enables deprecated feature $feature\n";
   1132         } elsif (!grep { $feature eq $_ } @disablables) {
   1133             die "***** config $target enables unknown feature $feature\n";
   1134         }
   1135         delete $disabled{$feature};
   1136     }
   1137 }
   1138 disable();                      # Run a cascade now
   1139 
   1140 $target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
   1141 $target{cxxflags}//=$target{cflags} if $target{CXX};
   1142 $target{exe_extension}="";
   1143 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
   1144                                   || $config{target} =~ /^(?:Cygwin|mingw)/);
   1145 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
   1146 
   1147 ($target{shared_extension_simple}=$target{shared_extension})
   1148     =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||
   1149     unless defined($target{shared_extension_simple});
   1150 $target{dso_extension}//=$target{shared_extension_simple};
   1151 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
   1152     if ($config{target} =~ /^(?:Cygwin|mingw)/);
   1153 
   1154 # Fill %config with values from %user, and in case those are undefined or
   1155 # empty, use values from %target (acting as a default).
   1156 foreach (keys %user) {
   1157     my $ref_type = ref $user{$_};
   1158 
   1159     # Temporary function.  Takes an intended ref type (empty string or "ARRAY")
   1160     # and a value that's to be coerced into that type.
   1161     my $mkvalue = sub {
   1162         my $type = shift;
   1163         my $value = shift;
   1164         my $undef_p = shift;
   1165 
   1166         die "Too many arguments for \$mkvalue" if @_;
   1167 
   1168         while (ref $value eq 'CODE') {
   1169             $value = $value->();
   1170         }
   1171 
   1172         if ($type eq 'ARRAY') {
   1173             return undef unless defined $value;
   1174             return undef if ref $value ne 'ARRAY' && !$value;
   1175             return undef if ref $value eq 'ARRAY' && !@$value;
   1176             return [ $value ] unless ref $value eq 'ARRAY';
   1177         }
   1178         return undef unless $value;
   1179         return $value;
   1180     };
   1181 
   1182     $config{$_} =
   1183         $mkvalue->($ref_type, $user{$_})
   1184         || $mkvalue->($ref_type, $target{$_});
   1185     delete $config{$_} unless defined $config{$_};
   1186 }
   1187 
   1188 # Finish up %config by appending things the user gave us on the command line
   1189 # apart from "make variables"
   1190 foreach (keys %useradd) {
   1191     # The must all be lists, so we assert that here
   1192     die "internal error: \$useradd{$_} isn't an ARRAY\n"
   1193         unless ref $useradd{$_} eq 'ARRAY';
   1194 
   1195     if (defined $config{$_}) {
   1196         push @{$config{$_}}, @{$useradd{$_}};
   1197     } else {
   1198         $config{$_} = [ @{$useradd{$_}} ];
   1199     }
   1200 }
   1201 # At this point, we can forget everything about %user and %useradd,
   1202 # because it's now all been merged into the corresponding $config entry
   1203 
   1204 if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
   1205     disable('static', 'pic', 'threads');
   1206 }
   1207 
   1208 # Allow overriding the build file name
   1209 $config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
   1210 
   1211 # Make sure build_scheme is consistent.
   1212 $target{build_scheme} = [ $target{build_scheme} ]
   1213     if ref($target{build_scheme}) ne "ARRAY";
   1214 
   1215 my ($builder, $builder_platform, @builder_opts) =
   1216     @{$target{build_scheme}};
   1217 
   1218 foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
   1219                       $builder_platform."-checker.pm")) {
   1220     my $checker_path = catfile($srcdir, "Configurations", $checker);
   1221     if (-f $checker_path) {
   1222         my $fn = $ENV{CONFIGURE_CHECKER_WARN}
   1223             ? sub { warn $@; } : sub { die $@; };
   1224         if (! do $checker_path) {
   1225             if ($@) {
   1226                 $fn->($@);
   1227             } elsif ($!) {
   1228                 $fn->($!);
   1229             } else {
   1230                 $fn->("The detected tools didn't match the platform\n");
   1231             }
   1232         }
   1233         last;
   1234     }
   1235 }
   1236 
   1237 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
   1238 
   1239 if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
   1240         {
   1241         push @{$config{cflags}}, "-mno-cygwin";
   1242         push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
   1243         push @{$config{shared_ldflag}}, "-mno-cygwin";
   1244         }
   1245 
   1246 if ($target =~ /linux.*-mips/ && !$disabled{asm}
   1247         && !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
   1248         # minimally required architecture flags for assembly modules
   1249         my $value;
   1250         $value = '-mips2' if ($target =~ /mips32/);
   1251         $value = '-mips3' if ($target =~ /mips64/);
   1252         unshift @{$config{cflags}}, $value;
   1253         unshift @{$config{cxxflags}}, $value if $config{CXX};
   1254 }
   1255 
   1256 # If threads aren't disabled, check how possible they are
   1257 unless ($disabled{threads}) {
   1258     if ($auto_threads) {
   1259         # Enabled by default, disable it forcibly if unavailable
   1260         if ($target{thread_scheme} eq "(unknown)") {
   1261             disable("unavailable", 'threads');
   1262         }
   1263     } else {
   1264         # The user chose to enable threads explicitly, let's see
   1265         # if there's a chance that's possible
   1266         if ($target{thread_scheme} eq "(unknown)") {
   1267             # If the user asked for "threads" and we don't have internal
   1268             # knowledge how to do it, [s]he is expected to provide any
   1269             # system-dependent compiler options that are necessary.  We
   1270             # can't truly check that the given options are correct, but
   1271             # we expect the user to know what [s]He is doing.
   1272             if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
   1273                 die "You asked for multi-threading support, but didn't\n"
   1274                     ,"provide any system-specific compiler options\n";
   1275             }
   1276         }
   1277     }
   1278 }
   1279 
   1280 # If threads still aren't disabled, add a C macro to ensure the source
   1281 # code knows about it.  Any other flag is taken care of by the configs.
   1282 unless($disabled{threads}) {
   1283     push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS";
   1284 }
   1285 
   1286 # With "deprecated" disable all deprecated features.
   1287 if (defined($disabled{"deprecated"})) {
   1288         $config{api} = $maxapi;
   1289 }
   1290 
   1291 my $no_shared_warn=0;
   1292 if ($target{shared_target} eq "")
   1293         {
   1294         $no_shared_warn = 1
   1295             if (!$disabled{shared} || !$disabled{"dynamic-engine"});
   1296         disable('no-shared-target', 'pic');
   1297         }
   1298 
   1299 if ($disabled{"dynamic-engine"}) {
   1300         $config{dynamic_engines} = 0;
   1301 } else {
   1302         $config{dynamic_engines} = 1;
   1303 }
   1304 
   1305 unless ($disabled{asan}) {
   1306     push @{$config{cflags}}, "-fsanitize=address";
   1307 }
   1308 
   1309 unless ($disabled{ubsan}) {
   1310     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
   1311     # platforms.
   1312     push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
   1313 }
   1314 
   1315 unless ($disabled{msan}) {
   1316   push @{$config{cflags}}, "-fsanitize=memory";
   1317 }
   1318 
   1319 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
   1320         && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
   1321     push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
   1322     push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
   1323 }
   1324 #
   1325 # Platform fix-ups
   1326 #
   1327 
   1328 # This saves the build files from having to check
   1329 if ($disabled{pic})
   1330         {
   1331         foreach (qw(shared_cflag shared_cxxflag shared_cppflag
   1332                     shared_defines shared_includes shared_ldflag
   1333                     module_cflags module_cxxflags module_cppflags
   1334                     module_defines module_includes module_lflags))
   1335                 {
   1336                 delete $config{$_};
   1337                 $target{$_} = "";
   1338                 }
   1339         }
   1340 else
   1341         {
   1342         push @{$config{lib_defines}}, "OPENSSL_PIC";
   1343         }
   1344 
   1345 if ($target{sys_id} ne "")
   1346         {
   1347         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
   1348         }
   1349 
   1350 unless ($disabled{asm}) {
   1351     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
   1352     push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c");
   1353 
   1354     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
   1355 
   1356     # bn-586 is the only one implementing bn_*_part_words
   1357     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
   1358     push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/);
   1359 
   1360     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
   1361     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
   1362     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
   1363     push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/);
   1364 
   1365     if ($target{sha1_asm_src}) {
   1366         push @{$config{lib_defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
   1367         push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
   1368         push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
   1369     }
   1370     if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
   1371         push @{$config{lib_defines}}, "KECCAK1600_ASM";
   1372     }
   1373     if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
   1374         push @{$config{lib_defines}}, "RC4_ASM";
   1375     }
   1376     if ($target{md5_asm_src}) {
   1377         push @{$config{lib_defines}}, "MD5_ASM";
   1378     }
   1379     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
   1380     if ($target{rmd160_asm_src}) {
   1381         push @{$config{lib_defines}}, "RMD160_ASM";
   1382     }
   1383     if ($target{aes_asm_src}) {
   1384         push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
   1385         push @{$config{lib_defines}}, "AESNI_ASM" if ($target{aes_asm_src} =~ m/\baesni-/);;
   1386         # aes-ctr.fake is not a real file, only indication that assembler
   1387         # module implements AES_ctr32_encrypt...
   1388         push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
   1389         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
   1390         push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
   1391         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
   1392         push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
   1393         push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
   1394     }
   1395     if ($target{wp_asm_src} =~ /mmx/) {
   1396         if ($config{processor} eq "386") {
   1397             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
   1398         } elsif (!$disabled{"whirlpool"}) {
   1399             push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
   1400         }
   1401     }
   1402     if ($target{modes_asm_src} =~ /ghash-/) {
   1403         push @{$config{lib_defines}}, "GHASH_ASM";
   1404     }
   1405     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
   1406         push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
   1407     }
   1408     if ($target{ec_asm_src} =~ /x25519/) {
   1409         push @{$config{lib_defines}}, "X25519_ASM";
   1410     }
   1411     if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
   1412         push @{$config{dso_defines}}, "PADLOCK_ASM";
   1413     }
   1414     if ($target{poly1305_asm_src} ne "") {
   1415         push @{$config{lib_defines}}, "POLY1305_ASM";
   1416     }
   1417 }
   1418 
   1419 my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
   1420 my %predefined_CXX = $config{CXX}
   1421     ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
   1422     : ();
   1423 
   1424 # Check for makedepend capabilities.
   1425 if (!$disabled{makedepend}) {
   1426     if ($config{target} =~ /^(VC|vms)-/) {
   1427         # For VC- and vms- targets, there's nothing more to do here.  The
   1428         # functionality is hard coded in the corresponding build files for
   1429         # cl (Windows) and CC/DECC (VMS).
   1430     } elsif (($predefined_C{__GNUC__} // -1) >= 3
   1431              && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
   1432         # We know that GNU C version 3 and up as well as all clang
   1433         # versions support dependency generation, but Xcode did not
   1434         # handle $cc -M before clang support (but claims __GNUC__ = 3)
   1435         $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}";
   1436     } else {
   1437         # In all other cases, we look for 'makedepend', and disable the
   1438         # capability if not found.
   1439         $config{makedepprog} = which('makedepend');
   1440         disable('unavailable', 'makedepend') unless $config{makedepprog};
   1441     }
   1442 }
   1443 
   1444 if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
   1445     # probe for -Wa,--noexecstack option...
   1446     if ($predefined_C{__clang__}) {
   1447         # clang has builtin assembler, which doesn't recognize --help,
   1448         # but it apparently recognizes the option in question on all
   1449         # supported platforms even when it's meaningless. In other words
   1450         # probe would fail, but probed option always accepted...
   1451         push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
   1452     } else {
   1453         my $cc = $config{CROSS_COMPILE}.$config{CC};
   1454         open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
   1455         while(<PIPE>) {
   1456             if (m/--noexecstack/) {
   1457                 push @{$config{cflags}}, "-Wa,--noexecstack";
   1458                 last;
   1459             }
   1460         }
   1461         close(PIPE);
   1462         unlink("null.$$.o");
   1463     }
   1464 }
   1465 
   1466 # Deal with bn_ops ###################################################
   1467 
   1468 $config{bn_ll}                  =0;
   1469 $config{export_var_as_fn}       =0;
   1470 my $def_int="unsigned int";
   1471 $config{rc4_int}                =$def_int;
   1472 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
   1473 
   1474 my $count = 0;
   1475 foreach (sort split(/\s+/,$target{bn_ops})) {
   1476     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
   1477     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
   1478     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
   1479     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
   1480     ($config{b64l},$config{b64},$config{b32})
   1481         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
   1482     ($config{b64l},$config{b64},$config{b32})
   1483         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
   1484     ($config{b64l},$config{b64},$config{b32})
   1485         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
   1486 }
   1487 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
   1488     if $count > 1;
   1489 
   1490 
   1491 # Hack cflags for better warnings (dev option) #######################
   1492 
   1493 # "Stringify" the C and C++ flags string.  This permits it to be made part of
   1494 # a string and works as well on command lines.
   1495 $config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
   1496                         @{$config{cflags}} ];
   1497 $config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
   1498                           @{$config{cxxflags}} ] if $config{CXX};
   1499 
   1500 if (defined($config{api})) {
   1501     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
   1502     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
   1503     push @{$config{defines}}, $apiflag;
   1504 }
   1505 
   1506 my @strict_warnings_collection=();
   1507 if ($strict_warnings)
   1508         {
   1509         my $wopt;
   1510         my $gccver = $predefined_C{__GNUC__} // -1;
   1511 
   1512         if ($gccver >= 4)
   1513                 {
   1514                 push @strict_warnings_collection, @gcc_devteam_warn;
   1515                 push @strict_warnings_collection, @clang_devteam_warn
   1516                     if (defined($predefined_C{__clang__}));
   1517                 }
   1518         elsif ($config{target} =~ /^VC-/)
   1519                 {
   1520                 push @strict_warnings_collection, @cl_devteam_warn;
   1521                 }
   1522         else
   1523                 {
   1524                 warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike, or MSVC"
   1525                 }
   1526         }
   1527 
   1528 $config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
   1529                               ? @strict_warnings_collection
   1530                               : ( $_ ) }
   1531                     @{$config{CFLAGS}} ];
   1532 
   1533 unless ($disabled{"crypto-mdebug-backtrace"})
   1534         {
   1535         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
   1536                 {
   1537                 push @{$config{cflags}}, $wopt
   1538                         unless grep { $_ eq $wopt } @{$config{cflags}};
   1539                 }
   1540         if ($target =~ /^BSD-/)
   1541                 {
   1542                 push @{$config{ex_libs}}, "-lexecinfo";
   1543                 }
   1544         }
   1545 
   1546 unless ($disabled{afalgeng}) {
   1547     $config{afalgeng}="";
   1548     if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
   1549         my $minver = 4*10000 + 1*100 + 0;
   1550         if ($config{CROSS_COMPILE} eq "") {
   1551             my $verstr = `uname -r`;
   1552             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
   1553             ($mi2) = $mi2 =~ /(\d+)/;
   1554             my $ver = $ma*10000 + $mi1*100 + $mi2;
   1555             if ($ver < $minver) {
   1556                 disable('too-old-kernel', 'afalgeng');
   1557             } else {
   1558                 push @{$config{engdirs}}, "afalg";
   1559             }
   1560         } else {
   1561             disable('cross-compiling', 'afalgeng');
   1562         }
   1563     } else {
   1564         disable('not-linux', 'afalgeng');
   1565     }
   1566 }
   1567 
   1568 unless ($disabled{devcryptoeng}) {
   1569     if ($target =~ m/^BSD/) {
   1570         my $maxver = 5*100 + 7;
   1571         my $sysstr = `uname -s`;
   1572         my $verstr = `uname -r`;
   1573         $sysstr =~ s|\R$||;
   1574         $verstr =~ s|\R$||;
   1575         my ($ma, $mi, @rest) = split m|\.|, $verstr;
   1576         my $ver = $ma*100 + $mi;
   1577         if ($sysstr eq 'OpenBSD' && $ver >= $maxver) {
   1578             disable('too-new-kernel', 'devcryptoeng');
   1579         }
   1580     }
   1581 }
   1582 
   1583 # Get the extra flags used when building shared libraries and modules.  We
   1584 # do this late because some of them depend on %disabled.
   1585 
   1586 # Make the flags to build DSOs the same as for shared libraries unless they
   1587 # are already defined
   1588 $target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
   1589 $target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
   1590 $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
   1591 {
   1592     my $shared_info_pl =
   1593         catfile(dirname($0), "Configurations", "shared-info.pl");
   1594     my %shared_info = read_eval_file($shared_info_pl);
   1595     push @{$target{_conf_fname_int}}, $shared_info_pl;
   1596     my $si = $target{shared_target};
   1597     while (ref $si ne "HASH") {
   1598         last if ! defined $si;
   1599         if (ref $si eq "CODE") {
   1600             $si = $si->();
   1601         } else {
   1602             $si = $shared_info{$si};
   1603         }
   1604     }
   1605 
   1606     # Some of the 'shared_target' values don't have any entries in
   1607     # %shared_info.  That's perfectly fine, AS LONG AS the build file
   1608     # template knows how to handle this.  That is currently the case for
   1609     # Windows and VMS.
   1610     if (defined $si) {
   1611         # Just as above, copy certain shared_* attributes to the corresponding
   1612         # module_ attribute unless the latter is already defined
   1613         $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
   1614         $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
   1615         $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
   1616         foreach (sort keys %$si) {
   1617             $target{$_} = defined $target{$_}
   1618                 ? add($si->{$_})->($target{$_})
   1619                 : $si->{$_};
   1620         }
   1621     }
   1622 }
   1623 
   1624 # ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
   1625 
   1626 my %disabled_info = ();         # For configdata.pm
   1627 foreach my $what (sort keys %disabled) {
   1628     $config{options} .= " no-$what";
   1629 
   1630     if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic',
   1631                                 'dynamic-engine', 'makedepend',
   1632                                 'zlib-dynamic', 'zlib', 'sse2' )) {
   1633         (my $WHAT = uc $what) =~ s|-|_|g;
   1634 
   1635         # Fix up C macro end names
   1636         $WHAT = "RMD160" if $what eq "ripemd";
   1637 
   1638         # fix-up crypto/directory name(s)
   1639         $what = "ripemd" if $what eq "rmd160";
   1640         $what = "whrlpool" if $what eq "whirlpool";
   1641 
   1642         my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
   1643 
   1644         if ((grep { $what eq $_ } @{$config{sdirs}})
   1645                 && $what ne 'async' && $what ne 'err' && $what ne 'dso') {
   1646             @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}};
   1647             $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ];
   1648 
   1649             if ($what ne 'engine') {
   1650                 push @{$config{openssl_algorithm_defines}}, $macro;
   1651             } else {
   1652                 @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
   1653                 push @{$disabled_info{engine}->{skipped}}, catdir('engines');
   1654                 push @{$config{openssl_other_defines}}, $macro;
   1655             }
   1656         } else {
   1657             push @{$config{openssl_other_defines}}, $macro;
   1658         }
   1659 
   1660     }
   1661 }
   1662 
   1663 if ($disabled{"dynamic-engine"}) {
   1664     push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
   1665 } else {
   1666     push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE";
   1667 }
   1668 
   1669 # If we use the unified build, collect information from build.info files
   1670 my %unified_info = ();
   1671 
   1672 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
   1673 if ($builder eq "unified") {
   1674     use with_fallback qw(Text::Template);
   1675 
   1676     sub cleandir {
   1677         my $base = shift;
   1678         my $dir = shift;
   1679         my $relativeto = shift || ".";
   1680 
   1681         $dir = catdir($base,$dir) unless isabsolute($dir);
   1682 
   1683         # Make sure the directories we're building in exists
   1684         mkpath($dir);
   1685 
   1686         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
   1687         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
   1688         return $res;
   1689     }
   1690 
   1691     sub cleanfile {
   1692         my $base = shift;
   1693         my $file = shift;
   1694         my $relativeto = shift || ".";
   1695 
   1696         $file = catfile($base,$file) unless isabsolute($file);
   1697 
   1698         my $d = dirname($file);
   1699         my $f = basename($file);
   1700 
   1701         # Make sure the directories we're building in exists
   1702         mkpath($d);
   1703 
   1704         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
   1705         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
   1706         return $res;
   1707     }
   1708 
   1709     # Store the name of the template file we will build the build file from
   1710     # in %config.  This may be useful for the build file itself.
   1711     my @build_file_template_names =
   1712         ( $builder_platform."-".$target{build_file}.".tmpl",
   1713           $target{build_file}.".tmpl" );
   1714     my @build_file_templates = ();
   1715 
   1716     # First, look in the user provided directory, if given
   1717     if (defined env($local_config_envname)) {
   1718         @build_file_templates =
   1719             map {
   1720                 if ($^O eq 'VMS') {
   1721                     # VMS environment variables are logical names,
   1722                     # which can be used as is
   1723                     $local_config_envname . ':' . $_;
   1724                 } else {
   1725                     catfile(env($local_config_envname), $_);
   1726                 }
   1727             }
   1728             @build_file_template_names;
   1729     }
   1730     # Then, look in our standard directory
   1731     push @build_file_templates,
   1732         ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
   1733           @build_file_template_names );
   1734 
   1735     my $build_file_template;
   1736     for $_ (@build_file_templates) {
   1737         $build_file_template = $_;
   1738         last if -f $build_file_template;
   1739 
   1740         $build_file_template = undef;
   1741     }
   1742     if (!defined $build_file_template) {
   1743         die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
   1744     }
   1745     $config{build_file_templates}
   1746       = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
   1747                     $blddir),
   1748           $build_file_template,
   1749           cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
   1750                     $blddir) ];
   1751 
   1752     my @build_infos = ( [ ".", "build.info" ] );
   1753     foreach (@{$config{dirs}}) {
   1754         push @build_infos, [ $_, "build.info" ]
   1755             if (-f catfile($srcdir, $_, "build.info"));
   1756     }
   1757     foreach (@{$config{sdirs}}) {
   1758         push @build_infos, [ catdir("crypto", $_), "build.info" ]
   1759             if (-f catfile($srcdir, "crypto", $_, "build.info"));
   1760     }
   1761     foreach (@{$config{engdirs}}) {
   1762         push @build_infos, [ catdir("engines", $_), "build.info" ]
   1763             if (-f catfile($srcdir, "engines", $_, "build.info"));
   1764     }
   1765     foreach (@{$config{tdirs}}) {
   1766         push @build_infos, [ catdir("test", $_), "build.info" ]
   1767             if (-f catfile($srcdir, "test", $_, "build.info"));
   1768     }
   1769 
   1770     $config{build_infos} = [ ];
   1771 
   1772     my %ordinals = ();
   1773     foreach (@build_infos) {
   1774         my $sourced = catdir($srcdir, $_->[0]);
   1775         my $buildd = catdir($blddir, $_->[0]);
   1776 
   1777         mkpath($buildd);
   1778 
   1779         my $f = $_->[1];
   1780         # The basic things we're trying to build
   1781         my @programs = ();
   1782         my @programs_install = ();
   1783         my @libraries = ();
   1784         my @libraries_install = ();
   1785         my @engines = ();
   1786         my @engines_install = ();
   1787         my @scripts = ();
   1788         my @scripts_install = ();
   1789         my @extra = ();
   1790         my @overrides = ();
   1791         my @intermediates = ();
   1792         my @rawlines = ();
   1793 
   1794         my %sources = ();
   1795         my %shared_sources = ();
   1796         my %includes = ();
   1797         my %depends = ();
   1798         my %renames = ();
   1799         my %sharednames = ();
   1800         my %generate = ();
   1801 
   1802         # We want to detect configdata.pm in the source tree, so we
   1803         # don't use it if the build tree is different.
   1804         my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
   1805 
   1806         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
   1807         my $template =
   1808             Text::Template->new(TYPE => 'FILE',
   1809                                 SOURCE => catfile($sourced, $f),
   1810                                 PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
   1811         die "Something went wrong with $sourced/$f: $!\n" unless $template;
   1812         my @text =
   1813             split /^/m,
   1814             $template->fill_in(HASH => { config => \%config,
   1815                                          target => \%target,
   1816                                          disabled => \%disabled,
   1817                                          withargs => \%withargs,
   1818                                          builddir => abs2rel($buildd, $blddir),
   1819                                          sourcedir => abs2rel($sourced, $blddir),
   1820                                          buildtop => abs2rel($blddir, $blddir),
   1821                                          sourcetop => abs2rel($srcdir, $blddir) },
   1822                                DELIMITERS => [ "{-", "-}" ]);
   1823 
   1824         # The top item of this stack has the following values
   1825         # -2 positive already run and we found ELSE (following ELSIF should fail)
   1826         # -1 positive already run (skip until ENDIF)
   1827         # 0 negatives so far (if we're at a condition, check it)
   1828         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
   1829         # 2 positive ELSE (following ELSIF should fail)
   1830         my @skip = ();
   1831         collect_information(
   1832             collect_from_array([ @text ],
   1833                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
   1834                                                 $l1 =~ s/\\$//; $l1.$l2 }),
   1835             # Info we're looking for
   1836             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
   1837             => sub {
   1838                 if (! @skip || $skip[$#skip] > 0) {
   1839                     push @skip, !! $1;
   1840                 } else {
   1841                     push @skip, -1;
   1842                 }
   1843             },
   1844             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
   1845             => sub { die "ELSIF out of scope" if ! @skip;
   1846                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
   1847                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
   1848                      $skip[$#skip] = !! $1
   1849                          if $skip[$#skip] == 0; },
   1850             qr/^\s*ELSE\s*$/
   1851             => sub { die "ELSE out of scope" if ! @skip;
   1852                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
   1853                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
   1854             qr/^\s*ENDIF\s*$/
   1855             => sub { die "ENDIF out of scope" if ! @skip;
   1856                      pop @skip; },
   1857             qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
   1858             => sub {
   1859                 if (!@skip || $skip[$#skip] > 0) {
   1860                     my $install = $1;
   1861                     my @x = tokenize($2);
   1862                     push @programs, @x;
   1863                     push @programs_install, @x unless $install;
   1864                 }
   1865             },
   1866             qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
   1867             => sub {
   1868                 if (!@skip || $skip[$#skip] > 0) {
   1869                     my $install = $1;
   1870                     my @x = tokenize($2);
   1871                     push @libraries, @x;
   1872                     push @libraries_install, @x unless $install;
   1873                 }
   1874             },
   1875             qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
   1876             => sub {
   1877                 if (!@skip || $skip[$#skip] > 0) {
   1878                     my $install = $1;
   1879                     my @x = tokenize($2);
   1880                     push @engines, @x;
   1881                     push @engines_install, @x unless $install;
   1882                 }
   1883             },
   1884             qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
   1885             => sub {
   1886                 if (!@skip || $skip[$#skip] > 0) {
   1887                     my $install = $1;
   1888                     my @x = tokenize($2);
   1889                     push @scripts, @x;
   1890                     push @scripts_install, @x unless $install;
   1891                 }
   1892             },
   1893             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
   1894             => sub { push @extra, tokenize($1)
   1895                          if !@skip || $skip[$#skip] > 0 },
   1896             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
   1897             => sub { push @overrides, tokenize($1)
   1898                          if !@skip || $skip[$#skip] > 0 },
   1899 
   1900             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
   1901             => sub { push @{$ordinals{$1}}, tokenize($2)
   1902                          if !@skip || $skip[$#skip] > 0 },
   1903             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1904             => sub { push @{$sources{$1}}, tokenize($2)
   1905                          if !@skip || $skip[$#skip] > 0 },
   1906             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1907             => sub { push @{$shared_sources{$1}}, tokenize($2)
   1908                          if !@skip || $skip[$#skip] > 0 },
   1909             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1910             => sub { push @{$includes{$1}}, tokenize($2)
   1911                          if !@skip || $skip[$#skip] > 0 },
   1912             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
   1913             => sub { push @{$depends{$1}}, tokenize($2)
   1914                          if !@skip || $skip[$#skip] > 0 },
   1915             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1916             => sub { push @{$generate{$1}}, $2
   1917                          if !@skip || $skip[$#skip] > 0 },
   1918             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1919             => sub { push @{$renames{$1}}, tokenize($2)
   1920                          if !@skip || $skip[$#skip] > 0 },
   1921             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
   1922             => sub { push @{$sharednames{$1}}, tokenize($2)
   1923                          if !@skip || $skip[$#skip] > 0 },
   1924             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
   1925             => sub {
   1926                 my $lineiterator = shift;
   1927                 my $target_kind = $1;
   1928                 while (defined $lineiterator->()) {
   1929                     s|\R$||;
   1930                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
   1931                         die "ENDRAW doesn't match BEGINRAW"
   1932                             if $1 ne $target_kind;
   1933                         last;
   1934                     }
   1935                     next if @skip && $skip[$#skip] <= 0;
   1936                     push @rawlines,  $_
   1937                         if ($target_kind eq $target{build_file}
   1938                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
   1939                 }
   1940             },
   1941             qr/^\s*(?:#.*)?$/ => sub { },
   1942             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
   1943             "BEFORE" => sub {
   1944                 if ($buildinfo_debug) {
   1945                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
   1946                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
   1947                 }
   1948             },
   1949             "AFTER" => sub {
   1950                 if ($buildinfo_debug) {
   1951                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
   1952                 }
   1953             },
   1954             );
   1955         die "runaway IF?" if (@skip);
   1956 
   1957         foreach (keys %renames) {
   1958             die "$_ renamed to more than one thing: "
   1959                 ,join(" ", @{$renames{$_}}),"\n"
   1960                 if scalar @{$renames{$_}} > 1;
   1961             my $dest = cleanfile($buildd, $_, $blddir);
   1962             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
   1963             die "$dest renamed to more than one thing: "
   1964                 ,$unified_info{rename}->{$dest}, $to
   1965                 unless !defined($unified_info{rename}->{$dest})
   1966                 or $unified_info{rename}->{$dest} eq $to;
   1967             $unified_info{rename}->{$dest} = $to;
   1968         }
   1969 
   1970         foreach (@programs) {
   1971             my $program = cleanfile($buildd, $_, $blddir);
   1972             if ($unified_info{rename}->{$program}) {
   1973                 $program = $unified_info{rename}->{$program};
   1974             }
   1975             $unified_info{programs}->{$program} = 1;
   1976         }
   1977 
   1978         foreach (@programs_install) {
   1979             my $program = cleanfile($buildd, $_, $blddir);
   1980             if ($unified_info{rename}->{$program}) {
   1981                 $program = $unified_info{rename}->{$program};
   1982             }
   1983             $unified_info{install}->{programs}->{$program} = 1;
   1984         }
   1985 
   1986         foreach (@libraries) {
   1987             my $library = cleanfile($buildd, $_, $blddir);
   1988             if ($unified_info{rename}->{$library}) {
   1989                 $library = $unified_info{rename}->{$library};
   1990             }
   1991             $unified_info{libraries}->{$library} = 1;
   1992         }
   1993 
   1994         foreach (@libraries_install) {
   1995             my $library = cleanfile($buildd, $_, $blddir);
   1996             if ($unified_info{rename}->{$library}) {
   1997                 $library = $unified_info{rename}->{$library};
   1998             }
   1999             $unified_info{install}->{libraries}->{$library} = 1;
   2000         }
   2001 
   2002         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
   2003 ENGINES can only be used if configured with 'dynamic-engine'.
   2004 This is usually a fault in a build.info file.
   2005 EOF
   2006         foreach (@engines) {
   2007             my $library = cleanfile($buildd, $_, $blddir);
   2008             if ($unified_info{rename}->{$library}) {
   2009                 $library = $unified_info{rename}->{$library};
   2010             }
   2011             $unified_info{engines}->{$library} = 1;
   2012         }
   2013 
   2014         foreach (@engines_install) {
   2015             my $library = cleanfile($buildd, $_, $blddir);
   2016             if ($unified_info{rename}->{$library}) {
   2017                 $library = $unified_info{rename}->{$library};
   2018             }
   2019             $unified_info{install}->{engines}->{$library} = 1;
   2020         }
   2021 
   2022         foreach (@scripts) {
   2023             my $script = cleanfile($buildd, $_, $blddir);
   2024             if ($unified_info{rename}->{$script}) {
   2025                 $script = $unified_info{rename}->{$script};
   2026             }
   2027             $unified_info{scripts}->{$script} = 1;
   2028         }
   2029 
   2030         foreach (@scripts_install) {
   2031             my $script = cleanfile($buildd, $_, $blddir);
   2032             if ($unified_info{rename}->{$script}) {
   2033                 $script = $unified_info{rename}->{$script};
   2034             }
   2035             $unified_info{install}->{scripts}->{$script} = 1;
   2036         }
   2037 
   2038         foreach (@extra) {
   2039             my $extra = cleanfile($buildd, $_, $blddir);
   2040             $unified_info{extra}->{$extra} = 1;
   2041         }
   2042 
   2043         foreach (@overrides) {
   2044             my $override = cleanfile($buildd, $_, $blddir);
   2045             $unified_info{overrides}->{$override} = 1;
   2046         }
   2047 
   2048         push @{$unified_info{rawlines}}, @rawlines;
   2049 
   2050         unless ($disabled{shared}) {
   2051             # Check sharednames.
   2052             foreach (keys %sharednames) {
   2053                 my $dest = cleanfile($buildd, $_, $blddir);
   2054                 if ($unified_info{rename}->{$dest}) {
   2055                     $dest = $unified_info{rename}->{$dest};
   2056                 }
   2057                 die "shared_name for $dest with multiple values: "
   2058                     ,join(" ", @{$sharednames{$_}}),"\n"
   2059                     if scalar @{$sharednames{$_}} > 1;
   2060                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
   2061                 die "shared_name found for a library $dest that isn't defined\n"
   2062                     unless $unified_info{libraries}->{$dest};
   2063                 die "shared_name for $dest with multiple values: "
   2064                     ,$unified_info{sharednames}->{$dest}, ", ", $to
   2065                     unless !defined($unified_info{sharednames}->{$dest})
   2066                     or $unified_info{sharednames}->{$dest} eq $to;
   2067                 $unified_info{sharednames}->{$dest} = $to;
   2068             }
   2069 
   2070             # Additionally, we set up sharednames for libraries that don't
   2071             # have any, as themselves.  Only for libraries that aren't
   2072             # explicitly static.
   2073             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
   2074                 if (!defined $unified_info{sharednames}->{$_}) {
   2075                     $unified_info{sharednames}->{$_} = $_
   2076                 }
   2077             }
   2078 
   2079             # Check that we haven't defined any library as both shared and
   2080             # explicitly static.  That is forbidden.
   2081             my @doubles = ();
   2082             foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
   2083                 (my $l = $_) =~ s/\.a$//;
   2084                 push @doubles, $l if defined $unified_info{sharednames}->{$l};
   2085             }
   2086             die "these libraries are both explicitly static and shared:\n  ",
   2087                 join(" ", @doubles), "\n"
   2088                 if @doubles;
   2089         }
   2090 
   2091         foreach (keys %sources) {
   2092             my $dest = $_;
   2093             my $ddest = cleanfile($buildd, $_, $blddir);
   2094             if ($unified_info{rename}->{$ddest}) {
   2095                 $ddest = $unified_info{rename}->{$ddest};
   2096             }
   2097             foreach (@{$sources{$dest}}) {
   2098                 my $s = cleanfile($sourced, $_, $blddir);
   2099 
   2100                 # If it isn't in the source tree, we assume it's generated
   2101                 # in the build tree
   2102                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
   2103                     $s = cleanfile($buildd, $_, $blddir);
   2104                 }
   2105                 # We recognise C++, C and asm files
   2106                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
   2107                     my $o = $_;
   2108                     $o =~ s/\.[csS]$/.o/; # C and assembler
   2109                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
   2110                     $o = cleanfile($buildd, $o, $blddir);
   2111                     $unified_info{sources}->{$ddest}->{$o} = 1;
   2112                     $unified_info{sources}->{$o}->{$s} = 1;
   2113                 } elsif ($s =~ /\.rc$/) {
   2114                     # We also recognise resource files
   2115                     my $o = $_;
   2116                     $o =~ s/\.rc$/.res/; # Resource configuration
   2117                     my $o = cleanfile($buildd, $o, $blddir);
   2118                     $unified_info{sources}->{$ddest}->{$o} = 1;
   2119                     $unified_info{sources}->{$o}->{$s} = 1;
   2120                 } else {
   2121                     $unified_info{sources}->{$ddest}->{$s} = 1;
   2122                 }
   2123             }
   2124         }
   2125 
   2126         foreach (keys %shared_sources) {
   2127             my $dest = $_;
   2128             my $ddest = cleanfile($buildd, $_, $blddir);
   2129             if ($unified_info{rename}->{$ddest}) {
   2130                 $ddest = $unified_info{rename}->{$ddest};
   2131             }
   2132             foreach (@{$shared_sources{$dest}}) {
   2133                 my $s = cleanfile($sourced, $_, $blddir);
   2134 
   2135                 # If it isn't in the source tree, we assume it's generated
   2136                 # in the build tree
   2137                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
   2138                     $s = cleanfile($buildd, $_, $blddir);
   2139                 }
   2140 
   2141                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
   2142                     # We recognise C++, C and asm files
   2143                     my $o = $_;
   2144                     $o =~ s/\.[csS]$/.o/; # C and assembler
   2145                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
   2146                     $o = cleanfile($buildd, $o, $blddir);
   2147                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
   2148                     $unified_info{sources}->{$o}->{$s} = 1;
   2149                 } elsif ($s =~ /\.rc$/) {
   2150                     # We also recognise resource files
   2151                     my $o = $_;
   2152                     $o =~ s/\.rc$/.res/; # Resource configuration
   2153                     my $o = cleanfile($buildd, $o, $blddir);
   2154                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
   2155                     $unified_info{sources}->{$o}->{$s} = 1;
   2156                 } elsif ($s =~ /\.(def|map|opt)$/) {
   2157                     # We also recognise .def / .map / .opt files
   2158                     # We know they are generated files
   2159                     my $def = cleanfile($buildd, $s, $blddir);
   2160                     $unified_info{shared_sources}->{$ddest}->{$def} = 1;
   2161                 } else {
   2162                     die "unrecognised source file type for shared library: $s\n";
   2163                 }
   2164             }
   2165         }
   2166 
   2167         foreach (keys %generate) {
   2168             my $dest = $_;
   2169             my $ddest = cleanfile($buildd, $_, $blddir);
   2170             if ($unified_info{rename}->{$ddest}) {
   2171                 $ddest = $unified_info{rename}->{$ddest};
   2172             }
   2173             die "more than one generator for $dest: "
   2174                     ,join(" ", @{$generate{$_}}),"\n"
   2175                     if scalar @{$generate{$_}} > 1;
   2176             my @generator = split /\s+/, $generate{$dest}->[0];
   2177             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
   2178             $unified_info{generate}->{$ddest} = [ @generator ];
   2179         }
   2180 
   2181         foreach (keys %depends) {
   2182             my $dest = $_;
   2183             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
   2184 
   2185             # If the destination doesn't exist in source, it can only be
   2186             # a generated file in the build tree.
   2187             if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) {
   2188                 $ddest = cleanfile($buildd, $_, $blddir);
   2189                 if ($unified_info{rename}->{$ddest}) {
   2190                     $ddest = $unified_info{rename}->{$ddest};
   2191                 }
   2192             }
   2193             foreach (@{$depends{$dest}}) {
   2194                 my $d = cleanfile($sourced, $_, $blddir);
   2195 
   2196                 # If we know it's generated, or assume it is because we can't
   2197                 # find it in the source tree, we set file we depend on to be
   2198                 # in the build tree rather than the source tree, and assume
   2199                 # and that there are lines to build it in a BEGINRAW..ENDRAW
   2200                 # section or in the Makefile template.
   2201                 if ($d eq $src_configdata
   2202                     || ! -f $d
   2203                     || (grep { $d eq $_ }
   2204                         map { cleanfile($srcdir, $_, $blddir) }
   2205                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
   2206                     $d = cleanfile($buildd, $_, $blddir);
   2207                 }
   2208                 # Take note if the file to depend on is being renamed
   2209                 # Take extra care with files ending with .a, they should
   2210                 # be treated without that extension, and the extension
   2211                 # should be added back after treatment.
   2212                 $d =~ /(\.a)?$/;
   2213                 my $e = $1 // "";
   2214                 $d = $`;
   2215                 if ($unified_info{rename}->{$d}) {
   2216                     $d = $unified_info{rename}->{$d};
   2217                 }
   2218                 $d .= $e;
   2219                 $unified_info{depends}->{$ddest}->{$d} = 1;
   2220             }
   2221         }
   2222 
   2223         foreach (keys %includes) {
   2224             my $dest = $_;
   2225             my $ddest = cleanfile($sourced, $_, $blddir);
   2226 
   2227             # If the destination doesn't exist in source, it can only be
   2228             # a generated file in the build tree.
   2229             if ($ddest eq $src_configdata || ! -f $ddest) {
   2230                 $ddest = cleanfile($buildd, $_, $blddir);
   2231                 if ($unified_info{rename}->{$ddest}) {
   2232                     $ddest = $unified_info{rename}->{$ddest};
   2233                 }
   2234             }
   2235             foreach (@{$includes{$dest}}) {
   2236                 my $is = cleandir($sourced, $_, $blddir);
   2237                 my $ib = cleandir($buildd, $_, $blddir);
   2238                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
   2239                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
   2240                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
   2241                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
   2242             }
   2243         }
   2244     }
   2245 
   2246     my $ordinals_text = join(', ', sort keys %ordinals);
   2247     warn <<"EOF" if $ordinals_text;
   2248 
   2249 WARNING: ORDINALS were specified for $ordinals_text
   2250 They are ignored and should be replaced with a combination of GENERATE,
   2251 DEPEND and SHARED_SOURCE.
   2252 EOF
   2253 
   2254     # Massage the result
   2255 
   2256     # If the user configured no-shared, we allow no shared sources
   2257     if ($disabled{shared}) {
   2258         foreach (keys %{$unified_info{shared_sources}}) {
   2259             foreach (keys %{$unified_info{shared_sources}->{$_}}) {
   2260                 delete $unified_info{sources}->{$_};
   2261             }
   2262         }
   2263         $unified_info{shared_sources} = {};
   2264     }
   2265 
   2266     # If we depend on a header file or a perl module, add an inclusion of
   2267     # its directory to allow smoothe inclusion
   2268     foreach my $dest (keys %{$unified_info{depends}}) {
   2269         next if $dest eq "";
   2270         foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
   2271             next unless $d =~ /\.(h|pm)$/;
   2272             my $i = dirname($d);
   2273             my $spot =
   2274                 $d eq "configdata.pm" || defined($unified_info{generate}->{$d})
   2275                 ? 'build' : 'source';
   2276             push @{$unified_info{includes}->{$dest}->{$spot}}, $i
   2277                 unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
   2278         }
   2279     }
   2280 
   2281     # Trickle down includes placed on libraries, engines and programs to
   2282     # their sources (i.e. object files)
   2283     foreach my $dest (keys %{$unified_info{engines}},
   2284                       keys %{$unified_info{libraries}},
   2285                       keys %{$unified_info{programs}}) {
   2286         foreach my $k (("source", "build")) {
   2287             next unless defined($unified_info{includes}->{$dest}->{$k});
   2288             my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
   2289             foreach my $obj (grep /\.o$/,
   2290                              (keys %{$unified_info{sources}->{$dest} // {}},
   2291                               keys %{$unified_info{shared_sources}->{$dest} // {}})) {
   2292                 foreach my $inc (@incs) {
   2293                     unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
   2294                         unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
   2295                 }
   2296             }
   2297         }
   2298         delete $unified_info{includes}->{$dest};
   2299     }
   2300 
   2301     ### Make unified_info a bit more efficient
   2302     # One level structures
   2303     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
   2304         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
   2305     }
   2306     # Two level structures
   2307     foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
   2308         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
   2309             $unified_info{$l1}->{$l2} =
   2310                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
   2311         }
   2312     }
   2313     # Includes
   2314     foreach my $dest (sort keys %{$unified_info{includes}}) {
   2315         if (defined($unified_info{includes}->{$dest}->{build})) {
   2316             my @source_includes = ();
   2317             @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
   2318                 if defined($unified_info{includes}->{$dest}->{source});
   2319             $unified_info{includes}->{$dest} =
   2320                 [ @{$unified_info{includes}->{$dest}->{build}} ];
   2321             foreach my $inc (@source_includes) {
   2322                 push @{$unified_info{includes}->{$dest}}, $inc
   2323                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
   2324             }
   2325         } else {
   2326             $unified_info{includes}->{$dest} =
   2327                 [ @{$unified_info{includes}->{$dest}->{source}} ];
   2328         }
   2329     }
   2330 
   2331     # For convenience collect information regarding directories where
   2332     # files are generated, those generated files and the end product
   2333     # they end up in where applicable.  Then, add build rules for those
   2334     # directories
   2335     my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
   2336                      "dso" => [ @{$unified_info{engines}} ],
   2337                      "bin" => [ @{$unified_info{programs}} ],
   2338                      "script" => [ @{$unified_info{scripts}} ] );
   2339     foreach my $type (keys %loopinfo) {
   2340         foreach my $product (@{$loopinfo{$type}}) {
   2341             my %dirs = ();
   2342             my $pd = dirname($product);
   2343 
   2344             foreach (@{$unified_info{sources}->{$product} // []},
   2345                      @{$unified_info{shared_sources}->{$product} // []}) {
   2346                 my $d = dirname($_);
   2347 
   2348                 # We don't want to create targets for source directories
   2349                 # when building out of source
   2350                 next if ($config{sourcedir} ne $config{builddir}
   2351                              && $d =~ m|^\Q$config{sourcedir}\E|);
   2352                 # We already have a "test" target, and the current directory
   2353                 # is just silly to make a target for
   2354                 next if $d eq "test" || $d eq ".";
   2355 
   2356                 $dirs{$d} = 1;
   2357                 push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
   2358                     if $d ne $pd;
   2359             }
   2360             foreach (keys %dirs) {
   2361                 push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
   2362                     $product;
   2363             }
   2364         }
   2365     }
   2366 }
   2367 
   2368 # For the schemes that need it, we provide the old *_obj configs
   2369 # from the *_asm_obj ones
   2370 foreach (grep /_(asm|aux)_src$/, keys %target) {
   2371     my $src = $_;
   2372     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
   2373     $target{$obj} = $target{$src};
   2374     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
   2375     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
   2376 }
   2377 
   2378 # Write down our configuration where it fits #########################
   2379 
   2380 print "Creating configdata.pm\n";
   2381 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
   2382 print OUT <<"EOF";
   2383 #! $config{HASHBANGPERL}
   2384 
   2385 package configdata;
   2386 
   2387 use strict;
   2388 use warnings;
   2389 
   2390 use Exporter;
   2391 #use vars qw(\@ISA \@EXPORT);
   2392 our \@ISA = qw(Exporter);
   2393 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
   2394 
   2395 EOF
   2396 print OUT "our %config = (\n";
   2397 foreach (sort keys %config) {
   2398     if (ref($config{$_}) eq "ARRAY") {
   2399         print OUT "  ", $_, " => [ ", join(", ",
   2400                                            map { quotify("perl", $_) }
   2401                                            @{$config{$_}}), " ],\n";
   2402     } elsif (ref($config{$_}) eq "HASH") {
   2403         print OUT "  ", $_, " => {";
   2404         if (scalar keys %{$config{$_}} > 0) {
   2405             print OUT "\n";
   2406             foreach my $key (sort keys %{$config{$_}}) {
   2407                 print OUT "      ",
   2408                     join(" => ",
   2409                          quotify("perl", $key),
   2410                          defined $config{$_}->{$key}
   2411                              ? quotify("perl", $config{$_}->{$key})
   2412                              : "undef");
   2413                 print OUT ",\n";
   2414             }
   2415             print OUT "  ";
   2416         }
   2417         print OUT "},\n";
   2418     } else {
   2419         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
   2420     }
   2421 }
   2422 print OUT <<"EOF";
   2423 );
   2424 
   2425 EOF
   2426 print OUT "our %target = (\n";
   2427 foreach (sort keys %target) {
   2428     if (ref($target{$_}) eq "ARRAY") {
   2429         print OUT "  ", $_, " => [ ", join(", ",
   2430                                            map { quotify("perl", $_) }
   2431                                            @{$target{$_}}), " ],\n";
   2432     } else {
   2433         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
   2434     }
   2435 }
   2436 print OUT <<"EOF";
   2437 );
   2438 
   2439 EOF
   2440 print OUT "our \%available_protocols = (\n";
   2441 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
   2442 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
   2443 print OUT <<"EOF";
   2444 );
   2445 
   2446 EOF
   2447 print OUT "our \@disablables = (\n";
   2448 foreach (@disablables) {
   2449     print OUT "  ", quotify("perl", $_), ",\n";
   2450 }
   2451 print OUT <<"EOF";
   2452 );
   2453 
   2454 EOF
   2455 print OUT "our \%disabled = (\n";
   2456 foreach (sort keys %disabled) {
   2457     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
   2458 }
   2459 print OUT <<"EOF";
   2460 );
   2461 
   2462 EOF
   2463 print OUT "our %withargs = (\n";
   2464 foreach (sort keys %withargs) {
   2465     if (ref($withargs{$_}) eq "ARRAY") {
   2466         print OUT "  ", $_, " => [ ", join(", ",
   2467                                            map { quotify("perl", $_) }
   2468                                            @{$withargs{$_}}), " ],\n";
   2469     } else {
   2470         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
   2471     }
   2472 }
   2473 print OUT <<"EOF";
   2474 );
   2475 
   2476 EOF
   2477 if ($builder eq "unified") {
   2478     my $recurse;
   2479     $recurse = sub {
   2480         my $indent = shift;
   2481         foreach (@_) {
   2482             if (ref $_ eq "ARRAY") {
   2483                 print OUT " "x$indent, "[\n";
   2484                 foreach (@$_) {
   2485                     $recurse->($indent + 4, $_);
   2486                 }
   2487                 print OUT " "x$indent, "],\n";
   2488             } elsif (ref $_ eq "HASH") {
   2489                 my %h = %$_;
   2490                 print OUT " "x$indent, "{\n";
   2491                 foreach (sort keys %h) {
   2492                     if (ref $h{$_} eq "") {
   2493                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
   2494                     } else {
   2495                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
   2496                         $recurse->($indent + 8, $h{$_});
   2497                     }
   2498                 }
   2499                 print OUT " "x$indent, "},\n";
   2500             } else {
   2501                 print OUT " "x$indent, quotify("perl", $_), ",\n";
   2502             }
   2503         }
   2504     };
   2505     print OUT "our %unified_info = (\n";
   2506     foreach (sort keys %unified_info) {
   2507         if (ref $unified_info{$_} eq "") {
   2508             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
   2509         } else {
   2510             print OUT " "x4, quotify("perl", $_), " =>\n";
   2511             $recurse->(8, $unified_info{$_});
   2512         }
   2513     }
   2514     print OUT <<"EOF";
   2515 );
   2516 
   2517 EOF
   2518 }
   2519 print OUT
   2520     "# The following data is only used when this files is use as a script\n";
   2521 print OUT "my \@makevars = (\n";
   2522 foreach (sort keys %user) {
   2523     print OUT "    '",$_,"',\n";
   2524 }
   2525 print OUT ");\n";
   2526 print OUT "my \%disabled_info = (\n";
   2527 foreach my $what (sort keys %disabled_info) {
   2528     print OUT "    '$what' => {\n";
   2529     foreach my $info (sort keys %{$disabled_info{$what}}) {
   2530         if (ref $disabled_info{$what}->{$info} eq 'ARRAY') {
   2531             print OUT "        $info => [ ",
   2532                 join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}),
   2533                 " ],\n";
   2534         } else {
   2535             print OUT "        $info => '", $disabled_info{$what}->{$info},
   2536                 "',\n";
   2537         }
   2538     }
   2539     print OUT "    },\n";
   2540 }
   2541 print OUT ");\n";
   2542 print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n";
   2543 print OUT << 'EOF';
   2544 # If run directly, we can give some answers, and even reconfigure
   2545 unless (caller) {
   2546     use Getopt::Long;
   2547     use File::Spec::Functions;
   2548     use File::Basename;
   2549     use Pod::Usage;
   2550 
   2551     my $here = dirname($0);
   2552 
   2553     my $dump = undef;
   2554     my $cmdline = undef;
   2555     my $options = undef;
   2556     my $target = undef;
   2557     my $envvars = undef;
   2558     my $makevars = undef;
   2559     my $buildparams = undef;
   2560     my $reconf = undef;
   2561     my $verbose = undef;
   2562     my $help = undef;
   2563     my $man = undef;
   2564     GetOptions('dump|d'                 => \$dump,
   2565                'command-line|c'         => \$cmdline,
   2566                'options|o'              => \$options,
   2567                'target|t'               => \$target,
   2568                'environment|e'          => \$envvars,
   2569                'make-variables|m'       => \$makevars,
   2570                'build-parameters|b'     => \$buildparams,
   2571                'reconfigure|reconf|r'   => \$reconf,
   2572                'verbose|v'              => \$verbose,
   2573                'help'                   => \$help,
   2574                'man'                    => \$man)
   2575         or die "Errors in command line arguments\n";
   2576 
   2577     unless ($dump || $cmdline || $options || $target || $envvars || $makevars
   2578             || $buildparams || $reconf || $verbose || $help || $man) {
   2579         print STDERR <<"_____";
   2580 You must give at least one option.
   2581 For more information, do '$0 --help'
   2582 _____
   2583         exit(2);
   2584     }
   2585 
   2586     if ($help) {
   2587         pod2usage(-exitval => 0,
   2588                   -verbose => 1);
   2589     }
   2590     if ($man) {
   2591         pod2usage(-exitval => 0,
   2592                   -verbose => 2);
   2593     }
   2594     if ($dump || $cmdline) {
   2595         print "\nCommand line (with current working directory = $here):\n\n";
   2596         print '    ',join(' ',
   2597                           $config{PERL},
   2598                           catfile($config{sourcedir}, 'Configure'),
   2599                           @{$config{perlargv}}), "\n";
   2600         print "\nPerl information:\n\n";
   2601         print '    ',$config{perl_cmd},"\n";
   2602         print '    ',$config{perl_version},' for ',$config{perl_archname},"\n";
   2603     }
   2604     if ($dump || $options) {
   2605         my $longest = 0;
   2606         my $longest2 = 0;
   2607         foreach my $what (@disablables) {
   2608             $longest = length($what) if $longest < length($what);
   2609             $longest2 = length($disabled{$what})
   2610                 if $disabled{$what} && $longest2 < length($disabled{$what});
   2611         }
   2612         print "\nEnabled features:\n\n";
   2613         foreach my $what (@disablables) {
   2614             print "    $what\n"
   2615                 unless grep { $_ =~ /^${what}$/ } keys %disabled;
   2616         }
   2617         print "\nDisabled features:\n\n";
   2618         foreach my $what (@disablables) {
   2619             my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled;
   2620             my $what3 = $what2[0];
   2621             if ($what3) {
   2622                 print "    $what3", ' ' x ($longest - length($what3) + 1),
   2623                     "[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1);
   2624                 print $disabled_info{$what3}->{macro}
   2625                     if $disabled_info{$what3}->{macro};
   2626                 print ' (skip ',
   2627                     join(', ', @{$disabled_info{$what3}->{skipped}}),
   2628                     ')'
   2629                     if $disabled_info{$what3}->{skipped};
   2630                 print "\n";
   2631             }
   2632         }
   2633     }
   2634     if ($dump || $target) {
   2635         print "\nConfig target attributes:\n\n";
   2636         foreach (sort keys %target) {
   2637             next if $_ =~ m|^_| || $_ eq 'template';
   2638             my $quotify = sub {
   2639                 map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
   2640             };
   2641             print '    ', $_, ' => ';
   2642             if (ref($target{$_}) eq "ARRAY") {
   2643                 print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
   2644             } else {
   2645                 print $quotify->($target{$_}), ",\n"
   2646             }
   2647         }
   2648     }
   2649     if ($dump || $envvars) {
   2650         print "\nRecorded environment:\n\n";
   2651         foreach (sort keys %{$config{perlenv}}) {
   2652             print '    ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
   2653         }
   2654     }
   2655     if ($dump || $makevars) {
   2656         print "\nMakevars:\n\n";
   2657         foreach my $var (@makevars) {
   2658             my $prefix = '';
   2659             $prefix = $config{CROSS_COMPILE}
   2660                 if grep { $var eq $_ } @user_crossable;
   2661             $prefix //= '';
   2662             print '    ',$var,' ' x (16 - length $var),'= ',
   2663                 (ref $config{$var} eq 'ARRAY'
   2664                  ? join(' ', @{$config{$var}})
   2665                  : $prefix.$config{$var}),
   2666                 "\n"
   2667                 if defined $config{$var};
   2668         }
   2669 
   2670         my @buildfile = ($config{builddir}, $config{build_file});
   2671         unshift @buildfile, $here
   2672             unless file_name_is_absolute($config{builddir});
   2673         my $buildfile = canonpath(catdir(@buildfile));
   2674         print <<"_____";
   2675 
   2676 NOTE: These variables only represent the configuration view.  The build file
   2677 template may have processed these variables further, please have a look at the
   2678 build file for more exact data:
   2679     $buildfile
   2680 _____
   2681     }
   2682     if ($dump || $buildparams) {
   2683         my @buildfile = ($config{builddir}, $config{build_file});
   2684         unshift @buildfile, $here
   2685             unless file_name_is_absolute($config{builddir});
   2686         print "\nbuild file:\n\n";
   2687         print "    ", canonpath(catfile(@buildfile)),"\n";
   2688 
   2689         print "\nbuild file templates:\n\n";
   2690         foreach (@{$config{build_file_templates}}) {
   2691             my @tmpl = ($_);
   2692             unshift @tmpl, $here
   2693                 unless file_name_is_absolute($config{sourcedir});
   2694             print '    ',canonpath(catfile(@tmpl)),"\n";
   2695         }
   2696     }
   2697     if ($reconf) {
   2698         if ($verbose) {
   2699             print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
   2700             foreach (sort keys %{$config{perlenv}}) {
   2701                 print '    ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
   2702             }
   2703         }
   2704 
   2705         chdir $here;
   2706         exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
   2707     }
   2708 }
   2709 
   2710 1;
   2711 
   2712 __END__
   2713 
   2714 =head1 NAME
   2715 
   2716 configdata.pm - configuration data for OpenSSL builds
   2717 
   2718 =head1 SYNOPSIS
   2719 
   2720 Interactive:
   2721 
   2722   perl configdata.pm [options]
   2723 
   2724 As data bank module:
   2725 
   2726   use configdata;
   2727 
   2728 =head1 DESCRIPTION
   2729 
   2730 This module can be used in two modes, interactively and as a module containing
   2731 all the data recorded by OpenSSL's Configure script.
   2732 
   2733 When used interactively, simply run it as any perl script, with at least one
   2734 option, and you will get the information you ask for.  See L</OPTIONS> below.
   2735 
   2736 When loaded as a module, you get a few databanks with useful information to
   2737 perform build related tasks.  The databanks are:
   2738 
   2739     %config             Configured things.
   2740     %target             The OpenSSL config target with all inheritances
   2741                         resolved.
   2742     %disabled           The features that are disabled.
   2743     @disablables        The list of features that can be disabled.
   2744     %withargs           All data given through --with-THING options.
   2745     %unified_info       All information that was computed from the build.info
   2746                         files.
   2747 
   2748 =head1 OPTIONS
   2749 
   2750 =over 4
   2751 
   2752 =item B<--help>
   2753 
   2754 Print a brief help message and exit.
   2755 
   2756 =item B<--man>
   2757 
   2758 Print the manual page and exit.
   2759 
   2760 =item B<--dump> | B<-d>
   2761 
   2762 Print all relevant configuration data.  This is equivalent to B<--command-line>
   2763 B<--options> B<--target> B<--environment> B<--make-variables>
   2764 B<--build-parameters>.
   2765 
   2766 =item B<--command-line> | B<-c>
   2767 
   2768 Print the current configuration command line.
   2769 
   2770 =item B<--options> | B<-o>
   2771 
   2772 Print the features, both enabled and disabled, and display defined macro and
   2773 skipped directories where applicable.
   2774 
   2775 =item B<--target> | B<-t>
   2776 
   2777 Print the config attributes for this config target.
   2778 
   2779 =item B<--environment> | B<-e>
   2780 
   2781 Print the environment variables and their values at the time of configuration.
   2782 
   2783 =item B<--make-variables> | B<-m>
   2784 
   2785 Print the main make variables generated in the current configuration
   2786 
   2787 =item B<--build-parameters> | B<-b>
   2788 
   2789 Print the build parameters, i.e. build file and build file templates.
   2790 
   2791 =item B<--reconfigure> | B<--reconf> | B<-r>
   2792 
   2793 Redo the configuration.
   2794 
   2795 =item B<--verbose> | B<-v>
   2796 
   2797 Verbose output.
   2798 
   2799 =back
   2800 
   2801 =cut
   2802 
   2803 EOF
   2804 close(OUT);
   2805 if ($builder_platform eq 'unix') {
   2806     my $mode = (0755 & ~umask);
   2807     chmod $mode, 'configdata.pm'
   2808         or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
   2809 }
   2810 
   2811 my %builders = (
   2812     unified => sub {
   2813         print 'Creating ',$target{build_file},"\n";
   2814         run_dofile(catfile($blddir, $target{build_file}),
   2815                    @{$config{build_file_templates}});
   2816     },
   2817     );
   2818 
   2819 $builders{$builder}->($builder_platform, @builder_opts);
   2820 
   2821 $SIG{__DIE__} = $orig_death_handler;
   2822 
   2823 print <<"EOF" if ($disabled{threads} eq "unavailable");
   2824 
   2825 The library could not be configured for supporting multi-threaded
   2826 applications as the compiler options required on this system are not known.
   2827 See file INSTALL for details if you need multi-threading.
   2828 EOF
   2829 
   2830 print <<"EOF" if ($no_shared_warn);
   2831 
   2832 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
   2833 platform, so we will pretend you gave the option 'no-pic', which also disables
   2834 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
   2835 or position independent code, please let us know (but please first make sure
   2836 you have tried with a current version of OpenSSL).
   2837 EOF
   2838 
   2839 print <<"EOF";
   2840 
   2841 **********************************************************************
   2842 ***                                                                ***
   2843 ***   OpenSSL has been successfully configured                     ***
   2844 ***                                                                ***
   2845 ***   If you encounter a problem while building, please open an    ***
   2846 ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
   2847 ***   and include the output from the following command:           ***
   2848 ***                                                                ***
   2849 ***       perl configdata.pm --dump                                ***
   2850 ***                                                                ***
   2851 ***   (If you are new to OpenSSL, you might want to consult the    ***
   2852 ***   'Troubleshooting' section in the INSTALL file first)         ***
   2853 ***                                                                ***
   2854 **********************************************************************
   2855 EOF
   2856 
   2857 exit(0);
   2858 
   2859 ######################################################################
   2860 #
   2861 # Helpers and utility functions
   2862 #
   2863 
   2864 # Death handler, to print a helpful message in case of failure #######
   2865 #
   2866 sub death_handler {
   2867     die @_ if $^S;              # To prevent the added message in eval blocks
   2868     my $build_file = $target{build_file} // "build file";
   2869     my @message = ( <<"_____", @_ );
   2870 
   2871 Failure!  $build_file wasn't produced.
   2872 Please read INSTALL and associated NOTES files.  You may also have to look over
   2873 your available compiler tool chain or change your configuration.
   2874 
   2875 _____
   2876 
   2877     # Dying is terminal, so it's ok to reset the signal handler here.
   2878     $SIG{__DIE__} = $orig_death_handler;
   2879     die @message;
   2880 }
   2881 
   2882 # Configuration file reading #########################################
   2883 
   2884 # Note: All of the helper functions are for lazy evaluation.  They all
   2885 # return a CODE ref, which will return the intended value when evaluated.
   2886 # Thus, whenever there's mention of a returned value, it's about that
   2887 # intended value.
   2888 
   2889 # Helper function to implement conditional inheritance depending on the
   2890 # value of $disabled{asm}.  Used in inherit_from values as follows:
   2891 #
   2892 #      inherit_from => [ "template", asm("asm_tmpl") ]
   2893 #
   2894 sub asm {
   2895     my @x = @_;
   2896     sub {
   2897         $disabled{asm} ? () : @x;
   2898     }
   2899 }
   2900 
   2901 # Helper function to implement conditional value variants, with a default
   2902 # plus additional values based on the value of $config{build_type}.
   2903 # Arguments are given in hash table form:
   2904 #
   2905 #       picker(default => "Basic string: ",
   2906 #              debug   => "debug",
   2907 #              release => "release")
   2908 #
   2909 # When configuring with --debug, the resulting string will be
   2910 # "Basic string: debug", and when not, it will be "Basic string: release"
   2911 #
   2912 # This can be used to create variants of sets of flags according to the
   2913 # build type:
   2914 #
   2915 #       cflags => picker(default => "-Wall",
   2916 #                        debug   => "-g -O0",
   2917 #                        release => "-O3")
   2918 #
   2919 sub picker {
   2920     my %opts = @_;
   2921     return sub { add($opts{default} || (),
   2922                      $opts{$config{build_type}} || ())->(); }
   2923 }
   2924 
   2925 # Helper function to combine several values of different types into one.
   2926 # This is useful if you want to combine a string with the result of a
   2927 # lazy function, such as:
   2928 #
   2929 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
   2930 #
   2931 sub combine {
   2932     my @stuff = @_;
   2933     return sub { add(@stuff)->(); }
   2934 }
   2935 
   2936 # Helper function to implement conditional values depending on the value
   2937 # of $disabled{threads}.  Can be used as follows:
   2938 #
   2939 #       cflags => combine("-Wall", threads("-pthread"))
   2940 #
   2941 sub threads {
   2942     my @flags = @_;
   2943     return sub { add($disabled{threads} ? () : @flags)->(); }
   2944 }
   2945 
   2946 sub shared {
   2947     my @flags = @_;
   2948     return sub { add($disabled{shared} ? () : @flags)->(); }
   2949 }
   2950 
   2951 our $add_called = 0;
   2952 # Helper function to implement adding values to already existing configuration
   2953 # values.  It handles elements that are ARRAYs, CODEs and scalars
   2954 sub _add {
   2955     my $separator = shift;
   2956 
   2957     # If there's any ARRAY in the collection of values OR the separator
   2958     # is undef, we will return an ARRAY of combined values, otherwise a
   2959     # string of joined values with $separator as the separator.
   2960     my $found_array = !defined($separator);
   2961 
   2962     my @values =
   2963         map {
   2964             my $res = $_;
   2965             while (ref($res) eq "CODE") {
   2966                 $res = $res->();
   2967             }
   2968             if (defined($res)) {
   2969                 if (ref($res) eq "ARRAY") {
   2970                     $found_array = 1;
   2971                     @$res;
   2972                 } else {
   2973                     $res;
   2974                 }
   2975             } else {
   2976                 ();
   2977             }
   2978     } (@_);
   2979 
   2980     $add_called = 1;
   2981 
   2982     if ($found_array) {
   2983         [ @values ];
   2984     } else {
   2985         join($separator, grep { defined($_) && $_ ne "" } @values);
   2986     }
   2987 }
   2988 sub add_before {
   2989     my $separator = " ";
   2990     if (ref($_[$#_]) eq "HASH") {
   2991         my $opts = pop;
   2992         $separator = $opts->{separator};
   2993     }
   2994     my @x = @_;
   2995     sub { _add($separator, @x, @_) };
   2996 }
   2997 sub add {
   2998     my $separator = " ";
   2999     if (ref($_[$#_]) eq "HASH") {
   3000         my $opts = pop;
   3001         $separator = $opts->{separator};
   3002     }
   3003     my @x = @_;
   3004     sub { _add($separator, @_, @x) };
   3005 }
   3006 
   3007 sub read_eval_file {
   3008     my $fname = shift;
   3009     my $content;
   3010     my @result;
   3011 
   3012     open F, "< $fname" or die "Can't open '$fname': $!\n";
   3013     {
   3014         undef local $/;
   3015         $content = <F>;
   3016     }
   3017     close F;
   3018     {
   3019         local $@;
   3020 
   3021         @result = ( eval $content );
   3022         warn $@ if $@;
   3023     }
   3024     return wantarray ? @result : $result[0];
   3025 }
   3026 
   3027 # configuration reader, evaluates the input file as a perl script and expects
   3028 # it to fill %targets with target configurations.  Those are then added to
   3029 # %table.
   3030 sub read_config {
   3031     my $fname = shift;
   3032     my %targets;
   3033 
   3034     {
   3035         # Protect certain tables from tampering
   3036         local %table = ();
   3037 
   3038         %targets = read_eval_file($fname);
   3039     }
   3040     my %preexisting = ();
   3041     foreach (sort keys %targets) {
   3042         $preexisting{$_} = 1 if $table{$_};
   3043     }
   3044     die <<"EOF",
   3045 The following config targets from $fname
   3046 shadow pre-existing config targets with the same name:
   3047 EOF
   3048         map { "  $_\n" } sort keys %preexisting
   3049         if %preexisting;
   3050 
   3051 
   3052     # For each target, check that it's configured with a hash table.
   3053     foreach (keys %targets) {
   3054         if (ref($targets{$_}) ne "HASH") {
   3055             if (ref($targets{$_}) eq "") {
   3056                 warn "Deprecated target configuration for $_, ignoring...\n";
   3057             } else {
   3058                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
   3059             }
   3060             delete $targets{$_};
   3061         } else {
   3062             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
   3063         }
   3064     }
   3065 
   3066     %table = (%table, %targets);
   3067 
   3068 }
   3069 
   3070 # configuration resolver.  Will only resolve all the lazy evaluation
   3071 # codeblocks for the chosen target and all those it inherits from,
   3072 # recursively
   3073 sub resolve_config {
   3074     my $target = shift;
   3075     my @breadcrumbs = @_;
   3076 
   3077 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
   3078 
   3079     if (grep { $_ eq $target } @breadcrumbs) {
   3080         die "inherit_from loop!  target backtrace:\n  "
   3081             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
   3082     }
   3083 
   3084     if (!defined($table{$target})) {
   3085         warn "Warning! target $target doesn't exist!\n";
   3086         return ();
   3087     }
   3088     # Recurse through all inheritances.  They will be resolved on the
   3089     # fly, so when this operation is done, they will all just be a
   3090     # bunch of attributes with string values.
   3091     # What we get here, though, are keys with references to lists of
   3092     # the combined values of them all.  We will deal with lists after
   3093     # this stage is done.
   3094     my %combined_inheritance = ();
   3095     if ($table{$target}->{inherit_from}) {
   3096         my @inherit_from =
   3097             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
   3098         foreach (@inherit_from) {
   3099             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
   3100 
   3101             # 'template' is a marker that's considered private to
   3102             # the config that had it.
   3103             delete $inherited_config{template};
   3104 
   3105             foreach (keys %inherited_config) {
   3106                 if (!$combined_inheritance{$_}) {
   3107                     $combined_inheritance{$_} = [];
   3108                 }
   3109                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
   3110             }
   3111         }
   3112     }
   3113 
   3114     # We won't need inherit_from in this target any more, since we've
   3115     # resolved all the inheritances that lead to this
   3116     delete $table{$target}->{inherit_from};
   3117 
   3118     # Now is the time to deal with those lists.  Here's the place to
   3119     # decide what shall be done with those lists, all based on the
   3120     # values of the target we're currently dealing with.
   3121     # - If a value is a coderef, it will be executed with the list of
   3122     #   inherited values as arguments.
   3123     # - If the corresponding key doesn't have a value at all or is the
   3124     #   empty string, the inherited value list will be run through the
   3125     #   default combiner (below), and the result becomes this target's
   3126     #   value.
   3127     # - Otherwise, this target's value is assumed to be a string that
   3128     #   will simply override the inherited list of values.
   3129     my $default_combiner = add();
   3130 
   3131     my %all_keys =
   3132         map { $_ => 1 } (keys %combined_inheritance,
   3133                          keys %{$table{$target}});
   3134 
   3135     sub process_values {
   3136         my $object    = shift;
   3137         my $inherited = shift;  # Always a [ list ]
   3138         my $target    = shift;
   3139         my $entry     = shift;
   3140 
   3141         $add_called = 0;
   3142 
   3143         while(ref($object) eq "CODE") {
   3144             $object = $object->(@$inherited);
   3145         }
   3146         if (!defined($object)) {
   3147             return ();
   3148         }
   3149         elsif (ref($object) eq "ARRAY") {
   3150             local $add_called;  # To make sure recursive calls don't affect it
   3151             return [ map { process_values($_, $inherited, $target, $entry) }
   3152                      @$object ];
   3153         } elsif (ref($object) eq "") {
   3154             return $object;
   3155         } else {
   3156             die "cannot handle reference type ",ref($object)
   3157                 ," found in target ",$target," -> ",$entry,"\n";
   3158         }
   3159     }
   3160 
   3161     foreach (sort keys %all_keys) {
   3162         my $previous = $combined_inheritance{$_};
   3163 
   3164         # Current target doesn't have a value for the current key?
   3165         # Assign it the default combiner, the rest of this loop body
   3166         # will handle it just like any other coderef.
   3167         if (!exists $table{$target}->{$_}) {
   3168             $table{$target}->{$_} = $default_combiner;
   3169         }
   3170 
   3171         $table{$target}->{$_} = process_values($table{$target}->{$_},
   3172                                                $combined_inheritance{$_},
   3173                                                $target, $_);
   3174         unless(defined($table{$target}->{$_})) {
   3175             delete $table{$target}->{$_};
   3176         }
   3177 #        if ($extra_checks &&
   3178 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
   3179 #            warn "$_ got replaced in $target\n";
   3180 #        }
   3181     }
   3182 
   3183     # Finally done, return the result.
   3184     return %{$table{$target}};
   3185 }
   3186 
   3187 sub usage
   3188         {
   3189         print STDERR $usage;
   3190         print STDERR "\npick os/compiler from:\n";
   3191         my $j=0;
   3192         my $i;
   3193         my $k=0;
   3194         foreach $i (sort keys %table)
   3195                 {
   3196                 next if $table{$i}->{template};
   3197                 next if $i =~ /^debug/;
   3198                 $k += length($i) + 1;
   3199                 if ($k > 78)
   3200                         {
   3201                         print STDERR "\n";
   3202                         $k=length($i);
   3203                         }
   3204                 print STDERR $i . " ";
   3205                 }
   3206         foreach $i (sort keys %table)
   3207                 {
   3208                 next if $table{$i}->{template};
   3209                 next if $i !~ /^debug/;
   3210                 $k += length($i) + 1;
   3211                 if ($k > 78)
   3212                         {
   3213                         print STDERR "\n";
   3214                         $k=length($i);
   3215                         }
   3216                 print STDERR $i . " ";
   3217                 }
   3218         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
   3219         exit(1);
   3220         }
   3221 
   3222 sub run_dofile
   3223 {
   3224     my $out = shift;
   3225     my @templates = @_;
   3226 
   3227     unlink $out || warn "Can't remove $out, $!"
   3228         if -f $out;
   3229     foreach (@templates) {
   3230         die "Can't open $_, $!" unless -f $_;
   3231     }
   3232     my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
   3233     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
   3234     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
   3235     system($cmd);
   3236     exit 1 if $? != 0;
   3237     rename("$out.new", $out) || die "Can't rename $out.new, $!";
   3238 }
   3239 
   3240 sub compiler_predefined {
   3241     state %predefined;
   3242     my $cc = shift;
   3243 
   3244     return () if $^O eq 'VMS';
   3245 
   3246     die 'compiler_predefined called without a compiler command'
   3247         unless $cc;
   3248 
   3249     if (! $predefined{$cc}) {
   3250 
   3251         $predefined{$cc} = {};
   3252 
   3253         # collect compiler pre-defines from gcc or gcc-alike...
   3254         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
   3255         while (my $l = <PIPE>) {
   3256             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
   3257             $predefined{$cc}->{$1} = $2 // '';
   3258         }
   3259         close(PIPE);
   3260     }
   3261 
   3262     return %{$predefined{$cc}};
   3263 }
   3264 
   3265 sub which
   3266 {
   3267     my ($name)=@_;
   3268 
   3269     if (eval { require IPC::Cmd; 1; }) {
   3270         IPC::Cmd->import();
   3271         return scalar IPC::Cmd::can_run($name);
   3272     } else {
   3273         # if there is $directories component in splitpath,
   3274         # then it's not something to test with $PATH...
   3275         return $name if (File::Spec->splitpath($name))[1];
   3276 
   3277         foreach (File::Spec->path()) {
   3278             my $fullpath = catfile($_, "$name$target{exe_extension}");
   3279             if (-f $fullpath and -x $fullpath) {
   3280                 return $fullpath;
   3281             }
   3282         }
   3283     }
   3284 }
   3285 
   3286 sub env
   3287 {
   3288     my $name = shift;
   3289     my %opts = @_;
   3290 
   3291     unless ($opts{cacheonly}) {
   3292         # Note that if $ENV{$name} doesn't exist or is undefined,
   3293         # $config{perlenv}->{$name} will be created with the value
   3294         # undef.  This is intentional.
   3295 
   3296         $config{perlenv}->{$name} = $ENV{$name}
   3297             if ! exists $config{perlenv}->{$name};
   3298     }
   3299     return $config{perlenv}->{$name};
   3300 }
   3301 
   3302 # Configuration printer ##############################################
   3303 
   3304 sub print_table_entry
   3305 {
   3306     local $now_printing = shift;
   3307     my %target = resolve_config($now_printing);
   3308     my $type = shift;
   3309 
   3310     # Don't print the templates
   3311     return if $target{template};
   3312 
   3313     my @sequence = (
   3314         "sys_id",
   3315         "cpp",
   3316         "cppflags",
   3317         "defines",
   3318         "includes",
   3319         "cc",
   3320         "cflags",
   3321         "unistd",
   3322         "ld",
   3323         "lflags",
   3324         "loutflag",
   3325         "ex_libs",
   3326         "bn_ops",
   3327         "apps_aux_src",
   3328         "cpuid_asm_src",
   3329         "uplink_aux_src",
   3330         "bn_asm_src",
   3331         "ec_asm_src",
   3332         "des_asm_src",
   3333         "aes_asm_src",
   3334         "bf_asm_src",
   3335         "md5_asm_src",
   3336         "cast_asm_src",
   3337         "sha1_asm_src",
   3338         "rc4_asm_src",
   3339         "rmd160_asm_src",
   3340         "rc5_asm_src",
   3341         "wp_asm_src",
   3342         "cmll_asm_src",
   3343         "modes_asm_src",
   3344         "padlock_asm_src",
   3345         "chacha_asm_src",
   3346         "poly1035_asm_src",
   3347         "thread_scheme",
   3348         "perlasm_scheme",
   3349         "dso_scheme",
   3350         "shared_target",
   3351         "shared_cflag",
   3352         "shared_defines",
   3353         "shared_ldflag",
   3354         "shared_rcflag",
   3355         "shared_extension",
   3356         "dso_extension",
   3357         "obj_extension",
   3358         "exe_extension",
   3359         "ranlib",
   3360         "ar",
   3361         "arflags",
   3362         "aroutflag",
   3363         "rc",
   3364         "rcflags",
   3365         "rcoutflag",
   3366         "mt",
   3367         "mtflags",
   3368         "mtinflag",
   3369         "mtoutflag",
   3370         "multilib",
   3371         "build_scheme",
   3372         );
   3373 
   3374     if ($type eq "TABLE") {
   3375         print "\n";
   3376         print "*** $now_printing\n";
   3377         foreach (@sequence) {
   3378             if (ref($target{$_}) eq "ARRAY") {
   3379                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
   3380             } else {
   3381                 printf "\$%-12s = %s\n", $_, $target{$_};
   3382             }
   3383         }
   3384     } elsif ($type eq "HASH") {
   3385         my $largest =
   3386             length((sort { length($a) <=> length($b) } @sequence)[-1]);
   3387         print "    '$now_printing' => {\n";
   3388         foreach (@sequence) {
   3389             if ($target{$_}) {
   3390                 if (ref($target{$_}) eq "ARRAY") {
   3391                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
   3392                 } else {
   3393                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
   3394                 }
   3395             }
   3396         }
   3397         print "    },\n";
   3398     }
   3399 }
   3400 
   3401 # Utility routines ###################################################
   3402 
   3403 # On VMS, if the given file is a logical name, File::Spec::Functions
   3404 # will consider it an absolute path.  There are cases when we want a
   3405 # purely syntactic check without checking the environment.
   3406 sub isabsolute {
   3407     my $file = shift;
   3408 
   3409     # On non-platforms, we just use file_name_is_absolute().
   3410     return file_name_is_absolute($file) unless $^O eq "VMS";
   3411 
   3412     # If the file spec includes a device or a directory spec,
   3413     # file_name_is_absolute() is perfectly safe.
   3414     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
   3415 
   3416     # Here, we know the given file spec isn't absolute
   3417     return 0;
   3418 }
   3419 
   3420 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
   3421 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
   3422 # realpath() requires that at least all path components except the last is an
   3423 # existing directory.  On VMS, the last component of the directory spec must
   3424 # exist.
   3425 sub absolutedir {
   3426     my $dir = shift;
   3427 
   3428     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
   3429     # will return the volume name for the device, no matter what.  Also,
   3430     # it will return an incorrect directory spec if the argument is a
   3431     # directory that doesn't exist.
   3432     if ($^O eq "VMS") {
   3433         return rel2abs($dir);
   3434     }
   3435 
   3436     # We use realpath() on Unix, since no other will properly clean out
   3437     # a directory spec.
   3438     use Cwd qw/realpath/;
   3439 
   3440     return realpath($dir);
   3441 }
   3442 
   3443 # Check if all paths are one and the same, using stat.  They must both exist
   3444 # We need this for the cases when File::Spec doesn't detect case insensitivity
   3445 # (File::Spec::Unix assumes case sensitivity)
   3446 sub samedir {
   3447     die "samedir expects two arguments\n" unless scalar @_ == 2;
   3448 
   3449     my @stat0 = stat($_[0]);    # First argument
   3450     my @stat1 = stat($_[1]);    # Second argument
   3451 
   3452     die "Couldn't stat $_[0]" unless @stat0;
   3453     die "Couldn't stat $_[1]" unless @stat1;
   3454 
   3455     # Compare device number
   3456     return 0 unless ($stat0[0] == $stat1[0]);
   3457     # Compare "inode".  The perl manual recommends comparing as
   3458     # string rather than as number.
   3459     return 0 unless ($stat0[1] eq $stat1[1]);
   3460 
   3461     return 1;                   # All the same
   3462 }
   3463 
   3464 sub quotify {
   3465     my %processors = (
   3466         perl    => sub { my $x = shift;
   3467                          $x =~ s/([\\\$\@"])/\\$1/g;
   3468                          return '"'.$x.'"'; },
   3469         maybeshell => sub { my $x = shift;
   3470                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
   3471                             if ($x ne $y || $x =~ m|\s|) {
   3472                                 return '"'.$y.'"';
   3473                             } else {
   3474                                 return $x;
   3475                             }
   3476                         },
   3477         );
   3478     my $for = shift;
   3479     my $processor =
   3480         defined($processors{$for}) ? $processors{$for} : sub { shift; };
   3481 
   3482     return map { $processor->($_); } @_;
   3483 }
   3484 
   3485 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
   3486 # $filename is a file name to read from
   3487 # $line_concat_cond_re is a regexp detecting a line continuation ending
   3488 # $line_concat is a CODEref that takes care of concatenating two lines
   3489 sub collect_from_file {
   3490     my $filename = shift;
   3491     my $line_concat_cond_re = shift;
   3492     my $line_concat = shift;
   3493 
   3494     open my $fh, $filename || die "unable to read $filename: $!\n";
   3495     return sub {
   3496         my $saved_line = "";
   3497         $_ = "";
   3498         while (<$fh>) {
   3499             s|\R$||;
   3500             if (defined $line_concat) {
   3501                 $_ = $line_concat->($saved_line, $_);
   3502                 $saved_line = "";
   3503             }
   3504             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
   3505                 $saved_line = $_;
   3506                 next;
   3507             }
   3508             return $_;
   3509         }
   3510         die "$filename ending with continuation line\n" if $_;
   3511         close $fh;
   3512         return undef;
   3513     }
   3514 }
   3515 
   3516 # collect_from_array($array, $line_concat_cond_re, $line_concat)
   3517 # $array is an ARRAYref of lines
   3518 # $line_concat_cond_re is a regexp detecting a line continuation ending
   3519 # $line_concat is a CODEref that takes care of concatenating two lines
   3520 sub collect_from_array {
   3521     my $array = shift;
   3522     my $line_concat_cond_re = shift;
   3523     my $line_concat = shift;
   3524     my @array = (@$array);
   3525 
   3526     return sub {
   3527         my $saved_line = "";
   3528         $_ = "";
   3529         while (defined($_ = shift @array)) {
   3530             s|\R$||;
   3531             if (defined $line_concat) {
   3532                 $_ = $line_concat->($saved_line, $_);
   3533                 $saved_line = "";
   3534             }
   3535             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
   3536                 $saved_line = $_;
   3537                 next;
   3538             }
   3539             return $_;
   3540         }
   3541         die "input text ending with continuation line\n" if $_;
   3542         return undef;
   3543     }
   3544 }
   3545 
   3546 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
   3547 # $lineiterator is a CODEref that delivers one line at a time.
   3548 # All following arguments are regex/CODEref pairs, where the regexp detects a
   3549 # line and the CODEref does something with the result of the regexp.
   3550 sub collect_information {
   3551     my $lineiterator = shift;
   3552     my %collectors = @_;
   3553 
   3554     while(defined($_ = $lineiterator->())) {
   3555         s|\R$||;
   3556         my $found = 0;
   3557         if ($collectors{"BEFORE"}) {
   3558             $collectors{"BEFORE"}->($_);
   3559         }
   3560         foreach my $re (keys %collectors) {
   3561             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
   3562                 $collectors{$re}->($lineiterator);
   3563                 $found = 1;
   3564             };
   3565         }
   3566         if ($collectors{"OTHERWISE"}) {
   3567             $collectors{"OTHERWISE"}->($lineiterator, $_)
   3568                 unless $found || !defined $collectors{"OTHERWISE"};
   3569         }
   3570         if ($collectors{"AFTER"}) {
   3571             $collectors{"AFTER"}->($_);
   3572         }
   3573     }
   3574 }
   3575 
   3576 # tokenize($line)
   3577 # $line is a line of text to split up into tokens
   3578 # returns a list of tokens
   3579 #
   3580 # Tokens are divided by spaces.  If the tokens include spaces, they
   3581 # have to be quoted with single or double quotes.  Double quotes
   3582 # inside a double quoted token must be escaped.  Escaping is done
   3583 # with backslash.
   3584 # Basically, the same quoting rules apply for " and ' as in any
   3585 # Unix shell.
   3586 sub tokenize {
   3587     my $line = my $debug_line = shift;
   3588     my @result = ();
   3589 
   3590     while ($line =~ s|^\s+||, $line ne "") {
   3591         my $token = "";
   3592         while ($line ne "" && $line !~ m|^\s|) {
   3593             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
   3594                 $token .= $1;
   3595                 $line = $';
   3596             } elsif ($line =~ m/^'([^']*)'/) {
   3597                 $token .= $1;
   3598                 $line = $';
   3599             } elsif ($line =~ m/^(\S+)/) {
   3600                 $token .= $1;
   3601                 $line = $';
   3602             }
   3603         }
   3604         push @result, $token;
   3605     }
   3606 
   3607     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
   3608         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
   3609         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
   3610     }
   3611     return @result;
   3612 }
   3613