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