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