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