Configure: adhere to $(CROSS_COMPILE)ranlib.
[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}  ||
913                    (which("$config{cross_compile_prefix}ranlib") ?
914                           "\$(CROSS_COMPILE)ranlib" : "true");
915 $target{ar} =      $ENV{'AR'}      || $target{ar}      || "ar";
916 $target{nm} =      $ENV{'NM'}      || $target{nm}      || "nm";
917
918 # For cflags, lflags, plib_lflags, ex_libs and defines, add the debug_
919 # or release_ attributes.
920 # Do it in such a way that no spurious space is appended (hence the grep).
921 $config{defines} = [];
922 $config{cflags} = "";
923 $config{ex_libs} = "";
924 $config{shared_ldflag} = "";
925
926 # Make sure build_scheme is consistent.
927 $target{build_scheme} = [ $target{build_scheme} ]
928     if ref($target{build_scheme}) ne "ARRAY";
929
930 my ($builder, $builder_platform, @builder_opts) =
931     @{$target{build_scheme}};
932
933 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
934
935 if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` =~ m/-mno-cygwin/m)
936         {
937         $config{cflags} .= " -mno-cygwin";
938         $config{shared_ldflag} .= " -mno-cygwin";
939         }
940
941 if ($target =~ /linux.*-mips/ && !$disabled{asm} && $user_cflags !~ /-m(ips|arch=)/) {
942         # minimally required architecture flags for assembly modules
943         $config{cflags}="-mips2 $config{cflags}" if ($target =~ /mips32/);
944         $config{cflags}="-mips3 $config{cflags}" if ($target =~ /mips64/);
945 }
946
947 my $no_shared_warn=0;
948 my $no_user_cflags=0;
949 my $no_user_defines=0;
950
951 # The DSO code currently always implements all functions so that no
952 # applications will have to worry about that from a compilation point
953 # of view. However, the "method"s may return zero unless that platform
954 # has support compiled in for them. Currently each method is enabled
955 # by a define "DSO_<name>" ... we translate the "dso_scheme" config
956 # string entry into using the following logic;
957 if (!$disabled{dso} && $target{dso_scheme} ne "")
958         {
959         $target{dso_scheme} =~ tr/[a-z]/[A-Z]/;
960         if ($target{dso_scheme} eq "DLFCN")
961                 {
962                 unshift @{$config{defines}}, "DSO_DLFCN", "HAVE_DLFCN_H";
963                 }
964         elsif ($target{dso_scheme} eq "DLFCN_NO_H")
965                 {
966                 unshift @{$config{defines}}, "DSO_DLFCN";
967                 }
968         else
969                 {
970                 unshift @{$config{defines}}, "DSO_$target{dso_scheme}";
971                 }
972         }
973
974 $config{ex_libs}="$libs$config{ex_libs}" if ($libs ne "");
975
976 if ($disabled{asm})
977         {
978         if ($config{fips})
979                 {
980                 @{$config{defines}} = grep !/^[BL]_ENDIAN$/, @{$config{defines}};
981                 @{$target{defines}} = grep !/^[BL]_ENDIAN$/, @{$target{defines}};
982                 }
983         }
984
985 # If threads aren't disabled, check how possible they are
986 unless ($disabled{threads}) {
987     if ($auto_threads) {
988         # Enabled by default, disable it forcibly if unavailable
989         if ($target{thread_scheme} eq "(unknown)") {
990             $disabled{threads} = "unavailable";
991         }
992     } else {
993         # The user chose to enable threads explicitly, let's see
994         # if there's a chance that's possible
995         if ($target{thread_scheme} eq "(unknown)") {
996             # If the user asked for "threads" and we don't have internal
997             # knowledge how to do it, [s]he is expected to provide any
998             # system-dependent compiler options that are necessary.  We
999             # can't truly check that the given options are correct, but
1000             # we expect the user to know what [s]He is doing.
1001             if ($no_user_cflags && $no_user_defines) {
1002                 die "You asked for multi-threading support, but didn't\n"
1003                     ,"provide any system-specific compiler options\n";
1004             }
1005         }
1006     }
1007 }
1008
1009 # If threads still aren't disabled, add a C macro to ensure the source
1010 # code knows about it.  Any other flag is taken care of by the configs.
1011 unless($disabled{threads}) {
1012     foreach (("defines", "openssl_thread_defines")) {
1013         push @{$config{$_}}, "OPENSSL_THREADS";
1014     }
1015 }
1016
1017 # With "deprecated" disable all deprecated features.
1018 if (defined($disabled{"deprecated"})) {
1019         $config{api} = $maxapi;
1020 }
1021
1022 if ($target{shared_target} eq "")
1023         {
1024         $no_shared_warn = 1
1025             if ((!$disabled{shared} || !$disabled{"dynamic-engine"})
1026                 && !$config{fips});
1027         $disabled{shared} = "no-shared-target";
1028         $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
1029             "no-shared-target";
1030         }
1031
1032 if ($disabled{"dynamic-engine"}) {
1033         push @{$config{defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
1034         $config{dynamic_engines} = 0;
1035 } else {
1036         push @{$config{defines}}, "OPENSSL_NO_STATIC_ENGINE";
1037         $config{dynamic_engines} = 1;
1038 }
1039
1040 unless ($disabled{fuzz}) {
1041     push @{$config{dirs}}, "fuzz";
1042     $config{cflags} .= "-fsanitize-coverage=edge,indirect-calls ";
1043 }
1044
1045 unless ($disabled{asan}) {
1046     $config{cflags} .= "-fsanitize=address ";
1047 }
1048
1049 unless ($disabled{ubsan}) {
1050     # -DPEDANTIC or -fnosanitize=aligmnent may also be required on some
1051     # platforms.
1052     $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all ";
1053 }
1054
1055 unless ($disabled{fuzz} && $disabled{asan} && $disabled{ubsan}) {
1056     $config{cflags} .= "-fno-omit-frame-pointer -g ";
1057 }
1058 #
1059 # Platform fix-ups
1060 #
1061
1062 # This saves the build files from having to check
1063 if ($disabled{pic})
1064         {
1065         $target{shared_cflag} = $target{shared_ldflag} =
1066                 $target{shared_rcflag} = "";
1067         }
1068 else
1069         {
1070         push @{$config{defines}}, "OPENSSL_PIC";
1071         }
1072
1073 if ($target{sys_id} ne "")
1074         {
1075         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1076         }
1077
1078 unless ($disabled{asm}) {
1079     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1080     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1081
1082     # bn-586 is the only one implementing bn_*_part_words
1083     push @{$config{defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1084     push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/);
1085
1086     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1087     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1088     push @{$config{defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1089
1090     if ($config{fips}) {
1091         push @{$config{openssl_other_defines}}, "OPENSSL_FIPS";
1092     }
1093
1094     if ($target{sha1_asm_src}) {
1095         push @{$config{defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1096         push @{$config{defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1097         push @{$config{defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1098     }
1099     if ($target{md5_asm_src}) {
1100         push @{$config{defines}}, "MD5_ASM";
1101     }
1102     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1103     if ($target{rmd160_asm_src}) {
1104         push @{$config{defines}}, "RMD160_ASM";
1105     }
1106     if ($target{aes_asm_src}) {
1107         push @{$config{defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1108         # aes-ctr.fake is not a real file, only indication that assembler
1109         # module implements AES_ctr32_encrypt...
1110         push @{$config{defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1111         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1112         push @{$config{defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1113         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2);
1114         push @{$config{defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1115         push @{$config{defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1116     }
1117     if ($target{wp_asm_src} =~ /mmx/) {
1118         if ($config{processor} eq "386") {
1119             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1120         } elsif (!$disabled{"whirlpool"}) {
1121             push @{$config{defines}}, "WHIRLPOOL_ASM";
1122         }
1123     }
1124     if ($target{modes_asm_src} =~ /ghash-/) {
1125         push @{$config{defines}}, "GHASH_ASM";
1126     }
1127     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1128         push @{$config{defines}}, "ECP_NISTZ256_ASM";
1129     }
1130     if ($target{poly1305_asm_src} ne "") {
1131         push @{$config{defines}}, "POLY1305_ASM";
1132     }
1133 }
1134
1135 my $ecc = $target{cc};
1136 if ($^O ne "VMS" && !$disabled{makedepend}) {
1137     # Is the compiler gcc or clang?  $ecc is used below to see if
1138     # error-checking can be turned on.
1139     my $ccpcc = "$config{cross_compile_prefix}$target{cc}";
1140     open(PIPE, "$ccpcc --version 2>&1 |");
1141     my $lines = 2;
1142     while ( <PIPE> ) {
1143         # Find the version number and save the major.
1144         m|(?:.*)\b(\d+)\.\d+\.\d+\b(?:.*)|;
1145         my $compiler_major = $1;
1146         # We know that GNU C version 3 and up as well as all clang
1147         # versions support dependency generation
1148         $config{makedepprog} = $ccpcc
1149             if (/clang/ || (/gcc/ && $compiler_major > 3));
1150         $ecc = "clang" if /clang/;
1151         $ecc = "gcc" if /gcc/;
1152         last if ($config{makedepprog} || !$lines--);
1153     }
1154     close(PIPE);
1155
1156     $config{makedepprog} = which('makedepend') unless $config{makedepprog};
1157     $disabled{makedepend} = "unavailable" unless $config{makedepprog};
1158 }
1159
1160
1161
1162 # Deal with bn_ops ###################################################
1163
1164 $config{bn_ll}                  =0;
1165 $config{export_var_as_fn}       =0;
1166 my $def_int="unsigned int";
1167 $config{rc4_int}                =$def_int;
1168 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1169
1170 my $count = 0;
1171 foreach (sort split(/\s+/,$target{bn_ops})) {
1172     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1173     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1174     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1175     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1176     ($config{b64l},$config{b64},$config{b32})
1177         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1178     ($config{b64l},$config{b64},$config{b32})
1179         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1180     ($config{b64l},$config{b64},$config{b32})
1181         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1182 }
1183 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1184     if $count > 1;
1185
1186
1187 # Hack cflags for better warnings (dev option) #######################
1188
1189 # "Stringify" the C flags string.  This permits it to be made part of a string
1190 # and works as well on command lines.
1191 $config{cflags} =~ s/([\\\"])/\\$1/g;
1192
1193 if (defined($config{api})) {
1194     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1195     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1196     push @{$config{defines}}, $apiflag;
1197 }
1198
1199 if ($strict_warnings)
1200         {
1201         my $wopt;
1202         die "ERROR --strict-warnings requires gcc or clang"
1203             unless $ecc eq 'gcc' || $ecc eq 'clang';
1204         foreach $wopt (split /\s+/, $gcc_devteam_warn)
1205                 {
1206                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1207                 }
1208         if ($ecc eq "clang")
1209                 {
1210                 foreach $wopt (split /\s+/, $clang_devteam_warn)
1211                         {
1212                         $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1213                         }
1214                 }
1215         }
1216
1217 unless ($disabled{"crypto-mdebug-backtrace"})
1218         {
1219         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1220                 {
1221                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1222                 }
1223         if ($target =~ /^BSD-/)
1224                 {
1225                 $config{ex_libs} .= " -lexecinfo";
1226                 }
1227         }
1228
1229 if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; }
1230 else                    { $no_user_cflags=1;  }
1231 if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; }
1232 else               { $no_user_defines=1;    }
1233
1234 # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
1235
1236 unless ($disabled{afalgeng}) {
1237     $config{afalgeng}="";
1238     if ($target =~ m/^linux/) {
1239         my $minver = 4*10000 + 1*100 + 0;
1240         if ($config{cross_compile_prefix} eq "") {
1241             my $verstr = `uname -r`;
1242             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1243             ($mi2) = $mi2 =~ /(\d+)/;
1244             my $ver = $ma*10000 + $mi1*100 + $mi2;
1245             if ($ver < $minver) {
1246                 $disabled{afalgeng} = "too-old-kernel";
1247             } else {
1248                 push @{$config{engdirs}}, "afalg";
1249             }
1250         } else {
1251             $disabled{afalgeng} = "cross-compiling";
1252         }
1253     } else {
1254         $disabled{afalgeng}  = "not-linux";
1255     }
1256 }
1257
1258 push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
1259
1260 # If we use the unified build, collect information from build.info files
1261 my %unified_info = ();
1262
1263 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1264 if ($builder eq "unified") {
1265     # Store the name of the template file we will build the build file from
1266     # in %config.  This may be useful for the build file itself.
1267     my $build_file_template;
1268
1269     for my $filename (( $builder_platform."-".$target{build_file}.".tmpl",
1270                         $target{build_file}.".tmpl" )) {
1271         if (defined $ENV{$local_config_envname}) {
1272             if ($^O eq 'VMS') {
1273                 # VMS environment variables are logical names,
1274                 # which can be used as is
1275                 $build_file_template = $local_config_envname . ':' . $filename;
1276             } else {
1277                 $build_file_template = catfile($ENV{$local_config_envname},
1278                                                $filename);
1279             }
1280         }
1281
1282         last if -f $build_file_template;
1283
1284         $build_file_template = catfile($srcdir, "Configurations", $filename);
1285
1286         last if -f $build_file_template;
1287     }
1288     $config{build_file_template} = $build_file_template;
1289
1290     use lib catdir(dirname(__FILE__),"util");
1291     use with_fallback qw(Text::Template);
1292
1293     sub cleandir {
1294         my $base = shift;
1295         my $dir = shift;
1296         my $relativeto = shift || ".";
1297
1298         $dir = catdir($base,$dir) unless isabsolute($dir);
1299
1300         # Make sure the directories we're building in exists
1301         mkpath($dir);
1302
1303         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1304         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1305         return $res;
1306     }
1307
1308     sub cleanfile {
1309         my $base = shift;
1310         my $file = shift;
1311         my $relativeto = shift || ".";
1312
1313         $file = catfile($base,$file) unless isabsolute($file);
1314
1315         my $d = dirname($file);
1316         my $f = basename($file);
1317
1318         # Make sure the directories we're building in exists
1319         mkpath($d);
1320
1321         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1322         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1323         return $res;
1324     }
1325
1326     my @build_infos = ( [ ".", "build.info" ] );
1327     foreach (@{$config{dirs}}) {
1328         push @build_infos, [ $_, "build.info" ]
1329             if (-f catfile($srcdir, $_, "build.info"));
1330     }
1331     foreach (@{$config{sdirs}}) {
1332         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1333             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1334     }
1335     foreach (@{$config{engdirs}}) {
1336         push @build_infos, [ catdir("engines", $_), "build.info" ]
1337             if (-f catfile($srcdir, "engines", $_, "build.info"));
1338     }
1339
1340     $config{build_infos} = [ ];
1341
1342     foreach (@build_infos) {
1343         my $sourced = catdir($srcdir, $_->[0]);
1344         my $buildd = catdir($blddir, $_->[0]);
1345
1346         mkpath($buildd);
1347
1348         my $f = $_->[1];
1349         # The basic things we're trying to build
1350         my @programs = ();
1351         my @libraries = ();
1352         my @engines = ();
1353         my @scripts = ();
1354         my @extra = ();
1355         my @overrides = ();
1356         my @intermediates = ();
1357         my @rawlines = ();
1358
1359         my %ordinals = ();
1360         my %sources = ();
1361         my %shared_sources = ();
1362         my %includes = ();
1363         my %depends = ();
1364         my %renames = ();
1365         my %sharednames = ();
1366         my %generate = ();
1367
1368         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1369         my $template = Text::Template->new(TYPE => 'FILE',
1370                                            SOURCE => catfile($sourced, $f));
1371         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1372         my @text =
1373             split /^/m,
1374             $template->fill_in(HASH => { config => \%config,
1375                                          target => \%target,
1376                                          disabled => \%disabled,
1377                                          builddir => abs2rel($buildd, $blddir),
1378                                          sourcedir => abs2rel($sourced, $blddir),
1379                                          buildtop => abs2rel($blddir, $blddir),
1380                                          sourcetop => abs2rel($srcdir, $blddir) },
1381                                DELIMITERS => [ "{-", "-}" ]);
1382
1383         # The top item of this stack has the following values
1384         # -2 positive already run and we found ELSE (following ELSIF should fail)
1385         # -1 positive already run (skip until ENDIF)
1386         # 0 negatives so far (if we're at a condition, check it)
1387         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1388         # 2 positive ELSE (following ELSIF should fail)
1389         my @skip = ();
1390         collect_information(
1391             collect_from_array([ @text ],
1392                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1393                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1394             # Info we're looking for
1395             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1396             => sub {
1397                 if (! @skip || $skip[$#skip] > 0) {
1398                     push @skip, !! $1;
1399                 } else {
1400                     push @skip, -1;
1401                 }
1402             },
1403             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1404             => sub { die "ELSIF out of scope" if ! @skip;
1405                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1406                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1407                      $skip[$#skip] = !! $1
1408                          if $skip[$#skip] == 0; },
1409             qr/^\s*ELSE\s*$/
1410             => sub { die "ELSE out of scope" if ! @skip;
1411                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1412                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1413             qr/^\s*ENDIF\s*$/
1414             => sub { die "ENDIF out of scope" if ! @skip;
1415                      pop @skip; },
1416             qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/
1417             => sub { push @programs, split(/\s+/, $1)
1418                          if !@skip || $skip[$#skip] > 0 },
1419             qr/^\s*LIBS\s*=\s*(.*)\s*$/
1420             => sub { push @libraries, split(/\s+/, $1)
1421                          if !@skip || $skip[$#skip] > 0 },
1422             qr/^\s*ENGINES\s*=\s*(.*)\s*$/
1423             => sub { push @engines, split(/\s+/, $1)
1424                          if !@skip || $skip[$#skip] > 0 },
1425             qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/
1426             => sub { push @scripts, split(/\s+/, $1)
1427                          if !@skip || $skip[$#skip] > 0 },
1428             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1429             => sub { push @extra, split(/\s+/, $1)
1430                          if !@skip || $skip[$#skip] > 0 },
1431             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1432             => sub { push @overrides, split(/\s+/, $1)
1433                          if !@skip || $skip[$#skip] > 0 },
1434
1435             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1436             => sub { push @{$ordinals{$1}}, split(/\s+/, $2)
1437                          if !@skip || $skip[$#skip] > 0 },
1438             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1439             => sub { push @{$sources{$1}}, split(/\s+/, $2)
1440                          if !@skip || $skip[$#skip] > 0 },
1441             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1442             => sub { push @{$shared_sources{$1}}, split(/\s+/, $2)
1443                          if !@skip || $skip[$#skip] > 0 },
1444             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1445             => sub { push @{$includes{$1}}, split(/\s+/, $2)
1446                          if !@skip || $skip[$#skip] > 0 },
1447             qr/^\s*DEPEND\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1448             => sub { push @{$depends{$1}}, split(/\s+/, $2)
1449                          if !@skip || $skip[$#skip] > 0 },
1450             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1451             => sub { push @{$generate{$1}}, $2
1452                          if !@skip || $skip[$#skip] > 0 },
1453             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1454             => sub { push @{$renames{$1}}, split(/\s+/, $2)
1455                          if !@skip || $skip[$#skip] > 0 },
1456             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1457             => sub { push @{$sharednames{$1}}, split(/\s+/, $2)
1458                          if !@skip || $skip[$#skip] > 0 },
1459             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1460             => sub {
1461                 my $lineiterator = shift;
1462                 my $target_kind = $1;
1463                 while (defined $lineiterator->()) {
1464                     s|\R$||;
1465                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1466                         die "ENDRAW doesn't match BEGINRAW"
1467                             if $1 ne $target_kind;
1468                         last;
1469                     }
1470                     next if @skip && $skip[$#skip] <= 0;
1471                     push @rawlines,  $_
1472                         if ($target_kind eq $target{build_file}
1473                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1474                 }
1475             },
1476             qr/^(?:#.*|\s*)$/ => sub { },
1477             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1478             "BEFORE" => sub {
1479                 if ($buildinfo_debug) {
1480                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1481                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1482                 }
1483             },
1484             "AFTER" => sub {
1485                 if ($buildinfo_debug) {
1486                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1487                 }
1488             },
1489             );
1490         die "runaway IF?" if (@skip);
1491
1492         foreach (keys %renames) {
1493             die "$_ renamed to more than one thing: "
1494                 ,join(" ", @{$renames{$_}}),"\n"
1495                 if scalar @{$renames{$_}} > 1;
1496             my $dest = cleanfile($buildd, $_, $blddir);
1497             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1498             die "$dest renamed to more than one thing: "
1499                 ,$unified_info{rename}->{$dest}, $to
1500                 unless !defined($unified_info{rename}->{$dest})
1501                 or $unified_info{rename}->{$dest} eq $to;
1502             $unified_info{rename}->{$dest} = $to;
1503         }
1504
1505         foreach (@programs) {
1506             my $program = cleanfile($buildd, $_, $blddir);
1507             if ($unified_info{rename}->{$program}) {
1508                 $program = $unified_info{rename}->{$program};
1509             }
1510             $unified_info{programs}->{$program} = 1;
1511         }
1512
1513         foreach (@libraries) {
1514             my $library = cleanfile($buildd, $_, $blddir);
1515             if ($unified_info{rename}->{$library}) {
1516                 $library = $unified_info{rename}->{$library};
1517             }
1518             $unified_info{libraries}->{$library} = 1;
1519         }
1520
1521         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
1522 ENGINES can only be used if configured with 'dynamic-engine'.
1523 This is usually a fault in a build.info file.
1524 EOF
1525         foreach (@engines) {
1526             my $library = cleanfile($buildd, $_, $blddir);
1527             if ($unified_info{rename}->{$library}) {
1528                 $library = $unified_info{rename}->{$library};
1529             }
1530             $unified_info{engines}->{$library} = 1;
1531         }
1532
1533         foreach (@scripts) {
1534             my $script = cleanfile($buildd, $_, $blddir);
1535             if ($unified_info{rename}->{$script}) {
1536                 $script = $unified_info{rename}->{$script};
1537             }
1538             $unified_info{scripts}->{$script} = 1;
1539         }
1540
1541         foreach (@extra) {
1542             my $extra = cleanfile($buildd, $_, $blddir);
1543             $unified_info{extra}->{$extra} = 1;
1544         }
1545
1546         foreach (@overrides) {
1547             my $override = cleanfile($buildd, $_, $blddir);
1548             $unified_info{overrides}->{$override} = 1;
1549         }
1550
1551         push @{$unified_info{rawlines}}, @rawlines;
1552
1553         unless ($disabled{shared}) {
1554             # Check sharednames.
1555             foreach (keys %sharednames) {
1556                 my $dest = cleanfile($buildd, $_, $blddir);
1557                 if ($unified_info{rename}->{$dest}) {
1558                     $dest = $unified_info{rename}->{$dest};
1559                 }
1560                 die "shared_name for $dest with multiple values: "
1561                     ,join(" ", @{$sharednames{$_}}),"\n"
1562                     if scalar @{$sharednames{$_}} > 1;
1563                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
1564                 die "shared_name found for a library $dest that isn't defined\n"
1565                     unless $unified_info{libraries}->{$dest};
1566                 die "shared_name for $dest with multiple values: "
1567                     ,$unified_info{sharednames}->{$dest}, ", ", $to
1568                     unless !defined($unified_info{sharednames}->{$dest})
1569                     or $unified_info{sharednames}->{$dest} eq $to;
1570                 $unified_info{sharednames}->{$dest} = $to;
1571             }
1572
1573             # Additionally, we set up sharednames for libraries that don't
1574             # have any, as themselves.
1575             foreach (keys %{$unified_info{libraries}}) {
1576                 if (!defined $unified_info{sharednames}->{$_}) {
1577                     $unified_info{sharednames}->{$_} = $_
1578                 }
1579             }
1580         }
1581
1582         foreach (keys %ordinals) {
1583             my $dest = $_;
1584             my $ddest = cleanfile($buildd, $_, $blddir);
1585             if ($unified_info{rename}->{$ddest}) {
1586                 $ddest = $unified_info{rename}->{$ddest};
1587             }
1588             foreach (@{$ordinals{$dest}}) {
1589                 my %known_ordinals =
1590                     (
1591                      crypto =>
1592                      cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
1593                      ssl =>
1594                      cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
1595                     );
1596                 my $o = $known_ordinals{$_};
1597                 die "Ordinals for $ddest defined more than once\n"
1598                     if $unified_info{ordinals}->{$ddest};
1599                 $unified_info{ordinals}->{$ddest} = [ $_, $o ];
1600             }
1601         }
1602
1603         foreach (keys %sources) {
1604             my $dest = $_;
1605             my $ddest = cleanfile($buildd, $_, $blddir);
1606             if ($unified_info{rename}->{$ddest}) {
1607                 $ddest = $unified_info{rename}->{$ddest};
1608             }
1609             foreach (@{$sources{$dest}}) {
1610                 my $s = cleanfile($sourced, $_, $blddir);
1611
1612                 # If it isn't in the source tree, we assume it's generated
1613                 # in the build tree
1614                 if (! -f $s) {
1615                     $s = cleanfile($buildd, $_, $blddir);
1616                 }
1617                 # We recognise C and asm files
1618                 if ($s =~ /\.[csS]\b$/) {
1619                     (my $o = $_) =~ s/\.[csS]\b$/.o/;
1620                     $o = cleanfile($buildd, $o, $blddir);
1621                     $unified_info{sources}->{$ddest}->{$o} = 1;
1622                     $unified_info{sources}->{$o}->{$s} = 1;
1623                 } else {
1624                     $unified_info{sources}->{$ddest}->{$s} = 1;
1625                 }
1626             }
1627         }
1628
1629         foreach (keys %shared_sources) {
1630             my $dest = $_;
1631             my $ddest = cleanfile($buildd, $_, $blddir);
1632             if ($unified_info{rename}->{$ddest}) {
1633                 $ddest = $unified_info{rename}->{$ddest};
1634             }
1635             foreach (@{$shared_sources{$dest}}) {
1636                 my $s = cleanfile($sourced, $_, $blddir);
1637
1638                 # If it isn't in the source tree, we assume it's generated
1639                 # in the build tree
1640                 if (! -f $s) {
1641                     $s = cleanfile($buildd, $_, $blddir);
1642                 }
1643                 # We recognise C and asm files
1644                 if ($s =~ /\.[csS]\b$/) {
1645                     (my $o = $_) =~ s/\.[csS]\b$/.o/;
1646                     $o = cleanfile($buildd, $o, $blddir);
1647                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
1648                     $unified_info{sources}->{$o}->{$s} = 1;
1649                 } else {
1650                     die "unrecognised source file type for shared library: $s\n";
1651                 }
1652             }
1653         }
1654
1655         foreach (keys %generate) {
1656             my $dest = $_;
1657             my $ddest = cleanfile($buildd, $_, $blddir);
1658             if ($unified_info{rename}->{$ddest}) {
1659                 $ddest = $unified_info{rename}->{$ddest};
1660             }
1661             die "more than one generator for $dest: "
1662                     ,join(" ", @{$generate{$_}}),"\n"
1663                     if scalar @{$generate{$_}} > 1;
1664             my @generator = split /\s+/, $generate{$dest}->[0];
1665             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
1666             $unified_info{generate}->{$ddest} = [ @generator ];
1667         }
1668
1669         foreach (keys %depends) {
1670             my $dest = $_;
1671             my $ddest = cleanfile($sourced, $_, $blddir);
1672
1673             # If the destination doesn't exist in source, it can only be
1674             # a generated file in the build tree.
1675             if (! -f $ddest) {
1676                 $ddest = cleanfile($buildd, $_, $blddir);
1677                 if ($unified_info{rename}->{$ddest}) {
1678                     $ddest = $unified_info{rename}->{$ddest};
1679                 }
1680             }
1681             foreach (@{$depends{$dest}}) {
1682                 my $d = cleanfile($sourced, $_, $blddir);
1683
1684                 # If we know it's generated, or assume it is because we can't
1685                 # find it in the source tree, we set file we depend on to be
1686                 # in the build tree rather than the source tree, and assume
1687                 # and that there are lines to build it in a BEGINRAW..ENDRAW
1688                 # section or in the Makefile template.
1689                 if (! -f $d
1690                     || (grep { $d eq $_ }
1691                         map { cleanfile($srcdir, $_, $blddir) }
1692                         (@generated_headers, @generated_by_make_headers))) {
1693                     $d = cleanfile($buildd, $_, $blddir);
1694                 }
1695                 # Take note if the file to depend on is being renamed
1696                 if ($unified_info{rename}->{$d}) {
1697                     $d = $unified_info{rename}->{$d};
1698                 }
1699                 $unified_info{depends}->{$ddest}->{$d} = 1;
1700                 # If we depend on a header file or a perl module, let's make
1701                 # sure it can get included
1702                 if ($d =~ /\.(h|pm)$/) {
1703                     my $i = dirname($d);
1704                     push @{$unified_info{includes}->{$ddest}}, $i
1705                         unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
1706                 }
1707             }
1708         }
1709
1710         foreach (keys %includes) {
1711             my $dest = $_;
1712             my $ddest = cleanfile($sourced, $_, $blddir);
1713
1714             # If the destination doesn't exist in source, it can only be
1715             # a generated file in the build tree.
1716             if (! -f $ddest) {
1717                 $ddest = cleanfile($buildd, $_, $blddir);
1718                 if ($unified_info{rename}->{$ddest}) {
1719                     $ddest = $unified_info{rename}->{$ddest};
1720                 }
1721             }
1722             foreach (@{$includes{$dest}}) {
1723                 my $i = cleandir($sourced, $_, $blddir);
1724                 push @{$unified_info{includes}->{$ddest}}, $i
1725                     unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}};
1726             }
1727         }
1728     }
1729
1730     ### Make unified_info a bit more efficient
1731     # One level structures
1732     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
1733         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
1734     }
1735     # Two level structures
1736     foreach my $l1 (("sources", "shared_sources", "ldadd", "depends")) {
1737         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
1738             $unified_info{$l1}->{$l2} =
1739                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
1740         }
1741     }
1742 }
1743
1744 # For the schemes that need it, we provide the old *_obj configs
1745 # from the *_asm_obj ones
1746 foreach (grep /_(asm|aux)_src$/, keys %target) {
1747     my $src = $_;
1748     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
1749     ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g;
1750 }
1751
1752 # Write down our configuration where it fits #########################
1753
1754 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
1755 print OUT <<"EOF";
1756 package configdata;
1757
1758 use strict;
1759 use warnings;
1760
1761 use Exporter;
1762 #use vars qw(\@ISA \@EXPORT);
1763 our \@ISA = qw(Exporter);
1764 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
1765
1766 EOF
1767 print OUT "our %config = (\n";
1768 foreach (sort keys %config) {
1769     if (ref($config{$_}) eq "ARRAY") {
1770         print OUT "  ", $_, " => [ ", join(", ",
1771                                            map { quotify("perl", $_) }
1772                                            @{$config{$_}}), " ],\n";
1773     } else {
1774         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
1775     }
1776 }
1777 print OUT <<"EOF";
1778 );
1779
1780 EOF
1781 print OUT "our %target = (\n";
1782 foreach (sort keys %target) {
1783     if (ref($target{$_}) eq "ARRAY") {
1784         print OUT "  ", $_, " => [ ", join(", ",
1785                                            map { quotify("perl", $_) }
1786                                            @{$target{$_}}), " ],\n";
1787     } else {
1788         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
1789     }
1790 }
1791 print OUT <<"EOF";
1792 );
1793
1794 EOF
1795 print OUT "our \%available_protocols = (\n";
1796 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
1797 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
1798 print OUT <<"EOF";
1799 );
1800
1801 EOF
1802 print OUT "our \@disablables = (\n";
1803 foreach (@disablables) {
1804     print OUT "  ", quotify("perl", $_), ",\n";
1805 }
1806 print OUT <<"EOF";
1807 );
1808
1809 EOF
1810 print OUT "our \%disabled = (\n";
1811 foreach (sort keys %disabled) {
1812     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
1813 }
1814 print OUT <<"EOF";
1815 );
1816
1817 EOF
1818 print OUT "our %withargs = (\n";
1819 foreach (sort keys %withargs) {
1820     if (ref($withargs{$_}) eq "ARRAY") {
1821         print OUT "  ", $_, " => [ ", join(", ",
1822                                            map { quotify("perl", $_) }
1823                                            @{$withargs{$_}}), " ],\n";
1824     } else {
1825         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
1826     }
1827 }
1828 print OUT <<"EOF";
1829 );
1830
1831 EOF
1832 if ($builder eq "unified") {
1833     my $recurse;
1834     $recurse = sub {
1835         my $indent = shift;
1836         foreach (@_) {
1837             if (ref $_ eq "ARRAY") {
1838                 print OUT " "x$indent, "[\n";
1839                 foreach (@$_) {
1840                     $recurse->($indent + 4, $_);
1841                 }
1842                 print OUT " "x$indent, "],\n";
1843             } elsif (ref $_ eq "HASH") {
1844                 my %h = %$_;
1845                 print OUT " "x$indent, "{\n";
1846                 foreach (sort keys %h) {
1847                     if (ref $h{$_} eq "") {
1848                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
1849                     } else {
1850                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
1851                         $recurse->($indent + 8, $h{$_});
1852                     }
1853                 }
1854                 print OUT " "x$indent, "},\n";
1855             } else {
1856                 print OUT " "x$indent, quotify("perl", $_), ",\n";
1857             }
1858         }
1859     };
1860     print OUT "our %unified_info = (\n";
1861     foreach (sort keys %unified_info) {
1862         if (ref $unified_info{$_} eq "") {
1863             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
1864         } else {
1865             print OUT " "x4, quotify("perl", $_), " =>\n";
1866             $recurse->(8, $unified_info{$_});
1867         }
1868     }
1869     print OUT <<"EOF";
1870 );
1871
1872 EOF
1873 }
1874 print OUT "1;\n";
1875 close(OUT);
1876
1877
1878 print "CC            =$config{cross_compile_prefix}$target{cc}\n";
1879 print "CFLAG         =$target{cflags} $config{cflags}\n";
1880 print "SHARED_CFLAG  =$target{shared_cflag}\n";
1881 print "DEFINES       =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n";
1882 print "LFLAG         =$target{lflags}\n";
1883 print "PLIB_LFLAG    =$target{plib_lflags}\n";
1884 print "EX_LIBS       =$target{ex_libs} $config{ex_libs}\n";
1885 print "APPS_OBJ      =$target{apps_obj}\n";
1886 print "CPUID_OBJ     =$target{cpuid_obj}\n";
1887 print "UPLINK_OBJ    =$target{uplink_obj}\n";
1888 print "BN_ASM        =$target{bn_obj}\n";
1889 print "EC_ASM        =$target{ec_obj}\n";
1890 print "DES_ENC       =$target{des_obj}\n";
1891 print "AES_ENC       =$target{aes_obj}\n";
1892 print "BF_ENC        =$target{bf_obj}\n";
1893 print "CAST_ENC      =$target{cast_obj}\n";
1894 print "RC4_ENC       =$target{rc4_obj}\n";
1895 print "RC5_ENC       =$target{rc5_obj}\n";
1896 print "MD5_OBJ_ASM   =$target{md5_obj}\n";
1897 print "SHA1_OBJ_ASM  =$target{sha1_obj}\n";
1898 print "RMD160_OBJ_ASM=$target{rmd160_obj}\n";
1899 print "CMLL_ENC      =$target{cmll_obj}\n";
1900 print "MODES_OBJ     =$target{modes_obj}\n";
1901 print "PADLOCK_OBJ   =$target{padlock_obj}\n";
1902 print "CHACHA_ENC    =$target{chacha_obj}\n";
1903 print "POLY1305_OBJ  =$target{poly1305_obj}\n";
1904 print "BLAKE2_OBJ    =$target{blake2_obj}\n";
1905 print "PROCESSOR     =$config{processor}\n";
1906 print "RANLIB        =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
1907                              "$config{cross_compile_prefix}ranlib" :
1908                              "$target{ranlib}", "\n";
1909 print "ARFLAGS       =$target{arflags}\n";
1910 print "PERL          =$config{perl}\n";
1911 print "\n";
1912 print "SIXTY_FOUR_BIT_LONG mode\n" if $config{b64l};
1913 print "SIXTY_FOUR_BIT mode\n" if $config{b64};
1914 print "THIRTY_TWO_BIT mode\n" if $config{b32};
1915 print "BN_LLONG mode\n" if $config{bn_ll};
1916 print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} ne $def_int;
1917
1918 for (@generated_headers) {
1919     mkpath(catdir($blddir, dirname($_)));
1920     run_dofile(catfile($blddir, $_),
1921                catfile($srcdir, $_.".in"));
1922 }
1923
1924 ###
1925 ### When the old "unixmake" scheme goes away, so does this function
1926 ###
1927 sub build_Makefile {
1928     run_dofile("Makefile","Makefile.in");
1929
1930     # Copy all Makefile.in to Makefile (except top-level)
1931     use File::Find;
1932     use IO::File;
1933     find(
1934         {
1935             preprocess => sub {
1936                 grep(!/^\./, @_);
1937             },
1938             wanted => sub {
1939                 return if ($_ ne "Makefile.in" || $File::Find::dir eq ".");
1940                 my $in = IO::File->new($_, "r") or
1941                     die sprintf "Error reading Makefile.in in %s: !$\n",
1942                     $File::Find::dir;
1943                 my $out = IO::File->new("Makefile", "w") or
1944                     die sprintf "Error writing Makefile in %s: !$\n",
1945                     $File::Find::dir;
1946                 print $out "# Generated from $_, do not edit\n";
1947                 while (my $line = <$in>) { print $out $line }
1948                 $in->close() or
1949                     die sprintf "Error reading Makefile.in in %s: !$\n",
1950                     $File::Find::dir;
1951                 $out->close() or
1952                     die sprintf "Error writing Makefile in %s: !$\n",
1953                     $File::Find::dir;
1954             },
1955         },
1956         ".");
1957 }
1958
1959 my %builders = (
1960     unified => sub {
1961         run_dofile(catfile($blddir, $target{build_file}),
1962                    $config{build_file_template},
1963                    catfile($srcdir, "Configurations", "common.tmpl"));
1964     },
1965     unixmake => sub {
1966         build_Makefile();
1967
1968         run_dofile("util/domd", "util/domd.in");
1969         chmod 0755, "util/domd";
1970     },
1971     );
1972
1973 $builders{$builder}->($builder_platform, @builder_opts);
1974
1975 print <<"EOF";
1976
1977 Configured for $target.
1978 EOF
1979
1980 print <<"EOF" if ($disabled{threads} eq "unavailable");
1981
1982 The library could not be configured for supporting multi-threaded
1983 applications as the compiler options required on this system are not known.
1984 See file INSTALL for details if you need multi-threading.
1985 EOF
1986
1987 print <<"EOF" if ($no_shared_warn);
1988
1989 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
1990 platform, so we will pretend you gave the option 'no-pic', which also disables
1991 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
1992 or position independent code, please let us know (but please first make sure
1993 you have tried with a current version of OpenSSL).
1994 EOF
1995
1996 print <<"EOF" if (-f catfile($srcdir, "configdata.pm") && $srcdir ne $blddir);
1997
1998 WARNING: there are indications that another build was made in the source
1999 directory.  This build may have picked up artifacts from that build, the
2000 safest course of action is to clean the source directory and redo this
2001 configuration.
2002 EOF
2003
2004 exit(0);
2005
2006 ######################################################################
2007 #
2008 # Helpers and utility functions
2009 #
2010
2011 # Configuration file reading #########################################
2012
2013 # Note: All of the helper functions are for lazy evaluation.  They all
2014 # return a CODE ref, which will return the intended value when evaluated.
2015 # Thus, whenever there's mention of a returned value, it's about that
2016 # intended value.
2017
2018 # Helper function to implement conditional inheritance depending on the
2019 # value of $disabled{asm}.  Used in inherit_from values as follows:
2020 #
2021 #      inherit_from => [ "template", asm("asm_tmpl") ]
2022 #
2023 sub asm {
2024     my @x = @_;
2025     sub {
2026         $disabled{asm} ? () : @x;
2027     }
2028 }
2029
2030 # Helper function to implement conditional value variants, with a default
2031 # plus additional values based on the value of $config{build_type}.
2032 # Arguments are given in hash table form:
2033 #
2034 #       picker(default => "Basic string: ",
2035 #              debug   => "debug",
2036 #              release => "release")
2037 #
2038 # When configuring with --debug, the resulting string will be
2039 # "Basic string: debug", and when not, it will be "Basic string: release"
2040 #
2041 # This can be used to create variants of sets of flags according to the
2042 # build type:
2043 #
2044 #       cflags => picker(default => "-Wall",
2045 #                        debug   => "-g -O0",
2046 #                        release => "-O3")
2047 #
2048 sub picker {
2049     my %opts = @_;
2050     return sub { add($opts{default} || (),
2051                      $opts{$config{build_type}} || ())->(); }
2052 }
2053
2054 # Helper function to combine several values of different types into one.
2055 # This is useful if you want to combine a string with the result of a
2056 # lazy function, such as:
2057 #
2058 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2059 #
2060 sub combine {
2061     my @stuff = @_;
2062     return sub { add(@stuff)->(); }
2063 }
2064
2065 # Helper function to implement conditional values depending on the value
2066 # of $disabled{threads}.  Can be used as follows:
2067 #
2068 #       cflags => combine("-Wall", threads("-pthread"))
2069 #
2070 sub threads {
2071     my @flags = @_;
2072     return sub { add($disabled{threads} ? () : @flags)->(); }
2073 }
2074
2075
2076
2077 our $add_called = 0;
2078 # Helper function to implement adding values to already existing configuration
2079 # values.  It handles elements that are ARRAYs, CODEs and scalars
2080 sub _add {
2081     my $separator = shift;
2082
2083     # If there's any ARRAY in the collection of values OR the separator
2084     # is undef, we will return an ARRAY of combined values, otherwise a
2085     # string of joined values with $separator as the separator.
2086     my $found_array = !defined($separator);
2087
2088     my @values =
2089         map {
2090             my $res = $_;
2091             while (ref($res) eq "CODE") {
2092                 $res = $res->();
2093             }
2094             if (defined($res)) {
2095                 if (ref($res) eq "ARRAY") {
2096                     $found_array = 1;
2097                     @$res;
2098                 } else {
2099                     $res;
2100                 }
2101             } else {
2102                 ();
2103             }
2104     } (@_);
2105
2106     $add_called = 1;
2107
2108     if ($found_array) {
2109         [ @values ];
2110     } else {
2111         join($separator, grep { defined($_) && $_ ne "" } @values);
2112     }
2113 }
2114 sub add_before {
2115     my $separator = " ";
2116     if (ref($_[$#_]) eq "HASH") {
2117         my $opts = pop;
2118         $separator = $opts->{separator};
2119     }
2120     my @x = @_;
2121     sub { _add($separator, @x, @_) };
2122 }
2123 sub add {
2124     my $separator = " ";
2125     if (ref($_[$#_]) eq "HASH") {
2126         my $opts = pop;
2127         $separator = $opts->{separator};
2128     }
2129     my @x = @_;
2130     sub { _add($separator, @_, @x) };
2131 }
2132
2133 # configuration reader, evaluates the input file as a perl script and expects
2134 # it to fill %targets with target configurations.  Those are then added to
2135 # %table.
2136 sub read_config {
2137     my $fname = shift;
2138     open(CONFFILE, "< $fname")
2139         or die "Can't open configuration file '$fname'!\n";
2140     my $x = $/;
2141     undef $/;
2142     my $content = <CONFFILE>;
2143     $/ = $x;
2144     close(CONFFILE);
2145     my %targets = ();
2146     {
2147         local %table = %::table;    # Protect %table from tampering
2148
2149         eval $content;
2150         warn $@ if $@;
2151     }
2152
2153     # For each target, check that it's configured with a hash table.
2154     foreach (keys %targets) {
2155         if (ref($targets{$_}) ne "HASH") {
2156             if (ref($targets{$_}) eq "") {
2157                 warn "Deprecated target configuration for $_, ignoring...\n";
2158             } else {
2159                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
2160             }
2161             delete $targets{$_};
2162         }
2163     }
2164
2165     %table = (%table, %targets);
2166
2167 }
2168
2169 # configuration resolver.  Will only resolve all the lazy evaluation
2170 # codeblocks for the chosen target and all those it inherits from,
2171 # recursively
2172 sub resolve_config {
2173     my $target = shift;
2174     my @breadcrumbs = @_;
2175
2176 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
2177
2178     if (grep { $_ eq $target } @breadcrumbs) {
2179         die "inherit_from loop!  target backtrace:\n  "
2180             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
2181     }
2182
2183     if (!defined($table{$target})) {
2184         warn "Warning! target $target doesn't exist!\n";
2185         return ();
2186     }
2187     # Recurse through all inheritances.  They will be resolved on the
2188     # fly, so when this operation is done, they will all just be a
2189     # bunch of attributes with string values.
2190     # What we get here, though, are keys with references to lists of
2191     # the combined values of them all.  We will deal with lists after
2192     # this stage is done.
2193     my %combined_inheritance = ();
2194     if ($table{$target}->{inherit_from}) {
2195         my @inherit_from =
2196             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
2197         foreach (@inherit_from) {
2198             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
2199
2200             # 'template' is a marker that's considered private to
2201             # the config that had it.
2202             delete $inherited_config{template};
2203
2204             foreach (keys %inherited_config) {
2205                 if (!$combined_inheritance{$_}) {
2206                     $combined_inheritance{$_} = [];
2207                 }
2208                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
2209             }
2210         }
2211     }
2212
2213     # We won't need inherit_from in this target any more, since we've
2214     # resolved all the inheritances that lead to this
2215     delete $table{$target}->{inherit_from};
2216
2217     # Now is the time to deal with those lists.  Here's the place to
2218     # decide what shall be done with those lists, all based on the
2219     # values of the target we're currently dealing with.
2220     # - If a value is a coderef, it will be executed with the list of
2221     #   inherited values as arguments.
2222     # - If the corresponding key doesn't have a value at all or is the
2223     #   empty string, the inherited value list will be run through the
2224     #   default combiner (below), and the result becomes this target's
2225     #   value.
2226     # - Otherwise, this target's value is assumed to be a string that
2227     #   will simply override the inherited list of values.
2228     my $default_combiner = add();
2229
2230     my %all_keys =
2231         map { $_ => 1 } (keys %combined_inheritance,
2232                          keys %{$table{$target}});
2233
2234     sub process_values {
2235         my $object    = shift;
2236         my $inherited = shift;  # Always a [ list ]
2237         my $target    = shift;
2238         my $entry     = shift;
2239
2240         $add_called = 0;
2241
2242         while(ref($object) eq "CODE") {
2243             $object = $object->(@$inherited);
2244         }
2245         if (!defined($object)) {
2246             return ();
2247         }
2248         elsif (ref($object) eq "ARRAY") {
2249             local $add_called;  # To make sure recursive calls don't affect it
2250             return [ map { process_values($_, $inherited, $target, $entry) }
2251                      @$object ];
2252         } elsif (ref($object) eq "") {
2253             return $object;
2254         } else {
2255             die "cannot handle reference type ",ref($object)
2256                 ," found in target ",$target," -> ",$entry,"\n";
2257         }
2258     }
2259
2260     foreach (sort keys %all_keys) {
2261         my $previous = $combined_inheritance{$_};
2262
2263         # Current target doesn't have a value for the current key?
2264         # Assign it the default combiner, the rest of this loop body
2265         # will handle it just like any other coderef.
2266         if (!exists $table{$target}->{$_}) {
2267             $table{$target}->{$_} = $default_combiner;
2268         }
2269
2270         $table{$target}->{$_} = process_values($table{$target}->{$_},
2271                                                $combined_inheritance{$_},
2272                                                $target, $_);
2273         unless(defined($table{$target}->{$_})) {
2274             delete $table{$target}->{$_};
2275         }
2276 #        if ($extra_checks &&
2277 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
2278 #            warn "$_ got replaced in $target\n";
2279 #        }
2280     }
2281
2282     # Finally done, return the result.
2283     return %{$table{$target}};
2284 }
2285
2286 sub usage
2287         {
2288         print STDERR $usage;
2289         print STDERR "\npick os/compiler from:\n";
2290         my $j=0;
2291         my $i;
2292         my $k=0;
2293         foreach $i (sort keys %table)
2294                 {
2295                 next if $table{$i}->{template};
2296                 next if $i =~ /^debug/;
2297                 $k += length($i) + 1;
2298                 if ($k > 78)
2299                         {
2300                         print STDERR "\n";
2301                         $k=length($i);
2302                         }
2303                 print STDERR $i . " ";
2304                 }
2305         foreach $i (sort keys %table)
2306                 {
2307                 next if $table{$i}->{template};
2308                 next if $i !~ /^debug/;
2309                 $k += length($i) + 1;
2310                 if ($k > 78)
2311                         {
2312                         print STDERR "\n";
2313                         $k=length($i);
2314                         }
2315                 print STDERR $i . " ";
2316                 }
2317         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
2318         exit(1);
2319         }
2320
2321 sub run_dofile
2322 {
2323     my $out = shift;
2324     my @templates = @_;
2325
2326     unlink $out || warn "Can't remove $out, $!"
2327         if -f $out;
2328     foreach (@templates) {
2329         die "Can't open $_, $!" unless -f $_;
2330     }
2331     my $cmd = "$config{perl} \"-I.\" \"-Mconfigdata\" $dofile -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
2332     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
2333     system($cmd);
2334     exit 1 if $? != 0;
2335     rename("$out.new", $out) || die "Can't rename $out.new, $!";
2336 }
2337
2338 # Configuration printer ##############################################
2339
2340 sub print_table_entry
2341 {
2342     my $target = shift;
2343     my %target = resolve_config($target);
2344     my $type = shift;
2345
2346     # Don't print the templates
2347     return if $target{template};
2348
2349     my @sequence = (
2350         "sys_id",
2351         "cc",
2352         "cflags",
2353         "defines",
2354         "unistd",
2355         "ld",
2356         "lflags",
2357         "plib_lflags",
2358         "ex_libs",
2359         "bn_ops",
2360         "cpuid_obj",
2361         "bn_obj",
2362         "ec_obj",
2363         "des_obj",
2364         "aes_obj",
2365         "bf_obj",
2366         "md5_obj",
2367         "sha1_obj",
2368         "cast_obj",
2369         "rc4_obj",
2370         "rmd160_obj",
2371         "rc5_obj",
2372         "wp_obj",
2373         "cmll_obj",
2374         "modes_obj",
2375         "padlock_obj",
2376         "thread_scheme",
2377         "perlasm_scheme",
2378         "dso_scheme",
2379         "shared_target",
2380         "shared_cflag",
2381         "shared_ldflag",
2382         "shared_rcflag",
2383         "shared_extension",
2384         "shared_extension_simple",
2385         "shared_import_extension",
2386         "dso_extension",
2387         "obj_extension",
2388         "exe_extension",
2389         "ranlib",
2390         "ar",
2391         "arflags",
2392         "multilib",
2393         "build_scheme",
2394         );
2395
2396     if ($type eq "TABLE") {
2397         print "\n";
2398         print "*** $target\n";
2399         foreach (@sequence) {
2400             if (ref($target{$_}) eq "ARRAY") {
2401                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
2402             } else {
2403                 printf "\$%-12s = %s\n", $_, $target{$_};
2404             }
2405         }
2406     } elsif ($type eq "HASH") {
2407         my $largest =
2408             length((sort { length($a) <=> length($b) } @sequence)[-1]);
2409         print "    '$target' => {\n";
2410         foreach (@sequence) {
2411             if ($target{$_}) {
2412                 if (ref($target{$_}) eq "ARRAY") {
2413                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
2414                 } else {
2415                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
2416                 }
2417             }
2418         }
2419         print "    },\n";
2420     }
2421 }
2422
2423 # Utility routines ###################################################
2424
2425 # On VMS, if the given file is a logical name, File::Spec::Functions
2426 # will consider it an absolute path.  There are cases when we want a
2427 # purely syntactic check without checking the environment.
2428 sub isabsolute {
2429     my $file = shift;
2430
2431     # On non-platforms, we just use file_name_is_absolute().
2432     return file_name_is_absolute($file) unless $^O eq "VMS";
2433
2434     # If the file spec includes a device or a directpry spec,
2435     # file_name_is_absolute() is perfectly safe.
2436     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
2437
2438     # Here, we know the given file spec isn't absolute
2439     return 0;
2440 }
2441
2442 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
2443 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
2444 # realpath() requires that at least all path components except the last is an
2445 # existing directory.  On VMS, the last component of the directory spec must
2446 # exist.
2447 sub absolutedir {
2448     my $dir = shift;
2449
2450     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
2451     # will return the volume name for the device, no matter what.  Also,
2452     # it will return an incorrect directory spec if the argument is a
2453     # directory that doesn't exist.
2454     if ($^O eq "VMS") {
2455         return rel2abs($dir);
2456     }
2457
2458     # We use realpath() on Unix, since no other will properly clean out
2459     # a directory spec.
2460     use Cwd qw/realpath/;
2461
2462     return realpath($dir);
2463 }
2464
2465 sub which
2466         {
2467         my($name)=@_;
2468         my $path;
2469         foreach $path (split /:/, $ENV{PATH})
2470                 {
2471                 my $fullpath = "$path/$name$target{exe_extension}";
2472                 if (-f $fullpath and -x $fullpath)
2473                         {
2474                         return $fullpath
2475                             unless ($name eq "perl" and
2476                                     system("$fullpath -e " . '\'exit($]<5.0);\''));
2477                         }
2478                 }
2479         }
2480
2481 sub quotify {
2482     my %processors = (
2483         perl    => sub { my $x = shift;
2484                          $x =~ s/([\\\$\@"])/\\$1/g;
2485                          return '"'.$x.'"'; },
2486         );
2487     my $for = shift;
2488     my $processor =
2489         defined($processors{$for}) ? $processors{$for} : sub { shift; };
2490
2491     return map { $processor->($_); } @_;
2492 }
2493
2494 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
2495 # $filename is a file name to read from
2496 # $line_concat_cond_re is a regexp detecting a line continuation ending
2497 # $line_concat is a CODEref that takes care of concatenating two lines
2498 sub collect_from_file {
2499     my $filename = shift;
2500     my $line_concat_cond_re = shift;
2501     my $line_concat = shift;
2502
2503     open my $fh, $filename || die "unable to read $filename: $!\n";
2504     return sub {
2505         my $saved_line = "";
2506         $_ = "";
2507         while (<$fh>) {
2508             s|\R$||;
2509             if (defined $line_concat) {
2510                 $_ = $line_concat->($saved_line, $_);
2511                 $saved_line = "";
2512             }
2513             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2514                 $saved_line = $_;
2515                 next;
2516             }
2517             return $_;
2518         }
2519         die "$filename ending with continuation line\n" if $_;
2520         close $fh;
2521         return undef;
2522     }
2523 }
2524
2525 # collect_from_array($array, $line_concat_cond_re, $line_concat)
2526 # $array is an ARRAYref of lines
2527 # $line_concat_cond_re is a regexp detecting a line continuation ending
2528 # $line_concat is a CODEref that takes care of concatenating two lines
2529 sub collect_from_array {
2530     my $array = shift;
2531     my $line_concat_cond_re = shift;
2532     my $line_concat = shift;
2533     my @array = (@$array);
2534
2535     return sub {
2536         my $saved_line = "";
2537         $_ = "";
2538         while (defined($_ = shift @array)) {
2539             s|\R$||;
2540             if (defined $line_concat) {
2541                 $_ = $line_concat->($saved_line, $_);
2542                 $saved_line = "";
2543             }
2544             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2545                 $saved_line = $_;
2546                 next;
2547             }
2548             return $_;
2549         }
2550         die "input text ending with continuation line\n" if $_;
2551         return undef;
2552     }
2553 }
2554
2555 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
2556 # $lineiterator is a CODEref that delivers one line at a time.
2557 # All following arguments are regex/CODEref pairs, where the regexp detects a
2558 # line and the CODEref does something with the result of the regexp.
2559 sub collect_information {
2560     my $lineiterator = shift;
2561     my %collectors = @_;
2562
2563     while(defined($_ = $lineiterator->())) {
2564         s|\R$||;
2565         my $found = 0;
2566         if ($collectors{"BEFORE"}) {
2567             $collectors{"BEFORE"}->($_);
2568         }
2569         foreach my $re (keys %collectors) {
2570             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
2571                 $collectors{$re}->($lineiterator);
2572                 $found = 1;
2573             };
2574         }
2575         if ($collectors{"OTHERWISE"}) {
2576             $collectors{"OTHERWISE"}->($lineiterator, $_)
2577                 unless $found || !defined $collectors{"OTHERWISE"};
2578         }
2579         if ($collectors{"AFTER"}) {
2580             $collectors{"AFTER"}->($_);
2581         }
2582     }
2583 }