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