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