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