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