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