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