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