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