2 # Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
4 # Licensed under the OpenSSL license (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
10 # generate a .def file
12 # It does this by parsing the header files and looking for the
13 # prototyped functions: it then prunes the output.
15 # Intermediary files are created, call libcrypto.num and libssl.num,
16 # The format of these files is:
18 # routine-name nnnn vers info
20 # The "nnnn" and "vers" fields are the numeric id and version for the symbol
21 # respectively. The "info" part is actually a colon-separated string of fields
22 # with the following meaning:
24 # existence:platform:kind:algorithms
26 # - "existence" can be "EXIST" or "NOEXIST" depending on if the symbol is
27 # found somewhere in the source,
28 # - "platforms" is empty if it exists on all platforms, otherwise it contains
29 # comma-separated list of the platform, just as they are if the symbol exists
30 # for those platforms, or prepended with a "!" if not. This helps resolve
31 # symbol name variants for platforms where the names are too long for the
32 # compiler or linker, or if the systems is case insensitive and there is a
33 # clash, or the symbol is implemented differently (see
34 # EXPORT_VAR_AS_FUNCTION). This script assumes renaming of symbols is found
35 # in the file crypto/symhacks.h.
36 # The semantics for the platforms is that every item is checked against the
37 # environment. For the negative items ("!FOO"), if any of them is false
38 # (i.e. "FOO" is true) in the environment, the corresponding symbol can't be
39 # used. For the positive items, if all of them are false in the environment,
40 # the corresponding symbol can't be used. Any combination of positive and
41 # negative items are possible, and of course leave room for some redundancy.
42 # - "kind" is "FUNCTION" or "VARIABLE". The meaning of that is obvious.
43 # - "algorithms" is a comma-separated list of algorithm names. This helps
44 # exclude symbols that are part of an algorithm that some user wants to
50 use File::Spec::Functions;
53 use lib "$FindBin::Bin/perl";
56 # When building a "variant" shared library, with a custom SONAME, also customize
57 # all the symbol versions. This produces a shared object that can coexist
58 # without conflict in the same address space as a default build, or an object
59 # with a different variant tag.
61 # For example, with a target definition that includes:
63 # shlib_variant => "-opt",
65 # we build the following objects:
69 # if ($l = readlink) {
70 # printf "%s -> %s\n", $_, $l
75 # libcrypto-opt.so.1.1
76 # libcrypto.so -> libcrypto-opt.so.1.1
78 # libssl.so -> libssl-opt.so.1.1
80 # whose SONAMEs and dependencies are:
84 # readelf -d $l | egrep 'SONAME|NEEDED.*(ssl|crypto)'
87 # 0x000000000000000e (SONAME) Library soname: [libcrypto-opt.so.1.1]
89 # 0x0000000000000001 (NEEDED) Shared library: [libcrypto-opt.so.1.1]
90 # 0x000000000000000e (SONAME) Library soname: [libssl-opt.so.1.1]
92 # We case-fold the variant tag to upper case and replace all non-alnum
93 # characters with "_". This yields the following symbol versions:
95 # $ nm libcrypto.so | grep -w A
96 # 0000000000000000 A OPENSSL_OPT_1_1_0
97 # 0000000000000000 A OPENSSL_OPT_1_1_0a
98 # 0000000000000000 A OPENSSL_OPT_1_1_0c
99 # 0000000000000000 A OPENSSL_OPT_1_1_0d
100 # 0000000000000000 A OPENSSL_OPT_1_1_0f
101 # 0000000000000000 A OPENSSL_OPT_1_1_0g
102 # $ nm libssl.so | grep -w A
103 # 0000000000000000 A OPENSSL_OPT_1_1_0
104 # 0000000000000000 A OPENSSL_OPT_1_1_0d
106 (my $SO_VARIANT = qq{\U$target{"shlib_variant"}}) =~ s/\W/_/g;
110 my $crypto_num= catfile($config{sourcedir},"util","libcrypto.num");
111 my $ssl_num= catfile($config{sourcedir},"util","libssl.num");
120 my $do_checkexist = 0;
127 # Set this to make typesafe STACK definitions appear in DEF
128 my $safe_stack_def = 0;
130 my @known_platforms = ( "__FreeBSD__", "PERL5",
131 "EXPORT_VAR_AS_FUNCTION", "ZLIB", "_WIN32"
133 my @known_ossl_platforms = ( "UNIX", "VMS", "WIN32", "WINNT", "OS2" );
134 my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
135 "CAST", "MD2", "MD4", "MD5", "SHA", "SHA0", "SHA1",
136 "SHA256", "SHA512", "RMD160",
137 "MDC2", "WHIRLPOOL", "RSA", "DSA", "DH", "EC", "EC2M",
138 "HMAC", "AES", "CAMELLIA", "SEED", "GOST", "ARIA", "SM4",
139 "SCRYPT", "CHACHA", "POLY1305", "BLAKE2",
141 # EC_NISTP_64_GCC_128
142 "EC_NISTP_64_GCC_128",
143 # Envelope "algorithms"
144 "EVP", "X509", "ASN1_TYPEDEFS",
145 # Helper "algorithms"
146 "BIO", "COMP", "BUFFER", "LHASH", "STACK", "ERR",
148 # External "algorithms"
149 "FP_API", "STDIO", "SOCK", "DGRAM",
152 "STATIC_ENGINE", "ENGINE", "HW", "GMP",
155 # Certificate Transparency
160 "PSK", "SRP", "HEARTBEATS",
167 "SSL3_METHOD", "TLS1_METHOD", "TLS1_1_METHOD", "TLS1_2_METHOD", "DTLS1_METHOD", "DTLS1_2_METHOD",
170 # Deprecated functions
171 "DEPRECATEDIN_0_9_8",
172 "DEPRECATEDIN_1_0_0",
173 "DEPRECATEDIN_1_1_0",
174 "DEPRECATEDIN_1_2_0",
190 # APPLINK (win build feature?)
194 my %disabled_algorithms;
196 foreach (@known_algorithms) {
197 $disabled_algorithms{$_} = 0;
199 # disabled by default
200 $disabled_algorithms{"STATIC_ENGINE"} = 1;
202 my $apiv = sprintf "%x%02x%02x", split(/\./, $config{api});
203 foreach (keys %disabled_algorithms) {
204 if (/^DEPRECATEDIN_(\d+)_(\d+)_(\d+)$/) {
205 my $depv = sprintf "%x%02x%02x", $1, $2, $3;
206 $disabled_algorithms{$_} = 1 if $apiv ge $depv;
212 foreach (@ARGV, split(/ /, $config{options}))
214 $debug=1 if $_ eq "debug";
215 $W32=1 if $_ eq "32";
216 die "win16 not supported" if $_ eq "16";
225 $VMS=1 if $_ eq "VMS";
226 if ($_ eq "zlib" || $_ eq "enable-zlib" || $_ eq "zlib-dynamic"
227 || $_ eq "enable-zlib-dynamic") {
231 $do_crypto=1 if $_ eq "libcrypto" || $_ eq "crypto";
232 $do_ssl=1 if $_ eq "libssl" || $_ eq "ssl";
234 $do_update=1 if $_ eq "update";
235 $do_rewrite=1 if $_ eq "rewrite";
236 $do_ctest=1 if $_ eq "ctest";
237 $do_ctestall=1 if $_ eq "ctestall";
238 $do_checkexist=1 if $_ eq "exist";
239 if (/^(enable|disable|no)-(.*)$/) {
242 if (exists $disabled_algorithms{$alg}) {
243 $disabled_algorithms{$alg} = $1 eq "enable" ? 0 : 1;
248 $libname = $unified_info{sharednames}->{libcrypto} if $do_crypto;
249 $libname = $unified_info{sharednames}->{libssl} if $do_ssl;
256 $libname="LIBCRYPTO";
260 # If no platform is given, assume WIN32
261 if ($W32 + $VMS + $linux == 0) {
264 die "Please, only one platform at a time"
265 if ($W32 + $VMS + $linux > 1);
267 if (!$do_ssl && !$do_crypto)
269 print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT | OS2 | linux | VMS ]\n";
273 %ssl_list=&load_numbers($ssl_num);
275 %crypto_list=&load_numbers($crypto_num);
276 $max_crypto = $max_num;
278 my $ssl="include/openssl/ssl.h";
279 $ssl.=" include/openssl/sslerr.h";
280 $ssl.=" include/openssl/tls1.h";
281 $ssl.=" include/openssl/srtp.h";
283 # When scanning include/openssl, skip all SSL files and some internal ones.
285 foreach my $f ( split(/\s+/, $ssl) ) {
288 $skipthese{'include/openssl/conf_api.h'} = 1;
289 $skipthese{'include/openssl/ebcdic.h'} = 1;
290 $skipthese{'include/openssl/opensslconf.h'} = 1;
292 # We use headers found in include/openssl and include/internal only.
293 # The latter is needed so libssl.so/.dll/.exe can link properly.
294 my $crypto ="include/internal/dso.h";
295 $crypto.=" include/internal/o_dir.h";
296 $crypto.=" include/internal/o_str.h";
297 $crypto.=" include/internal/err.h";
298 $crypto.=" include/internal/rand.h";
299 foreach my $f ( glob(catfile($config{sourcedir},'include/openssl/*.h')) ) {
300 my $fn = "include/openssl/" . lc(basename($f));
301 $crypto .= " $fn" if !defined $skipthese{$fn} && $f !~ m@/[a-z]+err\.h$@;
304 my $symhacks="include/openssl/symhacks.h";
306 my @ssl_symbols = &do_defs("LIBSSL", $ssl, $symhacks);
307 my @crypto_symbols = &do_defs("LIBCRYPTO", $crypto, $symhacks);
313 &maybe_add_info("LIBSSL",*ssl_list,@ssl_symbols);
314 if ($do_rewrite == 1) {
315 open(OUT, ">$ssl_num");
316 &rewrite_numbers(*OUT,"LIBSSL",*ssl_list,@ssl_symbols);
318 open(OUT, ">>$ssl_num");
320 &update_numbers(*OUT,"LIBSSL",*ssl_list,$max_ssl,@ssl_symbols);
324 if($do_crypto == 1) {
326 &maybe_add_info("LIBCRYPTO",*crypto_list,@crypto_symbols);
327 if ($do_rewrite == 1) {
328 open(OUT, ">$crypto_num");
329 &rewrite_numbers(*OUT,"LIBCRYPTO",*crypto_list,@crypto_symbols);
331 open(OUT, ">>$crypto_num");
333 &update_numbers(*OUT,"LIBCRYPTO",*crypto_list,$max_crypto,@crypto_symbols);
337 } elsif ($do_checkexist) {
338 &check_existing(*ssl_list, @ssl_symbols)
340 &check_existing(*crypto_list, @crypto_symbols)
342 } elsif ($do_ctest || $do_ctestall) {
346 /* Test file to check all DEF file symbols are present by trying
347 * to link to all of them. This is *not* intended to be run!
353 &print_test_file(*STDOUT,"LIBSSL",*ssl_list,$do_ctestall,@ssl_symbols)
356 &print_test_file(*STDOUT,"LIBCRYPTO",*crypto_list,$do_ctestall,@crypto_symbols)
363 &print_def_file(*STDOUT,$libname,*ssl_list,@ssl_symbols)
366 &print_def_file(*STDOUT,$libname,*crypto_list,@crypto_symbols)
374 my($name,$files,$symhacksfile)=@_;
378 my %platform; # For anything undefined, we assume ""
379 my %kind; # For anything undefined, we assume "FUNCTION"
380 my %algorithm; # For anything undefined, we assume ""
382 my %variant_cnt; # To be able to allocate "name{n}" if "name"
383 # is the same name as the original.
385 my %unknown_algorithms = ();
388 foreach $file (split(/\s+/,$symhacksfile." ".$files))
390 my $fn = catfile($config{sourcedir},$file);
391 print STDERR "DEBUG: starting on $fn:\n" if $debug;
392 open(IN,"<$fn") || die "Can't open $fn, $!,";
393 my $line = "", my $def= "";
395 (map { $_ => 0 } @known_platforms),
396 (map { "OPENSSL_SYS_".$_ => 0 } @known_ossl_platforms),
397 (map { "OPENSSL_NO_".$_ => 0 } @known_algorithms),
398 (map { "OPENSSL_USE_".$_ => 0 } @known_algorithms),
399 (grep /^DEPRECATED_/, @known_algorithms),
406 my $symhacking = $file eq $symhacksfile;
407 my @current_platforms = ();
408 my @current_algorithms = ();
410 # params: symbol, alias, platforms, kind
411 # The reason to put this subroutine in a variable is that
412 # it will otherwise create it's own, unshared, version of
413 # %tag and %variant...
414 my $make_variant = sub
416 my ($s, $a, $p, $k) = @_;
419 print STDERR "DEBUG: make_variant: Entered with ",$s,", ",$a,", ",(defined($p)?$p:""),", ",(defined($k)?$k:""),"\n" if $debug;
424 map { $tag{$_} == 1 ? $_ : "" }
431 map { $tag{$_} == 1 ? $_ : "" }
436 map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ : "" }
437 @known_ossl_platforms));
438 print STDERR "DEBUG: make_variant: a1 = $a1; a2 = $a2\n" if $debug;
439 if ($a1 eq "") { $a1 = $a2; }
440 elsif ($a1 ne "" && $a2 ne "") { $a1 .= ",".$a2; }
443 if (!defined($variant_cnt{$s}))
445 $variant_cnt{$s} = 0;
448 $a .= "{$variant_cnt{$s}}";
450 my $toadd = $a.":".$a1.(defined($k)?":".$k:"");
451 my $togrep = $s.'(\{[0-9]+\})?:'.$a1.(defined($k)?":".$k:"");
452 if (!grep(/^$togrep$/,
453 split(/;/, defined($variant{$s})?$variant{$s}:""))) {
454 if (defined($variant{$s})) { $variant{$s} .= ";"; }
455 $variant{$s} .= $toadd;
457 print STDERR "DEBUG: make_variant: Exit with variant of ",$s," = ",$variant{$s},"\n" if $debug;
460 print STDERR "DEBUG: parsing ----------\n" if $debug;
462 s|\R$||; # Better chomp
464 #Inside a DEPRECATEDIN
465 $stored_multiline .= $_;
466 print STDERR "DEBUG: Continuing multiline DEPRECATEDIN: $stored_multiline\n" if $debug;
467 $parens = count_parens($stored_multiline);
469 $def .= do_deprecated($stored_multiline,
471 \@current_algorithms);
475 if (/\/\* Error codes for the \w+ functions\. \*\//)
486 $line = $`; # keep what was before the backslash
491 if (not /\*\//) { # multi-line comment...
492 $line = $_; # ... just accumulate
495 s/\/\*.*?\*\///gs;# wipe it
501 $cpp-- if /^#\s*endif/;
504 if (/^#.*ifdef.*cplusplus/) {
509 s/{[^{}]*}//gs; # ignore {} blocks
510 print STDERR "DEBUG: \$def=\"$def\"\n" if $debug && $def ne "";
511 print STDERR "DEBUG: \$_=\"$_\"\n" if $debug;
512 if (/^\#\s*if\s+OPENSSL_API_COMPAT\s*(\S)\s*(0x[0-9a-fA-F]{8})L\s*$/) {
515 if ($op ne '<' && $op ne '>=') {
516 die "$file unacceptable operator $op: $_\n";
518 my ($one, $major, $minor) =
522 my $t = "DEPRECATEDIN_${one}_${major}_${minor}";
525 $tag{$t}=($op eq '<' ? 1 : -1);
526 print STDERR "DEBUG: $file: found tag $t = $tag{$t}\n" if $debug;
527 } elsif (/^\#\s*ifndef\s+(.*)/) {
531 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
532 } elsif (/^\#\s*if\s+!defined\(([^\)]+)\)/) {
534 if (/^\#\s*if\s+(!defined\(([^\)]+)\)(\s+\&\&\s+!defined\(([^\)]+)\))*)$/) {
537 foreach $tmp_ (split '\&\&',$tmp_1) {
538 $tmp_ =~ /!defined\(([^\)]+)\)/;
539 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
544 print STDERR "Warning: $file: complicated expression: $_" if $debug; # because it is O...
545 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
549 } elsif (/^\#\s*ifdef\s+(\S*)/) {
553 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
554 } elsif (/^\#\s*if\s+defined\(([^\)]+)\)/) {
556 if (/^\#\s*if\s+(defined\(([^\)]+)\)(\s+\|\|\s+defined\(([^\)]+)\))*)$/) {
559 foreach $tmp_ (split '\|\|',$tmp_1) {
560 $tmp_ =~ /defined\(([^\)]+)\)/;
561 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
566 print STDERR "Warning: $file: complicated expression: $_\n" if $debug; # because it is O...
567 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
571 } elsif (/^\#\s*error\s+(\w+) is disabled\./) {
573 while($tag[$tag_i] ne "-") {
574 if ($tag[$tag_i] eq "OPENSSL_NO_".$1) {
575 $tag{$tag[$tag_i]}=2;
576 print STDERR "DEBUG: $file: changed tag $1 = 2\n" if $debug;
580 } elsif (/^\#\s*endif/) {
582 while($tag_i > 0 && $tag[$tag_i] ne "-") {
584 print STDERR "DEBUG: \$t=\"$t\"\n" if $debug;
590 print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug;
592 if ($t =~ /^OPENSSL_NO_([A-Z0-9_]+)$/) {
594 } elsif($t =~ /^OPENSSL_USE_([A-Z0-9_]+)$/) {
600 && !grep(/^$t$/, @known_algorithms)) {
601 $unknown_algorithms{$t} = 1;
602 #print STDERR "DEBUG: Added as unknown algorithm: $t\n" if $debug;
607 } elsif (/^\#\s*else/) {
609 die "$file unmatched else\n" if $tag_i < 0;
610 while($tag[$tag_i] ne "-") {
613 print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug;
616 } elsif (/^\#\s*if\s+1/) {
621 print STDERR "DEBUG: $file: found 1\n" if $debug;
622 } elsif (/^\#\s*if\s+0/) {
627 print STDERR "DEBUG: $file: found 0\n" if $debug;
628 } elsif (/^\#\s*if\s+/) {
629 #Some other unrecognized "if" style
631 } elsif (/^\#\s*define\s+(\w+)\s+(\w+)/
632 && $symhacking && $tag{'TRUE'} != -1) {
633 # This is for aliasing. When we find an alias,
635 &$make_variant($1,$2);
636 print STDERR "DEBUG: $file: defined $1 = $2\n" if $debug;
641 map { $tag{$_} == 1 ? $_ :
642 $tag{$_} == -1 ? "!".$_ : "" }
644 push @current_platforms
646 map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ :
647 $tag{"OPENSSL_SYS_".$_} == -1 ? "!".$_ : "" }
648 @known_ossl_platforms);
649 @current_algorithms = ();
650 @current_algorithms =
652 map { $tag{"OPENSSL_NO_".$_} == -1 ? $_ : "" }
654 push @current_algorithms
656 map { $tag{"OPENSSL_USE_".$_} == 1 ? $_ : "" }
658 push @current_algorithms,
659 grep { /^DEPRECATEDIN_/ && $tag{$_} == 1 }
663 .join(',',@current_platforms).":"
664 .join(',',@current_algorithms).";";
667 if ($tag{'TRUE'} != -1) {
668 if (/^\s*DEFINE_STACK_OF\s*\(\s*(\w*)\s*\)/
669 || /^\s*DEFINE_STACK_OF_CONST\s*\(\s*(\w*)\s*\)/) {
671 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
672 $def .= "int d2i_$3(void);";
673 $def .= "int i2d_$3(void);";
674 # Variant for platforms that do not
675 # have to access global variables
676 # in shared libraries through functions
679 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
680 .join(',',@current_algorithms).";";
681 $def .= "OPENSSL_EXTERN int $2_it;";
684 .join(',',@current_platforms).":"
685 .join(',',@current_algorithms).";";
686 # Variant for platforms that have to
687 # access global variables in shared
688 # libraries through functions
689 &$make_variant("$2_it","$2_it",
690 "EXPORT_VAR_AS_FUNCTION",
693 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_fname\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
694 $def .= "int d2i_$3(void);";
695 $def .= "int i2d_$3(void);";
696 $def .= "int $3_free(void);";
697 $def .= "int $3_new(void);";
698 # Variant for platforms that do not
699 # have to access global variables
700 # in shared libraries through functions
703 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
704 .join(',',@current_algorithms).";";
705 $def .= "OPENSSL_EXTERN int $2_it;";
708 .join(',',@current_platforms).":"
709 .join(',',@current_algorithms).";";
710 # Variant for platforms that have to
711 # access global variables in shared
712 # libraries through functions
713 &$make_variant("$2_it","$2_it",
714 "EXPORT_VAR_AS_FUNCTION",
717 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS\s*\(\s*(\w*)\s*\)/ ||
718 /^\s*DECLARE_ASN1_FUNCTIONS_const\s*\(\s*(\w*)\s*\)/) {
719 $def .= "int d2i_$1(void);";
720 $def .= "int i2d_$1(void);";
721 $def .= "int $1_free(void);";
722 $def .= "int $1_new(void);";
723 # Variant for platforms that do not
724 # have to access global variables
725 # in shared libraries through functions
728 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
729 .join(',',@current_algorithms).";";
730 $def .= "OPENSSL_EXTERN int $1_it;";
733 .join(',',@current_platforms).":"
734 .join(',',@current_algorithms).";";
735 # Variant for platforms that have to
736 # access global variables in shared
737 # libraries through functions
738 &$make_variant("$1_it","$1_it",
739 "EXPORT_VAR_AS_FUNCTION",
742 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS_const\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
743 $def .= "int d2i_$2(void);";
744 $def .= "int i2d_$2(void);";
745 # Variant for platforms that do not
746 # have to access global variables
747 # in shared libraries through functions
750 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
751 .join(',',@current_algorithms).";";
752 $def .= "OPENSSL_EXTERN int $2_it;";
755 .join(',',@current_platforms).":"
756 .join(',',@current_algorithms).";";
757 # Variant for platforms that have to
758 # access global variables in shared
759 # libraries through functions
760 &$make_variant("$2_it","$2_it",
761 "EXPORT_VAR_AS_FUNCTION",
764 } elsif (/^\s*DECLARE_ASN1_ALLOC_FUNCTIONS\s*\(\s*(\w*)\s*\)/) {
765 $def .= "int $1_free(void);";
766 $def .= "int $1_new(void);";
768 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
769 $def .= "int d2i_$2(void);";
770 $def .= "int i2d_$2(void);";
771 $def .= "int $2_free(void);";
772 $def .= "int $2_new(void);";
773 # Variant for platforms that do not
774 # have to access global variables
775 # in shared libraries through functions
778 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
779 .join(',',@current_algorithms).";";
780 $def .= "OPENSSL_EXTERN int $2_it;";
783 .join(',',@current_platforms).":"
784 .join(',',@current_algorithms).";";
785 # Variant for platforms that have to
786 # access global variables in shared
787 # libraries through functions
788 &$make_variant("$2_it","$2_it",
789 "EXPORT_VAR_AS_FUNCTION",
792 } elsif (/^\s*DECLARE_ASN1_ITEM\s*\(\s*(\w*)\s*\)/) {
793 # Variant for platforms that do not
794 # have to access global variables
795 # in shared libraries through functions
798 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
799 .join(',',@current_algorithms).";";
800 $def .= "OPENSSL_EXTERN int $1_it;";
803 .join(',',@current_platforms).":"
804 .join(',',@current_algorithms).";";
805 # Variant for platforms that have to
806 # access global variables in shared
807 # libraries through functions
808 &$make_variant("$1_it","$1_it",
809 "EXPORT_VAR_AS_FUNCTION",
812 } elsif (/^\s*DECLARE_ASN1_NDEF_FUNCTION\s*\(\s*(\w*)\s*\)/) {
813 $def .= "int i2d_$1_NDEF(void);";
814 } elsif (/^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) {
816 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION\s*\(\s*(\w*)\s*\)/) {
817 $def .= "int $1_print_ctx(void);";
819 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
820 $def .= "int $2_print_ctx(void);";
822 } elsif (/^\s*DECLARE_PKCS12_STACK_OF\s*\(\s*(\w*)\s*\)/) {
824 } elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ ||
825 /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ ||
826 /^DECLARE_PEM_rw_const\s*\(\s*(\w*)\s*,/ ) {
829 .join(',',@current_platforms).":"
830 .join(',',"STDIO",@current_algorithms).";";
831 $def .= "int PEM_read_$1(void);";
832 $def .= "int PEM_write_$1(void);";
835 .join(',',@current_platforms).":"
836 .join(',',@current_algorithms).";";
837 # Things that are everywhere
838 $def .= "int PEM_read_bio_$1(void);";
839 $def .= "int PEM_write_bio_$1(void);";
841 } elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ ||
842 /^DECLARE_PEM_write_const\s*\(\s*(\w*)\s*,/ ||
843 /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) {
846 .join(',',@current_platforms).":"
847 .join(',',"STDIO",@current_algorithms).";";
848 $def .= "int PEM_write_$1(void);";
851 .join(',',@current_platforms).":"
852 .join(',',@current_algorithms).";";
853 # Things that are everywhere
854 $def .= "int PEM_write_bio_$1(void);";
856 } elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ ||
857 /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) {
860 .join(',',@current_platforms).":"
861 .join(',',"STDIO",@current_algorithms).";";
862 $def .= "int PEM_read_$1(void);";
865 .join(',',@current_platforms).":"
866 .join(',',"STDIO",@current_algorithms).";";
867 # Things that are everywhere
868 $def .= "int PEM_read_bio_$1(void);";
870 } elsif (/^OPENSSL_DECLARE_GLOBAL\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
871 # Variant for platforms that do not
872 # have to access global variables
873 # in shared libraries through functions
876 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
877 .join(',',@current_algorithms).";";
878 $def .= "OPENSSL_EXTERN int _shadow_$2;";
881 .join(',',@current_platforms).":"
882 .join(',',@current_algorithms).";";
883 # Variant for platforms that have to
884 # access global variables in shared
885 # libraries through functions
886 &$make_variant("_shadow_$2","_shadow_$2",
887 "EXPORT_VAR_AS_FUNCTION",
889 } elsif (/^\s*DEPRECATEDIN/) {
890 $parens = count_parens($_);
892 $def .= do_deprecated($_,
894 \@current_algorithms);
896 $stored_multiline = $_;
897 print STDERR "DEBUG: Found multiline DEPRECATEDIN starting with: $stored_multiline\n" if $debug;
900 } elsif ($tag{'CONST_STRICT'} != 1) {
901 if (/\{|\/\*|\([^\)]*$/) {
910 die "$file: Unmatched tags\n" if $#tag >= 0;
915 print STDERR "DEBUG: postprocessing ----------\n" if $debug;
916 foreach (split /;/, $def) {
917 my $s; my $k = "FUNCTION"; my $p; my $a;
921 next if(/typedef\W/);
924 # Reduce argument lists to empty ()
925 # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
927 s/\([^\(\)]+\)/\{\}/gs;
928 s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f
930 # pretend as we didn't use curly braces: {} -> ()
933 s/STACK_OF\(\)/void/gs;
934 s/LHASH_OF\(\)/void/gs;
936 print STDERR "DEBUG: \$_ = \"$_\"\n" if $debug;
937 if (/^\#INFO:([^:]*):(.*)$/) {
940 print STDERR "DEBUG: found info on platforms ($plats) and algorithms ($algs)\n" if $debug;
942 } elsif (/^\s*OPENSSL_EXTERN\s.*?(\w+(\{[0-9]+\})?)(\[[0-9]*\])*\s*$/) {
945 print STDERR "DEBUG: found external variable $s\n" if $debug;
946 } elsif (/TYPEDEF_\w+_OF/s) {
948 } elsif (/(\w+)\s*\(\).*/s) { # first token prior [first] () is
949 $s = $1; # a function name!
950 print STDERR "DEBUG: found function $s\n" if $debug;
951 } elsif (/\(/ and not (/=/)) {
952 print STDERR "File $file: cannot parse: $_;\n";
965 &reduce_platforms((defined($platform{$s})?$platform{$s}.',':"").$p);
966 $algorithm{$s} .= ','.$a;
968 if (defined($variant{$s})) {
969 foreach $v (split /;/,$variant{$s}) {
970 (my $r, my $p, my $k) = split(/:/,$v);
971 my $ip = join ',',map({ /^!(.*)$/ ? $1 : "!".$_ } split /,/, $p);
973 if (!defined($k)) { $k = $kind{$s}; }
974 $kind{$r} = $k."(".$s.")";
975 $algorithm{$r} = $algorithm{$s};
976 $platform{$r} = &reduce_platforms($platform{$s}.",".$p.",".$p);
977 $platform{$s} = &reduce_platforms($platform{$s}.','.$ip.','.$ip);
978 print STDERR "DEBUG: \$variant{\"$s\"} = ",$v,"; \$r = $r; \$p = ",$platform{$r},"; \$a = ",$algorithm{$r},"; \$kind = ",$kind{$r},"\n" if $debug;
981 print STDERR "DEBUG: \$s = $s; \$p = ",$platform{$s},"; \$a = ",$algorithm{$s},"; \$kind = ",$kind{$s},"\n" if $debug;
985 # Prune the returned symbols
987 delete $syms{"bn_dump1"};
988 $platform{"BIO_s_log"} .= ",!WIN32,!macintosh";
990 $platform{"PEM_read_NS_CERT_SEQ"} = "VMS";
991 $platform{"PEM_write_NS_CERT_SEQ"} = "VMS";
992 $platform{"PEM_read_P8_PRIV_KEY_INFO"} = "VMS";
993 $platform{"PEM_write_P8_PRIV_KEY_INFO"} = "VMS";
997 push @ret, map { $_."\\".&info_string($_,"EXIST",
1000 $algorithm{$_}) } keys %syms;
1002 if (keys %unknown_algorithms) {
1003 print STDERR "WARNING: mkdef.pl doesn't know the following algorithms:\n";
1004 print STDERR "\t",join("\n\t",keys %unknown_algorithms),"\n";
1009 # Param: string of comma-separated platform-specs.
1010 sub reduce_platforms
1012 my ($platforms) = @_;
1013 my $pl = defined($platforms) ? $platforms : "";
1014 my %p = map { $_ => 0 } split /,/, $pl;
1017 print STDERR "DEBUG: Entered reduce_platforms with \"$platforms\"\n"
1019 # We do this, because if there's code like the following, it really
1020 # means the function exists in all cases and should therefore be
1021 # everywhere. By increasing and decreasing, we may attain 0:
1028 foreach $platform (split /,/, $pl) {
1029 if ($platform =~ /^!(.*)$/) {
1035 foreach $platform (keys %p) {
1036 if ($p{$platform} == 0) { delete $p{$platform}; }
1041 $ret = join(',',sort(map { $p{$_} < 0 ? "!".$_ : $_ } keys %p));
1042 print STDERR "DEBUG: Exiting reduce_platforms with \"$ret\"\n"
1049 (my $symbol, my $exist, my $platforms, my $kind, my $algorithms) = @_;
1051 my %a = defined($algorithms) ?
1052 map { $_ => 1 } split /,/, $algorithms : ();
1053 my $k = defined($kind) ? $kind : "FUNCTION";
1055 my $p = &reduce_platforms($platforms);
1062 $ret .= ":".join(',',sort keys %a);
1068 (my $name, *nums, my @symbols) = @_;
1073 foreach $sym (@symbols) {
1074 (my $s, my $i) = split /\\/, $sym;
1075 if (defined($nums{$s})) {
1076 $i =~ s/^(.*?:.*?:\w+)(\(\w+\))?/$1/;
1077 (my $n, my $vers, my $dummy) = split /\\/, $nums{$s};
1078 if (!defined($dummy) || $i ne $dummy) {
1079 $nums{$s} = $n."\\".$vers."\\".$i;
1081 print STDERR "DEBUG: maybe_add_info for $s: \"$dummy\" => \"$i\"\n" if $debug;
1087 my @s=sort { &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") } keys %nums;
1089 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1090 if (!defined($syms{$sym}) && $i !~ /^NOEXIST:/) {
1092 print STDERR "DEBUG: maybe_add_info for $sym: -> undefined\n" if $debug;
1096 print STDERR "$name: $new_info old symbols have updated info\n";
1098 print STDERR "You should do a rewrite to fix this.\n";
1104 # Param: string of comma-separated keywords, each possibly prefixed with a "!"
1107 my ($keywords_txt,$platforms) = @_;
1108 my (@keywords) = split /,/,$keywords_txt;
1109 my ($falsesum, $truesum) = (0, 1);
1111 # Param: one keyword
1114 my ($keyword,$platforms) = @_;
1118 if ($keyword eq "UNIX" && $UNIX) { return 1; }
1119 if ($keyword eq "VMS" && $VMS) { return 1; }
1120 if ($keyword eq "WIN32" && $W32) { return 1; }
1121 if ($keyword eq "_WIN32" && $W32) { return 1; }
1122 if ($keyword eq "WINNT" && $NT) { return 1; }
1123 # Special platforms:
1124 # EXPORT_VAR_AS_FUNCTION means that global variables
1125 # will be represented as functions.
1126 if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && $W32) {
1129 if ($keyword eq "ZLIB" && $zlib) { return 1; }
1133 if ($disabled_algorithms{$keyword} == 1) { return 0;}
1135 # Nothing recognise as true
1140 foreach $k (@keywords) {
1141 if ($k =~ /^!(.*)$/) {
1142 $falsesum += &recognise($1,$platforms);
1144 $truesum *= &recognise($k,$platforms);
1147 print STDERR "DEBUG: [",$#keywords,",",$#keywords < 0,"] is_valid($keywords_txt) => (\!$falsesum) && $truesum = ",(!$falsesum) && $truesum,"\n" if $debug;
1148 return (!$falsesum) && $truesum;
1153 (*OUT,my $name,*nums,my $testall,my @symbols)=@_;
1154 my $n = 1; my @e; my @r;
1155 my $sym; my $prev = ""; my $prefSSLeay;
1157 (@e)=grep(/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1158 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:.*/ && !/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1159 @symbols=((sort @e),(sort @r));
1161 foreach $sym (@symbols) {
1162 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1164 $v = 1 if $i=~ /^.*?:.*?:VARIABLE/;
1165 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1166 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1167 if (!defined($nums{$s})) {
1168 print STDERR "Warning: $s does not have a number assigned\n"
1170 } elsif (is_valid($p,1) && is_valid($a,0)) {
1171 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1173 print OUT "\t/* The following has already appeared previously */\n";
1174 print STDERR "Warning: Symbol '",$s2,"' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1176 $prev = $s2; # To warn about duplicates...
1178 (my $nn, my $vers, my $ni) = split /\\/, $nums{$s2};
1180 print OUT "\textern int $s2; /* type unknown */ /* $nn $ni */\n";
1182 print OUT "\textern int $s2(); /* type unknown */ /* $nn $ni */\n";
1190 return $config{version};
1195 (*OUT,my $name,*nums,my @symbols)=@_;
1196 my $n = 1; my @e; my @r; my @v; my $prev="";
1198 my $libname = $name;
1199 my $http_vendor = 'www.openssl.org/';
1200 my $version = get_version();
1201 my $what = "OpenSSL: implementation of Secure Socket Layer";
1202 my $description = "$what $version, $name - http://$http_vendor";
1203 my $prevsymversion = "", $prevprevsymversion = "";
1206 my $symvtextcount = 0;
1212 ; Definition file for the DLL version of the $name library from OpenSSL
1215 LIBRARY $libname $liboptions
1224 IDENTIFICATION=$version
1228 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1231 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:FUNCTION/,@symbols);
1232 (@v)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:VARIABLE/,@symbols);
1234 # VMS needs to have the symbols on slot number order
1235 @symbols=(map { $_->[1] }
1236 sort { $a->[0] <=> $b->[0] }
1237 map { (my $s, my $i) = $_ =~ /^(.*?)\\(.*)$/;
1238 die "Error: $s doesn't have a number assigned\n"
1239 if !defined($nums{$s});
1240 (my $n, my @rest) = split /\\/, $nums{$s};
1241 [ $n, $_ ] } (@e, @r, @v));
1243 @symbols=((sort @e),(sort @r), (sort @v));
1246 my ($baseversion, $currversion) = get_openssl_version();
1249 if (!defined($thisversion)) {
1250 $thisversion = $baseversion;
1252 $thisversion = get_next_version($thisversion);
1254 foreach $sym (@symbols) {
1255 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1257 $v = 1 if $i =~ /^.*?:.*?:VARIABLE/;
1258 if (!defined($nums{$s})) {
1259 die "Error: $s does not have a number assigned\n"
1262 (my $n, my $symversion, my $dummy) = split /\\/, $nums{$s};
1264 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1265 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1266 if (is_valid($p,1) && is_valid($a,0)) {
1267 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1269 print STDERR "Warning: Symbol '",$s2,
1270 "' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),
1271 ", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1273 $prev = $s2; # To warn about duplicates...
1275 next if $symversion ne $thisversion;
1276 if ($symversion ne $prevsymversion) {
1277 if ($prevsymversion ne "") {
1278 if ($prevprevsymversion ne "") {
1279 print OUT "} OPENSSL${SO_VARIANT}_"
1280 ."$prevprevsymversion;\n\n";
1285 print OUT "OPENSSL${SO_VARIANT}_$symversion {\n global:\n";
1286 $prevprevsymversion = $prevsymversion;
1287 $prevsymversion = $symversion;
1289 print OUT " $s2;\n";
1291 while(++$prevnum < $n) {
1292 my $symline=" ,SPARE -\n ,SPARE -\n";
1293 if ($symvtextcount + length($symline) - 2 > 1024) {
1294 print OUT ")\nSYMBOL_VECTOR=(-\n";
1295 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1297 if ($symvtextcount == 16) {
1298 # Take away first comma
1302 $symvtextcount += length($symline) - 2;
1304 (my $s_uc = $s) =~ tr/a-z/A-Z/;
1306 $v ? "DATA" : "PROCEDURE";
1309 ? " ,$s_uc/$s=$symtype -\n ,$s=$symtype -\n"
1310 : " ,$s=$symtype -\n ,SPARE -\n");
1311 if ($symvtextcount + length($symline) - 2 > 1024) {
1312 print OUT ")\nSYMBOL_VECTOR=(-\n";
1313 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1315 if ($symvtextcount == 16) {
1316 # Take away first comma
1320 $symvtextcount += length($symline) - 2;
1322 printf OUT " %s%-39s DATA\n",
1325 printf OUT " %s%s\n",
1331 } while ($linux && $thisversion ne $currversion);
1333 if ($prevprevsymversion ne "") {
1334 print OUT " local: *;\n} OPENSSL${SO_VARIANT}_$prevprevsymversion;\n\n";
1336 print OUT " local: *;\n};\n\n";
1340 (my $libvmaj, my $libvmin, my $libvedit) =
1341 $currversion =~ /^(\d+)_(\d+)_(\d+)$/;
1342 # The reason to multiply the edit number with 100 is to make space
1343 # for the possibility that we want to encode the patch letters
1344 print OUT "GSMATCH=LEQUAL,",($libvmaj * 100 + $libvmin),",",($libvedit * 100),"\n";
1360 my ($baseversion, $currversion) = get_openssl_version();
1362 open(IN,"<$name") || die "unable to open $name:$!\n";
1364 s|\R$||; # Better chomp
1368 if (defined $ret{$a[0]}) {
1369 # This is actually perfectly OK
1370 #print STDERR "Warning: Symbol '",$a[0],"' redefined. old=",$ret{$a[0]},", new=",$a[1],"\n";
1372 if ($max_num > $a[1]) {
1373 print STDERR "Warning: Number decreased from ",$max_num," to ",$a[1],"\n";
1375 elsif ($max_num == $a[1]) {
1376 # This is actually perfectly OK
1377 #print STDERR "Warning: Symbol ",$a[0]," has same number as previous ",$prev,": ",$a[1],"\n";
1378 if ($a[0] eq $prev) {
1380 $a[0] .= "{$prev_cnt}";
1387 # Existence will be proven later, in do_defs
1391 #Sanity check the version number
1392 if (defined $prevversion) {
1393 check_version_lte($prevversion, $a[2]);
1395 check_version_lte($a[2], $currversion);
1396 $prevversion = $a[2];
1397 $ret{$a[0]}=$a[1]."\\".$a[2]."\\".$a[3]; # \\ is a special marker
1399 $max_num = $a[1] if $a[1] > $max_num;
1403 print STDERR "Warning: $num_noinfo symbols were without info.";
1405 printf STDERR " The rewrite will fix this.\n";
1407 printf STDERR " You should do a rewrite to fix this.\n";
1416 (my $str, my $what) = @_;
1417 (my $n, my $v, my $i) = split(/\\/,$str);
1427 (*OUT,$name,*nums,@symbols)=@_;
1430 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1431 my $r; my %r; my %rsyms;
1433 (my $s, my $i) = split /\\/, $r;
1434 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1435 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1436 $r{$a} = $s."\\".$i;
1441 foreach $_ (@symbols) {
1442 (my $n, my $i) = split /\\/;
1447 &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n")
1451 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1452 next if defined($i) && $i =~ /^.*?:.*?:\w+\(\w+\)/;
1453 next if defined($rsyms{$sym});
1454 print STDERR "DEBUG: rewrite_numbers for sym = ",$sym,": i = ",$i,", n = ",$n,", rsym{sym} = ",$rsyms{$sym},"syms{sym} = ",$syms{$sym},"\n" if $debug;
1455 $i="NOEXIST::FUNCTION:"
1456 if !defined($i) || $i eq "" || !defined($syms{$sym});
1458 $s2 =~ s/\{[0-9]+\}$//;
1459 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1460 if (exists $r{$sym}) {
1461 (my $s, $i) = split /\\/,$r{$sym};
1463 $s2 =~ s/\{[0-9]+\}$//;
1464 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1471 (*OUT,$name,*nums,my $start_num, my @symbols)=@_;
1476 ($basevers, $vers) = get_openssl_version();
1478 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1479 my $r; my %r; my %rsyms;
1481 (my $s, my $i) = split /\\/, $r;
1482 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1483 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1484 $r{$a} = $s."\\".$i;
1488 foreach $sym (@symbols) {
1489 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1490 next if $i =~ /^.*?:.*?:\w+\(\w+\)/;
1491 next if defined($rsyms{$sym});
1492 die "ERROR: Symbol $sym had no info attached to it."
1494 if (!exists $nums{$s}) {
1497 $s2 =~ s/\{[0-9]+\}$//;
1498 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2, ++$start_num,$vers,$i;
1499 if (exists $r{$s}) {
1500 ($s, $i) = split /\\/,$r{$s};
1501 $s =~ s/\{[0-9]+\}$//;
1502 printf OUT "%s%-39s %d\t%s\t%s\n","",$s, $start_num,$vers,$i;
1507 print STDERR "$name: Added $new_syms new symbols\n";
1509 print STDERR "$name: No new symbols added\n";
1515 (*nums, my @symbols)=@_;
1516 my %existing; my @remaining;
1518 foreach $sym (@symbols) {
1519 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1522 foreach $sym (keys %nums) {
1523 if (!exists $existing{$sym}) {
1524 push @remaining, $sym;
1528 print STDERR "The following symbols do not seem to exist:\n";
1529 foreach $sym (@remaining) {
1530 print STDERR "\t",$sym,"\n";
1537 my $line = shift(@_);
1539 my $open = $line =~ tr/\(//;
1540 my $close = $line =~ tr/\)//;
1542 return $open - $close;
1545 #Parse opensslv.h to get the current version number. Also work out the base
1546 #version, i.e. the lowest version number that is binary compatible with this
1548 sub get_openssl_version()
1550 my $fn = catfile($config{sourcedir},"include","openssl","opensslv.h");
1551 open (IN, "$fn") || die "Can't open opensslv.h";
1554 if (/OPENSSL_VERSION_TEXT\s+"OpenSSL (\d\.\d\.)(\d[a-z]*)(-| )/) {
1556 (my $baseversion = $1) =~ s/\./_/g;
1558 return ($baseversion."0", $baseversion.$suffix);
1561 die "Can't find OpenSSL version number\n";
1564 #Given an OpenSSL version number, calculate the next version number. If the
1565 #version number gets to a.b.czz then we go to a.b.(c+1)
1566 sub get_next_version()
1568 my $thisversion = shift;
1570 my ($base, $letter) = $thisversion =~ /^(\d_\d_\d)([a-z]{0,2})$/;
1572 if ($letter eq "zz") {
1573 my $lastnum = substr($base, -1);
1574 return substr($base, 0, length($base)-1).(++$lastnum);
1576 return $base.get_next_letter($letter);
1579 #Given the letters off the end of an OpenSSL version string, calculate what
1580 #the letters for the next release would be.
1581 sub get_next_letter()
1583 my $thisletter = shift;
1584 my $baseletter = "";
1587 if ($thisletter eq "") {
1590 if ((length $thisletter) > 1) {
1591 ($baseletter, $endletter) = $thisletter =~ /([a-z]+)([a-z])/;
1593 $endletter = $thisletter;
1596 if ($endletter eq "z") {
1597 return $thisletter."a";
1599 return $baseletter.(++$endletter);
1603 #Check if a version is less than or equal to the current version. Its a fatal
1604 #error if not. They must also only differ in letters, or the last number (i.e.
1605 #the first two numbers must be the same)
1606 sub check_version_lte()
1608 my ($testversion, $currversion) = @_;
1613 my ($cvnums) = $currversion =~ /^(\d_\d_\d)[a-z]*$/;
1614 my ($tvnums) = $testversion =~ /^(\d_\d_\d)[a-z]*$/;
1616 #Die if we can't parse the version numbers or they don't look sane
1617 die "Invalid version number: $testversion and $currversion\n"
1618 if (!defined($cvnums) || !defined($tvnums)
1619 || length($cvnums) != 5
1620 || length($tvnums) != 5);
1622 #If the base versions (without letters) don't match check they only differ
1624 if ($cvnums ne $tvnums) {
1625 die "Invalid version number: $testversion "
1626 ."for current version $currversion\n"
1627 if (substr($cvnums, 0, 4) ne substr($tvnums, 0, 4));
1630 #If we get here then the base version (i.e. the numbers) are the same - they
1631 #only differ in the letters
1633 $lentv = length $testversion;
1634 $lencv = length $currversion;
1636 #If the testversion has more letters than the current version then it must
1637 #be later (or malformed)
1638 if ($lentv > $lencv) {
1639 die "Invalid version number: $testversion "
1640 ."is greater than $currversion\n";
1643 #Get the last letter from the current version
1644 my ($cvletter) = $currversion =~ /([a-z])$/;
1645 if (defined $cvletter) {
1646 ($cvbase) = $currversion =~ /(\d_\d_\d[a-z]*)$cvletter$/;
1648 $cvbase = $currversion;
1650 die "Unable to parse version number $currversion" if (!defined $cvbase);
1652 my ($tvletter) = $testversion =~ /([a-z])$/;
1653 if (defined $tvletter) {
1654 ($tvbase) = $testversion =~ /(\d_\d_\d[a-z]*)$tvletter$/;
1656 $tvbase = $testversion;
1658 die "Unable to parse version number $testversion" if (!defined $tvbase);
1660 if ($lencv > $lentv) {
1661 #If current version has more letters than testversion then testversion
1662 #minus the final letter must be a substring of the current version
1663 die "Invalid version number $testversion "
1664 ."is greater than $currversion or is invalid\n"
1665 if (index($cvbase, $tvbase) != 0);
1667 #If both versions have the same number of letters then they must be
1668 #equal up to the last letter, and the last letter in testversion must
1669 #be less than or equal to the last letter in current version.
1670 die "Invalid version number $testversion "
1671 ."is greater than $currversion\n"
1672 if (($cvbase ne $tvbase) && ($tvletter gt $cvletter));
1678 my ($decl, $plats, $algs) = @_;
1679 $decl =~ /^\s*(DEPRECATEDIN_\d+_\d+_\d+)\s*\((.*)\)\s*$/
1680 or die "Bad DEPRECATEDIN: $decl\n";
1681 my $info1 .= "#INFO:";
1682 $info1 .= join(',', @{$plats}) . ":";
1684 $info1 .= join(',',@{$algs}, $1) . ";";
1685 $info2 .= join(',',@{$algs}) . ";";
1686 return $info1 . $2 . ";" . $info2;