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