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;
112 my $crypto_num= catfile($config{sourcedir},"util","libcrypto.num");
113 my $ssl_num= catfile($config{sourcedir},"util","libssl.num");
122 my $do_checkexist = 0;
129 # Set this to make typesafe STACK definitions appear in DEF
130 my $safe_stack_def = 0;
132 my @known_platforms = ( "__FreeBSD__", "PERL5",
133 "EXPORT_VAR_AS_FUNCTION", "ZLIB", "_WIN32"
135 my @known_ossl_platforms = ( "UNIX", "VMS", "WIN32", "WINNT", "OS2" );
136 my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
137 "CAST", "MD2", "MD4", "MD5", "SHA", "SHA0", "SHA1",
138 "SHA256", "SHA512", "RMD160",
139 "MDC2", "WHIRLPOOL", "RSA", "DSA", "DH", "EC", "EC2M",
140 "HMAC", "AES", "CAMELLIA", "SEED", "GOST", "ARIA", "SM4",
141 "SCRYPT", "CHACHA", "POLY1305", "BLAKE2",
143 # EC_NISTP_64_GCC_128
144 "EC_NISTP_64_GCC_128",
145 # Envelope "algorithms"
146 "EVP", "X509", "ASN1_TYPEDEFS",
147 # Helper "algorithms"
148 "BIO", "COMP", "BUFFER", "LHASH", "STACK", "ERR",
150 # External "algorithms"
151 "FP_API", "STDIO", "SOCK", "DGRAM",
154 "STATIC_ENGINE", "ENGINE", "HW", "GMP",
157 # Certificate Transparency
162 "PSK", "SRP", "HEARTBEATS",
169 "SSL3_METHOD", "TLS1_METHOD", "TLS1_1_METHOD", "TLS1_2_METHOD", "DTLS1_METHOD", "DTLS1_2_METHOD",
172 # Deprecated functions
173 "DEPRECATEDIN_0_9_8",
174 "DEPRECATEDIN_1_0_0",
175 "DEPRECATEDIN_1_1_0",
176 "DEPRECATEDIN_1_2_0",
192 # APPLINK (win build feature?)
196 my %disabled_algorithms;
198 foreach (@known_algorithms) {
199 $disabled_algorithms{$_} = 0;
201 # disabled by default
202 $disabled_algorithms{"STATIC_ENGINE"} = 1;
204 my $apiv = sprintf "%x%02x%02x", split(/\./, $config{api});
205 foreach (keys %disabled_algorithms) {
206 if (/^DEPRECATEDIN_(\d+)_(\d+)_(\d+)$/) {
207 my $depv = sprintf "%x%02x%02x", $1, $2, $3;
208 $disabled_algorithms{$_} = 1 if $apiv ge $depv;
214 foreach (@ARGV, split(/ /, $config{options}))
216 $debug=1 if $_ eq "debug";
217 $trace=1 if $_ eq "trace";
218 $verbose=1 if $_ eq "verbose";
219 $W32=1 if $_ eq "32";
220 die "win16 not supported" if $_ eq "16";
229 $VMS=1 if $_ eq "VMS";
230 if ($_ eq "zlib" || $_ eq "enable-zlib" || $_ eq "zlib-dynamic"
231 || $_ eq "enable-zlib-dynamic") {
235 $do_crypto=1 if $_ eq "libcrypto" || $_ eq "crypto";
236 $do_ssl=1 if $_ eq "libssl" || $_ eq "ssl";
238 $do_update=1 if $_ eq "update";
239 $do_rewrite=1 if $_ eq "rewrite";
240 $do_ctest=1 if $_ eq "ctest";
241 $do_ctestall=1 if $_ eq "ctestall";
242 $do_checkexist=1 if $_ eq "exist";
243 if (/^(enable|disable|no)-(.*)$/) {
246 if (exists $disabled_algorithms{$alg}) {
247 $disabled_algorithms{$alg} = $1 eq "enable" ? 0 : 1;
252 $libname = $unified_info{sharednames}->{libcrypto} if $do_crypto;
253 $libname = $unified_info{sharednames}->{libssl} if $do_ssl;
260 $libname="LIBCRYPTO";
264 # If no platform is given, assume WIN32
265 if ($W32 + $VMS + $linux == 0) {
268 die "Please, only one platform at a time"
269 if ($W32 + $VMS + $linux > 1);
271 if (!$do_ssl && !$do_crypto)
273 print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT | OS2 | linux | VMS ]\n";
277 %ssl_list=&load_numbers($ssl_num);
279 %crypto_list=&load_numbers($crypto_num);
280 $max_crypto = $max_num;
282 my $ssl="include/openssl/ssl.h";
283 $ssl.=" include/openssl/sslerr.h";
284 $ssl.=" include/openssl/tls1.h";
285 $ssl.=" include/openssl/srtp.h";
287 # When scanning include/openssl, skip all SSL files and some internal ones.
289 foreach my $f ( split(/\s+/, $ssl) ) {
292 $skipthese{'include/openssl/conf_api.h'} = 1;
293 $skipthese{'include/openssl/ebcdic.h'} = 1;
294 $skipthese{'include/openssl/opensslconf.h'} = 1;
296 # We use headers found in include/openssl and include/internal only.
297 # The latter is needed so libssl.so/.dll/.exe can link properly.
298 my $crypto ="include/internal/dso.h";
299 $crypto.=" include/internal/o_dir.h";
300 $crypto.=" include/internal/o_str.h";
301 $crypto.=" include/internal/err.h";
302 $crypto.=" include/internal/rand.h";
303 foreach my $f ( glob(catfile($config{sourcedir},'include/openssl/*.h')) ) {
304 my $fn = "include/openssl/" . lc(basename($f));
305 $crypto .= " $fn" if !defined $skipthese{$fn} && $f !~ m@/[a-z]+err\.h$@;
308 my $symhacks="include/openssl/symhacks.h";
310 my @ssl_symbols = &do_defs("LIBSSL", $ssl, $symhacks);
311 my @crypto_symbols = &do_defs("LIBCRYPTO", $crypto, $symhacks);
317 &maybe_add_info("LIBSSL",*ssl_list,@ssl_symbols);
318 if ($do_rewrite == 1) {
319 open(OUT, ">$ssl_num");
320 &rewrite_numbers(*OUT,"LIBSSL",*ssl_list,@ssl_symbols);
322 open(OUT, ">>$ssl_num");
324 &update_numbers(*OUT,"LIBSSL",*ssl_list,$max_ssl,@ssl_symbols);
328 if($do_crypto == 1) {
330 &maybe_add_info("LIBCRYPTO",*crypto_list,@crypto_symbols);
331 if ($do_rewrite == 1) {
332 open(OUT, ">$crypto_num");
333 &rewrite_numbers(*OUT,"LIBCRYPTO",*crypto_list,@crypto_symbols);
335 open(OUT, ">>$crypto_num");
337 &update_numbers(*OUT,"LIBCRYPTO",*crypto_list,$max_crypto,@crypto_symbols);
341 } elsif ($do_checkexist) {
342 &check_existing(*ssl_list, @ssl_symbols)
344 &check_existing(*crypto_list, @crypto_symbols)
346 } elsif ($do_ctest || $do_ctestall) {
350 /* Test file to check all DEF file symbols are present by trying
351 * to link to all of them. This is *not* intended to be run!
357 &print_test_file(*STDOUT,"LIBSSL",*ssl_list,$do_ctestall,@ssl_symbols)
360 &print_test_file(*STDOUT,"LIBCRYPTO",*crypto_list,$do_ctestall,@crypto_symbols)
367 &print_def_file(*STDOUT,$libname,*ssl_list,@ssl_symbols)
370 &print_def_file(*STDOUT,$libname,*crypto_list,@crypto_symbols)
378 my($name,$files,$symhacksfile)=@_;
382 my %platform; # For anything undefined, we assume ""
383 my %kind; # For anything undefined, we assume "FUNCTION"
384 my %algorithm; # For anything undefined, we assume ""
386 my %variant_cnt; # To be able to allocate "name{n}" if "name"
387 # is the same name as the original.
389 my %unknown_algorithms = ();
392 foreach $file (split(/\s+/,$symhacksfile." ".$files))
394 my $fn = catfile($config{sourcedir},$file);
395 print STDERR "DEBUG: starting on $fn:\n" if $debug;
396 print STDERR "TRACE: start reading $fn\n" if $trace;
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\s*\(([^\)]+)\)/) {
539 if (/^\#\s*if\s+(!defined\s*\(([^\)]+)\)(\s+\&\&\s+!defined\s*\(([^\)]+)\))*)$/) {
542 foreach $tmp_ (split '\&\&',$tmp_1) {
543 $tmp_ =~ /!defined\s*\(([^\)]+)\)/;
544 print STDERR "DEBUG: $file: found tag $1 = -1\n" if $debug;
549 print STDERR "Warning: $file: taking only '!defined($1)' of complicated expression: $_" if $verbose; # 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\s*\(([^\)]+)\)/) {
561 if (/^\#\s*if\s+(defined\s*\(([^\)]+)\)(\s+\|\|\s+defined\s*\(([^\)]+)\))*)$/) {
564 foreach $tmp_ (split '\|\|',$tmp_1) {
565 $tmp_ =~ /defined\s*\(([^\)]+)\)/;
566 print STDERR "DEBUG: $file: found tag $1 = 1\n" if $debug;
571 print STDERR "Warning: $file: taking only 'defined($1)' of complicated expression: $_\n" if $verbose; # 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 print STDERR "Warning: $file: ignoring unrecognized expression: $_\n" if $verbose; # because it is O...
637 } elsif (/^\#\s*define\s+(\w+)\s+(\w+)/
638 && $symhacking && $tag{'TRUE'} != -1) {
639 # This is for aliasing. When we find an alias,
641 &$make_variant($1,$2);
642 print STDERR "DEBUG: $file: defined $1 = $2\n" if $debug;
647 map { $tag{$_} == 1 ? $_ :
648 $tag{$_} == -1 ? "!".$_ : "" }
650 push @current_platforms
652 map { $tag{"OPENSSL_SYS_".$_} == 1 ? $_ :
653 $tag{"OPENSSL_SYS_".$_} == -1 ? "!".$_ : "" }
654 @known_ossl_platforms);
655 @current_algorithms = ();
656 @current_algorithms =
658 map { $tag{"OPENSSL_NO_".$_} == -1 ? $_ : "" }
660 push @current_algorithms
662 map { $tag{"OPENSSL_USE_".$_} == 1 ? $_ : "" }
664 push @current_algorithms,
665 grep { /^DEPRECATEDIN_/ && $tag{$_} == 1 }
669 .join(',',@current_platforms).":"
670 .join(',',@current_algorithms).";";
673 if ($tag{'TRUE'} != -1) {
674 if (/^\s*DEFINE_STACK_OF\s*\(\s*(\w*)\s*\)/
675 || /^\s*DEFINE_STACK_OF_CONST\s*\(\s*(\w*)\s*\)/) {
677 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
678 $def .= "int d2i_$3(void);";
679 $def .= "int i2d_$3(void);";
680 # Variant for platforms that do not
681 # have to access global variables
682 # in shared libraries through functions
685 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
686 .join(',',@current_algorithms).";";
687 $def .= "OPENSSL_EXTERN int $2_it;";
690 .join(',',@current_platforms).":"
691 .join(',',@current_algorithms).";";
692 # Variant for platforms that have to
693 # access global variables in shared
694 # libraries through functions
695 &$make_variant("$2_it","$2_it",
696 "EXPORT_VAR_AS_FUNCTION",
699 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_fname\s*\(\s*(\w*)\s*,\s*(\w*)\s*,\s*(\w*)\s*\)/) {
700 $def .= "int d2i_$3(void);";
701 $def .= "int i2d_$3(void);";
702 $def .= "int $3_free(void);";
703 $def .= "int $3_new(void);";
704 # Variant for platforms that do not
705 # have to access global variables
706 # in shared libraries through functions
709 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
710 .join(',',@current_algorithms).";";
711 $def .= "OPENSSL_EXTERN int $2_it;";
714 .join(',',@current_platforms).":"
715 .join(',',@current_algorithms).";";
716 # Variant for platforms that have to
717 # access global variables in shared
718 # libraries through functions
719 &$make_variant("$2_it","$2_it",
720 "EXPORT_VAR_AS_FUNCTION",
723 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS\s*\(\s*(\w*)\s*\)/ ||
724 /^\s*DECLARE_ASN1_FUNCTIONS_const\s*\(\s*(\w*)\s*\)/) {
725 $def .= "int d2i_$1(void);";
726 $def .= "int i2d_$1(void);";
727 $def .= "int $1_free(void);";
728 $def .= "int $1_new(void);";
729 # Variant for platforms that do not
730 # have to access global variables
731 # in shared libraries through functions
734 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
735 .join(',',@current_algorithms).";";
736 $def .= "OPENSSL_EXTERN int $1_it;";
739 .join(',',@current_platforms).":"
740 .join(',',@current_algorithms).";";
741 # Variant for platforms that have to
742 # access global variables in shared
743 # libraries through functions
744 &$make_variant("$1_it","$1_it",
745 "EXPORT_VAR_AS_FUNCTION",
748 } elsif (/^\s*DECLARE_ASN1_ENCODE_FUNCTIONS_const\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
749 $def .= "int d2i_$2(void);";
750 $def .= "int i2d_$2(void);";
751 # Variant for platforms that do not
752 # have to access global variables
753 # in shared libraries through functions
756 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
757 .join(',',@current_algorithms).";";
758 $def .= "OPENSSL_EXTERN int $2_it;";
761 .join(',',@current_platforms).":"
762 .join(',',@current_algorithms).";";
763 # Variant for platforms that have to
764 # access global variables in shared
765 # libraries through functions
766 &$make_variant("$2_it","$2_it",
767 "EXPORT_VAR_AS_FUNCTION",
770 } elsif (/^\s*DECLARE_ASN1_ALLOC_FUNCTIONS\s*\(\s*(\w*)\s*\)/) {
771 $def .= "int $1_free(void);";
772 $def .= "int $1_new(void);";
774 } elsif (/^\s*DECLARE_ASN1_FUNCTIONS_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
775 $def .= "int d2i_$2(void);";
776 $def .= "int i2d_$2(void);";
777 $def .= "int $2_free(void);";
778 $def .= "int $2_new(void);";
779 # Variant for platforms that do not
780 # have to access global variables
781 # in shared libraries through functions
784 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
785 .join(',',@current_algorithms).";";
786 $def .= "OPENSSL_EXTERN int $2_it;";
789 .join(',',@current_platforms).":"
790 .join(',',@current_algorithms).";";
791 # Variant for platforms that have to
792 # access global variables in shared
793 # libraries through functions
794 &$make_variant("$2_it","$2_it",
795 "EXPORT_VAR_AS_FUNCTION",
798 } elsif (/^\s*DECLARE_ASN1_ITEM\s*\(\s*(\w*)\s*\)/) {
799 # Variant for platforms that do not
800 # have to access global variables
801 # in shared libraries through functions
804 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
805 .join(',',@current_algorithms).";";
806 $def .= "OPENSSL_EXTERN int $1_it;";
809 .join(',',@current_platforms).":"
810 .join(',',@current_algorithms).";";
811 # Variant for platforms that have to
812 # access global variables in shared
813 # libraries through functions
814 &$make_variant("$1_it","$1_it",
815 "EXPORT_VAR_AS_FUNCTION",
818 } elsif (/^\s*DECLARE_ASN1_NDEF_FUNCTION\s*\(\s*(\w*)\s*\)/) {
819 $def .= "int i2d_$1_NDEF(void);";
820 } elsif (/^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) {
822 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION\s*\(\s*(\w*)\s*\)/) {
823 $def .= "int $1_print_ctx(void);";
825 } elsif (/^\s*DECLARE_ASN1_PRINT_FUNCTION_name\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
826 $def .= "int $2_print_ctx(void);";
828 } elsif (/^\s*DECLARE_PKCS12_STACK_OF\s*\(\s*(\w*)\s*\)/) {
830 } elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ ||
831 /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ ||
832 /^DECLARE_PEM_rw_const\s*\(\s*(\w*)\s*,/ ) {
835 .join(',',@current_platforms).":"
836 .join(',',"STDIO",@current_algorithms).";";
837 $def .= "int PEM_read_$1(void);";
838 $def .= "int PEM_write_$1(void);";
841 .join(',',@current_platforms).":"
842 .join(',',@current_algorithms).";";
843 # Things that are everywhere
844 $def .= "int PEM_read_bio_$1(void);";
845 $def .= "int PEM_write_bio_$1(void);";
847 } elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ ||
848 /^DECLARE_PEM_write_const\s*\(\s*(\w*)\s*,/ ||
849 /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) {
852 .join(',',@current_platforms).":"
853 .join(',',"STDIO",@current_algorithms).";";
854 $def .= "int PEM_write_$1(void);";
857 .join(',',@current_platforms).":"
858 .join(',',@current_algorithms).";";
859 # Things that are everywhere
860 $def .= "int PEM_write_bio_$1(void);";
862 } elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ ||
863 /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) {
866 .join(',',@current_platforms).":"
867 .join(',',"STDIO",@current_algorithms).";";
868 $def .= "int PEM_read_$1(void);";
871 .join(',',@current_platforms).":"
872 .join(',',"STDIO",@current_algorithms).";";
873 # Things that are everywhere
874 $def .= "int PEM_read_bio_$1(void);";
876 } elsif (/^OPENSSL_DECLARE_GLOBAL\s*\(\s*(\w*)\s*,\s*(\w*)\s*\)/) {
877 # Variant for platforms that do not
878 # have to access global variables
879 # in shared libraries through functions
882 .join(',',"!EXPORT_VAR_AS_FUNCTION",@current_platforms).":"
883 .join(',',@current_algorithms).";";
884 $def .= "OPENSSL_EXTERN int _shadow_$2;";
887 .join(',',@current_platforms).":"
888 .join(',',@current_algorithms).";";
889 # Variant for platforms that have to
890 # access global variables in shared
891 # libraries through functions
892 &$make_variant("_shadow_$2","_shadow_$2",
893 "EXPORT_VAR_AS_FUNCTION",
895 } elsif (/^\s*DEPRECATEDIN/) {
896 $parens = count_parens($_);
898 $def .= do_deprecated($_,
900 \@current_algorithms);
902 $stored_multiline = $_;
903 print STDERR "DEBUG: Found multiline DEPRECATEDIN starting with: $stored_multiline\n" if $debug;
906 } elsif ($tag{'CONST_STRICT'} != 1) {
907 if (/\{|\/\*|\([^\)]*$/) {
916 die "$file: Unmatched tags\n" if $#tag >= 0;
921 print STDERR "DEBUG: postprocessing ----------\n" if $debug;
922 foreach (split /;/, $def) {
923 my $s; my $k = "FUNCTION"; my $p; my $a;
927 next if(/typedef\W/);
930 print STDERR "TRACE: processing $_\n" if $trace && !/^\#INFO:/;
931 # Reduce argument lists to empty ()
932 # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
933 my $nsubst = 1; # prevent infinite loop, e.g., on int fn()
934 while($nsubst && /\(.*\)/s) {
935 $nsubst = s/\([^\(\)]+\)/\{\}/gs;
936 $nsubst+= s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f
938 # pretend as we didn't use curly braces: {} -> ()
941 s/STACK_OF\(\)/void/gs;
942 s/LHASH_OF\(\)/void/gs;
944 print STDERR "DEBUG: \$_ = \"$_\"\n" if $debug;
945 if (/^\#INFO:([^:]*):(.*)$/) {
948 print STDERR "DEBUG: found info on platforms ($plats) and algorithms ($algs)\n" if $debug;
950 } elsif (/^\s*OPENSSL_EXTERN\s.*?(\w+(\{[0-9]+\})?)(\[[0-9]*\])*\s*$/) {
953 print STDERR "DEBUG: found external variable $s\n" if $debug;
954 } elsif (/TYPEDEF_\w+_OF/s) {
956 } elsif (/(\w+)\s*\(\).*/s) { # first token prior [first] () is
957 $s = $1; # a function name!
958 print STDERR "DEBUG: found function $s\n" if $debug;
959 } elsif (/\(/ and not (/=/)) {
960 print STDERR "File $file: cannot parse: $_;\n";
973 &reduce_platforms((defined($platform{$s})?$platform{$s}.',':"").$p);
974 $algorithm{$s} .= ','.$a;
976 if (defined($variant{$s})) {
977 foreach $v (split /;/,$variant{$s}) {
978 (my $r, my $p, my $k) = split(/:/,$v);
979 my $ip = join ',',map({ /^!(.*)$/ ? $1 : "!".$_ } split /,/, $p);
981 if (!defined($k)) { $k = $kind{$s}; }
982 $kind{$r} = $k."(".$s.")";
983 $algorithm{$r} = $algorithm{$s};
984 $platform{$r} = &reduce_platforms($platform{$s}.",".$p.",".$p);
985 $platform{$s} = &reduce_platforms($platform{$s}.','.$ip.','.$ip);
986 print STDERR "DEBUG: \$variant{\"$s\"} = ",$v,"; \$r = $r; \$p = ",$platform{$r},"; \$a = ",$algorithm{$r},"; \$kind = ",$kind{$r},"\n" if $debug;
989 print STDERR "DEBUG: \$s = $s; \$p = ",$platform{$s},"; \$a = ",$algorithm{$s},"; \$kind = ",$kind{$s},"\n" if $debug;
993 # Prune the returned symbols
995 delete $syms{"bn_dump1"};
996 $platform{"BIO_s_log"} .= ",!WIN32,!macintosh";
998 $platform{"PEM_read_NS_CERT_SEQ"} = "VMS";
999 $platform{"PEM_write_NS_CERT_SEQ"} = "VMS";
1000 $platform{"PEM_read_P8_PRIV_KEY_INFO"} = "VMS";
1001 $platform{"PEM_write_P8_PRIV_KEY_INFO"} = "VMS";
1003 # Info we know about
1005 push @ret, map { $_."\\".&info_string($_,"EXIST",
1008 $algorithm{$_}) } keys %syms;
1010 if (keys %unknown_algorithms) {
1011 print STDERR "WARNING: mkdef.pl doesn't know the following algorithms:\n";
1012 print STDERR "\t",join("\n\t",keys %unknown_algorithms),"\n";
1017 # Param: string of comma-separated platform-specs.
1018 sub reduce_platforms
1020 my ($platforms) = @_;
1021 my $pl = defined($platforms) ? $platforms : "";
1022 my %p = map { $_ => 0 } split /,/, $pl;
1025 print STDERR "DEBUG: Entered reduce_platforms with \"$platforms\"\n"
1027 # We do this, because if there's code like the following, it really
1028 # means the function exists in all cases and should therefore be
1029 # everywhere. By increasing and decreasing, we may attain 0:
1036 foreach $platform (split /,/, $pl) {
1037 if ($platform =~ /^!(.*)$/) {
1043 foreach $platform (keys %p) {
1044 if ($p{$platform} == 0) { delete $p{$platform}; }
1049 $ret = join(',',sort(map { $p{$_} < 0 ? "!".$_ : $_ } keys %p));
1050 print STDERR "DEBUG: Exiting reduce_platforms with \"$ret\"\n"
1057 (my $symbol, my $exist, my $platforms, my $kind, my $algorithms) = @_;
1059 my %a = defined($algorithms) ?
1060 map { $_ => 1 } split /,/, $algorithms : ();
1061 my $k = defined($kind) ? $kind : "FUNCTION";
1063 my $p = &reduce_platforms($platforms);
1070 $ret .= ":".join(',',sort keys %a);
1076 (my $name, *nums, my @symbols) = @_;
1081 foreach $sym (@symbols) {
1082 (my $s, my $i) = split /\\/, $sym;
1083 if (defined($nums{$s})) {
1084 $i =~ s/^(.*?:.*?:\w+)(\(\w+\))?/$1/;
1085 (my $n, my $vers, my $dummy) = split /\\/, $nums{$s};
1086 if (!defined($dummy) || $i ne $dummy) {
1087 $nums{$s} = $n."\\".$vers."\\".$i;
1089 print STDERR "DEBUG: maybe_add_info for $s: \"$dummy\" => \"$i\"\n" if $debug;
1095 my @s=sort { &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n") } keys %nums;
1097 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1098 if (!defined($syms{$sym}) && $i !~ /^NOEXIST:/) {
1100 print STDERR "DEBUG: maybe_add_info for $sym: -> undefined\n" if $debug;
1104 print STDERR "$name: $new_info old symbols have updated info\n";
1106 print STDERR "You should do a rewrite to fix this.\n";
1112 # Param: string of comma-separated keywords, each possibly prefixed with a "!"
1115 my ($keywords_txt,$platforms) = @_;
1116 my (@keywords) = split /,/,$keywords_txt;
1117 my ($falsesum, $truesum) = (0, 1);
1119 # Param: one keyword
1122 my ($keyword,$platforms) = @_;
1126 if ($keyword eq "UNIX" && $UNIX) { return 1; }
1127 if ($keyword eq "VMS" && $VMS) { return 1; }
1128 if ($keyword eq "WIN32" && $W32) { return 1; }
1129 if ($keyword eq "_WIN32" && $W32) { return 1; }
1130 if ($keyword eq "WINNT" && $NT) { return 1; }
1131 # Special platforms:
1132 # EXPORT_VAR_AS_FUNCTION means that global variables
1133 # will be represented as functions.
1134 if ($keyword eq "EXPORT_VAR_AS_FUNCTION" && $W32) {
1137 if ($keyword eq "ZLIB" && $zlib) { return 1; }
1141 if ($disabled_algorithms{$keyword} == 1) { return 0;}
1143 # Nothing recognise as true
1148 foreach $k (@keywords) {
1149 if ($k =~ /^!(.*)$/) {
1150 $falsesum += &recognise($1,$platforms);
1152 $truesum *= &recognise($k,$platforms);
1155 print STDERR "DEBUG: [",$#keywords,",",$#keywords < 0,"] is_valid($keywords_txt) => (\!$falsesum) && $truesum = ",(!$falsesum) && $truesum,"\n" if $debug;
1156 return (!$falsesum) && $truesum;
1161 (*OUT,my $name,*nums,my $testall,my @symbols)=@_;
1162 my $n = 1; my @e; my @r;
1163 my $sym; my $prev = ""; my $prefSSLeay;
1165 (@e)=grep(/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1166 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:.*/ && !/^SSLeay(\{[0-9]+\})?\\.*?:.*?:.*/,@symbols);
1167 @symbols=((sort @e),(sort @r));
1169 foreach $sym (@symbols) {
1170 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1172 $v = 1 if $i=~ /^.*?:.*?:VARIABLE/;
1173 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1174 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1175 if (!defined($nums{$s})) {
1176 print STDERR "Warning: $s does not have a number assigned\n"
1178 } elsif (is_valid($p,1) && is_valid($a,0)) {
1179 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1181 print OUT "\t/* The following has already appeared previously */\n";
1182 print STDERR "Warning: Symbol '",$s2,"' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1184 $prev = $s2; # To warn about duplicates...
1186 (my $nn, my $vers, my $ni) = split /\\/, $nums{$s2};
1188 print OUT "\textern int $s2; /* type unknown */ /* $nn $ni */\n";
1190 print OUT "\textern int $s2(); /* type unknown */ /* $nn $ni */\n";
1198 return $config{version};
1203 (*OUT,my $name,*nums,my @symbols)=@_;
1204 my $n = 1; my @e; my @r; my @v; my $prev="";
1206 my $libname = $name;
1207 my $http_vendor = 'www.openssl.org/';
1208 my $version = get_version();
1209 my $what = "OpenSSL: implementation of Secure Socket Layer";
1210 my $description = "$what $version, $name - http://$http_vendor";
1211 my $prevsymversion = "", $prevprevsymversion = "";
1214 my $symvtextcount = 0;
1220 ; Definition file for the DLL version of the $name library from OpenSSL
1223 LIBRARY $libname $liboptions
1232 IDENTIFICATION=$version
1236 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1239 (@r)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:FUNCTION/,@symbols);
1240 (@v)=grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:VARIABLE/,@symbols);
1242 # VMS needs to have the symbols on slot number order
1243 @symbols=(map { $_->[1] }
1244 sort { $a->[0] <=> $b->[0] }
1245 map { (my $s, my $i) = $_ =~ /^(.*?)\\(.*)$/;
1246 die "Error: $s doesn't have a number assigned\n"
1247 if !defined($nums{$s});
1248 (my $n, my @rest) = split /\\/, $nums{$s};
1249 [ $n, $_ ] } (@e, @r, @v));
1251 @symbols=((sort @e),(sort @r), (sort @v));
1254 my ($baseversion, $currversion) = get_openssl_version();
1257 if (!defined($thisversion)) {
1258 $thisversion = $baseversion;
1260 $thisversion = get_next_version($thisversion);
1262 foreach $sym (@symbols) {
1263 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1265 $v = 1 if $i =~ /^.*?:.*?:VARIABLE/;
1266 if (!defined($nums{$s})) {
1267 die "Error: $s does not have a number assigned\n"
1270 (my $n, my $symversion, my $dummy) = split /\\/, $nums{$s};
1272 my $p = ($i =~ /^[^:]*:([^:]*):/,$1);
1273 my $a = ($i =~ /^[^:]*:[^:]*:[^:]*:([^:]*)/,$1);
1274 if (is_valid($p,1) && is_valid($a,0)) {
1275 my $s2 = ($s =~ /^(.*?)(\{[0-9]+\})?$/, $1);
1277 print STDERR "Warning: Symbol '",$s2,
1278 "' redefined. old=",($nums{$prev} =~ /^(.*?)\\/,$1),
1279 ", new=",($nums{$s2} =~ /^(.*?)\\/,$1),"\n";
1281 $prev = $s2; # To warn about duplicates...
1283 next if $symversion ne $thisversion;
1284 if ($symversion ne $prevsymversion) {
1285 if ($prevsymversion ne "") {
1286 if ($prevprevsymversion ne "") {
1287 print OUT "} OPENSSL${SO_VARIANT}_"
1288 ."$prevprevsymversion;\n\n";
1293 print OUT "OPENSSL${SO_VARIANT}_$symversion {\n global:\n";
1294 $prevprevsymversion = $prevsymversion;
1295 $prevsymversion = $symversion;
1297 print OUT " $s2;\n";
1299 while(++$prevnum < $n) {
1300 my $symline=" ,SPARE -\n ,SPARE -\n";
1301 if ($symvtextcount + length($symline) - 2 > 1024) {
1302 print OUT ")\nSYMBOL_VECTOR=(-\n";
1303 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1305 if ($symvtextcount == 16) {
1306 # Take away first comma
1310 $symvtextcount += length($symline) - 2;
1312 (my $s_uc = $s) =~ tr/a-z/A-Z/;
1314 $v ? "DATA" : "PROCEDURE";
1317 ? " ,$s_uc/$s=$symtype -\n ,$s=$symtype -\n"
1318 : " ,$s=$symtype -\n ,SPARE -\n");
1319 if ($symvtextcount + length($symline) - 2 > 1024) {
1320 print OUT ")\nSYMBOL_VECTOR=(-\n";
1321 $symvtextcount = 16; # length of "SYMBOL_VECTOR=(-"
1323 if ($symvtextcount == 16) {
1324 # Take away first comma
1328 $symvtextcount += length($symline) - 2;
1330 printf OUT " %s%-39s DATA\n",
1333 printf OUT " %s%s\n",
1339 } while ($linux && $thisversion ne $currversion);
1341 if ($prevprevsymversion ne "") {
1342 print OUT " local: *;\n} OPENSSL${SO_VARIANT}_$prevprevsymversion;\n\n";
1344 print OUT " local: *;\n};\n\n";
1348 (my $libvmaj, my $libvmin, my $libvedit) =
1349 $currversion =~ /^(\d+)_(\d+)_(\d+)$/;
1350 # The reason to multiply the edit number with 100 is to make space
1351 # for the possibility that we want to encode the patch letters
1352 print OUT "GSMATCH=LEQUAL,",($libvmaj * 100 + $libvmin),",",($libvedit * 100),"\n";
1368 my ($baseversion, $currversion) = get_openssl_version();
1370 open(IN,"<$name") || die "unable to open $name:$!\n";
1372 s|\R$||; # Better chomp
1376 if (defined $ret{$a[0]}) {
1377 # This is actually perfectly OK
1378 #print STDERR "Warning: Symbol '",$a[0],"' redefined. old=",$ret{$a[0]},", new=",$a[1],"\n";
1380 if ($max_num > $a[1]) {
1381 print STDERR "Warning: Number decreased from ",$max_num," to ",$a[1],"\n";
1383 elsif ($max_num == $a[1]) {
1384 # This is actually perfectly OK
1385 #print STDERR "Warning: Symbol ",$a[0]," has same number as previous ",$prev,": ",$a[1],"\n";
1386 if ($a[0] eq $prev) {
1388 $a[0] .= "{$prev_cnt}";
1395 # Existence will be proven later, in do_defs
1399 #Sanity check the version number
1400 if (defined $prevversion) {
1401 check_version_lte($prevversion, $a[2]);
1403 check_version_lte($a[2], $currversion);
1404 $prevversion = $a[2];
1405 $ret{$a[0]}=$a[1]."\\".$a[2]."\\".$a[3]; # \\ is a special marker
1407 $max_num = $a[1] if $a[1] > $max_num;
1411 print STDERR "Warning: $num_noinfo symbols were without info." if $verbose || !$do_rewrite;
1413 printf STDERR " The rewrite will fix this.\n" if $verbose;
1415 printf STDERR " You should do a rewrite to fix this.\n";
1424 (my $str, my $what) = @_;
1425 (my $n, my $v, my $i) = split(/\\/,$str);
1435 (*OUT,$name,*nums,@symbols)=@_;
1438 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1439 my $r; my %r; my %rsyms;
1441 (my $s, my $i) = split /\\/, $r;
1442 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1443 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1444 $r{$a} = $s."\\".$i;
1449 foreach $_ (@symbols) {
1450 (my $n, my $i) = split /\\/;
1455 &parse_number($nums{$a},"n") <=> &parse_number($nums{$b},"n")
1459 (my $n, my $vers, my $i) = split /\\/, $nums{$sym};
1460 next if defined($i) && $i =~ /^.*?:.*?:\w+\(\w+\)/;
1461 next if defined($rsyms{$sym});
1462 print STDERR "DEBUG: rewrite_numbers for sym = ",$sym,": i = ",$i,", n = ",$n,", rsym{sym} = ",$rsyms{$sym},"syms{sym} = ",$syms{$sym},"\n" if $debug;
1463 $i="NOEXIST::FUNCTION:"
1464 if !defined($i) || $i eq "" || !defined($syms{$sym});
1466 $s2 =~ s/\{[0-9]+\}$//;
1467 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1468 if (exists $r{$sym}) {
1469 (my $s, $i) = split /\\/,$r{$sym};
1471 $s2 =~ s/\{[0-9]+\}$//;
1472 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2,$n,$vers,$i;
1479 (*OUT,$name,*nums,my $start_num, my @symbols)=@_;
1484 ($basevers, $vers) = get_openssl_version();
1486 my @r = grep(/^\w+(\{[0-9]+\})?\\.*?:.*?:\w+\(\w+\)/,@symbols);
1487 my $r; my %r; my %rsyms;
1489 (my $s, my $i) = split /\\/, $r;
1490 my $a = $1 if $i =~ /^.*?:.*?:\w+\((\w+)\)/;
1491 $i =~ s/^(.*?:.*?:\w+)\(\w+\)/$1/;
1492 $r{$a} = $s."\\".$i;
1496 foreach $sym (@symbols) {
1497 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1498 next if $i =~ /^.*?:.*?:\w+\(\w+\)/;
1499 next if defined($rsyms{$sym});
1500 die "ERROR: Symbol $sym had no info attached to it."
1502 if (!exists $nums{$s}) {
1505 $s2 =~ s/\{[0-9]+\}$//;
1506 printf OUT "%s%-39s %d\t%s\t%s\n","",$s2, ++$start_num,$vers,$i;
1507 if (exists $r{$s}) {
1508 ($s, $i) = split /\\/,$r{$s};
1509 $s =~ s/\{[0-9]+\}$//;
1510 printf OUT "%s%-39s %d\t%s\t%s\n","",$s, $start_num,$vers,$i;
1515 print STDERR "$name: Added $new_syms new symbols\n";
1517 print STDERR "$name: No new symbols added\n";
1523 (*nums, my @symbols)=@_;
1524 my %existing; my @remaining;
1526 foreach $sym (@symbols) {
1527 (my $s, my $i) = $sym =~ /^(.*?)\\(.*)$/;
1530 foreach $sym (keys %nums) {
1531 if (!exists $existing{$sym}) {
1532 push @remaining, $sym;
1536 print STDERR "The following symbols do not seem to exist:\n";
1537 foreach $sym (@remaining) {
1538 print STDERR "\t",$sym,"\n";
1545 my $line = shift(@_);
1547 my $open = $line =~ tr/\(//;
1548 my $close = $line =~ tr/\)//;
1550 return $open - $close;
1553 #Parse opensslv.h to get the current version number. Also work out the base
1554 #version, i.e. the lowest version number that is binary compatible with this
1556 sub get_openssl_version()
1558 my $fn = catfile($config{sourcedir},"include","openssl","opensslv.h");
1559 open (IN, "$fn") || die "Can't open opensslv.h";
1562 if (/OPENSSL_VERSION_TEXT\s+"OpenSSL (\d\.\d\.)(\d[a-z]*)(-| )/) {
1564 (my $baseversion = $1) =~ s/\./_/g;
1566 return ($baseversion."0", $baseversion.$suffix);
1569 die "Can't find OpenSSL version number\n";
1572 #Given an OpenSSL version number, calculate the next version number. If the
1573 #version number gets to a.b.czz then we go to a.b.(c+1)
1574 sub get_next_version()
1576 my $thisversion = shift;
1578 my ($base, $letter) = $thisversion =~ /^(\d_\d_\d)([a-z]{0,2})$/;
1580 if ($letter eq "zz") {
1581 my $lastnum = substr($base, -1);
1582 return substr($base, 0, length($base)-1).(++$lastnum);
1584 return $base.get_next_letter($letter);
1587 #Given the letters off the end of an OpenSSL version string, calculate what
1588 #the letters for the next release would be.
1589 sub get_next_letter()
1591 my $thisletter = shift;
1592 my $baseletter = "";
1595 if ($thisletter eq "") {
1598 if ((length $thisletter) > 1) {
1599 ($baseletter, $endletter) = $thisletter =~ /([a-z]+)([a-z])/;
1601 $endletter = $thisletter;
1604 if ($endletter eq "z") {
1605 return $thisletter."a";
1607 return $baseletter.(++$endletter);
1611 #Check if a version is less than or equal to the current version. Its a fatal
1612 #error if not. They must also only differ in letters, or the last number (i.e.
1613 #the first two numbers must be the same)
1614 sub check_version_lte()
1616 my ($testversion, $currversion) = @_;
1621 my ($cvnums) = $currversion =~ /^(\d_\d_\d)[a-z]*$/;
1622 my ($tvnums) = $testversion =~ /^(\d_\d_\d)[a-z]*$/;
1624 #Die if we can't parse the version numbers or they don't look sane
1625 die "Invalid version number: $testversion and $currversion\n"
1626 if (!defined($cvnums) || !defined($tvnums)
1627 || length($cvnums) != 5
1628 || length($tvnums) != 5);
1630 #If the base versions (without letters) don't match check they only differ
1632 if ($cvnums ne $tvnums) {
1633 die "Invalid version number: $testversion "
1634 ."for current version $currversion\n"
1635 if (substr($cvnums, 0, 4) ne substr($tvnums, 0, 4));
1638 #If we get here then the base version (i.e. the numbers) are the same - they
1639 #only differ in the letters
1641 $lentv = length $testversion;
1642 $lencv = length $currversion;
1644 #If the testversion has more letters than the current version then it must
1645 #be later (or malformed)
1646 if ($lentv > $lencv) {
1647 die "Invalid version number: $testversion "
1648 ."is greater than $currversion\n";
1651 #Get the last letter from the current version
1652 my ($cvletter) = $currversion =~ /([a-z])$/;
1653 if (defined $cvletter) {
1654 ($cvbase) = $currversion =~ /(\d_\d_\d[a-z]*)$cvletter$/;
1656 $cvbase = $currversion;
1658 die "Unable to parse version number $currversion" if (!defined $cvbase);
1660 my ($tvletter) = $testversion =~ /([a-z])$/;
1661 if (defined $tvletter) {
1662 ($tvbase) = $testversion =~ /(\d_\d_\d[a-z]*)$tvletter$/;
1664 $tvbase = $testversion;
1666 die "Unable to parse version number $testversion" if (!defined $tvbase);
1668 if ($lencv > $lentv) {
1669 #If current version has more letters than testversion then testversion
1670 #minus the final letter must be a substring of the current version
1671 die "Invalid version number $testversion "
1672 ."is greater than $currversion or is invalid\n"
1673 if (index($cvbase, $tvbase) != 0);
1675 #If both versions have the same number of letters then they must be
1676 #equal up to the last letter, and the last letter in testversion must
1677 #be less than or equal to the last letter in current version.
1678 die "Invalid version number $testversion "
1679 ."is greater than $currversion\n"
1680 if (($cvbase ne $tvbase) && ($tvletter gt $cvletter));
1686 my ($decl, $plats, $algs) = @_;
1687 $decl =~ /^\s*(DEPRECATEDIN_\d+_\d+_\d+)\s*\((.*)\)\s*$/
1688 or die "Bad DEPRECATEDIN: $decl\n";
1689 my $info1 .= "#INFO:";
1690 $info1 .= join(',', @{$plats}) . ":";
1692 $info1 .= join(',',@{$algs}, $1) . ";";
1693 $info2 .= join(',',@{$algs}) . ";";
1694 return $info1 . $2 . ";" . $info2;