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