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