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