Address a timing side channel whereby it is possible to determine some
[openssl.git] / Configure
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 # Copyright 2016-2017 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 $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";
25
26 # Options:
27 #
28 # --config      add the given configuration file, which will be read after
29 #               any "Configurations*" files that are found in the same
30 #               directory as this script.
31 # --prefix      prefix for the OpenSSL installation, which includes the
32 #               directories bin, lib, include, share/man, share/doc/openssl
33 #               This becomes the value of INSTALLTOP in Makefile
34 #               (Default: /usr/local)
35 # --openssldir  OpenSSL data area, such as openssl.cnf, certificates and keys.
36 #               If it's a relative directory, it will be added on the directory
37 #               given with --prefix.
38 #               This becomes the value of OPENSSLDIR in Makefile and in C.
39 #               (Default: PREFIX/ssl)
40 #
41 # --cross-compile-prefix Add specified prefix to binutils components.
42 #
43 # --api         One of 0.9.8, 1.0.0 or 1.1.0.  Do not compile support for
44 #               interfaces deprecated as of the specified OpenSSL version.
45 #
46 # no-hw-xxx     do not compile support for specific crypto hardware.
47 #               Generic OpenSSL-style methods relating to this support
48 #               are always compiled but return NULL if the hardware
49 #               support isn't compiled.
50 # no-hw         do not compile support for any crypto hardware.
51 # [no-]threads  [don't] try to create a library that is suitable for
52 #               multithreaded applications (default is "threads" if we
53 #               know how to do it)
54 # [no-]shared   [don't] try to create shared libraries when supported.
55 # [no-]pic      [don't] try to build position independent code when supported.
56 #               If disabled, it also disables shared and dynamic-engine.
57 # no-asm        do not use assembler
58 # no-dso        do not compile in any native shared-library methods. This
59 #               will ensure that all methods just return NULL.
60 # no-egd        do not compile support for the entropy-gathering daemon APIs
61 # [no-]zlib     [don't] compile support for zlib compression.
62 # zlib-dynamic  Like "zlib", but the zlib library is expected to be a shared
63 #               library and will be loaded in run-time by the OpenSSL library.
64 # sctp          include SCTP support
65 # enable-weak-ssl-ciphers
66 #               Enable weak ciphers that are disabled by default.
67 # 386           generate 80386 code in assembly modules
68 # no-sse2       disables IA-32 SSE2 code in assembly modules, the above
69 #               mentioned '386' option implies this one
70 # no-<cipher>   build without specified algorithm (rsa, idea, rc5, ...)
71 # -<xxx> +<xxx> compiler options are passed through
72 # -static       while -static is also a pass-through compiler option (and
73 #               as such is limited to environments where it's actually
74 #               meaningful), it triggers a number configuration options,
75 #               namely no-dso, no-pic, no-shared and no-threads. It is
76 #               argued that the only reason to produce statically linked
77 #               binaries (and in context it means executables linked with
78 #               -static flag, and not just executables linked with static
79 #               libcrypto.a) is to eliminate dependency on specific run-time,
80 #               a.k.a. libc version. The mentioned config options are meant
81 #               to achieve just that. Unfortunately on Linux it's impossible
82 #               to eliminate the dependency completely for openssl executable
83 #               because of getaddrinfo and gethostbyname calls, which can
84 #               invoke dynamically loadable library facility anyway to meet
85 #               the lookup requests. For this reason on Linux statically
86 #               linked openssl executable has rather debugging value than
87 #               production quality.
88 #
89 # DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items
90 #               provided to stack calls. Generates unique stack functions for
91 #               each possible stack type.
92 # BN_LLONG      use the type 'long long' in crypto/bn/bn.h
93 # RC4_CHAR      use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
94 # Following are set automatically by this script
95 #
96 # MD5_ASM       use some extra md5 assembler,
97 # SHA1_ASM      use some extra sha1 assembler, must define L_ENDIAN for x86
98 # RMD160_ASM    use some extra ripemd160 assembler,
99 # SHA256_ASM    sha256_block is implemented in assembler
100 # SHA512_ASM    sha512_block is implemented in assembler
101 # AES_ASM       AES_[en|de]crypt is implemented in assembler
102
103 # Minimum warning options... any contributions to OpenSSL should at least get
104 # past these.
105
106 # DEBUG_UNUSED enables __owur (warn unused result) checks.
107 # -DPEDANTIC complements -pedantic and is meant to mask code that
108 # is not strictly standard-compliant and/or implementation-specific,
109 # e.g. inline assembly, disregards to alignment requirements, such
110 # that -pedantic would complain about. Incidentally -DPEDANTIC has
111 # to be used even in sanitized builds, because sanitizer too is
112 # supposed to and does take notice of non-standard behaviour. Then
113 # -pedantic with pre-C9x compiler would also complain about 'long
114 # long' not being supported. As 64-bit algorithms are common now,
115 # it grew impossible to resolve this without sizeable additional
116 # code, so we just tell compiler to be pedantic about everything
117 # but 'long long' type.
118
119 my $gcc_devteam_warn = "-DDEBUG_UNUSED"
120         . " -DPEDANTIC -pedantic -Wno-long-long"
121         . " -Wall"
122         . " -Wextra"
123         . " -Wno-unused-parameter"
124         . " -Wno-missing-field-initializers"
125         . " -Wswitch"
126         . " -Wsign-compare"
127         . " -Wmissing-prototypes"
128         . " -Wshadow"
129         . " -Wformat"
130         . " -Wtype-limits"
131         . " -Wundef"
132         . " -Werror"
133         ;
134
135 # These are used in addition to $gcc_devteam_warn when the compiler is clang.
136 # TODO(openssl-team): fix problems and investigate if (at least) the
137 # following warnings can also be enabled:
138 #       -Wcast-align
139 #       -Wunreachable-code -- no, too ugly/compiler-specific
140 #       -Wlanguage-extension-token -- no, we use asm()
141 #       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
142 #       -Wextended-offsetof -- no, needed in CMS ASN1 code
143 my $clang_devteam_warn = ""
144         . " -Wswitch-default"
145         . " -Wno-parentheses-equality"
146         . " -Wno-language-extension-token"
147         . " -Wno-extended-offsetof"
148         . " -Wconditional-uninitialized"
149         . " -Wincompatible-pointer-types-discards-qualifiers"
150         . " -Wmissing-variable-declarations"
151         . " -Wno-unknown-warning-option"
152         ;
153
154 # This adds backtrace information to the memory leak info.  Is only used
155 # when crypto-mdebug-backtrace is enabled.
156 my $memleak_devteam_backtrace = "-rdynamic";
157
158 my $strict_warnings = 0;
159
160 # As for $BSDthreads. Idea is to maintain "collective" set of flags,
161 # which would cover all BSD flavors. -pthread applies to them all,
162 # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
163 # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
164 # which has to be accompanied by explicit -D_THREAD_SAFE and
165 # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
166 # seems to be sufficient?
167 our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
168
169 #
170 # API compatibility name to version number mapping.
171 #
172 my $maxapi = "1.1.0";           # API for "no-deprecated" builds
173 my $apitable = {
174     "1.1.0" => "0x10100000L",
175     "1.0.0" => "0x10000000L",
176     "0.9.8" => "0x00908000L",
177 };
178
179 our %table = ();
180 our %config = ();
181 our %withargs = ();
182
183 # Forward declarations ###############################################
184
185 # read_config(filename)
186 #
187 # Reads a configuration file and populates %table with the contents
188 # (which the configuration file places in %targets).
189 sub read_config;
190
191 # resolve_config(target)
192 #
193 # Resolves all the late evaluations, inheritances and so on for the
194 # chosen target and any target it inherits from.
195 sub resolve_config;
196
197
198 # Information collection #############################################
199
200 # Unified build supports separate build dir
201 my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
202 my $blddir = catdir(absolutedir("."));         # catdir ensures local syntax
203 my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
204
205 my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
206
207 $config{sourcedir} = abs2rel($srcdir);
208 $config{builddir} = abs2rel($blddir);
209
210 # Collect reconfiguration information if needed
211 my @argvcopy=@ARGV;
212
213 if (grep /^reconf(igure)?$/, @argvcopy) {
214     if (-f "./configdata.pm") {
215         my $file = "./configdata.pm";
216         unless (my $return = do $file) {
217             die "couldn't parse $file: $@" if $@;
218             die "couldn't do $file: $!"    unless defined $return;
219             die "couldn't run $file"       unless $return;
220         }
221
222         @argvcopy = defined($configdata::config{perlargv}) ?
223             @{$configdata::config{perlargv}} : ();
224         die "Incorrect data to reconfigure, please do a normal configuration\n"
225             if (grep(/^reconf/,@argvcopy));
226         $ENV{CROSS_COMPILE} = $configdata::config{cross_compile_prefix}
227             if defined($configdata::config{cross_compile_prefix});
228         $ENV{CC} = $configdata::config{cc}
229             if defined($configdata::config{cc});
230         $ENV{CXX} = $configdata::config{cxx}
231             if defined($configdata::config{cxx});
232         $ENV{BUILDFILE} = $configdata::config{build_file}
233             if defined($configdata::config{build_file});
234         $ENV{$local_config_envname} = $configdata::config{local_config_dir}
235             if defined($configdata::config{local_config_dir});
236
237         print "Reconfiguring with: ", join(" ",@argvcopy), "\n";
238         print "    CROSS_COMPILE = ",$ENV{CROSS_COMPILE},"\n"
239             if $ENV{CROSS_COMPILE};
240         print "    CC = ",$ENV{CC},"\n" if $ENV{CC};
241         print "    CXX = ",$ENV{CXX},"\n" if $ENV{CXX};
242         print "    BUILDFILE = ",$ENV{BUILDFILE},"\n" if $ENV{BUILDFILE};
243         print "    $local_config_envname = ",$ENV{$local_config_envname},"\n"
244             if $ENV{$local_config_envname};
245     } else {
246         die "Insufficient data to reconfigure, please do a normal configuration\n";
247     }
248 }
249
250 $config{perlargv} = [ @argvcopy ];
251
252 # Collect version numbers
253 $config{version} = "unknown";
254 $config{version_num} = "unknown";
255 $config{shlib_version_number} = "unknown";
256 $config{shlib_version_history} = "unknown";
257
258 collect_information(
259     collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
260     qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
261     qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/      => sub { $config{version_num}=$1 },
262     qr/SHLIB_VERSION_NUMBER *"([^"]+)"/      => sub { $config{shlib_version_number}=$1 },
263     qr/SHLIB_VERSION_HISTORY *"([^"]*)"/     => sub { $config{shlib_version_history}=$1 }
264     );
265 if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
266
267 ($config{major}, $config{minor})
268     = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
269 ($config{shlib_major}, $config{shlib_minor})
270     = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
271 die "erroneous version information in opensslv.h: ",
272     "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
273     if ($config{major} eq "" || $config{minor} eq ""
274         || $config{shlib_major} eq "" ||  $config{shlib_minor} eq "");
275
276 # Collect target configurations
277
278 my $pattern = catfile(dirname($0), "Configurations", "*.conf");
279 foreach (sort glob($pattern)) {
280     &read_config($_);
281 }
282
283 if (defined $ENV{$local_config_envname}) {
284     if ($^O eq 'VMS') {
285         # VMS environment variables are logical names,
286         # which can be used as is
287         $pattern = $local_config_envname . ':' . '*.conf';
288     } else {
289         $pattern = catfile($ENV{$local_config_envname}, '*.conf');
290     }
291
292     foreach (sort glob($pattern)) {
293         &read_config($_);
294     }
295 }
296
297 $config{prefix}="";
298 $config{openssldir}="";
299 $config{processor}="";
300 $config{libdir}="";
301 $config{cross_compile_prefix}="";
302 my $auto_threads=1;    # enable threads automatically? true by default
303 my $default_ranlib;
304
305 # Top level directories to build
306 $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
307 # crypto/ subdirectories to build
308 $config{sdirs} = [
309     "objects",
310     "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",
311     "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
312     "bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
313     "buffer", "bio", "stack", "lhash", "rand", "err",
314     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
315     "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
316     ];
317 # test/ subdirectories to build
318 $config{tdirs} = [ "ossl_shim" ];
319
320 # Known TLS and DTLS protocols
321 my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
322 my @dtls = qw(dtls1 dtls1_2);
323
324 # Explicitly known options that are possible to disable.  They can
325 # be regexps, and will be used like this: /^no-${option}$/
326 # For developers: keep it sorted alphabetically
327
328 my @disablables = (
329     "afalgeng",
330     "aria",
331     "asan",
332     "asm",
333     "async",
334     "autoalginit",
335     "autoerrinit",
336     "bf",
337     "blake2",
338     "camellia",
339     "capieng",
340     "cast",
341     "chacha",
342     "cmac",
343     "cms",
344     "comp",
345     "crypto-mdebug",
346     "crypto-mdebug-backtrace",
347     "ct",
348     "deprecated",
349     "des",
350     "devcryptoeng",
351     "dgram",
352     "dh",
353     "dsa",
354     "dso",
355     "dtls",
356     "dynamic-engine",
357     "ec",
358     "ec2m",
359     "ecdh",
360     "ecdsa",
361     "ec_nistp_64_gcc_128",
362     "egd",
363     "engine",
364     "err",
365     "external-tests",
366     "filenames",
367     "fuzz-libfuzzer",
368     "fuzz-afl",
369     "gost",
370     "heartbeats",
371     "hw(-.+)?",
372     "idea",
373     "makedepend",
374     "md2",
375     "md4",
376     "mdc2",
377     "msan",
378     "multiblock",
379     "nextprotoneg",
380     "ocb",
381     "ocsp",
382     "pic",
383     "poly1305",
384     "posix-io",
385     "psk",
386     "rc2",
387     "rc4",
388     "rc5",
389     "rdrand",
390     "rfc3779",
391     "rmd160",
392     "scrypt",
393     "sctp",
394     "seed",
395     "shared",
396     "siphash",
397     "sm4",
398     "sock",
399     "srp",
400     "srtp",
401     "sse2",
402     "ssl",
403     "ssl-trace",
404     "static-engine",
405     "stdio",
406     "tests",
407     "threads",
408     "tls",
409     "tls13downgrade",
410     "ts",
411     "ubsan",
412     "ui-console",
413     "unit-test",
414     "whirlpool",
415     "weak-ssl-ciphers",
416     "zlib",
417     "zlib-dynamic",
418     );
419 foreach my $proto ((@tls, @dtls))
420         {
421         push(@disablables, $proto);
422         push(@disablables, "$proto-method") unless $proto eq "tls1_3";
423         }
424
425 my %deprecated_disablables = (
426     "ssl2" => undef,
427     "buf-freelists" => undef,
428     "ripemd" => "rmd160",
429     "ui" => "ui-console",
430     );
431
432 # All of the following is disabled by default (RC5 was enabled before 0.9.8):
433
434 our %disabled = ( # "what"         => "comment"
435                   "aria"                => "default",
436                   "asan"                => "default",
437                   "crypto-mdebug"       => "default",
438                   "crypto-mdebug-backtrace" => "default",
439                   "devcryptoeng"        => "default",
440                   "ec_nistp_64_gcc_128" => "default",
441                   "egd"                 => "default",
442                   "external-tests"      => "default",
443                   "fuzz-libfuzzer"      => "default",
444                   "fuzz-afl"            => "default",
445                   "heartbeats"          => "default",
446                   "md2"                 => "default",
447                   "msan"                => "default",
448                   "rc5"                 => "default",
449                   "sctp"                => "default",
450                   "ssl-trace"           => "default",
451                   "ssl3"                => "default",
452                   "ssl3-method"         => "default",
453                   "ubsan"               => "default",
454           #TODO(TLS1.3): Temporarily disabled while this is a WIP
455                   "tls1_3"              => "default",
456                   "tls13downgrade"      => "default",
457                   "unit-test"           => "default",
458                   "weak-ssl-ciphers"    => "default",
459                   "zlib"                => "default",
460                   "zlib-dynamic"        => "default",
461                 );
462
463 # Note: => pair form used for aesthetics, not to truly make a hash table
464 my @disable_cascades = (
465     # "what"            => [ "cascade", ... ]
466     sub { $config{processor} eq "386" }
467                         => [ "sse2" ],
468     "ssl"               => [ "ssl3" ],
469     "ssl3-method"       => [ "ssl3" ],
470     "zlib"              => [ "zlib-dynamic" ],
471     "des"               => [ "mdc2" ],
472     "ec"                => [ "ecdsa", "ecdh" ],
473
474     "dgram"             => [ "dtls", "sctp" ],
475     "sock"              => [ "dgram" ],
476     "dtls"              => [ @dtls ],
477     sub { 0 == scalar grep { !$disabled{$_} } @dtls }
478                         => [ "dtls" ],
479
480     # SSL 3.0, (D)TLS 1.0 and TLS 1.1 require MD5 and SHA
481     "md5"               => [ "ssl", "tls1", "tls1_1", "dtls1" ],
482     "sha"               => [ "ssl", "tls1", "tls1_1", "dtls1" ],
483
484     # Additionally, SSL 3.0 requires either RSA or DSA+DH
485     sub { $disabled{rsa}
486           && ($disabled{dsa} || $disabled{dh}); }
487                         => [ "ssl" ],
488
489     # (D)TLS 1.0 and TLS 1.1 also require either RSA or DSA+DH
490     # or ECDSA + ECDH.  (D)TLS 1.2 has this requirement as well.
491     # (XXX: We don't support PSK-only builds).
492     sub { $disabled{rsa}
493           && ($disabled{dsa} || $disabled{dh})
494           && ($disabled{ecdsa} || $disabled{ecdh}); }
495                         => [ "tls1", "tls1_1", "tls1_2", "tls1_3",
496                              "dtls1", "dtls1_2" ],
497
498     "tls"               => [ @tls ],
499     sub { 0 == scalar grep { !$disabled{$_} } @tls }
500                         => [ "tls" ],
501
502     # SRP and HEARTBEATS require TLSEXT
503     "tlsext"            => [ "srp", "heartbeats" ],
504
505     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
506
507     # Without DSO, we can't load dynamic engines, so don't build them dynamic
508     "dso"               => [ "dynamic-engine" ],
509
510     # Without position independent code, there can be no shared libraries or DSOs
511     "pic"               => [ "shared" ],
512     "shared"            => [ "dynamic-engine" ],
513     "engine"            => [ "afalgeng", "devcryptoeng" ],
514
515     # no-autoalginit is only useful when building non-shared
516     "autoalginit"       => [ "shared", "apps" ],
517
518     "stdio"             => [ "apps", "capieng", "egd" ],
519     "apps"              => [ "tests" ],
520     "tests"             => [ "external-tests" ],
521     "comp"              => [ "zlib" ],
522     "ec"                => [ "tls1_3" ],
523     sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
524
525     sub { !$disabled{"msan"} } => [ "asm" ],
526     );
527
528 # Avoid protocol support holes.  Also disable all versions below N, if version
529 # N is disabled while N+1 is enabled.
530 #
531 my @list = (reverse @tls);
532 while ((my $first, my $second) = (shift @list, shift @list)) {
533     last unless @list;
534     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
535                               => [ @list ] );
536     unshift @list, $second;
537 }
538 my @list = (reverse @dtls);
539 while ((my $first, my $second) = (shift @list, shift @list)) {
540     last unless @list;
541     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
542                               => [ @list ] );
543     unshift @list, $second;
544 }
545
546 # Explicit "no-..." options will be collected in %disabled along with the defaults.
547 # To remove something from %disabled, use "enable-foo".
548 # For symmetry, "disable-foo" is a synonym for "no-foo".
549
550 my $no_sse2=0;
551
552 &usage if ($#ARGV < 0);
553
554 my $user_cflags="";
555 my @user_defines=();
556 $config{openssl_api_defines}=[];
557 $config{openssl_algorithm_defines}=[];
558 $config{openssl_thread_defines}=[];
559 $config{openssl_sys_defines}=[];
560 $config{openssl_other_defines}=[];
561 my $libs="";
562 my $target="";
563 $config{options}="";
564 $config{build_type} = "release";
565
566 my %unsupported_options = ();
567 my %deprecated_options = ();
568 # If you change this, update apps/version.c
569 my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
570 my @seed_sources = ();
571 while (@argvcopy)
572         {
573         $_ = shift @argvcopy;
574         # VMS is a case insensitive environment, and depending on settings
575         # out of our control, we may receive options uppercased.  Let's
576         # downcase at least the part before any equal sign.
577         if ($^O eq "VMS")
578                 {
579                 s/^([^=]*)/lc($1)/e;
580                 }
581         s /^-no-/no-/; # some people just can't read the instructions
582
583         # rewrite some options in "enable-..." form
584         s /^-?-?shared$/enable-shared/;
585         s /^sctp$/enable-sctp/;
586         s /^threads$/enable-threads/;
587         s /^zlib$/enable-zlib/;
588         s /^zlib-dynamic$/enable-zlib-dynamic/;
589
590         if (/^(no|disable|enable)-(.+)$/)
591                 {
592                 my $word = $2;
593                 if (!exists $deprecated_disablables{$word}
594                         && !grep { $word =~ /^${_}$/ } @disablables)
595                         {
596                         $unsupported_options{$_} = 1;
597                         next;
598                         }
599                 }
600         if (/^no-(.+)$/ || /^disable-(.+)$/)
601                 {
602                 foreach my $proto ((@tls, @dtls))
603                         {
604                         if ($1 eq "$proto-method")
605                                 {
606                                 $disabled{"$proto"} = "option($proto-method)";
607                                 last;
608                                 }
609                         }
610                 if ($1 eq "dtls")
611                         {
612                         foreach my $proto (@dtls)
613                                 {
614                                 $disabled{$proto} = "option(dtls)";
615                                 }
616                         $disabled{"dtls"} = "option(dtls)";
617                         }
618                 elsif ($1 eq "ssl")
619                         {
620                         # Last one of its kind
621                         $disabled{"ssl3"} = "option(ssl)";
622                         }
623                 elsif ($1 eq "tls")
624                         {
625                         # XXX: Tests will fail if all SSL/TLS
626                         # protocols are disabled.
627                         foreach my $proto (@tls)
628                                 {
629                                 $disabled{$proto} = "option(tls)";
630                                 }
631                         }
632                 elsif ($1 eq "static-engine")
633                         {
634                         delete $disabled{"dynamic-engine"};
635                         }
636                 elsif ($1 eq "dynamic-engine")
637                         {
638                         $disabled{"dynamic-engine"} = "option";
639                         }
640                 elsif (exists $deprecated_disablables{$1})
641                         {
642                         $deprecated_options{$_} = 1;
643                         if (defined $deprecated_disablables{$1})
644                                 {
645                                 $disabled{$deprecated_disablables{$1}} = "option";
646                                 }
647                         }
648                 else
649                         {
650                         $disabled{$1} = "option";
651                         }
652                 # No longer an automatic choice
653                 $auto_threads = 0 if ($1 eq "threads");
654                 }
655         elsif (/^enable-(.+)$/)
656                 {
657                 if ($1 eq "static-engine")
658                         {
659                         $disabled{"dynamic-engine"} = "option";
660                         }
661                 elsif ($1 eq "dynamic-engine")
662                         {
663                         delete $disabled{"dynamic-engine"};
664                         }
665                 elsif ($1 eq "zlib-dynamic")
666                         {
667                         delete $disabled{"zlib"};
668                         }
669                 my $algo = $1;
670                 delete $disabled{$algo};
671
672                 # No longer an automatic choice
673                 $auto_threads = 0 if ($1 eq "threads");
674                 }
675         elsif (/^--strict-warnings$/)
676                 {
677                 $strict_warnings = 1;
678                 }
679         elsif (/^--debug$/)
680                 {
681                 $config{build_type} = "debug";
682                 }
683         elsif (/^--release$/)
684                 {
685                 $config{build_type} = "release";
686                 }
687         elsif (/^386$/)
688                 { $config{processor}=386; }
689         elsif (/^fips$/)
690                 {
691                 die "FIPS mode not supported\n";
692                 }
693         elsif (/^rsaref$/)
694                 {
695                 # No RSAref support any more since it's not needed.
696                 # The check for the option is there so scripts aren't
697                 # broken
698                 }
699         elsif (/^nofipscanistercheck$/)
700                 {
701                 die "FIPS mode not supported\n";
702                 }
703         elsif (/^[-+]/)
704                 {
705                 if (/^--prefix=(.*)$/)
706                         {
707                         $config{prefix}=$1;
708                         die "Directory given with --prefix MUST be absolute\n"
709                                 unless file_name_is_absolute($config{prefix});
710                         }
711                 elsif (/^--api=(.*)$/)
712                         {
713                         $config{api}=$1;
714                         }
715                 elsif (/^--libdir=(.*)$/)
716                         {
717                         $config{libdir}=$1;
718                         }
719                 elsif (/^--openssldir=(.*)$/)
720                         {
721                         $config{openssldir}=$1;
722                         }
723                 elsif (/^--with-zlib-lib=(.*)$/)
724                         {
725                         $withargs{zlib_lib}=$1;
726                         }
727                 elsif (/^--with-zlib-include=(.*)$/)
728                         {
729                         $withargs{zlib_include}=$1;
730                         }
731                 elsif (/^--with-fuzzer-lib=(.*)$/)
732                         {
733                         $withargs{fuzzer_lib}=$1;
734                         }
735                 elsif (/^--with-fuzzer-include=(.*)$/)
736                         {
737                         $withargs{fuzzer_include}=$1;
738                         }
739                 elsif (/^--with-rand-seed=(.*)$/)
740                         {
741                         foreach my $x (split(m|,|, $1))
742                             {
743                             die "Unknown --with-rand-seed choice $x\n"
744                                 if ! grep { $x eq $_ } @known_seed_sources;
745                             push @seed_sources, $x;
746                             }
747                         }
748                 elsif (/^--cross-compile-prefix=(.*)$/)
749                         {
750                         $config{cross_compile_prefix}=$1;
751                         }
752                 elsif (/^--config=(.*)$/)
753                         {
754                         read_config $1;
755                         }
756                 elsif (/^-[lL](.*)$/ or /^-Wl,/)
757                         {
758                         $libs.=$_." ";
759                         }
760                 elsif (/^-framework$/)
761                         {
762                         $libs.=$_." ".shift(@argvcopy)." ";
763                         }
764                 elsif (/^-rpath$/ or /^-R$/)
765                         # -rpath is the OSF1 rpath flag
766                         # -R is the old Solaris rpath flag
767                         {
768                         my $rpath = shift(@argvcopy) || "";
769                         $rpath .= " " if $rpath ne "";
770                         $libs.=$_." ".$rpath;
771                         }
772                 elsif (/^-static$/)
773                         {
774                         $libs.=$_." ";
775                         $disabled{"dso"} = "forced";
776                         $disabled{"pic"} = "forced";
777                         $disabled{"shared"} = "forced";
778                         $disabled{"threads"} = "forced";
779                         }
780                 elsif (/^-D(.*)$/)
781                         {
782                         push @user_defines, $1;
783                         }
784                 else    # common if (/^[-+]/), just pass down...
785                         {
786                         $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
787                         $user_cflags.=" ".$_;
788                         }
789                 }
790         else
791                 {
792                 die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
793                 $target=$_;
794                 }
795         unless ($_ eq $target || /^no-/ || /^disable-/)
796                 {
797                 # "no-..." follows later after implied disactivations
798                 # have been derived.  (Don't take this too seriously,
799                 # we really only write OPTIONS to the Makefile out of
800                 # nostalgia.)
801
802                 if ($config{options} eq "")
803                         { $config{options} = $_; }
804                 else
805                         { $config{options} .= " ".$_; }
806                 }
807
808         if (defined($config{api}) && !exists $apitable->{$config{api}}) {
809                 die "***** Unsupported api compatibility level: $config{api}\n",
810         }
811
812         if (keys %deprecated_options)
813                 {
814                 warn "***** Deprecated options: ",
815                         join(", ", keys %deprecated_options), "\n";
816                 }
817         if (keys %unsupported_options)
818                 {
819                 die "***** Unsupported options: ",
820                         join(", ", keys %unsupported_options), "\n";
821                 }
822         }
823
824 if ($libs =~ /(^|\s)-Wl,-rpath,/
825     && !$disabled{shared}
826     && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
827     die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
828         "***** any of asan, msan or ubsan\n";
829 }
830
831 if (scalar(@seed_sources) == 0) {
832     print "Using implicit seed configuration\n";
833     push @seed_sources, 'os';
834 }
835 die "Cannot seed with none and anything else"
836     if scalar(grep { $_ eq 'none' } @seed_sources) > 0
837         && scalar(@seed_sources) > 1;
838 push @{$config{openssl_other_defines}},
839      map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
840         @seed_sources;
841
842 my @tocheckfor = (keys %disabled);
843 while (@tocheckfor) {
844     my %new_tocheckfor = ();
845     my @cascade_copy = (@disable_cascades);
846     while (@cascade_copy) {
847         my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy);
848         if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
849             foreach(grep { !defined($disabled{$_}) } @$descendents) {
850                 $new_tocheckfor{$_} = 1; $disabled{$_} = "forced";
851             }
852         }
853     }
854     @tocheckfor = (keys %new_tocheckfor);
855 }
856
857 our $die = sub { die @_; };
858 if ($target eq "TABLE") {
859     local $die = sub { warn @_; };
860     foreach (sort keys %table) {
861         print_table_entry($_, "TABLE");
862     }
863     exit 0;
864 }
865
866 if ($target eq "LIST") {
867     foreach (sort keys %table) {
868         print $_,"\n" unless $table{$_}->{template};
869     }
870     exit 0;
871 }
872
873 if ($target eq "HASH") {
874     local $die = sub { warn @_; };
875     print "%table = (\n";
876     foreach (sort keys %table) {
877         print_table_entry($_, "HASH");
878     }
879     exit 0;
880 }
881
882 print "Configuring OpenSSL version $config{version} ($config{version_num})\n";
883 print "for $target\n";
884
885 # Backward compatibility?
886 if ($target =~ m/^CygWin32(-.*)$/) {
887     $target = "Cygwin".$1;
888 }
889
890 # Support for legacy targets having a name starting with 'debug-'
891 my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
892 if ($d) {
893     $config{build_type} = "debug";
894
895     # If we do not find debug-foo in the table, the target is set to foo.
896     if (!$table{$target}) {
897         $target = $t;
898     }
899 }
900 $config{target} = $target;
901 my %target = resolve_config($target);
902
903 &usage if (!%target || $target{template});
904
905 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
906 $config{conf_files} = [ sort keys %conf_files ];
907 %target = ( %{$table{DEFAULTS}}, %target );
908
909 foreach my $feature (@{$target{disable}}) {
910     if (exists $deprecated_disablables{$feature}) {
911         warn "***** config $target disables deprecated feature $feature\n";
912     } elsif (!grep { $feature eq $_ } @disablables) {
913         die "***** config $target disables unknown feature $feature\n";
914     }
915     $disabled{$feature} = 'config';
916 }
917 foreach my $feature (@{$target{enable}}) {
918     if ("default" eq ($disabled{$_} // "")) {
919         if (exists $deprecated_disablables{$feature}) {
920             warn "***** config $target enables deprecated feature $feature\n";
921         } elsif (!grep { $feature eq $_ } @disablables) {
922             die "***** config $target enables unknown feature $feature\n";
923         }
924         delete $disabled{$_};
925     }
926 }
927
928 foreach (sort (keys %disabled))
929         {
930         $config{options} .= " no-$_";
931
932         printf "    no-%-12s %-10s", $_, "[$disabled{$_}]";
933
934         if (/^dso$/)
935                 { }
936         elsif (/^threads$/)
937                 { }
938         elsif (/^shared$/)
939                 { }
940         elsif (/^pic$/)
941                 { }
942         elsif (/^zlib$/)
943                 { }
944         elsif (/^dynamic-engine$/)
945                 { }
946         elsif (/^makedepend$/)
947                 { }
948         elsif (/^zlib-dynamic$/)
949                 { }
950         elsif (/^sse2$/)
951                 { $no_sse2 = 1; }
952         elsif (/^engine$/)
953                 {
954                 @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
955                 @{$config{sdirs}} = grep !/^engine$/, @{$config{sdirs}};
956                 push @{$config{openssl_other_defines}}, "OPENSSL_NO_ENGINE";
957                 print " OPENSSL_NO_ENGINE (skip engines)";
958                 }
959         else
960                 {
961                 my ($WHAT, $what);
962
963                 ($WHAT = $what = $_) =~ tr/[\-a-z]/[_A-Z]/;
964
965                 # Fix up C macro end names
966                 $WHAT = "RMD160" if $what eq "ripemd";
967
968                 # fix-up crypto/directory name(s)
969                 $what = "ripemd" if $what eq "rmd160";
970                 $what = "whrlpool" if $what eq "whirlpool";
971
972                 if ($what ne "async" && $what ne "err"
973                     && grep { $_ eq $what } @{$config{sdirs}})
974                         {
975                         push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$WHAT";
976                         @{$config{sdirs}} = grep { $_ ne $what} @{$config{sdirs}};
977
978                         print " OPENSSL_NO_$WHAT (skip dir)";
979                         }
980                 else
981                         {
982                         push @{$config{openssl_other_defines}}, "OPENSSL_NO_$WHAT";
983                         print " OPENSSL_NO_$WHAT";
984
985                         if (/^err$/)    { push @user_defines, "OPENSSL_NO_ERR"; }
986                         }
987                 }
988
989         print "\n";
990         }
991
992 $target{cxxflags}=$target{cflags} unless defined $target{cxxflags};
993 $target{exe_extension}="";
994 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
995                                   || $config{target} =~ /^(?:Cygwin|mingw)/);
996 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
997
998 ($target{shared_extension_simple}=$target{shared_extension})
999     =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||;
1000 $target{dso_extension}=$target{shared_extension_simple};
1001 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
1002     if ($config{target} =~ /^(?:Cygwin|mingw)/);
1003
1004
1005 $config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'}
1006     if $config{cross_compile_prefix} eq "";
1007
1008 # Allow overriding the names of some tools.  USE WITH CARE
1009 # Note: only Unix cares about HASHBANGPERL...  that explains
1010 # the default string.
1011 $config{perl} =    ($^O ne "VMS" ? $^X : "perl");
1012 $config{hashbangperl} =
1013     $ENV{'HASHBANGPERL'}           || $ENV{'PERL'}     || "/usr/bin/env perl";
1014 $target{cc} =      $ENV{'CC'}      || $target{cc}      || "cc";
1015 $target{cxx} =     $ENV{'CXX'}     || $target{cxx}     || "c++";
1016 $target{ranlib} =  $ENV{'RANLIB'}  || $target{ranlib}  ||
1017                    (which("$config{cross_compile_prefix}ranlib") ?
1018                           "\$(CROSS_COMPILE)ranlib" : "true");
1019 $target{ar} =      $ENV{'AR'}      || $target{ar}      || "ar";
1020 $target{nm} =      $ENV{'NM'}      || $target{nm}      || "nm";
1021 $target{rc} =
1022     $ENV{'RC'}  || $ENV{'WINDRES'} || $target{rc}      || "windres";
1023
1024 # Allow overriding the build file name
1025 $target{build_file} = $ENV{BUILDFILE} || $target{build_file} || "Makefile";
1026
1027 # Cache information necessary for reconfiguration
1028 $config{cc} = $target{cc};
1029 $config{cxx} = $target{cxx};
1030 $config{build_file} = $target{build_file};
1031
1032 # For cflags, lflags, plib_lflags, ex_libs and defines, add the debug_
1033 # or release_ attributes.
1034 # Do it in such a way that no spurious space is appended (hence the grep).
1035 $config{defines} = [];
1036 $config{cflags} = "";
1037 $config{cxxflags} = "";
1038 $config{ex_libs} = "";
1039 $config{shared_ldflag} = "";
1040
1041 # Make sure build_scheme is consistent.
1042 $target{build_scheme} = [ $target{build_scheme} ]
1043     if ref($target{build_scheme}) ne "ARRAY";
1044
1045 my ($builder, $builder_platform, @builder_opts) =
1046     @{$target{build_scheme}};
1047
1048 foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
1049                       $builder_platform."-checker.pm")) {
1050     my $checker_path = catfile($srcdir, "Configurations", $checker);
1051     if (-f $checker_path) {
1052         my $fn = $ENV{CONFIGURE_CHECKER_WARN}
1053             ? sub { warn $@; } : sub { die $@; };
1054         if (! do $checker_path) {
1055             if ($@) {
1056                 $fn->($@);
1057             } elsif ($!) {
1058                 $fn->($!);
1059             } else {
1060                 $fn->("The detected tools didn't match the platform\n");
1061             }
1062         }
1063         last;
1064     }
1065 }
1066
1067 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
1068
1069 if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` =~ m/-mno-cygwin/m)
1070         {
1071         $config{cflags} .= " -mno-cygwin";
1072         $config{shared_ldflag} .= " -mno-cygwin";
1073         }
1074
1075 if ($target =~ /linux.*-mips/ && !$disabled{asm} && $user_cflags !~ /-m(ips|arch=)/) {
1076         # minimally required architecture flags for assembly modules
1077         $config{cflags}="-mips2 $config{cflags}" if ($target =~ /mips32/);
1078         $config{cflags}="-mips3 $config{cflags}" if ($target =~ /mips64/);
1079 }
1080
1081 my $no_shared_warn=0;
1082 my $no_user_cflags=0;
1083 my $no_user_defines=0;
1084
1085 # The DSO code currently always implements all functions so that no
1086 # applications will have to worry about that from a compilation point
1087 # of view. However, the "method"s may return zero unless that platform
1088 # has support compiled in for them. Currently each method is enabled
1089 # by a define "DSO_<name>" ... we translate the "dso_scheme" config
1090 # string entry into using the following logic;
1091 if (!$disabled{dso} && $target{dso_scheme} ne "")
1092         {
1093         $target{dso_scheme} =~ tr/[a-z]/[A-Z]/;
1094         if ($target{dso_scheme} eq "DLFCN")
1095                 {
1096                 unshift @{$config{defines}}, "DSO_DLFCN", "HAVE_DLFCN_H";
1097                 }
1098         elsif ($target{dso_scheme} eq "DLFCN_NO_H")
1099                 {
1100                 unshift @{$config{defines}}, "DSO_DLFCN";
1101                 }
1102         else
1103                 {
1104                 unshift @{$config{defines}}, "DSO_$target{dso_scheme}";
1105                 }
1106         }
1107
1108 $config{ex_libs}="$libs$config{ex_libs}" if ($libs ne "");
1109
1110 # If threads aren't disabled, check how possible they are
1111 unless ($disabled{threads}) {
1112     if ($auto_threads) {
1113         # Enabled by default, disable it forcibly if unavailable
1114         if ($target{thread_scheme} eq "(unknown)") {
1115             $disabled{threads} = "unavailable";
1116         }
1117     } else {
1118         # The user chose to enable threads explicitly, let's see
1119         # if there's a chance that's possible
1120         if ($target{thread_scheme} eq "(unknown)") {
1121             # If the user asked for "threads" and we don't have internal
1122             # knowledge how to do it, [s]he is expected to provide any
1123             # system-dependent compiler options that are necessary.  We
1124             # can't truly check that the given options are correct, but
1125             # we expect the user to know what [s]He is doing.
1126             if ($no_user_cflags && $no_user_defines) {
1127                 die "You asked for multi-threading support, but didn't\n"
1128                     ,"provide any system-specific compiler options\n";
1129             }
1130         }
1131     }
1132 }
1133
1134 # If threads still aren't disabled, add a C macro to ensure the source
1135 # code knows about it.  Any other flag is taken care of by the configs.
1136 unless($disabled{threads}) {
1137     foreach (("defines", "openssl_thread_defines")) {
1138         push @{$config{$_}}, "OPENSSL_THREADS";
1139     }
1140 }
1141
1142 # With "deprecated" disable all deprecated features.
1143 if (defined($disabled{"deprecated"})) {
1144         $config{api} = $maxapi;
1145 }
1146
1147 if ($target{shared_target} eq "")
1148         {
1149         $no_shared_warn = 1
1150             if (!$disabled{shared} || !$disabled{"dynamic-engine"});
1151         $disabled{shared} = "no-shared-target";
1152         $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
1153             "no-shared-target";
1154         }
1155
1156 if ($disabled{"dynamic-engine"}) {
1157         push @{$config{defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
1158         $config{dynamic_engines} = 0;
1159 } else {
1160         push @{$config{defines}}, "OPENSSL_NO_STATIC_ENGINE";
1161         $config{dynamic_engines} = 1;
1162 }
1163
1164 unless ($disabled{asan}) {
1165     $config{cflags} .= "-fsanitize=address ";
1166 }
1167
1168 unless ($disabled{ubsan}) {
1169     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
1170     # platforms.
1171     $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all ";
1172 }
1173
1174 unless ($disabled{msan}) {
1175   $config{cflags} .= "-fsanitize=memory ";
1176 }
1177
1178 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
1179         && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
1180     $config{cflags} .= "-fno-omit-frame-pointer -g ";
1181 }
1182 #
1183 # Platform fix-ups
1184 #
1185
1186 # This saves the build files from having to check
1187 if ($disabled{pic})
1188         {
1189         $target{shared_cflag} = $target{shared_ldflag} =
1190                 $target{shared_rcflag} = "";
1191         }
1192 else
1193         {
1194         push @{$config{defines}}, "OPENSSL_PIC";
1195         }
1196
1197 if ($target{sys_id} ne "")
1198         {
1199         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1200         }
1201
1202 unless ($disabled{asm}) {
1203     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1204     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1205
1206     # bn-586 is the only one implementing bn_*_part_words
1207     push @{$config{defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1208     push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/);
1209
1210     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1211     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1212     push @{$config{defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1213
1214     if ($target{sha1_asm_src}) {
1215         push @{$config{defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1216         push @{$config{defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1217         push @{$config{defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1218     }
1219     if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
1220         push @{$config{defines}}, "RC4_ASM";
1221     }
1222     if ($target{md5_asm_src}) {
1223         push @{$config{defines}}, "MD5_ASM";
1224     }
1225     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1226     if ($target{rmd160_asm_src}) {
1227         push @{$config{defines}}, "RMD160_ASM";
1228     }
1229     if ($target{aes_asm_src}) {
1230         push @{$config{defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1231         # aes-ctr.fake is not a real file, only indication that assembler
1232         # module implements AES_ctr32_encrypt...
1233         push @{$config{defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1234         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1235         push @{$config{defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1236         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2);
1237         push @{$config{defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1238         push @{$config{defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1239     }
1240     if ($target{wp_asm_src} =~ /mmx/) {
1241         if ($config{processor} eq "386") {
1242             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1243         } elsif (!$disabled{"whirlpool"}) {
1244             push @{$config{defines}}, "WHIRLPOOL_ASM";
1245         }
1246     }
1247     if ($target{modes_asm_src} =~ /ghash-/) {
1248         push @{$config{defines}}, "GHASH_ASM";
1249     }
1250     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1251         push @{$config{defines}}, "ECP_NISTZ256_ASM";
1252     }
1253     if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
1254         push @{$config{defines}}, "PADLOCK_ASM";
1255     }
1256     if ($target{poly1305_asm_src} ne "") {
1257         push @{$config{defines}}, "POLY1305_ASM";
1258     }
1259 }
1260
1261 my %predefined;
1262
1263 if ($^O ne "VMS") {
1264     my $cc = "$config{cross_compile_prefix}$target{cc}";
1265
1266     # collect compiler pre-defines from gcc or gcc-alike...
1267     open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
1268     while (<PIPE>) {
1269         m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
1270         $predefined{$1} = $2 // "";
1271     }
1272     close(PIPE);
1273
1274     if (!$disabled{makedepend}) {
1275         # We know that GNU C version 3 and up as well as all clang
1276         # versions support dependency generation
1277         if ($predefined{__GNUC__} >= 3) {
1278             $config{makedepprog} = $cc;
1279         } else {
1280             $config{makedepprog} = which('makedepend');
1281             $disabled{makedepend} = "unavailable" unless $config{makedepprog};
1282         }
1283     }
1284 }
1285
1286
1287
1288 # Deal with bn_ops ###################################################
1289
1290 $config{bn_ll}                  =0;
1291 $config{export_var_as_fn}       =0;
1292 my $def_int="unsigned int";
1293 $config{rc4_int}                =$def_int;
1294 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1295
1296 my $count = 0;
1297 foreach (sort split(/\s+/,$target{bn_ops})) {
1298     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1299     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1300     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1301     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1302     ($config{b64l},$config{b64},$config{b32})
1303         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1304     ($config{b64l},$config{b64},$config{b32})
1305         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1306     ($config{b64l},$config{b64},$config{b32})
1307         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1308 }
1309 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1310     if $count > 1;
1311
1312
1313 # Hack cflags for better warnings (dev option) #######################
1314
1315 # "Stringify" the C flags string.  This permits it to be made part of a string
1316 # and works as well on command lines.
1317 $config{cflags} =~ s/([\\\"])/\\$1/g;
1318
1319 if (defined($config{api})) {
1320     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1321     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1322     push @{$config{defines}}, $apiflag;
1323 }
1324
1325 if (defined($predefined{__clang__}) && !$disabled{asm}) {
1326     $config{cflags} .= " -Qunused-arguments";
1327 }
1328
1329 if ($strict_warnings)
1330         {
1331         my $wopt;
1332         my $gccver = $predefined{__GNUC__} // -1;
1333
1334         die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike"
1335             unless $gccver >= 4;
1336         $gcc_devteam_warn .= " -Wmisleading-indentation" if $gccver >= 6;
1337         foreach $wopt (split /\s+/, $gcc_devteam_warn)
1338                 {
1339                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1340                 }
1341         if (defined($predefined{__clang__}))
1342                 {
1343                 foreach $wopt (split /\s+/, $clang_devteam_warn)
1344                         {
1345                         $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1346                         }
1347                 }
1348         }
1349
1350 unless ($disabled{"crypto-mdebug-backtrace"})
1351         {
1352         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1353                 {
1354                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1355                 }
1356         if ($target =~ /^BSD-/)
1357                 {
1358                 $config{ex_libs} .= " -lexecinfo";
1359                 }
1360         }
1361
1362 if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; $config{cxxflags}="$config{cxxflags}$user_cflags";}
1363 else                    { $no_user_cflags=1;  }
1364 if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; }
1365 else               { $no_user_defines=1;    }
1366
1367 # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
1368
1369 unless ($disabled{afalgeng}) {
1370     $config{afalgeng}="";
1371     if ($target =~ m/^linux/) {
1372         my $minver = 4*10000 + 1*100 + 0;
1373         if ($config{cross_compile_prefix} eq "") {
1374             my $verstr = `uname -r`;
1375             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1376             ($mi2) = $mi2 =~ /(\d+)/;
1377             my $ver = $ma*10000 + $mi1*100 + $mi2;
1378             if ($ver < $minver) {
1379                 $disabled{afalgeng} = "too-old-kernel";
1380             } else {
1381                 push @{$config{engdirs}}, "afalg";
1382             }
1383         } else {
1384             $disabled{afalgeng} = "cross-compiling";
1385         }
1386     } else {
1387         $disabled{afalgeng}  = "not-linux";
1388     }
1389 }
1390
1391 push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
1392
1393 # If we use the unified build, collect information from build.info files
1394 my %unified_info = ();
1395
1396 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1397 if ($builder eq "unified") {
1398     use with_fallback qw(Text::Template);
1399
1400     sub cleandir {
1401         my $base = shift;
1402         my $dir = shift;
1403         my $relativeto = shift || ".";
1404
1405         $dir = catdir($base,$dir) unless isabsolute($dir);
1406
1407         # Make sure the directories we're building in exists
1408         mkpath($dir);
1409
1410         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1411         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1412         return $res;
1413     }
1414
1415     sub cleanfile {
1416         my $base = shift;
1417         my $file = shift;
1418         my $relativeto = shift || ".";
1419
1420         $file = catfile($base,$file) unless isabsolute($file);
1421
1422         my $d = dirname($file);
1423         my $f = basename($file);
1424
1425         # Make sure the directories we're building in exists
1426         mkpath($d);
1427
1428         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1429         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1430         return $res;
1431     }
1432
1433     # Store the name of the template file we will build the build file from
1434     # in %config.  This may be useful for the build file itself.
1435     my @build_file_template_names =
1436         ( $builder_platform."-".$target{build_file}.".tmpl",
1437           $target{build_file}.".tmpl" );
1438     my @build_file_templates = ();
1439
1440     # First, look in the user provided directory, if given
1441     if (defined $ENV{$local_config_envname}) {
1442         @build_file_templates =
1443             map {
1444                 if ($^O eq 'VMS') {
1445                     # VMS environment variables are logical names,
1446                     # which can be used as is
1447                     $local_config_envname . ':' . $_;
1448                 } else {
1449                     catfile($ENV{$local_config_envname}, $_);
1450                 }
1451             }
1452             @build_file_template_names;
1453     }
1454     # Then, look in our standard directory
1455     push @build_file_templates,
1456         ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
1457           @build_file_template_names );
1458
1459     my $build_file_template;
1460     for $_ (@build_file_templates) {
1461         $build_file_template = $_;
1462         last if -f $build_file_template;
1463
1464         $build_file_template = undef;
1465     }
1466     if (!defined $build_file_template) {
1467         die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
1468     }
1469     $config{build_file_templates}
1470       = [ $build_file_template,
1471           cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
1472                     $blddir) ];
1473
1474     my @build_infos = ( [ ".", "build.info" ] );
1475     foreach (@{$config{dirs}}) {
1476         push @build_infos, [ $_, "build.info" ]
1477             if (-f catfile($srcdir, $_, "build.info"));
1478     }
1479     foreach (@{$config{sdirs}}) {
1480         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1481             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1482     }
1483     foreach (@{$config{engdirs}}) {
1484         push @build_infos, [ catdir("engines", $_), "build.info" ]
1485             if (-f catfile($srcdir, "engines", $_, "build.info"));
1486     }
1487     foreach (@{$config{tdirs}}) {
1488         push @build_infos, [ catdir("test", $_), "build.info" ]
1489             if (-f catfile($srcdir, "test", $_, "build.info"));
1490     }
1491
1492     $config{build_infos} = [ ];
1493
1494     foreach (@build_infos) {
1495         my $sourced = catdir($srcdir, $_->[0]);
1496         my $buildd = catdir($blddir, $_->[0]);
1497
1498         mkpath($buildd);
1499
1500         my $f = $_->[1];
1501         # The basic things we're trying to build
1502         my @programs = ();
1503         my @programs_install = ();
1504         my @libraries = ();
1505         my @libraries_install = ();
1506         my @engines = ();
1507         my @engines_install = ();
1508         my @scripts = ();
1509         my @scripts_install = ();
1510         my @extra = ();
1511         my @overrides = ();
1512         my @intermediates = ();
1513         my @rawlines = ();
1514
1515         my %ordinals = ();
1516         my %sources = ();
1517         my %shared_sources = ();
1518         my %includes = ();
1519         my %depends = ();
1520         my %renames = ();
1521         my %sharednames = ();
1522         my %generate = ();
1523
1524         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1525         my $template =
1526             Text::Template->new(TYPE => 'FILE',
1527                                 SOURCE => catfile($sourced, $f),
1528                                 PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
1529         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1530         my @text =
1531             split /^/m,
1532             $template->fill_in(HASH => { config => \%config,
1533                                          target => \%target,
1534                                          disabled => \%disabled,
1535                                          withargs => \%withargs,
1536                                          builddir => abs2rel($buildd, $blddir),
1537                                          sourcedir => abs2rel($sourced, $blddir),
1538                                          buildtop => abs2rel($blddir, $blddir),
1539                                          sourcetop => abs2rel($srcdir, $blddir) },
1540                                DELIMITERS => [ "{-", "-}" ]);
1541
1542         # The top item of this stack has the following values
1543         # -2 positive already run and we found ELSE (following ELSIF should fail)
1544         # -1 positive already run (skip until ENDIF)
1545         # 0 negatives so far (if we're at a condition, check it)
1546         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1547         # 2 positive ELSE (following ELSIF should fail)
1548         my @skip = ();
1549         collect_information(
1550             collect_from_array([ @text ],
1551                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1552                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1553             # Info we're looking for
1554             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1555             => sub {
1556                 if (! @skip || $skip[$#skip] > 0) {
1557                     push @skip, !! $1;
1558                 } else {
1559                     push @skip, -1;
1560                 }
1561             },
1562             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1563             => sub { die "ELSIF out of scope" if ! @skip;
1564                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1565                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1566                      $skip[$#skip] = !! $1
1567                          if $skip[$#skip] == 0; },
1568             qr/^\s*ELSE\s*$/
1569             => sub { die "ELSE out of scope" if ! @skip;
1570                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1571                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1572             qr/^\s*ENDIF\s*$/
1573             => sub { die "ENDIF out of scope" if ! @skip;
1574                      pop @skip; },
1575             qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
1576             => sub {
1577                 if (!@skip || $skip[$#skip] > 0) {
1578                     my $install = $1;
1579                     my @x = tokenize($2);
1580                     push @programs, @x;
1581                     push @programs_install, @x unless $install;
1582                 }
1583             },
1584             qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
1585             => sub {
1586                 if (!@skip || $skip[$#skip] > 0) {
1587                     my $install = $1;
1588                     my @x = tokenize($2);
1589                     push @libraries, @x;
1590                     push @libraries_install, @x unless $install;
1591                 }
1592             },
1593             qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
1594             => sub {
1595                 if (!@skip || $skip[$#skip] > 0) {
1596                     my $install = $1;
1597                     my @x = tokenize($2);
1598                     push @engines, @x;
1599                     push @engines_install, @x unless $install;
1600                 }
1601             },
1602             qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
1603             => sub {
1604                 if (!@skip || $skip[$#skip] > 0) {
1605                     my $install = $1;
1606                     my @x = tokenize($2);
1607                     push @scripts, @x;
1608                     push @scripts_install, @x unless $install;
1609                 }
1610             },
1611             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1612             => sub { push @extra, tokenize($1)
1613                          if !@skip || $skip[$#skip] > 0 },
1614             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1615             => sub { push @overrides, tokenize($1)
1616                          if !@skip || $skip[$#skip] > 0 },
1617
1618             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1619             => sub { push @{$ordinals{$1}}, tokenize($2)
1620                          if !@skip || $skip[$#skip] > 0 },
1621             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1622             => sub { push @{$sources{$1}}, tokenize($2)
1623                          if !@skip || $skip[$#skip] > 0 },
1624             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1625             => sub { push @{$shared_sources{$1}}, tokenize($2)
1626                          if !@skip || $skip[$#skip] > 0 },
1627             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1628             => sub { push @{$includes{$1}}, tokenize($2)
1629                          if !@skip || $skip[$#skip] > 0 },
1630             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
1631             => sub { push @{$depends{$1}}, tokenize($2)
1632                          if !@skip || $skip[$#skip] > 0 },
1633             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1634             => sub { push @{$generate{$1}}, $2
1635                          if !@skip || $skip[$#skip] > 0 },
1636             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1637             => sub { push @{$renames{$1}}, tokenize($2)
1638                          if !@skip || $skip[$#skip] > 0 },
1639             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1640             => sub { push @{$sharednames{$1}}, tokenize($2)
1641                          if !@skip || $skip[$#skip] > 0 },
1642             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1643             => sub {
1644                 my $lineiterator = shift;
1645                 my $target_kind = $1;
1646                 while (defined $lineiterator->()) {
1647                     s|\R$||;
1648                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1649                         die "ENDRAW doesn't match BEGINRAW"
1650                             if $1 ne $target_kind;
1651                         last;
1652                     }
1653                     next if @skip && $skip[$#skip] <= 0;
1654                     push @rawlines,  $_
1655                         if ($target_kind eq $target{build_file}
1656                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1657                 }
1658             },
1659             qr/^\s*(?:#.*)?$/ => sub { },
1660             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1661             "BEFORE" => sub {
1662                 if ($buildinfo_debug) {
1663                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1664                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1665                 }
1666             },
1667             "AFTER" => sub {
1668                 if ($buildinfo_debug) {
1669                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1670                 }
1671             },
1672             );
1673         die "runaway IF?" if (@skip);
1674
1675         foreach (keys %renames) {
1676             die "$_ renamed to more than one thing: "
1677                 ,join(" ", @{$renames{$_}}),"\n"
1678                 if scalar @{$renames{$_}} > 1;
1679             my $dest = cleanfile($buildd, $_, $blddir);
1680             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1681             die "$dest renamed to more than one thing: "
1682                 ,$unified_info{rename}->{$dest}, $to
1683                 unless !defined($unified_info{rename}->{$dest})
1684                 or $unified_info{rename}->{$dest} eq $to;
1685             $unified_info{rename}->{$dest} = $to;
1686         }
1687
1688         foreach (@programs) {
1689             my $program = cleanfile($buildd, $_, $blddir);
1690             if ($unified_info{rename}->{$program}) {
1691                 $program = $unified_info{rename}->{$program};
1692             }
1693             $unified_info{programs}->{$program} = 1;
1694         }
1695
1696         foreach (@programs_install) {
1697             my $program = cleanfile($buildd, $_, $blddir);
1698             if ($unified_info{rename}->{$program}) {
1699                 $program = $unified_info{rename}->{$program};
1700             }
1701             $unified_info{install}->{programs}->{$program} = 1;
1702         }
1703
1704         foreach (@libraries) {
1705             my $library = cleanfile($buildd, $_, $blddir);
1706             if ($unified_info{rename}->{$library}) {
1707                 $library = $unified_info{rename}->{$library};
1708             }
1709             $unified_info{libraries}->{$library} = 1;
1710         }
1711
1712         foreach (@libraries_install) {
1713             my $library = cleanfile($buildd, $_, $blddir);
1714             if ($unified_info{rename}->{$library}) {
1715                 $library = $unified_info{rename}->{$library};
1716             }
1717             $unified_info{install}->{libraries}->{$library} = 1;
1718         }
1719
1720         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
1721 ENGINES can only be used if configured with 'dynamic-engine'.
1722 This is usually a fault in a build.info file.
1723 EOF
1724         foreach (@engines) {
1725             my $library = cleanfile($buildd, $_, $blddir);
1726             if ($unified_info{rename}->{$library}) {
1727                 $library = $unified_info{rename}->{$library};
1728             }
1729             $unified_info{engines}->{$library} = 1;
1730         }
1731
1732         foreach (@engines_install) {
1733             my $library = cleanfile($buildd, $_, $blddir);
1734             if ($unified_info{rename}->{$library}) {
1735                 $library = $unified_info{rename}->{$library};
1736             }
1737             $unified_info{install}->{engines}->{$library} = 1;
1738         }
1739
1740         foreach (@scripts) {
1741             my $script = cleanfile($buildd, $_, $blddir);
1742             if ($unified_info{rename}->{$script}) {
1743                 $script = $unified_info{rename}->{$script};
1744             }
1745             $unified_info{scripts}->{$script} = 1;
1746         }
1747
1748         foreach (@scripts_install) {
1749             my $script = cleanfile($buildd, $_, $blddir);
1750             if ($unified_info{rename}->{$script}) {
1751                 $script = $unified_info{rename}->{$script};
1752             }
1753             $unified_info{install}->{scripts}->{$script} = 1;
1754         }
1755
1756         foreach (@extra) {
1757             my $extra = cleanfile($buildd, $_, $blddir);
1758             $unified_info{extra}->{$extra} = 1;
1759         }
1760
1761         foreach (@overrides) {
1762             my $override = cleanfile($buildd, $_, $blddir);
1763             $unified_info{overrides}->{$override} = 1;
1764         }
1765
1766         push @{$unified_info{rawlines}}, @rawlines;
1767
1768         unless ($disabled{shared}) {
1769             # Check sharednames.
1770             foreach (keys %sharednames) {
1771                 my $dest = cleanfile($buildd, $_, $blddir);
1772                 if ($unified_info{rename}->{$dest}) {
1773                     $dest = $unified_info{rename}->{$dest};
1774                 }
1775                 die "shared_name for $dest with multiple values: "
1776                     ,join(" ", @{$sharednames{$_}}),"\n"
1777                     if scalar @{$sharednames{$_}} > 1;
1778                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
1779                 die "shared_name found for a library $dest that isn't defined\n"
1780                     unless $unified_info{libraries}->{$dest};
1781                 die "shared_name for $dest with multiple values: "
1782                     ,$unified_info{sharednames}->{$dest}, ", ", $to
1783                     unless !defined($unified_info{sharednames}->{$dest})
1784                     or $unified_info{sharednames}->{$dest} eq $to;
1785                 $unified_info{sharednames}->{$dest} = $to;
1786             }
1787
1788             # Additionally, we set up sharednames for libraries that don't
1789             # have any, as themselves.  Only for libraries that aren't
1790             # explicitely static.
1791             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
1792                 if (!defined $unified_info{sharednames}->{$_}) {
1793                     $unified_info{sharednames}->{$_} = $_
1794                 }
1795             }
1796
1797             # Check that we haven't defined any library as both shared and
1798             # explicitely static.  That is forbidden.
1799             my @doubles = ();
1800             foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
1801                 (my $l = $_) =~ s/\.a$//;
1802                 push @doubles, $l if defined $unified_info{sharednames}->{$l};
1803             }
1804             die "these libraries are both explicitely static and shared:\n  ",
1805                 join(" ", @doubles), "\n"
1806                 if @doubles;
1807         }
1808
1809         foreach (keys %ordinals) {
1810             my $dest = $_;
1811             my $ddest = cleanfile($buildd, $_, $blddir);
1812             if ($unified_info{rename}->{$ddest}) {
1813                 $ddest = $unified_info{rename}->{$ddest};
1814             }
1815             foreach (@{$ordinals{$dest}}) {
1816                 my %known_ordinals =
1817                     (
1818                      crypto =>
1819                      cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
1820                      ssl =>
1821                      cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
1822                     );
1823                 my $o = $known_ordinals{$_};
1824                 die "Ordinals for $ddest defined more than once\n"
1825                     if $unified_info{ordinals}->{$ddest};
1826                 $unified_info{ordinals}->{$ddest} = [ $_, $o ];
1827             }
1828         }
1829
1830         foreach (keys %sources) {
1831             my $dest = $_;
1832             my $ddest = cleanfile($buildd, $_, $blddir);
1833             if ($unified_info{rename}->{$ddest}) {
1834                 $ddest = $unified_info{rename}->{$ddest};
1835             }
1836             foreach (@{$sources{$dest}}) {
1837                 my $s = cleanfile($sourced, $_, $blddir);
1838
1839                 # If it isn't in the source tree, we assume it's generated
1840                 # in the build tree
1841                 if (! -f $s) {
1842                     $s = cleanfile($buildd, $_, $blddir);
1843                 }
1844                 # We recognise C++, C and asm files
1845                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
1846                     my $o = $_;
1847                     $o =~ s/\.[csS]$/.o/; # C and assembler
1848                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
1849                     $o = cleanfile($buildd, $o, $blddir);
1850                     $unified_info{sources}->{$ddest}->{$o} = 1;
1851                     $unified_info{sources}->{$o}->{$s} = 1;
1852                 } else {
1853                     $unified_info{sources}->{$ddest}->{$s} = 1;
1854                 }
1855             }
1856         }
1857
1858         foreach (keys %shared_sources) {
1859             my $dest = $_;
1860             my $ddest = cleanfile($buildd, $_, $blddir);
1861             if ($unified_info{rename}->{$ddest}) {
1862                 $ddest = $unified_info{rename}->{$ddest};
1863             }
1864             foreach (@{$shared_sources{$dest}}) {
1865                 my $s = cleanfile($sourced, $_, $blddir);
1866
1867                 # If it isn't in the source tree, we assume it's generated
1868                 # in the build tree
1869                 if (! -f $s) {
1870                     $s = cleanfile($buildd, $_, $blddir);
1871                 }
1872                 # We recognise C++, C and asm files
1873                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
1874                     my $o = $_;
1875                     $o =~ s/\.[csS]$/.o/; # C and assembler
1876                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
1877                     $o = cleanfile($buildd, $o, $blddir);
1878                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
1879                     $unified_info{sources}->{$o}->{$s} = 1;
1880                 } else {
1881                     die "unrecognised source file type for shared library: $s\n";
1882                 }
1883             }
1884         }
1885
1886         foreach (keys %generate) {
1887             my $dest = $_;
1888             my $ddest = cleanfile($buildd, $_, $blddir);
1889             if ($unified_info{rename}->{$ddest}) {
1890                 $ddest = $unified_info{rename}->{$ddest};
1891             }
1892             die "more than one generator for $dest: "
1893                     ,join(" ", @{$generate{$_}}),"\n"
1894                     if scalar @{$generate{$_}} > 1;
1895             my @generator = split /\s+/, $generate{$dest}->[0];
1896             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
1897             $unified_info{generate}->{$ddest} = [ @generator ];
1898         }
1899
1900         foreach (keys %depends) {
1901             my $dest = $_;
1902             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
1903
1904             # If the destination doesn't exist in source, it can only be
1905             # a generated file in the build tree.
1906             if ($ddest ne "" && ! -f $ddest) {
1907                 $ddest = cleanfile($buildd, $_, $blddir);
1908                 if ($unified_info{rename}->{$ddest}) {
1909                     $ddest = $unified_info{rename}->{$ddest};
1910                 }
1911             }
1912             foreach (@{$depends{$dest}}) {
1913                 my $d = cleanfile($sourced, $_, $blddir);
1914
1915                 # If we know it's generated, or assume it is because we can't
1916                 # find it in the source tree, we set file we depend on to be
1917                 # in the build tree rather than the source tree, and assume
1918                 # and that there are lines to build it in a BEGINRAW..ENDRAW
1919                 # section or in the Makefile template.
1920                 if (! -f $d
1921                     || (grep { $d eq $_ }
1922                         map { cleanfile($srcdir, $_, $blddir) }
1923                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
1924                     $d = cleanfile($buildd, $_, $blddir);
1925                 }
1926                 # Take note if the file to depend on is being renamed
1927                 # Take extra care with files ending with .a, they should
1928                 # be treated without that extension, and the extension
1929                 # should be added back after treatment.
1930                 $d =~ /(\.a)?$/;
1931                 my $e = $1 // "";
1932                 $d = $`;
1933                 if ($unified_info{rename}->{$d}) {
1934                     $d = $unified_info{rename}->{$d};
1935                 }
1936                 $d .= $e;
1937                 $unified_info{depends}->{$ddest}->{$d} = 1;
1938                 # If we depend on a header file or a perl module, let's make
1939                 # sure it can get included
1940                 if ($dest ne "" && $d =~ /\.(h|pm)$/) {
1941                     my $i = dirname($d);
1942                     push @{$unified_info{includes}->{$ddest}->{source}}, $i
1943                         unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}->{source}};
1944                 }
1945             }
1946         }
1947
1948         foreach (keys %includes) {
1949             my $dest = $_;
1950             my $ddest = cleanfile($sourced, $_, $blddir);
1951
1952             # If the destination doesn't exist in source, it can only be
1953             # a generated file in the build tree.
1954             if (! -f $ddest) {
1955                 $ddest = cleanfile($buildd, $_, $blddir);
1956                 if ($unified_info{rename}->{$ddest}) {
1957                     $ddest = $unified_info{rename}->{$ddest};
1958                 }
1959             }
1960             foreach (@{$includes{$dest}}) {
1961                 my $is = cleandir($sourced, $_, $blddir);
1962                 my $ib = cleandir($buildd, $_, $blddir);
1963                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
1964                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
1965                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
1966                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
1967             }
1968         }
1969     }
1970
1971     ### Make unified_info a bit more efficient
1972     # One level structures
1973     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
1974         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
1975     }
1976     # Two level structures
1977     foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
1978         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
1979             $unified_info{$l1}->{$l2} =
1980                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
1981         }
1982     }
1983     # Includes
1984     foreach my $dest (sort keys %{$unified_info{includes}}) {
1985         if (defined($unified_info{includes}->{$dest}->{build})) {
1986             my @source_includes =
1987                 ( @{$unified_info{includes}->{$dest}->{source}} );
1988             $unified_info{includes}->{$dest} =
1989                 [ @{$unified_info{includes}->{$dest}->{build}} ];
1990             foreach my $inc (@source_includes) {
1991                 push @{$unified_info{includes}->{$dest}}, $inc
1992                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
1993             }
1994         } else {
1995             $unified_info{includes}->{$dest} =
1996                 [ @{$unified_info{includes}->{$dest}->{source}} ];
1997         }
1998     }
1999 }
2000
2001 # For the schemes that need it, we provide the old *_obj configs
2002 # from the *_asm_obj ones
2003 foreach (grep /_(asm|aux)_src$/, keys %target) {
2004     my $src = $_;
2005     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
2006     $target{$obj} = $target{$src};
2007     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
2008     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
2009 }
2010
2011 # Write down our configuration where it fits #########################
2012
2013 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
2014 print OUT <<"EOF";
2015 package configdata;
2016
2017 use strict;
2018 use warnings;
2019
2020 use Exporter;
2021 #use vars qw(\@ISA \@EXPORT);
2022 our \@ISA = qw(Exporter);
2023 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
2024
2025 EOF
2026 print OUT "our %config = (\n";
2027 foreach (sort keys %config) {
2028     if (ref($config{$_}) eq "ARRAY") {
2029         print OUT "  ", $_, " => [ ", join(", ",
2030                                            map { quotify("perl", $_) }
2031                                            @{$config{$_}}), " ],\n";
2032     } else {
2033         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
2034     }
2035 }
2036 print OUT <<"EOF";
2037 );
2038
2039 EOF
2040 print OUT "our %target = (\n";
2041 foreach (sort keys %target) {
2042     if (ref($target{$_}) eq "ARRAY") {
2043         print OUT "  ", $_, " => [ ", join(", ",
2044                                            map { quotify("perl", $_) }
2045                                            @{$target{$_}}), " ],\n";
2046     } else {
2047         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
2048     }
2049 }
2050 print OUT <<"EOF";
2051 );
2052
2053 EOF
2054 print OUT "our \%available_protocols = (\n";
2055 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
2056 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
2057 print OUT <<"EOF";
2058 );
2059
2060 EOF
2061 print OUT "our \@disablables = (\n";
2062 foreach (@disablables) {
2063     print OUT "  ", quotify("perl", $_), ",\n";
2064 }
2065 print OUT <<"EOF";
2066 );
2067
2068 EOF
2069 print OUT "our \%disabled = (\n";
2070 foreach (sort keys %disabled) {
2071     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
2072 }
2073 print OUT <<"EOF";
2074 );
2075
2076 EOF
2077 print OUT "our %withargs = (\n";
2078 foreach (sort keys %withargs) {
2079     if (ref($withargs{$_}) eq "ARRAY") {
2080         print OUT "  ", $_, " => [ ", join(", ",
2081                                            map { quotify("perl", $_) }
2082                                            @{$withargs{$_}}), " ],\n";
2083     } else {
2084         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
2085     }
2086 }
2087 print OUT <<"EOF";
2088 );
2089
2090 EOF
2091 if ($builder eq "unified") {
2092     my $recurse;
2093     $recurse = sub {
2094         my $indent = shift;
2095         foreach (@_) {
2096             if (ref $_ eq "ARRAY") {
2097                 print OUT " "x$indent, "[\n";
2098                 foreach (@$_) {
2099                     $recurse->($indent + 4, $_);
2100                 }
2101                 print OUT " "x$indent, "],\n";
2102             } elsif (ref $_ eq "HASH") {
2103                 my %h = %$_;
2104                 print OUT " "x$indent, "{\n";
2105                 foreach (sort keys %h) {
2106                     if (ref $h{$_} eq "") {
2107                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
2108                     } else {
2109                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
2110                         $recurse->($indent + 8, $h{$_});
2111                     }
2112                 }
2113                 print OUT " "x$indent, "},\n";
2114             } else {
2115                 print OUT " "x$indent, quotify("perl", $_), ",\n";
2116             }
2117         }
2118     };
2119     print OUT "our %unified_info = (\n";
2120     foreach (sort keys %unified_info) {
2121         if (ref $unified_info{$_} eq "") {
2122             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
2123         } else {
2124             print OUT " "x4, quotify("perl", $_), " =>\n";
2125             $recurse->(8, $unified_info{$_});
2126         }
2127     }
2128     print OUT <<"EOF";
2129 );
2130
2131 EOF
2132 }
2133 print OUT "1;\n";
2134 close(OUT);
2135
2136 print "\n";
2137 print "PROCESSOR     =$config{processor}\n" if $config{processor};
2138 print "PERL          =$config{perl}\n";
2139 print "PERLVERSION   =$Config{version} for $Config{archname}\n";
2140 print "HASHBANGPERL  =$config{hashbangperl}\n";
2141 print "CC            =$config{cross_compile_prefix}$target{cc}\n";
2142 print "CFLAG         =$target{cflags} $config{cflags}\n";
2143 print "CXX           =$config{cross_compile_prefix}$target{cxx}\n"
2144     if defined $target{cxx};
2145 print "CXXFLAG       =$target{cxxflags} $config{cxxflags}\n"
2146     if defined $target{cxx};
2147 print "DEFINES       =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n";
2148 #print "RANLIB        =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
2149 #                             "$config{cross_compile_prefix}ranlib" :
2150 #                             "$target{ranlib}", "\n";
2151 print "EX_LIBS       =$target{ex_libs} $config{ex_libs}\n";
2152
2153 my %builders = (
2154     unified => sub {
2155         run_dofile(catfile($blddir, $target{build_file}),
2156                    @{$config{build_file_templates}});
2157     },
2158     );
2159
2160 $builders{$builder}->($builder_platform, @builder_opts);
2161
2162 print <<"EOF" if ($disabled{threads} eq "unavailable");
2163
2164 The library could not be configured for supporting multi-threaded
2165 applications as the compiler options required on this system are not known.
2166 See file INSTALL for details if you need multi-threading.
2167 EOF
2168
2169 print <<"EOF" if ($no_shared_warn);
2170
2171 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2172 platform, so we will pretend you gave the option 'no-pic', which also disables
2173 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2174 or position independent code, please let us know (but please first make sure
2175 you have tried with a current version of OpenSSL).
2176 EOF
2177
2178 print <<"EOF" if (-f catfile($srcdir, "configdata.pm") && $srcdir ne $blddir);
2179
2180 WARNING: there are indications that another build was made in the source
2181 directory.  This build may have picked up artifacts from that build, the
2182 safest course of action is to clean the source directory and redo this
2183 configuration.
2184 EOF
2185
2186 exit(0);
2187
2188 ######################################################################
2189 #
2190 # Helpers and utility functions
2191 #
2192
2193 # Configuration file reading #########################################
2194
2195 # Note: All of the helper functions are for lazy evaluation.  They all
2196 # return a CODE ref, which will return the intended value when evaluated.
2197 # Thus, whenever there's mention of a returned value, it's about that
2198 # intended value.
2199
2200 # Helper function to implement conditional inheritance depending on the
2201 # value of $disabled{asm}.  Used in inherit_from values as follows:
2202 #
2203 #      inherit_from => [ "template", asm("asm_tmpl") ]
2204 #
2205 sub asm {
2206     my @x = @_;
2207     sub {
2208         $disabled{asm} ? () : @x;
2209     }
2210 }
2211
2212 # Helper function to implement conditional value variants, with a default
2213 # plus additional values based on the value of $config{build_type}.
2214 # Arguments are given in hash table form:
2215 #
2216 #       picker(default => "Basic string: ",
2217 #              debug   => "debug",
2218 #              release => "release")
2219 #
2220 # When configuring with --debug, the resulting string will be
2221 # "Basic string: debug", and when not, it will be "Basic string: release"
2222 #
2223 # This can be used to create variants of sets of flags according to the
2224 # build type:
2225 #
2226 #       cflags => picker(default => "-Wall",
2227 #                        debug   => "-g -O0",
2228 #                        release => "-O3")
2229 #
2230 sub picker {
2231     my %opts = @_;
2232     return sub { add($opts{default} || (),
2233                      $opts{$config{build_type}} || ())->(); }
2234 }
2235
2236 # Helper function to combine several values of different types into one.
2237 # This is useful if you want to combine a string with the result of a
2238 # lazy function, such as:
2239 #
2240 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2241 #
2242 sub combine {
2243     my @stuff = @_;
2244     return sub { add(@stuff)->(); }
2245 }
2246
2247 # Helper function to implement conditional values depending on the value
2248 # of $disabled{threads}.  Can be used as follows:
2249 #
2250 #       cflags => combine("-Wall", threads("-pthread"))
2251 #
2252 sub threads {
2253     my @flags = @_;
2254     return sub { add($disabled{threads} ? () : @flags)->(); }
2255 }
2256
2257
2258
2259 our $add_called = 0;
2260 # Helper function to implement adding values to already existing configuration
2261 # values.  It handles elements that are ARRAYs, CODEs and scalars
2262 sub _add {
2263     my $separator = shift;
2264
2265     # If there's any ARRAY in the collection of values OR the separator
2266     # is undef, we will return an ARRAY of combined values, otherwise a
2267     # string of joined values with $separator as the separator.
2268     my $found_array = !defined($separator);
2269
2270     my @values =
2271         map {
2272             my $res = $_;
2273             while (ref($res) eq "CODE") {
2274                 $res = $res->();
2275             }
2276             if (defined($res)) {
2277                 if (ref($res) eq "ARRAY") {
2278                     $found_array = 1;
2279                     @$res;
2280                 } else {
2281                     $res;
2282                 }
2283             } else {
2284                 ();
2285             }
2286     } (@_);
2287
2288     $add_called = 1;
2289
2290     if ($found_array) {
2291         [ @values ];
2292     } else {
2293         join($separator, grep { defined($_) && $_ ne "" } @values);
2294     }
2295 }
2296 sub add_before {
2297     my $separator = " ";
2298     if (ref($_[$#_]) eq "HASH") {
2299         my $opts = pop;
2300         $separator = $opts->{separator};
2301     }
2302     my @x = @_;
2303     sub { _add($separator, @x, @_) };
2304 }
2305 sub add {
2306     my $separator = " ";
2307     if (ref($_[$#_]) eq "HASH") {
2308         my $opts = pop;
2309         $separator = $opts->{separator};
2310     }
2311     my @x = @_;
2312     sub { _add($separator, @_, @x) };
2313 }
2314
2315 # configuration reader, evaluates the input file as a perl script and expects
2316 # it to fill %targets with target configurations.  Those are then added to
2317 # %table.
2318 sub read_config {
2319     my $fname = shift;
2320     open(CONFFILE, "< $fname")
2321         or die "Can't open configuration file '$fname'!\n";
2322     my $x = $/;
2323     undef $/;
2324     my $content = <CONFFILE>;
2325     $/ = $x;
2326     close(CONFFILE);
2327     my %targets = ();
2328     {
2329         # Protect certain tables from tampering
2330         local %table = %::table;
2331
2332         eval $content;
2333         warn $@ if $@;
2334     }
2335
2336     # For each target, check that it's configured with a hash table.
2337     foreach (keys %targets) {
2338         if (ref($targets{$_}) ne "HASH") {
2339             if (ref($targets{$_}) eq "") {
2340                 warn "Deprecated target configuration for $_, ignoring...\n";
2341             } else {
2342                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
2343             }
2344             delete $targets{$_};
2345         } else {
2346             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
2347         }
2348     }
2349
2350     %table = (%table, %targets);
2351
2352 }
2353
2354 # configuration resolver.  Will only resolve all the lazy evaluation
2355 # codeblocks for the chosen target and all those it inherits from,
2356 # recursively
2357 sub resolve_config {
2358     my $target = shift;
2359     my @breadcrumbs = @_;
2360
2361 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
2362
2363     if (grep { $_ eq $target } @breadcrumbs) {
2364         die "inherit_from loop!  target backtrace:\n  "
2365             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
2366     }
2367
2368     if (!defined($table{$target})) {
2369         warn "Warning! target $target doesn't exist!\n";
2370         return ();
2371     }
2372     # Recurse through all inheritances.  They will be resolved on the
2373     # fly, so when this operation is done, they will all just be a
2374     # bunch of attributes with string values.
2375     # What we get here, though, are keys with references to lists of
2376     # the combined values of them all.  We will deal with lists after
2377     # this stage is done.
2378     my %combined_inheritance = ();
2379     if ($table{$target}->{inherit_from}) {
2380         my @inherit_from =
2381             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
2382         foreach (@inherit_from) {
2383             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
2384
2385             # 'template' is a marker that's considered private to
2386             # the config that had it.
2387             delete $inherited_config{template};
2388
2389             foreach (keys %inherited_config) {
2390                 if (!$combined_inheritance{$_}) {
2391                     $combined_inheritance{$_} = [];
2392                 }
2393                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
2394             }
2395         }
2396     }
2397
2398     # We won't need inherit_from in this target any more, since we've
2399     # resolved all the inheritances that lead to this
2400     delete $table{$target}->{inherit_from};
2401
2402     # Now is the time to deal with those lists.  Here's the place to
2403     # decide what shall be done with those lists, all based on the
2404     # values of the target we're currently dealing with.
2405     # - If a value is a coderef, it will be executed with the list of
2406     #   inherited values as arguments.
2407     # - If the corresponding key doesn't have a value at all or is the
2408     #   empty string, the inherited value list will be run through the
2409     #   default combiner (below), and the result becomes this target's
2410     #   value.
2411     # - Otherwise, this target's value is assumed to be a string that
2412     #   will simply override the inherited list of values.
2413     my $default_combiner = add();
2414
2415     my %all_keys =
2416         map { $_ => 1 } (keys %combined_inheritance,
2417                          keys %{$table{$target}});
2418
2419     sub process_values {
2420         my $object    = shift;
2421         my $inherited = shift;  # Always a [ list ]
2422         my $target    = shift;
2423         my $entry     = shift;
2424
2425         $add_called = 0;
2426
2427         while(ref($object) eq "CODE") {
2428             $object = $object->(@$inherited);
2429         }
2430         if (!defined($object)) {
2431             return ();
2432         }
2433         elsif (ref($object) eq "ARRAY") {
2434             local $add_called;  # To make sure recursive calls don't affect it
2435             return [ map { process_values($_, $inherited, $target, $entry) }
2436                      @$object ];
2437         } elsif (ref($object) eq "") {
2438             return $object;
2439         } else {
2440             die "cannot handle reference type ",ref($object)
2441                 ," found in target ",$target," -> ",$entry,"\n";
2442         }
2443     }
2444
2445     foreach (sort keys %all_keys) {
2446         my $previous = $combined_inheritance{$_};
2447
2448         # Current target doesn't have a value for the current key?
2449         # Assign it the default combiner, the rest of this loop body
2450         # will handle it just like any other coderef.
2451         if (!exists $table{$target}->{$_}) {
2452             $table{$target}->{$_} = $default_combiner;
2453         }
2454
2455         $table{$target}->{$_} = process_values($table{$target}->{$_},
2456                                                $combined_inheritance{$_},
2457                                                $target, $_);
2458         unless(defined($table{$target}->{$_})) {
2459             delete $table{$target}->{$_};
2460         }
2461 #        if ($extra_checks &&
2462 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
2463 #            warn "$_ got replaced in $target\n";
2464 #        }
2465     }
2466
2467     # Finally done, return the result.
2468     return %{$table{$target}};
2469 }
2470
2471 sub usage
2472         {
2473         print STDERR $usage;
2474         print STDERR "\npick os/compiler from:\n";
2475         my $j=0;
2476         my $i;
2477         my $k=0;
2478         foreach $i (sort keys %table)
2479                 {
2480                 next if $table{$i}->{template};
2481                 next if $i =~ /^debug/;
2482                 $k += length($i) + 1;
2483                 if ($k > 78)
2484                         {
2485                         print STDERR "\n";
2486                         $k=length($i);
2487                         }
2488                 print STDERR $i . " ";
2489                 }
2490         foreach $i (sort keys %table)
2491                 {
2492                 next if $table{$i}->{template};
2493                 next if $i !~ /^debug/;
2494                 $k += length($i) + 1;
2495                 if ($k > 78)
2496                         {
2497                         print STDERR "\n";
2498                         $k=length($i);
2499                         }
2500                 print STDERR $i . " ";
2501                 }
2502         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
2503         exit(1);
2504         }
2505
2506 sub run_dofile
2507 {
2508     my $out = shift;
2509     my @templates = @_;
2510
2511     unlink $out || warn "Can't remove $out, $!"
2512         if -f $out;
2513     foreach (@templates) {
2514         die "Can't open $_, $!" unless -f $_;
2515     }
2516     my $perlcmd = (quotify("maybeshell", $config{perl}))[0];
2517     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
2518     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
2519     system($cmd);
2520     exit 1 if $? != 0;
2521     rename("$out.new", $out) || die "Can't rename $out.new, $!";
2522 }
2523
2524 sub which
2525 {
2526     my ($name)=@_;
2527
2528     if (eval { require IPC::Cmd; 1; }) {
2529         IPC::Cmd->import();
2530         return scalar IPC::Cmd::can_run($name);
2531     } else {
2532         # if there is $directories component in splitpath,
2533         # then it's not something to test with $PATH...
2534         return $name if (File::Spec->splitpath($name))[1];
2535
2536         foreach (File::Spec->path()) {
2537             my $fullpath = catfile($_, "$name$target{exe_extension}");
2538             if (-f $fullpath and -x $fullpath) {
2539                 return $fullpath;
2540             }
2541         }
2542     }
2543 }
2544
2545 # Configuration printer ##############################################
2546
2547 sub print_table_entry
2548 {
2549     my $target = shift;
2550     my %target = resolve_config($target);
2551     my $type = shift;
2552
2553     # Don't print the templates
2554     return if $target{template};
2555
2556     my @sequence = (
2557         "sys_id",
2558         "cc",
2559         "cflags",
2560         "defines",
2561         "unistd",
2562         "ld",
2563         "lflags",
2564         "loutflag",
2565         "plib_lflags",
2566         "ex_libs",
2567         "bn_ops",
2568         "apps_aux_src",
2569         "cpuid_asm_src",
2570         "uplink_aux_src",
2571         "bn_asm_src",
2572         "ec_asm_src",
2573         "des_asm_src",
2574         "aes_asm_src",
2575         "bf_asm_src",
2576         "md5_asm_src",
2577         "cast_asm_src",
2578         "sha1_asm_src",
2579         "rc4_asm_src",
2580         "rmd160_asm_src",
2581         "rc5_asm_src",
2582         "wp_asm_src",
2583         "cmll_asm_src",
2584         "modes_asm_src",
2585         "padlock_asm_src",
2586         "chacha_asm_src",
2587         "poly1035_asm_src",
2588         "thread_scheme",
2589         "perlasm_scheme",
2590         "dso_scheme",
2591         "shared_target",
2592         "shared_cflag",
2593         "shared_defines",
2594         "shared_ldflag",
2595         "shared_rcflag",
2596         "shared_extension",
2597         "dso_extension",
2598         "obj_extension",
2599         "exe_extension",
2600         "ranlib",
2601         "ar",
2602         "arflags",
2603         "aroutflag",
2604         "rc",
2605         "rcflags",
2606         "rcoutflag",
2607         "mt",
2608         "mtflags",
2609         "mtinflag",
2610         "mtoutflag",
2611         "multilib",
2612         "build_scheme",
2613         );
2614
2615     if ($type eq "TABLE") {
2616         print "\n";
2617         print "*** $target\n";
2618         foreach (@sequence) {
2619             if (ref($target{$_}) eq "ARRAY") {
2620                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
2621             } else {
2622                 printf "\$%-12s = %s\n", $_, $target{$_};
2623             }
2624         }
2625     } elsif ($type eq "HASH") {
2626         my $largest =
2627             length((sort { length($a) <=> length($b) } @sequence)[-1]);
2628         print "    '$target' => {\n";
2629         foreach (@sequence) {
2630             if ($target{$_}) {
2631                 if (ref($target{$_}) eq "ARRAY") {
2632                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
2633                 } else {
2634                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
2635                 }
2636             }
2637         }
2638         print "    },\n";
2639     }
2640 }
2641
2642 # Utility routines ###################################################
2643
2644 # On VMS, if the given file is a logical name, File::Spec::Functions
2645 # will consider it an absolute path.  There are cases when we want a
2646 # purely syntactic check without checking the environment.
2647 sub isabsolute {
2648     my $file = shift;
2649
2650     # On non-platforms, we just use file_name_is_absolute().
2651     return file_name_is_absolute($file) unless $^O eq "VMS";
2652
2653     # If the file spec includes a device or a directory spec,
2654     # file_name_is_absolute() is perfectly safe.
2655     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
2656
2657     # Here, we know the given file spec isn't absolute
2658     return 0;
2659 }
2660
2661 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
2662 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
2663 # realpath() requires that at least all path components except the last is an
2664 # existing directory.  On VMS, the last component of the directory spec must
2665 # exist.
2666 sub absolutedir {
2667     my $dir = shift;
2668
2669     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
2670     # will return the volume name for the device, no matter what.  Also,
2671     # it will return an incorrect directory spec if the argument is a
2672     # directory that doesn't exist.
2673     if ($^O eq "VMS") {
2674         return rel2abs($dir);
2675     }
2676
2677     # We use realpath() on Unix, since no other will properly clean out
2678     # a directory spec.
2679     use Cwd qw/realpath/;
2680
2681     return realpath($dir);
2682 }
2683
2684 sub quotify {
2685     my %processors = (
2686         perl    => sub { my $x = shift;
2687                          $x =~ s/([\\\$\@"])/\\$1/g;
2688                          return '"'.$x.'"'; },
2689         maybeshell => sub { my $x = shift;
2690                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
2691                             if ($x ne $y || $x =~ m|\s|) {
2692                                 return '"'.$y.'"';
2693                             } else {
2694                                 return $x;
2695                             }
2696                         },
2697         );
2698     my $for = shift;
2699     my $processor =
2700         defined($processors{$for}) ? $processors{$for} : sub { shift; };
2701
2702     return map { $processor->($_); } @_;
2703 }
2704
2705 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
2706 # $filename is a file name to read from
2707 # $line_concat_cond_re is a regexp detecting a line continuation ending
2708 # $line_concat is a CODEref that takes care of concatenating two lines
2709 sub collect_from_file {
2710     my $filename = shift;
2711     my $line_concat_cond_re = shift;
2712     my $line_concat = shift;
2713
2714     open my $fh, $filename || die "unable to read $filename: $!\n";
2715     return sub {
2716         my $saved_line = "";
2717         $_ = "";
2718         while (<$fh>) {
2719             s|\R$||;
2720             if (defined $line_concat) {
2721                 $_ = $line_concat->($saved_line, $_);
2722                 $saved_line = "";
2723             }
2724             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2725                 $saved_line = $_;
2726                 next;
2727             }
2728             return $_;
2729         }
2730         die "$filename ending with continuation line\n" if $_;
2731         close $fh;
2732         return undef;
2733     }
2734 }
2735
2736 # collect_from_array($array, $line_concat_cond_re, $line_concat)
2737 # $array is an ARRAYref of lines
2738 # $line_concat_cond_re is a regexp detecting a line continuation ending
2739 # $line_concat is a CODEref that takes care of concatenating two lines
2740 sub collect_from_array {
2741     my $array = shift;
2742     my $line_concat_cond_re = shift;
2743     my $line_concat = shift;
2744     my @array = (@$array);
2745
2746     return sub {
2747         my $saved_line = "";
2748         $_ = "";
2749         while (defined($_ = shift @array)) {
2750             s|\R$||;
2751             if (defined $line_concat) {
2752                 $_ = $line_concat->($saved_line, $_);
2753                 $saved_line = "";
2754             }
2755             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2756                 $saved_line = $_;
2757                 next;
2758             }
2759             return $_;
2760         }
2761         die "input text ending with continuation line\n" if $_;
2762         return undef;
2763     }
2764 }
2765
2766 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
2767 # $lineiterator is a CODEref that delivers one line at a time.
2768 # All following arguments are regex/CODEref pairs, where the regexp detects a
2769 # line and the CODEref does something with the result of the regexp.
2770 sub collect_information {
2771     my $lineiterator = shift;
2772     my %collectors = @_;
2773
2774     while(defined($_ = $lineiterator->())) {
2775         s|\R$||;
2776         my $found = 0;
2777         if ($collectors{"BEFORE"}) {
2778             $collectors{"BEFORE"}->($_);
2779         }
2780         foreach my $re (keys %collectors) {
2781             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
2782                 $collectors{$re}->($lineiterator);
2783                 $found = 1;
2784             };
2785         }
2786         if ($collectors{"OTHERWISE"}) {
2787             $collectors{"OTHERWISE"}->($lineiterator, $_)
2788                 unless $found || !defined $collectors{"OTHERWISE"};
2789         }
2790         if ($collectors{"AFTER"}) {
2791             $collectors{"AFTER"}->($_);
2792         }
2793     }
2794 }
2795
2796 # tokenize($line)
2797 # $line is a line of text to split up into tokens
2798 # returns a list of tokens
2799 #
2800 # Tokens are divided by spaces.  If the tokens include spaces, they
2801 # have to be quoted with single or double quotes.  Double quotes
2802 # inside a double quoted token must be escaped.  Escaping is done
2803 # with backslash.
2804 # Basically, the same quoting rules apply for " and ' as in any
2805 # Unix shell.
2806 sub tokenize {
2807     my $line = my $debug_line = shift;
2808     my @result = ();
2809
2810     while ($line =~ s|^\s+||, $line ne "") {
2811         my $token = "";
2812         while ($line ne "" && $line !~ m|^\s|) {
2813             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
2814                 $token .= $1;
2815                 $line = $';
2816             } elsif ($line =~ m/^'([^']*)'/) {
2817                 $token .= $1;
2818                 $line = $';
2819             } elsif ($line =~ m/^(\S+)/) {
2820                 $token .= $1;
2821                 $line = $';
2822             }
2823         }
2824         push @result, $token;
2825     }
2826
2827     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
2828         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
2829         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
2830     }
2831     return @result;
2832 }