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