Ensure HMAC key gets cleansed after use
[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" ];
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     push @{$config{dirs}}, "fuzz";
1050     $config{cflags} .= "-fsanitize-coverage=edge,indirect-calls ";
1051 }
1052
1053 unless ($disabled{"fuzz-afl"}) {
1054     push @{$config{dirs}}, "fuzz";
1055 }
1056
1057 unless ($disabled{asan}) {
1058     $config{cflags} .= "-fsanitize=address ";
1059 }
1060
1061 unless ($disabled{ubsan}) {
1062     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
1063     # platforms.
1064     $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all ";
1065 }
1066
1067 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
1068         && $disabled{asan} && $disabled{ubsan}) {
1069     $config{cflags} .= "-fno-omit-frame-pointer -g ";
1070 }
1071 #
1072 # Platform fix-ups
1073 #
1074
1075 # This saves the build files from having to check
1076 if ($disabled{pic})
1077         {
1078         $target{shared_cflag} = $target{shared_ldflag} =
1079                 $target{shared_rcflag} = "";
1080         }
1081 else
1082         {
1083         push @{$config{defines}}, "OPENSSL_PIC";
1084         }
1085
1086 if ($target{sys_id} ne "")
1087         {
1088         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1089         }
1090
1091 unless ($disabled{asm}) {
1092     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1093     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1094
1095     # bn-586 is the only one implementing bn_*_part_words
1096     push @{$config{defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1097     push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/);
1098
1099     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1100     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1101     push @{$config{defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1102
1103     if ($config{fips}) {
1104         push @{$config{openssl_other_defines}}, "OPENSSL_FIPS";
1105     }
1106
1107     if ($target{sha1_asm_src}) {
1108         push @{$config{defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1109         push @{$config{defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1110         push @{$config{defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1111     }
1112     if ($target{md5_asm_src}) {
1113         push @{$config{defines}}, "MD5_ASM";
1114     }
1115     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1116     if ($target{rmd160_asm_src}) {
1117         push @{$config{defines}}, "RMD160_ASM";
1118     }
1119     if ($target{aes_asm_src}) {
1120         push @{$config{defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1121         # aes-ctr.fake is not a real file, only indication that assembler
1122         # module implements AES_ctr32_encrypt...
1123         push @{$config{defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1124         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1125         push @{$config{defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1126         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2);
1127         push @{$config{defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1128         push @{$config{defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1129     }
1130     if ($target{wp_asm_src} =~ /mmx/) {
1131         if ($config{processor} eq "386") {
1132             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1133         } elsif (!$disabled{"whirlpool"}) {
1134             push @{$config{defines}}, "WHIRLPOOL_ASM";
1135         }
1136     }
1137     if ($target{modes_asm_src} =~ /ghash-/) {
1138         push @{$config{defines}}, "GHASH_ASM";
1139     }
1140     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1141         push @{$config{defines}}, "ECP_NISTZ256_ASM";
1142     }
1143     if ($target{poly1305_asm_src} ne "") {
1144         push @{$config{defines}}, "POLY1305_ASM";
1145     }
1146 }
1147
1148 my $ecc = $target{cc};
1149 if ($^O ne "VMS" && !$disabled{makedepend}) {
1150     # Is the compiler gcc or clang?  $ecc is used below to see if
1151     # error-checking can be turned on.
1152     my $ccpcc = "$config{cross_compile_prefix}$target{cc}";
1153     open(PIPE, "$ccpcc --version 2>&1 |");
1154     my $lines = 2;
1155     while ( <PIPE> ) {
1156         # Find the version number and save the major.
1157         m|(?:.*)\b(\d+)\.\d+\.\d+\b(?:.*)|;
1158         my $compiler_major = $1;
1159         # We know that GNU C version 3 and up as well as all clang
1160         # versions support dependency generation
1161         $config{makedepprog} = $ccpcc
1162             if (/clang/ || (/gcc/ && $compiler_major > 3));
1163         $ecc = "clang" if /clang/;
1164         $ecc = "gcc" if /gcc/;
1165         last if ($config{makedepprog} || !$lines--);
1166     }
1167     close(PIPE);
1168
1169     $config{makedepprog} = which('makedepend') unless $config{makedepprog};
1170     $disabled{makedepend} = "unavailable" unless $config{makedepprog};
1171 }
1172
1173
1174
1175 # Deal with bn_ops ###################################################
1176
1177 $config{bn_ll}                  =0;
1178 $config{export_var_as_fn}       =0;
1179 my $def_int="unsigned int";
1180 $config{rc4_int}                =$def_int;
1181 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1182
1183 my $count = 0;
1184 foreach (sort split(/\s+/,$target{bn_ops})) {
1185     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1186     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1187     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1188     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1189     ($config{b64l},$config{b64},$config{b32})
1190         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1191     ($config{b64l},$config{b64},$config{b32})
1192         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1193     ($config{b64l},$config{b64},$config{b32})
1194         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1195 }
1196 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1197     if $count > 1;
1198
1199
1200 # Hack cflags for better warnings (dev option) #######################
1201
1202 # "Stringify" the C flags string.  This permits it to be made part of a string
1203 # and works as well on command lines.
1204 $config{cflags} =~ s/([\\\"])/\\$1/g;
1205
1206 if (defined($config{api})) {
1207     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1208     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1209     push @{$config{defines}}, $apiflag;
1210 }
1211
1212 if ($strict_warnings)
1213         {
1214         my $wopt;
1215         die "ERROR --strict-warnings requires gcc or clang"
1216             unless $ecc eq 'gcc' || $ecc eq 'clang';
1217         foreach $wopt (split /\s+/, $gcc_devteam_warn)
1218                 {
1219                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1220                 }
1221         if ($ecc eq "clang")
1222                 {
1223                 foreach $wopt (split /\s+/, $clang_devteam_warn)
1224                         {
1225                         $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1226                         }
1227                 }
1228         }
1229
1230 unless ($disabled{"crypto-mdebug-backtrace"})
1231         {
1232         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1233                 {
1234                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1235                 }
1236         if ($target =~ /^BSD-/)
1237                 {
1238                 $config{ex_libs} .= " -lexecinfo";
1239                 }
1240         }
1241
1242 if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; }
1243 else                    { $no_user_cflags=1;  }
1244 if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; }
1245 else               { $no_user_defines=1;    }
1246
1247 # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
1248
1249 unless ($disabled{afalgeng}) {
1250     $config{afalgeng}="";
1251     if ($target =~ m/^linux/) {
1252         my $minver = 4*10000 + 1*100 + 0;
1253         if ($config{cross_compile_prefix} eq "") {
1254             my $verstr = `uname -r`;
1255             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1256             ($mi2) = $mi2 =~ /(\d+)/;
1257             my $ver = $ma*10000 + $mi1*100 + $mi2;
1258             if ($ver < $minver) {
1259                 $disabled{afalgeng} = "too-old-kernel";
1260             } else {
1261                 push @{$config{engdirs}}, "afalg";
1262             }
1263         } else {
1264             $disabled{afalgeng} = "cross-compiling";
1265         }
1266     } else {
1267         $disabled{afalgeng}  = "not-linux";
1268     }
1269 }
1270
1271 push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
1272
1273 # If we use the unified build, collect information from build.info files
1274 my %unified_info = ();
1275
1276 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1277 if ($builder eq "unified") {
1278     # Store the name of the template file we will build the build file from
1279     # in %config.  This may be useful for the build file itself.
1280     my $build_file_template;
1281
1282     for my $filename (( $builder_platform."-".$target{build_file}.".tmpl",
1283                         $target{build_file}.".tmpl" )) {
1284         if (defined $ENV{$local_config_envname}) {
1285             if ($^O eq 'VMS') {
1286                 # VMS environment variables are logical names,
1287                 # which can be used as is
1288                 $build_file_template = $local_config_envname . ':' . $filename;
1289             } else {
1290                 $build_file_template = catfile($ENV{$local_config_envname},
1291                                                $filename);
1292             }
1293         }
1294
1295         last if -f $build_file_template;
1296
1297         $build_file_template = catfile($srcdir, "Configurations", $filename);
1298
1299         last if -f $build_file_template;
1300     }
1301     $config{build_file_template} = $build_file_template;
1302
1303     use lib catdir(dirname(__FILE__),"util");
1304     use with_fallback qw(Text::Template);
1305
1306     sub cleandir {
1307         my $base = shift;
1308         my $dir = shift;
1309         my $relativeto = shift || ".";
1310
1311         $dir = catdir($base,$dir) unless isabsolute($dir);
1312
1313         # Make sure the directories we're building in exists
1314         mkpath($dir);
1315
1316         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1317         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1318         return $res;
1319     }
1320
1321     sub cleanfile {
1322         my $base = shift;
1323         my $file = shift;
1324         my $relativeto = shift || ".";
1325
1326         $file = catfile($base,$file) unless isabsolute($file);
1327
1328         my $d = dirname($file);
1329         my $f = basename($file);
1330
1331         # Make sure the directories we're building in exists
1332         mkpath($d);
1333
1334         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1335         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1336         return $res;
1337     }
1338
1339     my @build_infos = ( [ ".", "build.info" ] );
1340     foreach (@{$config{dirs}}) {
1341         push @build_infos, [ $_, "build.info" ]
1342             if (-f catfile($srcdir, $_, "build.info"));
1343     }
1344     foreach (@{$config{sdirs}}) {
1345         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1346             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1347     }
1348     foreach (@{$config{engdirs}}) {
1349         push @build_infos, [ catdir("engines", $_), "build.info" ]
1350             if (-f catfile($srcdir, "engines", $_, "build.info"));
1351     }
1352
1353     $config{build_infos} = [ ];
1354
1355     foreach (@build_infos) {
1356         my $sourced = catdir($srcdir, $_->[0]);
1357         my $buildd = catdir($blddir, $_->[0]);
1358
1359         mkpath($buildd);
1360
1361         my $f = $_->[1];
1362         # The basic things we're trying to build
1363         my @programs = ();
1364         my @libraries = ();
1365         my @engines = ();
1366         my @scripts = ();
1367         my @extra = ();
1368         my @overrides = ();
1369         my @intermediates = ();
1370         my @rawlines = ();
1371
1372         my %ordinals = ();
1373         my %sources = ();
1374         my %shared_sources = ();
1375         my %includes = ();
1376         my %depends = ();
1377         my %renames = ();
1378         my %sharednames = ();
1379         my %generate = ();
1380
1381         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1382         my $template = Text::Template->new(TYPE => 'FILE',
1383                                            SOURCE => catfile($sourced, $f));
1384         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1385         my @text =
1386             split /^/m,
1387             $template->fill_in(HASH => { config => \%config,
1388                                          target => \%target,
1389                                          disabled => \%disabled,
1390                                          withargs => \%withargs,
1391                                          builddir => abs2rel($buildd, $blddir),
1392                                          sourcedir => abs2rel($sourced, $blddir),
1393                                          buildtop => abs2rel($blddir, $blddir),
1394                                          sourcetop => abs2rel($srcdir, $blddir) },
1395                                DELIMITERS => [ "{-", "-}" ]);
1396
1397         # The top item of this stack has the following values
1398         # -2 positive already run and we found ELSE (following ELSIF should fail)
1399         # -1 positive already run (skip until ENDIF)
1400         # 0 negatives so far (if we're at a condition, check it)
1401         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1402         # 2 positive ELSE (following ELSIF should fail)
1403         my @skip = ();
1404         collect_information(
1405             collect_from_array([ @text ],
1406                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1407                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1408             # Info we're looking for
1409             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1410             => sub {
1411                 if (! @skip || $skip[$#skip] > 0) {
1412                     push @skip, !! $1;
1413                 } else {
1414                     push @skip, -1;
1415                 }
1416             },
1417             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1418             => sub { die "ELSIF out of scope" if ! @skip;
1419                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1420                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1421                      $skip[$#skip] = !! $1
1422                          if $skip[$#skip] == 0; },
1423             qr/^\s*ELSE\s*$/
1424             => sub { die "ELSE out of scope" if ! @skip;
1425                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1426                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1427             qr/^\s*ENDIF\s*$/
1428             => sub { die "ENDIF out of scope" if ! @skip;
1429                      pop @skip; },
1430             qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/
1431             => sub { push @programs, tokenize($1)
1432                          if !@skip || $skip[$#skip] > 0 },
1433             qr/^\s*LIBS\s*=\s*(.*)\s*$/
1434             => sub { push @libraries, tokenize($1)
1435                          if !@skip || $skip[$#skip] > 0 },
1436             qr/^\s*ENGINES\s*=\s*(.*)\s*$/
1437             => sub { push @engines, tokenize($1)
1438                          if !@skip || $skip[$#skip] > 0 },
1439             qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/
1440             => sub { push @scripts, tokenize($1)
1441                          if !@skip || $skip[$#skip] > 0 },
1442             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1443             => sub { push @extra, tokenize($1)
1444                          if !@skip || $skip[$#skip] > 0 },
1445             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1446             => sub { push @overrides, tokenize($1)
1447                          if !@skip || $skip[$#skip] > 0 },
1448
1449             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1450             => sub { push @{$ordinals{$1}}, tokenize($2)
1451                          if !@skip || $skip[$#skip] > 0 },
1452             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1453             => sub { push @{$sources{$1}}, tokenize($2)
1454                          if !@skip || $skip[$#skip] > 0 },
1455             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1456             => sub { push @{$shared_sources{$1}}, tokenize($2)
1457                          if !@skip || $skip[$#skip] > 0 },
1458             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1459             => sub { push @{$includes{$1}}, tokenize($2)
1460                          if !@skip || $skip[$#skip] > 0 },
1461             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
1462             => sub { push @{$depends{$1}}, tokenize($2)
1463                          if !@skip || $skip[$#skip] > 0 },
1464             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1465             => sub { push @{$generate{$1}}, $2
1466                          if !@skip || $skip[$#skip] > 0 },
1467             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1468             => sub { push @{$renames{$1}}, tokenize($2)
1469                          if !@skip || $skip[$#skip] > 0 },
1470             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1471             => sub { push @{$sharednames{$1}}, tokenize($2)
1472                          if !@skip || $skip[$#skip] > 0 },
1473             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1474             => sub {
1475                 my $lineiterator = shift;
1476                 my $target_kind = $1;
1477                 while (defined $lineiterator->()) {
1478                     s|\R$||;
1479                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1480                         die "ENDRAW doesn't match BEGINRAW"
1481                             if $1 ne $target_kind;
1482                         last;
1483                     }
1484                     next if @skip && $skip[$#skip] <= 0;
1485                     push @rawlines,  $_
1486                         if ($target_kind eq $target{build_file}
1487                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1488                 }
1489             },
1490             qr/^(?:#.*|\s*)$/ => sub { },
1491             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1492             "BEFORE" => sub {
1493                 if ($buildinfo_debug) {
1494                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1495                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1496                 }
1497             },
1498             "AFTER" => sub {
1499                 if ($buildinfo_debug) {
1500                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1501                 }
1502             },
1503             );
1504         die "runaway IF?" if (@skip);
1505
1506         foreach (keys %renames) {
1507             die "$_ renamed to more than one thing: "
1508                 ,join(" ", @{$renames{$_}}),"\n"
1509                 if scalar @{$renames{$_}} > 1;
1510             my $dest = cleanfile($buildd, $_, $blddir);
1511             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1512             die "$dest renamed to more than one thing: "
1513                 ,$unified_info{rename}->{$dest}, $to
1514                 unless !defined($unified_info{rename}->{$dest})
1515                 or $unified_info{rename}->{$dest} eq $to;
1516             $unified_info{rename}->{$dest} = $to;
1517         }
1518
1519         foreach (@programs) {
1520             my $program = cleanfile($buildd, $_, $blddir);
1521             if ($unified_info{rename}->{$program}) {
1522                 $program = $unified_info{rename}->{$program};
1523             }
1524             $unified_info{programs}->{$program} = 1;
1525         }
1526
1527         foreach (@libraries) {
1528             my $library = cleanfile($buildd, $_, $blddir);
1529             if ($unified_info{rename}->{$library}) {
1530                 $library = $unified_info{rename}->{$library};
1531             }
1532             $unified_info{libraries}->{$library} = 1;
1533         }
1534
1535         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
1536 ENGINES can only be used if configured with 'dynamic-engine'.
1537 This is usually a fault in a build.info file.
1538 EOF
1539         foreach (@engines) {
1540             my $library = cleanfile($buildd, $_, $blddir);
1541             if ($unified_info{rename}->{$library}) {
1542                 $library = $unified_info{rename}->{$library};
1543             }
1544             $unified_info{engines}->{$library} = 1;
1545         }
1546
1547         foreach (@scripts) {
1548             my $script = cleanfile($buildd, $_, $blddir);
1549             if ($unified_info{rename}->{$script}) {
1550                 $script = $unified_info{rename}->{$script};
1551             }
1552             $unified_info{scripts}->{$script} = 1;
1553         }
1554
1555         foreach (@extra) {
1556             my $extra = cleanfile($buildd, $_, $blddir);
1557             $unified_info{extra}->{$extra} = 1;
1558         }
1559
1560         foreach (@overrides) {
1561             my $override = cleanfile($buildd, $_, $blddir);
1562             $unified_info{overrides}->{$override} = 1;
1563         }
1564
1565         push @{$unified_info{rawlines}}, @rawlines;
1566
1567         unless ($disabled{shared}) {
1568             # Check sharednames.
1569             foreach (keys %sharednames) {
1570                 my $dest = cleanfile($buildd, $_, $blddir);
1571                 if ($unified_info{rename}->{$dest}) {
1572                     $dest = $unified_info{rename}->{$dest};
1573                 }
1574                 die "shared_name for $dest with multiple values: "
1575                     ,join(" ", @{$sharednames{$_}}),"\n"
1576                     if scalar @{$sharednames{$_}} > 1;
1577                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
1578                 die "shared_name found for a library $dest that isn't defined\n"
1579                     unless $unified_info{libraries}->{$dest};
1580                 die "shared_name for $dest with multiple values: "
1581                     ,$unified_info{sharednames}->{$dest}, ", ", $to
1582                     unless !defined($unified_info{sharednames}->{$dest})
1583                     or $unified_info{sharednames}->{$dest} eq $to;
1584                 $unified_info{sharednames}->{$dest} = $to;
1585             }
1586
1587             # Additionally, we set up sharednames for libraries that don't
1588             # have any, as themselves.
1589             foreach (keys %{$unified_info{libraries}}) {
1590                 if (!defined $unified_info{sharednames}->{$_}) {
1591                     $unified_info{sharednames}->{$_} = $_
1592                 }
1593             }
1594         }
1595
1596         foreach (keys %ordinals) {
1597             my $dest = $_;
1598             my $ddest = cleanfile($buildd, $_, $blddir);
1599             if ($unified_info{rename}->{$ddest}) {
1600                 $ddest = $unified_info{rename}->{$ddest};
1601             }
1602             foreach (@{$ordinals{$dest}}) {
1603                 my %known_ordinals =
1604                     (
1605                      crypto =>
1606                      cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
1607                      ssl =>
1608                      cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
1609                     );
1610                 my $o = $known_ordinals{$_};
1611                 die "Ordinals for $ddest defined more than once\n"
1612                     if $unified_info{ordinals}->{$ddest};
1613                 $unified_info{ordinals}->{$ddest} = [ $_, $o ];
1614             }
1615         }
1616
1617         foreach (keys %sources) {
1618             my $dest = $_;
1619             my $ddest = cleanfile($buildd, $_, $blddir);
1620             if ($unified_info{rename}->{$ddest}) {
1621                 $ddest = $unified_info{rename}->{$ddest};
1622             }
1623             foreach (@{$sources{$dest}}) {
1624                 my $s = cleanfile($sourced, $_, $blddir);
1625
1626                 # If it isn't in the source tree, we assume it's generated
1627                 # in the build tree
1628                 if (! -f $s) {
1629                     $s = cleanfile($buildd, $_, $blddir);
1630                 }
1631                 # We recognise C and asm files
1632                 if ($s =~ /\.[csS]\b$/) {
1633                     (my $o = $_) =~ s/\.[csS]\b$/.o/;
1634                     $o = cleanfile($buildd, $o, $blddir);
1635                     $unified_info{sources}->{$ddest}->{$o} = 1;
1636                     $unified_info{sources}->{$o}->{$s} = 1;
1637                 } else {
1638                     $unified_info{sources}->{$ddest}->{$s} = 1;
1639                 }
1640             }
1641         }
1642
1643         foreach (keys %shared_sources) {
1644             my $dest = $_;
1645             my $ddest = cleanfile($buildd, $_, $blddir);
1646             if ($unified_info{rename}->{$ddest}) {
1647                 $ddest = $unified_info{rename}->{$ddest};
1648             }
1649             foreach (@{$shared_sources{$dest}}) {
1650                 my $s = cleanfile($sourced, $_, $blddir);
1651
1652                 # If it isn't in the source tree, we assume it's generated
1653                 # in the build tree
1654                 if (! -f $s) {
1655                     $s = cleanfile($buildd, $_, $blddir);
1656                 }
1657                 # We recognise C and asm files
1658                 if ($s =~ /\.[csS]\b$/) {
1659                     (my $o = $_) =~ s/\.[csS]\b$/.o/;
1660                     $o = cleanfile($buildd, $o, $blddir);
1661                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
1662                     $unified_info{sources}->{$o}->{$s} = 1;
1663                 } else {
1664                     die "unrecognised source file type for shared library: $s\n";
1665                 }
1666             }
1667         }
1668
1669         foreach (keys %generate) {
1670             my $dest = $_;
1671             my $ddest = cleanfile($buildd, $_, $blddir);
1672             if ($unified_info{rename}->{$ddest}) {
1673                 $ddest = $unified_info{rename}->{$ddest};
1674             }
1675             die "more than one generator for $dest: "
1676                     ,join(" ", @{$generate{$_}}),"\n"
1677                     if scalar @{$generate{$_}} > 1;
1678             my @generator = split /\s+/, $generate{$dest}->[0];
1679             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
1680             $unified_info{generate}->{$ddest} = [ @generator ];
1681         }
1682
1683         foreach (keys %depends) {
1684             my $dest = $_;
1685             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
1686
1687             # If the destination doesn't exist in source, it can only be
1688             # a generated file in the build tree.
1689             if ($ddest ne "" && ! -f $ddest) {
1690                 $ddest = cleanfile($buildd, $_, $blddir);
1691                 if ($unified_info{rename}->{$ddest}) {
1692                     $ddest = $unified_info{rename}->{$ddest};
1693                 }
1694             }
1695             foreach (@{$depends{$dest}}) {
1696                 my $d = cleanfile($sourced, $_, $blddir);
1697
1698                 # If we know it's generated, or assume it is because we can't
1699                 # find it in the source tree, we set file we depend on to be
1700                 # in the build tree rather than the source tree, and assume
1701                 # and that there are lines to build it in a BEGINRAW..ENDRAW
1702                 # section or in the Makefile template.
1703                 if (! -f $d
1704                     || (grep { $d eq $_ }
1705                         map { cleanfile($srcdir, $_, $blddir) }
1706                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
1707                     $d = cleanfile($buildd, $_, $blddir);
1708                 }
1709                 # Take note if the file to depend on is being renamed
1710                 if ($unified_info{rename}->{$d}) {
1711                     $d = $unified_info{rename}->{$d};
1712                 }
1713                 $unified_info{depends}->{$ddest}->{$d} = 1;
1714                 # If we depend on a header file or a perl module, let's make
1715                 # sure it can get included
1716                 if ($dest ne "" && $d =~ /\.(h|pm)$/) {
1717                     my $i = dirname($d);
1718                     push @{$unified_info{includes}->{$ddest}}, $i
1719                         unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
1720                 }
1721             }
1722         }
1723
1724         foreach (keys %includes) {
1725             my $dest = $_;
1726             my $ddest = cleanfile($sourced, $_, $blddir);
1727
1728             # If the destination doesn't exist in source, it can only be
1729             # a generated file in the build tree.
1730             if (! -f $ddest) {
1731                 $ddest = cleanfile($buildd, $_, $blddir);
1732                 if ($unified_info{rename}->{$ddest}) {
1733                     $ddest = $unified_info{rename}->{$ddest};
1734                 }
1735             }
1736             foreach (@{$includes{$dest}}) {
1737                 my $i = cleandir($sourced, $_, $blddir);
1738                 push @{$unified_info{includes}->{$ddest}}, $i
1739                     unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
1740             }
1741         }
1742     }
1743
1744     ### Make unified_info a bit more efficient
1745     # One level structures
1746     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
1747         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
1748     }
1749     # Two level structures
1750     foreach my $l1 (("sources", "shared_sources", "ldadd", "depends")) {
1751         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
1752             $unified_info{$l1}->{$l2} =
1753                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
1754         }
1755     }
1756 }
1757
1758 # For the schemes that need it, we provide the old *_obj configs
1759 # from the *_asm_obj ones
1760 foreach (grep /_(asm|aux)_src$/, keys %target) {
1761     my $src = $_;
1762     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
1763     ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g;
1764 }
1765
1766 # Write down our configuration where it fits #########################
1767
1768 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
1769 print OUT <<"EOF";
1770 package configdata;
1771
1772 use strict;
1773 use warnings;
1774
1775 use Exporter;
1776 #use vars qw(\@ISA \@EXPORT);
1777 our \@ISA = qw(Exporter);
1778 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
1779
1780 EOF
1781 print OUT "our %config = (\n";
1782 foreach (sort keys %config) {
1783     if (ref($config{$_}) eq "ARRAY") {
1784         print OUT "  ", $_, " => [ ", join(", ",
1785                                            map { quotify("perl", $_) }
1786                                            @{$config{$_}}), " ],\n";
1787     } else {
1788         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
1789     }
1790 }
1791 print OUT <<"EOF";
1792 );
1793
1794 EOF
1795 print OUT "our %target = (\n";
1796 foreach (sort keys %target) {
1797     if (ref($target{$_}) eq "ARRAY") {
1798         print OUT "  ", $_, " => [ ", join(", ",
1799                                            map { quotify("perl", $_) }
1800                                            @{$target{$_}}), " ],\n";
1801     } else {
1802         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
1803     }
1804 }
1805 print OUT <<"EOF";
1806 );
1807
1808 EOF
1809 print OUT "our \%available_protocols = (\n";
1810 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
1811 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
1812 print OUT <<"EOF";
1813 );
1814
1815 EOF
1816 print OUT "our \@disablables = (\n";
1817 foreach (@disablables) {
1818     print OUT "  ", quotify("perl", $_), ",\n";
1819 }
1820 print OUT <<"EOF";
1821 );
1822
1823 EOF
1824 print OUT "our \%disabled = (\n";
1825 foreach (sort keys %disabled) {
1826     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
1827 }
1828 print OUT <<"EOF";
1829 );
1830
1831 EOF
1832 print OUT "our %withargs = (\n";
1833 foreach (sort keys %withargs) {
1834     if (ref($withargs{$_}) eq "ARRAY") {
1835         print OUT "  ", $_, " => [ ", join(", ",
1836                                            map { quotify("perl", $_) }
1837                                            @{$withargs{$_}}), " ],\n";
1838     } else {
1839         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
1840     }
1841 }
1842 print OUT <<"EOF";
1843 );
1844
1845 EOF
1846 if ($builder eq "unified") {
1847     my $recurse;
1848     $recurse = sub {
1849         my $indent = shift;
1850         foreach (@_) {
1851             if (ref $_ eq "ARRAY") {
1852                 print OUT " "x$indent, "[\n";
1853                 foreach (@$_) {
1854                     $recurse->($indent + 4, $_);
1855                 }
1856                 print OUT " "x$indent, "],\n";
1857             } elsif (ref $_ eq "HASH") {
1858                 my %h = %$_;
1859                 print OUT " "x$indent, "{\n";
1860                 foreach (sort keys %h) {
1861                     if (ref $h{$_} eq "") {
1862                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
1863                     } else {
1864                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
1865                         $recurse->($indent + 8, $h{$_});
1866                     }
1867                 }
1868                 print OUT " "x$indent, "},\n";
1869             } else {
1870                 print OUT " "x$indent, quotify("perl", $_), ",\n";
1871             }
1872         }
1873     };
1874     print OUT "our %unified_info = (\n";
1875     foreach (sort keys %unified_info) {
1876         if (ref $unified_info{$_} eq "") {
1877             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
1878         } else {
1879             print OUT " "x4, quotify("perl", $_), " =>\n";
1880             $recurse->(8, $unified_info{$_});
1881         }
1882     }
1883     print OUT <<"EOF";
1884 );
1885
1886 EOF
1887 }
1888 print OUT "1;\n";
1889 close(OUT);
1890
1891
1892 print "CC            =$config{cross_compile_prefix}$target{cc}\n";
1893 print "CFLAG         =$target{cflags} $config{cflags}\n";
1894 print "SHARED_CFLAG  =$target{shared_cflag}\n";
1895 print "DEFINES       =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n";
1896 print "LFLAG         =$target{lflags}\n";
1897 print "PLIB_LFLAG    =$target{plib_lflags}\n";
1898 print "EX_LIBS       =$target{ex_libs} $config{ex_libs}\n";
1899 print "APPS_OBJ      =$target{apps_obj}\n";
1900 print "CPUID_OBJ     =$target{cpuid_obj}\n";
1901 print "UPLINK_OBJ    =$target{uplink_obj}\n";
1902 print "BN_ASM        =$target{bn_obj}\n";
1903 print "EC_ASM        =$target{ec_obj}\n";
1904 print "DES_ENC       =$target{des_obj}\n";
1905 print "AES_ENC       =$target{aes_obj}\n";
1906 print "BF_ENC        =$target{bf_obj}\n";
1907 print "CAST_ENC      =$target{cast_obj}\n";
1908 print "RC4_ENC       =$target{rc4_obj}\n";
1909 print "RC5_ENC       =$target{rc5_obj}\n";
1910 print "MD5_OBJ_ASM   =$target{md5_obj}\n";
1911 print "SHA1_OBJ_ASM  =$target{sha1_obj}\n";
1912 print "RMD160_OBJ_ASM=$target{rmd160_obj}\n";
1913 print "CMLL_ENC      =$target{cmll_obj}\n";
1914 print "MODES_OBJ     =$target{modes_obj}\n";
1915 print "PADLOCK_OBJ   =$target{padlock_obj}\n";
1916 print "CHACHA_ENC    =$target{chacha_obj}\n";
1917 print "POLY1305_OBJ  =$target{poly1305_obj}\n";
1918 print "BLAKE2_OBJ    =$target{blake2_obj}\n";
1919 print "PROCESSOR     =$config{processor}\n";
1920 print "RANLIB        =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
1921                              "$config{cross_compile_prefix}ranlib" :
1922                              "$target{ranlib}", "\n";
1923 print "ARFLAGS       =$target{arflags}\n";
1924 print "PERL          =$config{perl}\n";
1925 print "\n";
1926 print "SIXTY_FOUR_BIT_LONG mode\n" if $config{b64l};
1927 print "SIXTY_FOUR_BIT mode\n" if $config{b64};
1928 print "THIRTY_TWO_BIT mode\n" if $config{b32};
1929 print "BN_LLONG mode\n" if $config{bn_ll};
1930 print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} ne $def_int;
1931
1932 my %builders = (
1933     unified => sub {
1934         run_dofile(catfile($blddir, $target{build_file}),
1935                    $config{build_file_template},
1936                    catfile($srcdir, "Configurations", "common.tmpl"));
1937     },
1938     );
1939
1940 $builders{$builder}->($builder_platform, @builder_opts);
1941
1942 print <<"EOF";
1943
1944 Configured for $target.
1945 EOF
1946
1947 print <<"EOF" if ($disabled{threads} eq "unavailable");
1948
1949 The library could not be configured for supporting multi-threaded
1950 applications as the compiler options required on this system are not known.
1951 See file INSTALL for details if you need multi-threading.
1952 EOF
1953
1954 print <<"EOF" if ($no_shared_warn);
1955
1956 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
1957 platform, so we will pretend you gave the option 'no-pic', which also disables
1958 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
1959 or position independent code, please let us know (but please first make sure
1960 you have tried with a current version of OpenSSL).
1961 EOF
1962
1963 print <<"EOF" if (-f catfile($srcdir, "configdata.pm") && $srcdir ne $blddir);
1964
1965 WARNING: there are indications that another build was made in the source
1966 directory.  This build may have picked up artifacts from that build, the
1967 safest course of action is to clean the source directory and redo this
1968 configuration.
1969 EOF
1970
1971 exit(0);
1972
1973 ######################################################################
1974 #
1975 # Helpers and utility functions
1976 #
1977
1978 # Configuration file reading #########################################
1979
1980 # Note: All of the helper functions are for lazy evaluation.  They all
1981 # return a CODE ref, which will return the intended value when evaluated.
1982 # Thus, whenever there's mention of a returned value, it's about that
1983 # intended value.
1984
1985 # Helper function to implement conditional inheritance depending on the
1986 # value of $disabled{asm}.  Used in inherit_from values as follows:
1987 #
1988 #      inherit_from => [ "template", asm("asm_tmpl") ]
1989 #
1990 sub asm {
1991     my @x = @_;
1992     sub {
1993         $disabled{asm} ? () : @x;
1994     }
1995 }
1996
1997 # Helper function to implement conditional value variants, with a default
1998 # plus additional values based on the value of $config{build_type}.
1999 # Arguments are given in hash table form:
2000 #
2001 #       picker(default => "Basic string: ",
2002 #              debug   => "debug",
2003 #              release => "release")
2004 #
2005 # When configuring with --debug, the resulting string will be
2006 # "Basic string: debug", and when not, it will be "Basic string: release"
2007 #
2008 # This can be used to create variants of sets of flags according to the
2009 # build type:
2010 #
2011 #       cflags => picker(default => "-Wall",
2012 #                        debug   => "-g -O0",
2013 #                        release => "-O3")
2014 #
2015 sub picker {
2016     my %opts = @_;
2017     return sub { add($opts{default} || (),
2018                      $opts{$config{build_type}} || ())->(); }
2019 }
2020
2021 # Helper function to combine several values of different types into one.
2022 # This is useful if you want to combine a string with the result of a
2023 # lazy function, such as:
2024 #
2025 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2026 #
2027 sub combine {
2028     my @stuff = @_;
2029     return sub { add(@stuff)->(); }
2030 }
2031
2032 # Helper function to implement conditional values depending on the value
2033 # of $disabled{threads}.  Can be used as follows:
2034 #
2035 #       cflags => combine("-Wall", threads("-pthread"))
2036 #
2037 sub threads {
2038     my @flags = @_;
2039     return sub { add($disabled{threads} ? () : @flags)->(); }
2040 }
2041
2042
2043
2044 our $add_called = 0;
2045 # Helper function to implement adding values to already existing configuration
2046 # values.  It handles elements that are ARRAYs, CODEs and scalars
2047 sub _add {
2048     my $separator = shift;
2049
2050     # If there's any ARRAY in the collection of values OR the separator
2051     # is undef, we will return an ARRAY of combined values, otherwise a
2052     # string of joined values with $separator as the separator.
2053     my $found_array = !defined($separator);
2054
2055     my @values =
2056         map {
2057             my $res = $_;
2058             while (ref($res) eq "CODE") {
2059                 $res = $res->();
2060             }
2061             if (defined($res)) {
2062                 if (ref($res) eq "ARRAY") {
2063                     $found_array = 1;
2064                     @$res;
2065                 } else {
2066                     $res;
2067                 }
2068             } else {
2069                 ();
2070             }
2071     } (@_);
2072
2073     $add_called = 1;
2074
2075     if ($found_array) {
2076         [ @values ];
2077     } else {
2078         join($separator, grep { defined($_) && $_ ne "" } @values);
2079     }
2080 }
2081 sub add_before {
2082     my $separator = " ";
2083     if (ref($_[$#_]) eq "HASH") {
2084         my $opts = pop;
2085         $separator = $opts->{separator};
2086     }
2087     my @x = @_;
2088     sub { _add($separator, @x, @_) };
2089 }
2090 sub add {
2091     my $separator = " ";
2092     if (ref($_[$#_]) eq "HASH") {
2093         my $opts = pop;
2094         $separator = $opts->{separator};
2095     }
2096     my @x = @_;
2097     sub { _add($separator, @_, @x) };
2098 }
2099
2100 # configuration reader, evaluates the input file as a perl script and expects
2101 # it to fill %targets with target configurations.  Those are then added to
2102 # %table.
2103 sub read_config {
2104     my $fname = shift;
2105     open(CONFFILE, "< $fname")
2106         or die "Can't open configuration file '$fname'!\n";
2107     my $x = $/;
2108     undef $/;
2109     my $content = <CONFFILE>;
2110     $/ = $x;
2111     close(CONFFILE);
2112     my %targets = ();
2113     {
2114         local %table = %::table;    # Protect %table from tampering
2115
2116         eval $content;
2117         warn $@ if $@;
2118     }
2119
2120     # For each target, check that it's configured with a hash table.
2121     foreach (keys %targets) {
2122         if (ref($targets{$_}) ne "HASH") {
2123             if (ref($targets{$_}) eq "") {
2124                 warn "Deprecated target configuration for $_, ignoring...\n";
2125             } else {
2126                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
2127             }
2128             delete $targets{$_};
2129         }
2130     }
2131
2132     %table = (%table, %targets);
2133
2134 }
2135
2136 # configuration resolver.  Will only resolve all the lazy evaluation
2137 # codeblocks for the chosen target and all those it inherits from,
2138 # recursively
2139 sub resolve_config {
2140     my $target = shift;
2141     my @breadcrumbs = @_;
2142
2143 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
2144
2145     if (grep { $_ eq $target } @breadcrumbs) {
2146         die "inherit_from loop!  target backtrace:\n  "
2147             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
2148     }
2149
2150     if (!defined($table{$target})) {
2151         warn "Warning! target $target doesn't exist!\n";
2152         return ();
2153     }
2154     # Recurse through all inheritances.  They will be resolved on the
2155     # fly, so when this operation is done, they will all just be a
2156     # bunch of attributes with string values.
2157     # What we get here, though, are keys with references to lists of
2158     # the combined values of them all.  We will deal with lists after
2159     # this stage is done.
2160     my %combined_inheritance = ();
2161     if ($table{$target}->{inherit_from}) {
2162         my @inherit_from =
2163             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
2164         foreach (@inherit_from) {
2165             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
2166
2167             # 'template' is a marker that's considered private to
2168             # the config that had it.
2169             delete $inherited_config{template};
2170
2171             foreach (keys %inherited_config) {
2172                 if (!$combined_inheritance{$_}) {
2173                     $combined_inheritance{$_} = [];
2174                 }
2175                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
2176             }
2177         }
2178     }
2179
2180     # We won't need inherit_from in this target any more, since we've
2181     # resolved all the inheritances that lead to this
2182     delete $table{$target}->{inherit_from};
2183
2184     # Now is the time to deal with those lists.  Here's the place to
2185     # decide what shall be done with those lists, all based on the
2186     # values of the target we're currently dealing with.
2187     # - If a value is a coderef, it will be executed with the list of
2188     #   inherited values as arguments.
2189     # - If the corresponding key doesn't have a value at all or is the
2190     #   empty string, the inherited value list will be run through the
2191     #   default combiner (below), and the result becomes this target's
2192     #   value.
2193     # - Otherwise, this target's value is assumed to be a string that
2194     #   will simply override the inherited list of values.
2195     my $default_combiner = add();
2196
2197     my %all_keys =
2198         map { $_ => 1 } (keys %combined_inheritance,
2199                          keys %{$table{$target}});
2200
2201     sub process_values {
2202         my $object    = shift;
2203         my $inherited = shift;  # Always a [ list ]
2204         my $target    = shift;
2205         my $entry     = shift;
2206
2207         $add_called = 0;
2208
2209         while(ref($object) eq "CODE") {
2210             $object = $object->(@$inherited);
2211         }
2212         if (!defined($object)) {
2213             return ();
2214         }
2215         elsif (ref($object) eq "ARRAY") {
2216             local $add_called;  # To make sure recursive calls don't affect it
2217             return [ map { process_values($_, $inherited, $target, $entry) }
2218                      @$object ];
2219         } elsif (ref($object) eq "") {
2220             return $object;
2221         } else {
2222             die "cannot handle reference type ",ref($object)
2223                 ," found in target ",$target," -> ",$entry,"\n";
2224         }
2225     }
2226
2227     foreach (sort keys %all_keys) {
2228         my $previous = $combined_inheritance{$_};
2229
2230         # Current target doesn't have a value for the current key?
2231         # Assign it the default combiner, the rest of this loop body
2232         # will handle it just like any other coderef.
2233         if (!exists $table{$target}->{$_}) {
2234             $table{$target}->{$_} = $default_combiner;
2235         }
2236
2237         $table{$target}->{$_} = process_values($table{$target}->{$_},
2238                                                $combined_inheritance{$_},
2239                                                $target, $_);
2240         unless(defined($table{$target}->{$_})) {
2241             delete $table{$target}->{$_};
2242         }
2243 #        if ($extra_checks &&
2244 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
2245 #            warn "$_ got replaced in $target\n";
2246 #        }
2247     }
2248
2249     # Finally done, return the result.
2250     return %{$table{$target}};
2251 }
2252
2253 sub usage
2254         {
2255         print STDERR $usage;
2256         print STDERR "\npick os/compiler from:\n";
2257         my $j=0;
2258         my $i;
2259         my $k=0;
2260         foreach $i (sort keys %table)
2261                 {
2262                 next if $table{$i}->{template};
2263                 next if $i =~ /^debug/;
2264                 $k += length($i) + 1;
2265                 if ($k > 78)
2266                         {
2267                         print STDERR "\n";
2268                         $k=length($i);
2269                         }
2270                 print STDERR $i . " ";
2271                 }
2272         foreach $i (sort keys %table)
2273                 {
2274                 next if $table{$i}->{template};
2275                 next if $i !~ /^debug/;
2276                 $k += length($i) + 1;
2277                 if ($k > 78)
2278                         {
2279                         print STDERR "\n";
2280                         $k=length($i);
2281                         }
2282                 print STDERR $i . " ";
2283                 }
2284         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
2285         exit(1);
2286         }
2287
2288 sub run_dofile
2289 {
2290     my $out = shift;
2291     my @templates = @_;
2292
2293     unlink $out || warn "Can't remove $out, $!"
2294         if -f $out;
2295     foreach (@templates) {
2296         die "Can't open $_, $!" unless -f $_;
2297     }
2298     my $cmd = "$config{perl} \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
2299     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
2300     system($cmd);
2301     exit 1 if $? != 0;
2302     rename("$out.new", $out) || die "Can't rename $out.new, $!";
2303 }
2304
2305 sub which
2306 {
2307     my ($name)=@_;
2308
2309     if (eval { require IPC::Cmd; 1; }) {
2310         IPC::Cmd->import();
2311         return scalar IPC::Cmd::can_run($name);
2312     } else {
2313         # if there is $directories component in splitpath,
2314         # then it's not something to test with $PATH...
2315         return $name if (File::Spec->splitpath($name))[1];
2316
2317         foreach (File::Spec->path()) {
2318             my $fullpath = catfile($_, "$name$target{exe_extension}");
2319             if (-f $fullpath and -x $fullpath) {
2320                 return $fullpath;
2321             }
2322         }
2323     }
2324 }
2325
2326 # Configuration printer ##############################################
2327
2328 sub print_table_entry
2329 {
2330     my $target = shift;
2331     my %target = resolve_config($target);
2332     my $type = shift;
2333
2334     # Don't print the templates
2335     return if $target{template};
2336
2337     my @sequence = (
2338         "sys_id",
2339         "cc",
2340         "cflags",
2341         "defines",
2342         "unistd",
2343         "ld",
2344         "lflags",
2345         "plib_lflags",
2346         "ex_libs",
2347         "bn_ops",
2348         "cpuid_obj",
2349         "bn_obj",
2350         "ec_obj",
2351         "des_obj",
2352         "aes_obj",
2353         "bf_obj",
2354         "md5_obj",
2355         "sha1_obj",
2356         "cast_obj",
2357         "rc4_obj",
2358         "rmd160_obj",
2359         "rc5_obj",
2360         "wp_obj",
2361         "cmll_obj",
2362         "modes_obj",
2363         "padlock_obj",
2364         "thread_scheme",
2365         "perlasm_scheme",
2366         "dso_scheme",
2367         "shared_target",
2368         "shared_cflag",
2369         "shared_ldflag",
2370         "shared_rcflag",
2371         "shared_extension",
2372         "shared_extension_simple",
2373         "shared_import_extension",
2374         "dso_extension",
2375         "obj_extension",
2376         "exe_extension",
2377         "ranlib",
2378         "ar",
2379         "arflags",
2380         "multilib",
2381         "build_scheme",
2382         );
2383
2384     if ($type eq "TABLE") {
2385         print "\n";
2386         print "*** $target\n";
2387         foreach (@sequence) {
2388             if (ref($target{$_}) eq "ARRAY") {
2389                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
2390             } else {
2391                 printf "\$%-12s = %s\n", $_, $target{$_};
2392             }
2393         }
2394     } elsif ($type eq "HASH") {
2395         my $largest =
2396             length((sort { length($a) <=> length($b) } @sequence)[-1]);
2397         print "    '$target' => {\n";
2398         foreach (@sequence) {
2399             if ($target{$_}) {
2400                 if (ref($target{$_}) eq "ARRAY") {
2401                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
2402                 } else {
2403                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
2404                 }
2405             }
2406         }
2407         print "    },\n";
2408     }
2409 }
2410
2411 # Utility routines ###################################################
2412
2413 # On VMS, if the given file is a logical name, File::Spec::Functions
2414 # will consider it an absolute path.  There are cases when we want a
2415 # purely syntactic check without checking the environment.
2416 sub isabsolute {
2417     my $file = shift;
2418
2419     # On non-platforms, we just use file_name_is_absolute().
2420     return file_name_is_absolute($file) unless $^O eq "VMS";
2421
2422     # If the file spec includes a device or a directpry spec,
2423     # file_name_is_absolute() is perfectly safe.
2424     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
2425
2426     # Here, we know the given file spec isn't absolute
2427     return 0;
2428 }
2429
2430 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
2431 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
2432 # realpath() requires that at least all path components except the last is an
2433 # existing directory.  On VMS, the last component of the directory spec must
2434 # exist.
2435 sub absolutedir {
2436     my $dir = shift;
2437
2438     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
2439     # will return the volume name for the device, no matter what.  Also,
2440     # it will return an incorrect directory spec if the argument is a
2441     # directory that doesn't exist.
2442     if ($^O eq "VMS") {
2443         return rel2abs($dir);
2444     }
2445
2446     # We use realpath() on Unix, since no other will properly clean out
2447     # a directory spec.
2448     use Cwd qw/realpath/;
2449
2450     return realpath($dir);
2451 }
2452
2453 sub quotify {
2454     my %processors = (
2455         perl    => sub { my $x = shift;
2456                          $x =~ s/([\\\$\@"])/\\$1/g;
2457                          return '"'.$x.'"'; },
2458         );
2459     my $for = shift;
2460     my $processor =
2461         defined($processors{$for}) ? $processors{$for} : sub { shift; };
2462
2463     return map { $processor->($_); } @_;
2464 }
2465
2466 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
2467 # $filename is a file name to read from
2468 # $line_concat_cond_re is a regexp detecting a line continuation ending
2469 # $line_concat is a CODEref that takes care of concatenating two lines
2470 sub collect_from_file {
2471     my $filename = shift;
2472     my $line_concat_cond_re = shift;
2473     my $line_concat = shift;
2474
2475     open my $fh, $filename || die "unable to read $filename: $!\n";
2476     return sub {
2477         my $saved_line = "";
2478         $_ = "";
2479         while (<$fh>) {
2480             s|\R$||;
2481             if (defined $line_concat) {
2482                 $_ = $line_concat->($saved_line, $_);
2483                 $saved_line = "";
2484             }
2485             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2486                 $saved_line = $_;
2487                 next;
2488             }
2489             return $_;
2490         }
2491         die "$filename ending with continuation line\n" if $_;
2492         close $fh;
2493         return undef;
2494     }
2495 }
2496
2497 # collect_from_array($array, $line_concat_cond_re, $line_concat)
2498 # $array is an ARRAYref of lines
2499 # $line_concat_cond_re is a regexp detecting a line continuation ending
2500 # $line_concat is a CODEref that takes care of concatenating two lines
2501 sub collect_from_array {
2502     my $array = shift;
2503     my $line_concat_cond_re = shift;
2504     my $line_concat = shift;
2505     my @array = (@$array);
2506
2507     return sub {
2508         my $saved_line = "";
2509         $_ = "";
2510         while (defined($_ = shift @array)) {
2511             s|\R$||;
2512             if (defined $line_concat) {
2513                 $_ = $line_concat->($saved_line, $_);
2514                 $saved_line = "";
2515             }
2516             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2517                 $saved_line = $_;
2518                 next;
2519             }
2520             return $_;
2521         }
2522         die "input text ending with continuation line\n" if $_;
2523         return undef;
2524     }
2525 }
2526
2527 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
2528 # $lineiterator is a CODEref that delivers one line at a time.
2529 # All following arguments are regex/CODEref pairs, where the regexp detects a
2530 # line and the CODEref does something with the result of the regexp.
2531 sub collect_information {
2532     my $lineiterator = shift;
2533     my %collectors = @_;
2534
2535     while(defined($_ = $lineiterator->())) {
2536         s|\R$||;
2537         my $found = 0;
2538         if ($collectors{"BEFORE"}) {
2539             $collectors{"BEFORE"}->($_);
2540         }
2541         foreach my $re (keys %collectors) {
2542             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
2543                 $collectors{$re}->($lineiterator);
2544                 $found = 1;
2545             };
2546         }
2547         if ($collectors{"OTHERWISE"}) {
2548             $collectors{"OTHERWISE"}->($lineiterator, $_)
2549                 unless $found || !defined $collectors{"OTHERWISE"};
2550         }
2551         if ($collectors{"AFTER"}) {
2552             $collectors{"AFTER"}->($_);
2553         }
2554     }
2555 }
2556
2557 # tokenize($line)
2558 # $line is a line of text to split up into tokens
2559 # returns a list of tokens
2560 #
2561 # Tokens are divided by spaces.  If the tokens include spaces, they
2562 # have to be quoted with single or double quotes.  Double quotes
2563 # inside a double quoted token must be escaped.  Escaping is done
2564 # with backslash.
2565 # Basically, the same quoting rules apply for " and ' as in any
2566 # Unix shell.
2567 sub tokenize {
2568     my $line = my $debug_line = shift;
2569     my @result = ();
2570
2571     while ($line =~ s|^\s+||, $line ne "") {
2572         my $token = "";
2573         while ($line ne "" && $line !~ m|^\s|) {
2574             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
2575                 $token .= $1;
2576                 $line = $';
2577             } elsif ($line =~ m/^'([^']*)'/) {
2578                 $token .= $1;
2579                 $line = $';
2580             } elsif ($line =~ m/^(\S+)/) {
2581                 $token .= $1;
2582                 $line = $';
2583             }
2584         }
2585         push @result, $token;
2586     }
2587
2588     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
2589         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
2590         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
2591     }
2592     return @result;
2593 }