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