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