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_ssl=1 if $_ eq "libssl";
236 $do_crypto=1 if $_ eq "libcrypto";
237 if ($_ eq "crypto") {
241 $do_update=1 if $_ eq "update";
242 $do_rewrite=1 if $_ eq "rewrite";
243 $do_ctest=1 if $_ eq "ctest";
244 $do_ctestall=1 if $_ eq "ctestall";
245 $do_checkexist=1 if $_ eq "exist";
246 if (/^(enable|disable|no)-(.*)$/) {
249 if (exists $disabled_algorithms{$alg}) {
250 $disabled_algorithms{$alg} = $1 eq "enable" ? 0 : 1;
261 $libname="LIBCRYPTO";
265 # If no platform is given, assume WIN32
266 if ($W32 + $VMS + $linux == 0) {
269 die "Please, only one platform at a time"
270 if ($W32 + $VMS + $linux > 1);
272 if (!$do_ssl && !$do_crypto)
274 print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT | OS2 | linux | VMS ]\n";
278 %ssl_list=&load_numbers($ssl_num);
280 %crypto_list=&load_numbers($crypto_num);
281 $max_crypto = $max_num;
283 my $ssl="include/openssl/ssl.h";
284 $ssl.=" include/openssl/sslerr.h";
285 $ssl.=" include/openssl/tls1.h";
286 $ssl.=" include/openssl/srtp.h";
288 # When scanning include/openssl, skip all SSL files and some internal ones.
290 foreach my $f ( split(/\s+/, $ssl) ) {
293 $skipthese{'include/openssl/conf_api.h'} = 1;
294 $skipthese{'include/openssl/ebcdic.h'} = 1;
295 $skipthese{'include/openssl/opensslconf.h'} = 1;
297 # We use headers found in include/openssl and include/internal only.
298 # The latter is needed so libssl.so/.dll/.exe can link properly.
299 my $crypto ="include/internal/dso.h";
300 $crypto.=" include/internal/o_dir.h";
301 $crypto.=" include/internal/o_str.h";
302 $crypto.=" include/internal/err.h";
303 $crypto.=" include/internal/rand.h";
304 foreach my $f ( glob(catfile($config{sourcedir},'include/openssl/*.h')) ) {
305 my $fn = "include/openssl/" . lc(basename($f));
306 $crypto .= " $fn" if !defined $skipthese{$fn} && $f !~ m@/[a-z]+err\.h$@;
309 my $symhacks="include/openssl/symhacks.h";
311 my @ssl_symbols = &do_defs("LIBSSL", $ssl, $symhacks);
312 my @crypto_symbols = &do_defs("LIBCRYPTO", $crypto, $symhacks);
318 &maybe_add_info("LIBSSL",*ssl_list,@ssl_symbols);
319 if ($do_rewrite == 1) {
320 open(OUT, ">$ssl_num");
321 &rewrite_numbers(*OUT,"LIBSSL",*ssl_list,@ssl_symbols);
323 open(OUT, ">>$ssl_num");
325 &update_numbers(*OUT,"LIBSSL",*ssl_list,$max_ssl,@ssl_symbols);
329 if($do_crypto == 1) {
331 &maybe_add_info("LIBCRYPTO",*crypto_list,@crypto_symbols);
332 if ($do_rewrite == 1) {
333 open(OUT, ">$crypto_num");
334 &rewrite_numbers(*OUT,"LIBCRYPTO",*crypto_list,@crypto_symbols);
336 open(OUT, ">>$crypto_num");
338 &update_numbers(*OUT,"LIBCRYPTO",*crypto_list,$max_crypto,@crypto_symbols);
342 } elsif ($do_checkexist) {
343 &check_existing(*ssl_list, @ssl_symbols)
345 &check_existing(*crypto_list, @crypto_symbols)
347 } elsif ($do_ctest || $do_ctestall) {
351 /* Test file to check all DEF file symbols are present by trying
352 * to link to all of them. This is *not* intended to be run!
358 &print_test_file(*STDOUT,"LIBSSL",*ssl_list,$do_ctestall,@ssl_symbols)
361 &print_test_file(*STDOUT,"LIBCRYPTO",*crypto_list,$do_ctestall,@crypto_symbols)
368 &print_def_file(*STDOUT,$libname,*ssl_list,@ssl_symbols)
371 &print_def_file(*STDOUT,$libname,*crypto_list,@crypto_symbols)
379 my($name,$files,$symhacksfile)=@_;
383 my %platform; # For anything undefined, we assume ""
384 my %kind; # For anything undefined, we assume "FUNCTION"
385 my %algorithm; # For anything undefined, we assume ""
387 my %variant_cnt; # To be able to allocate "name{n}" if "name"
388 # is the same name as the original.
390 my %unknown_algorithms = ();
393 foreach $file (split(/\s+/,$symhacksfile." ".$files))
395 my $fn = catfile($config{sourcedir},$file);
396 print STDERR "DEBUG: starting on $fn:\n" if $debug;
397 open(IN,"<$fn") || die "Can't open $fn, $!,";
398 my $line = "", my $def= "";
400 (map { $_ => 0 } @known_platforms),
401 (map { "OPENSSL_SYS_".$_ => 0 } @known_ossl_platforms),
402 (map { "OPENSSL_NO_".$_ => 0 } @known_algorithms),
403 (map { "OPENSSL_USE_".$_ => 0 } @known_algorithms),
404 (grep /^DEPRECATED_/, @known_algorithms),
411 my $symhacking = $file eq $symhacksfile;
412 my @current_platforms = ();
413 my @current_algorithms = ();
415 # params: symbol, alias, platforms, kind
416 # The reason to put this subroutine in a variable is that
417 # it will otherwise create it's own, unshared, version of
418 # %tag and %variant...
419 my $make_variant = sub
421 my ($s, $a, $p, $k) = @_;
424 print STDERR "DEBUG: make_variant: Entered with ",$s,", ",$a,", ",(defined($p)?$p:""),", ",(defined($k)?$k:""),"\n" if $debug;
429 map { $tag{$_} == 1 ? $_ : "" }
436 map { $tag{$_} == 1 ? $_ : "" }
441 map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ : "" }
442 @known_ossl_platforms));
443 print STDERR "DEBUG: make_variant: a1 = $a1; a2 = $a2\n" if $debug;
444 if ($a1 eq "") { $a1 = $a2; }
445 elsif ($a1 ne "" && $a2 ne "") { $a1 .= ",".$a2; }
448 if (!defined($variant_cnt{$s}))
450 $variant_cnt{$s} = 0;
453 $a .= "{$variant_cnt{$s}}";
455 my $toadd = $a.":".$a1.(defined($k)?":".$k:"");
456 my $togrep = $s.'(\{[0-9]+\})?:'.$a1.(defined($k)?":".$k:"");
457 if (!grep(/^$togrep$/,
458 split(/;/, defined($variant{$s})?$variant{$s}:""))) {
459 if (defined($variant{$s})) { $variant{$s} .= ";"; }
460 $variant{$s} .= $toadd;
462 print STDERR "DEBUG: make_variant: Exit with variant of ",$s," = ",$variant{$s},"\n" if $debug;
465 print STDERR "DEBUG: parsing ----------\n" if $debug;
467 s|\R$||; # Better chomp
469 #Inside a DEPRECATEDIN
470 $stored_multiline .= $_;
471 print STDERR "DEBUG: Continuing multiline DEPRECATEDIN: $stored_multiline\n" if $debug;
472 $parens = count_parens($stored_multiline);
474 $def .= do_deprecated($stored_multiline,
476 \@current_algorithms);
480 if (/\/\* Error codes for the \w+ functions\. \*\//)
491 $line = $`; # keep what was before the backslash
496 if (not /\*\//) { # multi-line comment...
497 $line = $_; # ... just accumulate
500 s/\/\*.*?\*\///gs;# wipe it
506 $cpp-- if /^#\s*endif/;
509 if (/^#.*ifdef.*cplusplus/) {
514 s/{[^{}]*}//gs; # ignore {} blocks
515 print STDERR "DEBUG: \$def=\"$def\"\n" if $debug && $def ne "";
516 print STDERR "DEBUG: \$_=\"$_\"\n" if $debug;
517 if (/^\#\s*if\s+OPENSSL_API_COMPAT\s*(\S)\s*(0x[0-9a-fA-F]{8})L\s*$/) {
520 if ($op ne '<' && $op ne '>=') {
521 die "$file unacceptable operator $op: $_\n";
523 my ($one, $major, $minor) =
527 my $t = "DEPRECATEDIN_${one}_${major}_${minor}";
530 $tag{$t}=($op eq '<' ? 1 : -1);
531 print STDERR "DEBUG: $file: found tag $t = $tag{$t}\n" if $debug;
532 } elsif (/^\#\s*ifndef\s+(.*)/) {
536 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
537 } elsif (/^\#\s*if\s+!defined\(([^\)]+)\)/) {
539 if (/^\#\s*if\s+(!defined\(([^\)]+)\)(\s+\&\&\s+!defined\(([^\)]+)\))*)$/) {
542 foreach $tmp_ (split '\&\&',$tmp_1) {
543 $tmp_ =~ /!defined\(([^\)]+)\)/;
544 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
549 print STDERR "Warning: $file: complicated expression: $_" if $debug; # because it is O...
550 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
554 } elsif (/^\#\s*ifdef\s+(\S*)/) {
558 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
559 } elsif (/^\#\s*if\s+defined\(([^\)]+)\)/) {
561 if (/^\#\s*if\s+(defined\(([^\)]+)\)(\s+\|\|\s+defined\(([^\)]+)\))*)$/) {
564 foreach $tmp_ (split '\|\|',$tmp_1) {
565 $tmp_ =~ /defined\(([^\)]+)\)/;
566 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
571 print STDERR "Warning: $file: complicated expression: $_\n" if $debug; # because it is O...
572 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
576 } elsif (/^\#\s*error\s+(\w+) is disabled\./) {
578 while($tag[$tag_i] ne "-") {
579 if ($tag[$tag_i] eq "OPENSSL_NO_".$1) {
580 $tag{$tag[$tag_i]}=2;
581 print STDERR "DEBUG: $file: changed tag $1 = 2\n" if $debug;
585 } elsif (/^\#\s*endif/) {
587 while($tag_i > 0 && $tag[$tag_i] ne "-") {
589 print STDERR "DEBUG: \$t=\"$t\"\n" if $debug;
595 print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug;
597 if ($t =~ /^OPENSSL_NO_([A-Z0-9_]+)$/) {
599 } elsif($t =~ /^OPENSSL_USE_([A-Z0-9_]+)$/) {
605 && !grep(/^$t$/, @known_algorithms)) {
606 $unknown_algorithms{$t} = 1;
607 #print STDERR "DEBUG: Added as unknown algorithm: $t\n" if $debug;
612 } elsif (/^\#\s*else/) {
614 die "$file unmatched else\n" if $tag_i < 0;
615 while($tag[$tag_i] ne "-") {
618 print STDERR "DEBUG: $file: changed tag ",$t," = ",$tag{$t},"\n" if $debug;
621 } elsif (/^\#\s*if\s+1/) {
626 print STDERR "DEBUG: $file: found 1\n" if $debug;
627 } elsif (/^\#\s*if\s+0/) {
632 print STDERR "DEBUG: $file: found 0\n" if $debug;
633 } elsif (/^\#\s*if\s+/) {
634 #Some other unrecognized "if" style
636 } elsif (/^\#\s*define\s+(\w+)\s+(\w+)/
637 && $symhacking && $tag{'TRUE'} != -1) {
638 # This is for aliasing. When we find an alias,
640 &$make_variant($1,$2);
641 print STDERR "DEBUG: $file: defined $1 = $2\n" if $debug;
646 map { $tag{$_} == 1 ? $_ :
647 $tag{$_} == -1 ? "!".$_ : "" }
649 push @current_platforms
651 map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ :
652 $tag{"OPENSSL_SYS_".$_} == -1 ? "!".$_ : "" }
653 @known_ossl_platforms);
654 @current_algorithms = ();
655 @current_algorithms =
657 map { $tag{"OPENSSL_NO_".$_} == -1 ? $_ : "" }
659 push @current_algorithms
661 map { $tag{"OPENSSL_USE_".$_} == 1 ? $_ : "" }
663 push @current_algorithms,
664 grep { /^DEPRECATEDIN_/ && $tag{$_} == 1 }
668 .join(',',@current_platforms).":"
669 .join(',',@current_algorithms).";";
672 if ($tag{'TRUE'} != -1) {
673 if (/^\s*DEFINE_STACK_OF\s*\(\s*(\w*)\s*\)/
674 || /^\s*DEFINE_STACK_OF_CONST\s*\(\s*(\w*)\s*\)/) {
676 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
677 $def .= "int d2i_$3(void);";
678 $def .= "int i2d_$3(void);";
679 # Variant for platforms that do not
680 # have to access global variables
681 # in shared libraries through functions
684 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
685 .join(',',@current_algorithms).";";
686 $def .= "OPENSSL_EXTERN int $2_it;";
689 .join(',',@current_platforms).":"
690 .join(',',@current_algorithms).";";
691 # Variant for platforms that have to
692 # access global variables in shared
693 # libraries through functions
694 &$make_variant("$2_it","$2_it",
695 "EXPORT_VAR_AS_FUNCTION",
698 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_fname\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
699 $def .= "int d2i_$3(void);";
700 $def .= "int i2d_$3(void);";
701 $def .= "int $3_free(void);";
702 $def .= "int $3_new(void);";
703 # Variant for platforms that do not
704 # have to access global variables
705 # in shared libraries through functions
708 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
709 .join(',',@current_algorithms).";";
710 $def .= "OPENSSL_EXTERN int $2_it;";
713 .join(',',@current_platforms).":"
714 .join(',',@current_algorithms).";";
715 # Variant for platforms that have to
716 # access global variables in shared
717 # libraries through functions
718 &$make_variant("$2_it","$2_it",
719 "EXPORT_VAR_AS_FUNCTION",
722 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS\s*\(\s*(\w*)\s*\)/ ||
723 /^\s*DECLARE_ASN1_FUNCTIONS_const\s*\(\s*(\w*)\s*\)/) {
724 $def .= "int d2i_$1(void);";
725 $def .= "int i2d_$1(void);";
726 $def .= "int $1_free(void);";
727 $def .= "int $1_new(void);";
728 # Variant for platforms that do not
729 # have to access global variables
730 # in shared libraries through functions
733 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
734 .join(',',@current_algorithms).";";
735 $def .= "OPENSSL_EXTERN int $1_it;";
738 .join(',',@current_platforms).":"
739 .join(',',@current_algorithms).";";
740 # Variant for platforms that have to
741 # access global variables in shared
742 # libraries through functions
743 &$make_variant("$1_it","$1_it",
744 "EXPORT_VAR_AS_FUNCTION",
747 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS_const\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
748 $def .= "int d2i_$2(void);";
749 $def .= "int i2d_$2(void);";
750 # Variant for platforms that do not
751 # have to access global variables
752 # in shared libraries through functions
755 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
756 .join(',',@current_algorithms).";";
757 $def .= "OPENSSL_EXTERN int $2_it;";
760 .join(',',@current_platforms).":"
761 .join(',',@current_algorithms).";";
762 # Variant for platforms that have to
763 # access global variables in shared
764 # libraries through functions
765 &$make_variant("$2_it","$2_it",
766 "EXPORT_VAR_AS_FUNCTION",
769 } elsif (/^\s*DECLARE_ASN1_ALLOC_FUNCTIONS\s*\(\s*(\w*)\s*\)/) {
770 $def .= "int $1_free(void);";
771 $def .= "int $1_new(void);";
773 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
774 $def .= "int d2i_$2(void);";
775 $def .= "int i2d_$2(void);";
776 $def .= "int $2_free(void);";
777 $def .= "int $2_new(void);";
778 # Variant for platforms that do not
779 # have to access global variables
780 # in shared libraries through functions
783 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
784 .join(',',@current_algorithms).";";
785 $def .= "OPENSSL_EXTERN int $2_it;";
788 .join(',',@current_platforms).":"
789 .join(',',@current_algorithms).";";
790 # Variant for platforms that have to
791 # access global variables in shared
792 # libraries through functions
793 &$make_variant("$2_it","$2_it",
794 "EXPORT_VAR_AS_FUNCTION",
797 } elsif (/^\s*DECLARE_ASN1_ITEM\s*\(\s*(\w*)\s*\)/) {
798 # Variant for platforms that do not
799 # have to access global variables
800 # in shared libraries through functions
803 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
804 .join(',',@current_algorithms).";";
805 $def .= "OPENSSL_EXTERN int $1_it;";
808 .join(',',@current_platforms).":"
809 .join(',',@current_algorithms).";";
810 # Variant for platforms that have to
811 # access global variables in shared
812 # libraries through functions
813 &$make_variant("$1_it","$1_it",
814 "EXPORT_VAR_AS_FUNCTION",
817 } elsif (/^\s*DECLARE_ASN1_NDEF_FUNCTION\s*\(\s*(\w*)\s*\)/) {
818 $def .= "int i2d_$1_NDEF(void);";
819 } elsif (/^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) {
821 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION\s*\(\s*(\w*)\s*\)/) {
822 $def .= "int $1_print_ctx(void);";
824 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
825 $def .= "int $2_print_ctx(void);";
827 } elsif (/^\s*DECLARE_PKCS12_STACK_OF\s*\(\s*(\w*)\s*\)/) {
829 } elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ ||
830 /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ ||
831 /^DECLARE_PEM_rw_const\s*\(\s*(\w*)\s*,/ ) {
834 .join(',',@current_platforms).":"
835 .join(',',"STDIO",@current_algorithms).";";
836 $def .= "int PEM_read_$1(void);";
837 $def .= "int PEM_write_$1(void);";
840 .join(',',@current_platforms).":"
841 .join(',',@current_algorithms).";";
842 # Things that are everywhere
843 $def .= "int PEM_read_bio_$1(void);";
844 $def .= "int PEM_write_bio_$1(void);";
846 } elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ ||
847 /^DECLARE_PEM_write_const\s*\(\s*(\w*)\s*,/ ||
848 /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) {
851 .join(',',@current_platforms).":"
852 .join(',',"STDIO",@current_algorithms).";";
853 $def .= "int PEM_write_$1(void);";
856 .join(',',@current_platforms).":"
857 .join(',',@current_algorithms).";";
858 # Things that are everywhere
859 $def .= "int PEM_write_bio_$1(void);";
861 } elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ ||
862 /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) {
865 .join(',',@current_platforms).":"
866 .join(',',"STDIO",@current_algorithms).";";
867 $def .= "int PEM_read_$1(void);";
870 .join(',',@current_platforms).":"
871 .join(',',"STDIO",@current_algorithms).";";
872 # Things that are everywhere
873 $def .= "int PEM_read_bio_$1(void);";
875 } elsif (/^OPENSSL_DECLARE_GLOBAL\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
876 # Variant for platforms that do not
877 # have to access global variables
878 # in shared libraries through functions
881 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
882 .join(',',@current_algorithms).";";
883 $def .= "OPENSSL_EXTERN int _shadow_$2;";
886 .join(',',@current_platforms).":"
887 .join(',',@current_algorithms).";";
888 # Variant for platforms that have to
889 # access global variables in shared
890 # libraries through functions
891 &$make_variant("_shadow_$2","_shadow_$2",
892 "EXPORT_VAR_AS_FUNCTION",
894 } elsif (/^\s*DEPRECATEDIN/) {
895 $parens = count_parens($_);
897 $def .= do_deprecated($_,
899 \@current_algorithms);
901 $stored_multiline = $_;
902 print STDERR "DEBUG: Found multiline DEPRECATEDIN starting with: $stored_multiline\n" if $debug;
905 } elsif ($tag{'CONST_STRICT'} != 1) {
906 if (/\{|\/\*|\([^\)]*$/) {
915 die "$file: Unmatched tags\n" if $#tag >= 0;
920 print STDERR "DEBUG: postprocessing ----------\n" if $debug;
921 foreach (split /;/, $def) {
922 my $s; my $k = "FUNCTION"; my $p; my $a;
926 next if(/typedef\W/);
929 # Reduce argument lists to empty ()
930 # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
932 s/\([^\(\)]+\)/\{\}/gs;
933 s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f
935 # pretend as we didn't use curly braces: {} -> ()
938 s/STACK_OF\(\)/void/gs;
939 s/LHASH_OF\(\)/void/gs;
941 print STDERR "DEBUG: \$_ = \"$_\"\n" if $debug;
942 if (/^\#INFO:([^:]*):(.*)$/) {
945 print STDERR "DEBUG: found info on platforms ($plats) and algorithms ($algs)\n" if $debug;
947 } elsif (/^\s*OPENSSL_EXTERN\s.*?(\w+(\{[0-9]+\})?)(\[[0-9]*\])*\s*$/) {
950 print STDERR "DEBUG: found external variable $s\n" if $debug;
951 } elsif (/TYPEDEF_\w+_OF/s) {
953 } elsif (/(\w+)\s*\(\).*/s) { # first token prior [first] () is
954 $s = $1; # a function name!
955 print STDERR "DEBUG: found function $s\n" if $debug;
956 } elsif (/\(/ and not (/=/)) {
957 print STDERR "File $file: cannot parse: $_;\n";
970 &reduce_platforms((defined($platform{$s})?$platform{$s}.',':"").$p);
971 $algorithm{$s} .= ','.$a;
973 if (defined($variant{$s})) {
974 foreach $v (split /;/,$variant{$s}) {
975 (my $r, my $p, my $k) = split(/:/,$v);
976 my $ip = join ',',map({ /^!(.*)$/ ? $1 : "!".$_ } split /,/, $p);
978 if (!defined($k)) { $k = $kind{$s}; }
979 $kind{$r} = $k."(".$s.")";
980 $algorithm{$r} = $algorithm{$s};
981 $platform{$r} = &reduce_platforms($platform{$s}.",".$p.",".$p);
982 $platform{$s} = &reduce_platforms($platform{$s}.','.$ip.','.$ip);
983 print STDERR "DEBUG: \$variant{\"$s\"} = ",$v,"; \$r = $r; \$p = ",$platform{$r},"; \$a = ",$algorithm{$r},"; \$kind = ",$kind{$r},"\n" if $debug;
986 print STDERR "DEBUG: \$s = $s; \$p = ",$platform{$s},"; \$a = ",$algorithm{$s},"; \$kind = ",$kind{$s},"\n" if $debug;
990 # Prune the returned symbols
992 delete $syms{"bn_dump1"};
993 $platform{"BIO_s_log"} .= ",!WIN32,!macintosh";
995 $platform{"PEM_read_NS_CERT_SEQ"} = "VMS";
996 $platform{"PEM_write_NS_CERT_SEQ"} = "VMS";
997 $platform{"PEM_read_P8_PRIV_KEY_INFO"} = "VMS";
998 $platform{"PEM_write_P8_PRIV_KEY_INFO"} = "VMS";
1000 # Info we know about
1002 push @ret, map { $_."\\".&info_string($_,"EXIST",
1005 $algorithm{$_}) } keys %syms;
1007 if (keys %unknown_algorithms) {
1008 print STDERR "WARNING: mkdef.pl doesn't know the following algorithms:\n";
1009 print STDERR "\t",join("\n\t",keys %unknown_algorithms),"\n";
1014 # Param: string of comma-separated platform-specs.
1015 sub reduce_platforms
1017 my ($platforms) = @_;
1018 my $pl = defined($platforms) ? $platforms : "";
1019 my %p = map { $_ => 0 } split /,/, $pl;
1022 print STDERR "DEBUG: Entered reduce_platforms with \"$platforms\"\n"
1024 # We do this, because if there's code like the following, it really
1025 # means the function exists in all cases and should therefore be
1026 # everywhere. By increasing and decreasing, we may attain 0:
1033 foreach $platform (split /,/, $pl) {
1034 if ($platform =~ /^!(.*)$/) {
1040 foreach $platform (keys %p) {
1041 if ($p{$platform} == 0) { delete $p{$platform}; }
1046 $ret = join(',',sort(map { $p{$_} < 0 ? "!".$_ : $_ } keys %p));
1047 print STDERR "DEBUG: Exiting reduce_platforms with \"$ret\"\n"
1054 (my $symbol, my $exist, my $platforms, my $kind, my $algorithms) = @_;
1056 my %a = defined($algorithms) ?
1057 map { $_ => 1 } split /,/, $algorithms : ();
1058 my $k = defined($kind) ? $kind : "FUNCTION";
1060 my $p = &reduce_platforms($platforms);
1067 $ret .= ":".join(',',sort keys %a);
1073 (my $name, *nums, my @symbols) = @_;
1078 foreach $sym (@symbols) {
1079 (my $s, my $i) = split /\\/, $sym;
1080 if (defined($nums{$s})) {
1081 $i =~ s/^(.*?:.*?:\w+)(\(\w+\))?/$1/;
1082 (my $n, my $vers, my $dummy) = split /\\/, $nums{$s};
1083 if (!defined($dummy) || $i ne $dummy) {
1084 $nums{$s} = $n."\\".$vers."\\".$i;
1086 print STDERR "DEBUG: maybe_add_info for $s: \"$dummy\" => \"$i\"\n" if $debug;
1092 my @s=sort { &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") } keys %nums;
1094 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1095 if (!defined($syms{$sym}) && $i !~ /^NOEXIST:/) {
1097 print STDERR "DEBUG: maybe_add_info for $sym: -> undefined\n" if $debug;
1101 print STDERR "$name: $new_info old symbols have updated info\n";
1103 print STDERR "You should do a rewrite to fix this.\n";
1109 # Param: string of comma-separated keywords, each possibly prefixed with a "!"
1112 my ($keywords_txt,$platforms) = @_;
1113 my (@keywords) = split /,/,$keywords_txt;
1114 my ($falsesum, $truesum) = (0, 1);
1116 # Param: one keyword
1119 my ($keyword,$platforms) = @_;
1123 if ($keyword eq "UNIX" && $UNIX) { return 1; }
1124 if ($keyword eq "VMS" && $VMS) { return 1; }
1125 if ($keyword eq "WIN32" && $W32) { return 1; }
1126 if ($keyword eq "_WIN32" && $W32) { return 1; }
1127 if ($keyword eq "WINNT" && $NT) { return 1; }
1128 # Special platforms:
1129 # EXPORT_VAR_AS_FUNCTION means that global variables
1130 # will be represented as functions.
1131 if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && $W32) {
1134 if ($keyword eq "ZLIB" && $zlib) { return 1; }
1138 if ($disabled_algorithms{$keyword} == 1) { return 0;}
1140 # Nothing recognise as true
1145 foreach $k (@keywords) {
1146 if ($k =~ /^!(.*)$/) {
1147 $falsesum += &recognise($1,$platforms);
1149 $truesum *= &recognise($k,$platforms);
1152 print STDERR "DEBUG: [",$#keywords,",",$#keywords < 0,"] is_valid($keywords_txt) => (\!$falsesum) && $truesum = ",(!$falsesum) && $truesum,"\n" if $debug;
1153 return (!$falsesum) && $truesum;
1158 (*OUT,my $name,*nums,my $testall,my @symbols)=@_;
1159 my $n = 1; my @e; my @r;
1160 my $sym; my $prev = ""; my $prefSSLeay;
1162 (@e)=grep(/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1163 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:.*/ && !/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1164 @symbols=((sort @e),(sort @r));
1166 foreach $sym (@symbols) {
1167 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1169 $v = 1 if $i=~ /^.*?:.*?:VARIABLE/;
1170 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1171 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1172 if (!defined($nums{$s})) {
1173 print STDERR "Warning: $s does not have a number assigned\n"
1175 } elsif (is_valid($p,1) && is_valid($a,0)) {
1176 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1178 print OUT "\t/* The following has already appeared previously */\n";
1179 print STDERR "Warning: Symbol '",$s2,"' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1181 $prev = $s2; # To warn about duplicates...
1183 (my $nn, my $vers, my $ni) = split /\\/, $nums{$s2};
1185 print OUT "\textern int $s2; /* type unknown */ /* $nn $ni */\n";
1187 print OUT "\textern int $s2(); /* type unknown */ /* $nn $ni */\n";
1195 return $config{version};
1200 (*OUT,my $name,*nums,my @symbols)=@_;
1201 my $n = 1; my @e; my @r; my @v; my $prev="";
1203 my $libname = $name;
1204 my $http_vendor = 'www.openssl.org/';
1205 my $version = get_version();
1206 my $what = "OpenSSL: implementation of Secure Socket Layer";
1207 my $description = "$what $version, $name - http://$http_vendor";
1208 my $prevsymversion = "", $prevprevsymversion = "";
1211 my $symvtextcount = 0;
1220 ; Definition file for the DLL version of the $name library from OpenSSL
1223 LIBRARY $libname $liboptions
1235 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1238 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:FUNCTION/,@symbols);
1239 (@v)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:VARIABLE/,@symbols);
1241 # VMS needs to have the symbols on slot number order
1242 @symbols=(map { $_->[1] }
1243 sort { $a->[0] <=> $b->[0] }
1244 map { (my $s, my $i) = $_ =~ /^(.*?)\\(.*)$/;
1245 die "Error: $s doesn't have a number assigned\n"
1246 if !defined($nums{$s});
1247 (my $n, my @rest) = split /\\/, $nums{$s};
1248 [ $n, $_ ] } (@e, @r, @v));
1250 @symbols=((sort @e),(sort @r), (sort @v));
1253 my ($baseversion, $currversion) = get_openssl_version();
1256 if (!defined($thisversion)) {
1257 $thisversion = $baseversion;
1259 $thisversion = get_next_version($thisversion);
1261 foreach $sym (@symbols) {
1262 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1264 $v = 1 if $i =~ /^.*?:.*?:VARIABLE/;
1265 if (!defined($nums{$s})) {
1266 die "Error: $s does not have a number assigned\n"
1269 (my $n, my $symversion, my $dummy) = split /\\/, $nums{$s};
1271 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1272 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1273 if (is_valid($p,1) && is_valid($a,0)) {
1274 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1276 print STDERR "Warning: Symbol '",$s2,
1277 "' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),
1278 ", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1280 $prev = $s2; # To warn about duplicates...
1282 next if $symversion ne $thisversion;
1283 if ($symversion ne $prevsymversion) {
1284 if ($prevsymversion ne "") {
1285 if ($prevprevsymversion ne "") {
1286 print OUT "} OPENSSL${SO_VARIANT}_"
1287 ."$prevprevsymversion;\n\n";
1292 print OUT "OPENSSL${SO_VARIANT}_$symversion {\n global:\n";
1293 $prevprevsymversion = $prevsymversion;
1294 $prevsymversion = $symversion;
1296 print OUT " $s2;\n";
1298 while(++$prevnum < $n) {
1299 my $symline=" ,SPARE -\n ,SPARE -\n";
1300 if ($symvtextcount + length($symline) - 2 > 1024) {
1301 print OUT ")\nSYMBOL_VECTOR=(-\n";
1302 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1304 if ($symvtextcount == 16) {
1305 # Take away first comma
1309 $symvtextcount += length($symline) - 2;
1311 (my $s_uc = $s) =~ tr/a-z/A-Z/;
1313 $v ? "DATA" : "PROCEDURE";
1316 ? " ,$s_uc/$s=$symtype -\n ,$s=$symtype -\n"
1317 : " ,$s=$symtype -\n ,SPARE -\n");
1318 if ($symvtextcount + length($symline) - 2 > 1024) {
1319 print OUT ")\nSYMBOL_VECTOR=(-\n";
1320 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1322 if ($symvtextcount == 16) {
1323 # Take away first comma
1327 $symvtextcount += length($symline) - 2;
1329 printf OUT " %s%-39s DATA\n",
1332 printf OUT " %s%s\n",
1338 } while ($linux && $thisversion ne $currversion);
1340 if ($prevprevsymversion ne "") {
1341 print OUT " local: *;\n} OPENSSL${SO_VARIANT}_$prevprevsymversion;\n\n";
1343 print OUT " local: *;\n};\n\n";
1347 (my $libvmaj, my $libvmin, my $libvedit) =
1348 $currversion =~ /^(\d+)_(\d+)_(\d+)$/;
1349 # The reason to multiply the edit number with 100 is to make space
1350 # for the possibility that we want to encode the patch letters
1351 print OUT "GSMATCH=LEQUAL,",($libvmaj * 100 + $libvmin),",",($libvedit * 100),"\n";
1367 my ($baseversion, $currversion) = get_openssl_version();
1369 open(IN,"<$name") || die "unable to open $name:$!\n";
1371 s|\R$||; # Better chomp
1375 if (defined $ret{$a[0]}) {
1376 # This is actually perfectly OK
1377 #print STDERR "Warning: Symbol '",$a[0],"' redefined. old=",$ret{$a[0]},", new=",$a[1],"\n";
1379 if ($max_num > $a[1]) {
1380 print STDERR "Warning: Number decreased from ",$max_num," to ",$a[1],"\n";
1382 elsif ($max_num == $a[1]) {
1383 # This is actually perfectly OK
1384 #print STDERR "Warning: Symbol ",$a[0]," has same number as previous ",$prev,": ",$a[1],"\n";
1385 if ($a[0] eq $prev) {
1387 $a[0] .= "{$prev_cnt}";
1394 # Existence will be proven later, in do_defs
1398 #Sanity check the version number
1399 if (defined $prevversion) {
1400 check_version_lte($prevversion, $a[2]);
1402 check_version_lte($a[2], $currversion);
1403 $prevversion = $a[2];
1404 $ret{$a[0]}=$a[1]."\\".$a[2]."\\".$a[3]; # \\ is a special marker
1406 $max_num = $a[1] if $a[1] > $max_num;
1410 print STDERR "Warning: $num_noinfo symbols were without info.";
1412 printf STDERR " The rewrite will fix this.\n";
1414 printf STDERR " You should do a rewrite to fix this.\n";
1423 (my $str, my $what) = @_;
1424 (my $n, my $v, my $i) = split(/\\/,$str);
1434 (*OUT,$name,*nums,@symbols)=@_;
1437 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1438 my $r; my %r; my %rsyms;
1440 (my $s, my $i) = split /\\/, $r;
1441 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1442 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1443 $r{$a} = $s."\\".$i;
1448 foreach $_ (@symbols) {
1449 (my $n, my $i) = split /\\/;
1454 &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n")
1458 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1459 next if defined($i) && $i =~ /^.*?:.*?:\w+\(\w+\)/;
1460 next if defined($rsyms{$sym});
1461 print STDERR "DEBUG: rewrite_numbers for sym = ",$sym,": i = ",$i,", n = ",$n,", rsym{sym} = ",$rsyms{$sym},"syms{sym} = ",$syms{$sym},"\n" if $debug;
1462 $i="NOEXIST::FUNCTION:"
1463 if !defined($i) || $i eq "" || !defined($syms{$sym});
1465 $s2 =~ s/\{[0-9]+\}$//;
1466 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1467 if (exists $r{$sym}) {
1468 (my $s, $i) = split /\\/,$r{$sym};
1470 $s2 =~ s/\{[0-9]+\}$//;
1471 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1478 (*OUT,$name,*nums,my $start_num, my @symbols)=@_;
1483 ($basevers, $vers) = get_openssl_version();
1485 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1486 my $r; my %r; my %rsyms;
1488 (my $s, my $i) = split /\\/, $r;
1489 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1490 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1491 $r{$a} = $s."\\".$i;
1495 foreach $sym (@symbols) {
1496 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1497 next if $i =~ /^.*?:.*?:\w+\(\w+\)/;
1498 next if defined($rsyms{$sym});
1499 die "ERROR: Symbol $sym had no info attached to it."
1501 if (!exists $nums{$s}) {
1504 $s2 =~ s/\{[0-9]+\}$//;
1505 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2, ++$start_num,$vers,$i;
1506 if (exists $r{$s}) {
1507 ($s, $i) = split /\\/,$r{$s};
1508 $s =~ s/\{[0-9]+\}$//;
1509 printf OUT "%s%-39s %d\t%s\t%s\n","",$s, $start_num,$vers,$i;
1514 print STDERR "$name: Added $new_syms new symbols\n";
1516 print STDERR "$name: No new symbols added\n";
1522 (*nums, my @symbols)=@_;
1523 my %existing; my @remaining;
1525 foreach $sym (@symbols) {
1526 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1529 foreach $sym (keys %nums) {
1530 if (!exists $existing{$sym}) {
1531 push @remaining, $sym;
1535 print STDERR "The following symbols do not seem to exist:\n";
1536 foreach $sym (@remaining) {
1537 print STDERR "\t",$sym,"\n";
1544 my $line = shift(@_);
1546 my $open = $line =~ tr/\(//;
1547 my $close = $line =~ tr/\)//;
1549 return $open - $close;
1552 #Parse opensslv.h to get the current version number. Also work out the base
1553 #version, i.e. the lowest version number that is binary compatible with this
1555 sub get_openssl_version()
1557 my $fn = catfile($config{sourcedir},"include","openssl","opensslv.h");
1558 open (IN, "$fn") || die "Can't open opensslv.h";
1561 if (/OPENSSL_VERSION_TEXT\s+"OpenSSL (\d\.\d\.)(\d[a-z]*)(-| )/) {
1563 (my $baseversion = $1) =~ s/\./_/g;
1565 return ($baseversion."0", $baseversion.$suffix);
1568 die "Can't find OpenSSL version number\n";
1571 #Given an OpenSSL version number, calculate the next version number. If the
1572 #version number gets to a.b.czz then we go to a.b.(c+1)
1573 sub get_next_version()
1575 my $thisversion = shift;
1577 my ($base, $letter) = $thisversion =~ /^(\d_\d_\d)([a-z]{0,2})$/;
1579 if ($letter eq "zz") {
1580 my $lastnum = substr($base, -1);
1581 return substr($base, 0, length($base)-1).(++$lastnum);
1583 return $base.get_next_letter($letter);
1586 #Given the letters off the end of an OpenSSL version string, calculate what
1587 #the letters for the next release would be.
1588 sub get_next_letter()
1590 my $thisletter = shift;
1591 my $baseletter = "";
1594 if ($thisletter eq "") {
1597 if ((length $thisletter) > 1) {
1598 ($baseletter, $endletter) = $thisletter =~ /([a-z]+)([a-z])/;
1600 $endletter = $thisletter;
1603 if ($endletter eq "z") {
1604 return $thisletter."a";
1606 return $baseletter.(++$endletter);
1610 #Check if a version is less than or equal to the current version. Its a fatal
1611 #error if not. They must also only differ in letters, or the last number (i.e.
1612 #the first two numbers must be the same)
1613 sub check_version_lte()
1615 my ($testversion, $currversion) = @_;
1620 my ($cvnums) = $currversion =~ /^(\d_\d_\d)[a-z]*$/;
1621 my ($tvnums) = $testversion =~ /^(\d_\d_\d)[a-z]*$/;
1623 #Die if we can't parse the version numbers or they don't look sane
1624 die "Invalid version number: $testversion and $currversion\n"
1625 if (!defined($cvnums) || !defined($tvnums)
1626 || length($cvnums) != 5
1627 || length($tvnums) != 5);
1629 #If the base versions (without letters) don't match check they only differ
1631 if ($cvnums ne $tvnums) {
1632 die "Invalid version number: $testversion "
1633 ."for current version $currversion\n"
1634 if (substr($cvnums, 0, 4) ne substr($tvnums, 0, 4));
1637 #If we get here then the base version (i.e. the numbers) are the same - they
1638 #only differ in the letters
1640 $lentv = length $testversion;
1641 $lencv = length $currversion;
1643 #If the testversion has more letters than the current version then it must
1644 #be later (or malformed)
1645 if ($lentv > $lencv) {
1646 die "Invalid version number: $testversion "
1647 ."is greater than $currversion\n";
1650 #Get the last letter from the current version
1651 my ($cvletter) = $currversion =~ /([a-z])$/;
1652 if (defined $cvletter) {
1653 ($cvbase) = $currversion =~ /(\d_\d_\d[a-z]*)$cvletter$/;
1655 $cvbase = $currversion;
1657 die "Unable to parse version number $currversion" if (!defined $cvbase);
1659 my ($tvletter) = $testversion =~ /([a-z])$/;
1660 if (defined $tvletter) {
1661 ($tvbase) = $testversion =~ /(\d_\d_\d[a-z]*)$tvletter$/;
1663 $tvbase = $testversion;
1665 die "Unable to parse version number $testversion" if (!defined $tvbase);
1667 if ($lencv > $lentv) {
1668 #If current version has more letters than testversion then testversion
1669 #minus the final letter must be a substring of the current version
1670 die "Invalid version number $testversion "
1671 ."is greater than $currversion or is invalid\n"
1672 if (index($cvbase, $tvbase) != 0);
1674 #If both versions have the same number of letters then they must be
1675 #equal up to the last letter, and the last letter in testversion must
1676 #be less than or equal to the last letter in current version.
1677 die "Invalid version number $testversion "
1678 ."is greater than $currversion\n"
1679 if (($cvbase ne $tvbase) && ($tvletter gt $cvletter));
1685 my ($decl, $plats, $algs) = @_;
1686 $decl =~ /^\s*(DEPRECATEDIN_\d+_\d+_\d+)\s*\((.*)\)\s*$/
1687 or die "Bad DEPRECATEDIN: $decl\n";
1688 my $info1 .= "#INFO:";
1689 $info1 .= join(',', @{$plats}) . ":";
1691 $info1 .= join(',',@{$algs}, $1) . ";";
1692 $info2 .= join(',',@{$algs}) . ";";
1693 return $info1 . $2 . ";" . $info2;