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