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