1#!/usr/local/bin/perl -w 2# 3# generate a .def file 4# 5# It does this by parsing the header files and looking for the 6# prototyped functions: it then prunes the output. 7# 8 9my $crypto_num="util/libeay.num"; 10my $ssl_num= "util/ssleay.num"; 11 12my $do_update = 0; 13my $do_crypto = 0; 14my $do_ssl = 0; 15my $do_ctest = 0; 16my $rsaref = 0; 17 18my $W32=1; 19my $NT=0; 20# Set this to make typesafe STACK definitions appear in DEF 21my $safe_stack_def = 1; 22 23my $options=""; 24open(IN,"<Makefile.ssl") || die "unable to open Makefile.ssl!\n"; 25while(<IN>) { 26 $options=$1 if (/^OPTIONS=(.*)$/); 27} 28close(IN); 29 30# The following ciphers may be excluded (by Configure). This means functions 31# defined with ifndef(NO_XXX) are not included in the .def file, and everything 32# in directory xxx is ignored. 33my $no_rc2; my $no_rc4; my $no_rc5; my $no_idea; my $no_des; my $no_bf; 34my $no_cast; my $no_md2; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2; 35my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; 36 37foreach (@ARGV, split(/ /, $options)) 38 { 39 $W32=1 if $_ eq "32"; 40 $W32=0 if $_ eq "16"; 41 if($_ eq "NT") { 42 $W32 = 1; 43 $NT = 1; 44 } 45 $do_ssl=1 if $_ eq "ssleay"; 46 $do_ssl=1 if $_ eq "ssl"; 47 $do_crypto=1 if $_ eq "libeay"; 48 $do_crypto=1 if $_ eq "crypto"; 49 $do_update=1 if $_ eq "update"; 50 $do_ctest=1 if $_ eq "ctest"; 51 $rsaref=1 if $_ eq "rsaref"; 52 53 if (/^no-rc2$/) { $no_rc2=1; } 54 elsif (/^no-rc4$/) { $no_rc4=1; } 55 elsif (/^no-rc5$/) { $no_rc5=1; } 56 elsif (/^no-idea$/) { $no_idea=1; } 57 elsif (/^no-des$/) { $no_des=1; } 58 elsif (/^no-bf$/) { $no_bf=1; } 59 elsif (/^no-cast$/) { $no_cast=1; } 60 elsif (/^no-md2$/) { $no_md2=1; } 61 elsif (/^no-md5$/) { $no_md5=1; } 62 elsif (/^no-sha$/) { $no_sha=1; } 63 elsif (/^no-ripemd$/) { $no_ripemd=1; } 64 elsif (/^no-mdc2$/) { $no_mdc2=1; } 65 elsif (/^no-rsa$/) { $no_rsa=1; } 66 elsif (/^no-dsa$/) { $no_dsa=1; } 67 elsif (/^no-dh$/) { $no_dh=1; } 68 elsif (/^no-hmac$/) { $no_hmac=1; } 69 } 70 71 72if (!$do_ssl && !$do_crypto) 73 { 74 print STDERR "usage: $0 ( ssl | crypto ) [ 16 | 32 | NT ] [rsaref]\n"; 75 exit(1); 76 } 77 78%ssl_list=&load_numbers($ssl_num); 79$max_ssl = $max_num; 80%crypto_list=&load_numbers($crypto_num); 81$max_crypto = $max_num; 82 83my $ssl="ssl/ssl.h"; 84 85my $crypto ="crypto/crypto.h"; 86$crypto.=" crypto/des/des.h" unless $no_des; 87$crypto.=" crypto/idea/idea.h" unless $no_idea; 88$crypto.=" crypto/rc4/rc4.h" unless $no_rc4; 89$crypto.=" crypto/rc5/rc5.h" unless $no_rc5; 90$crypto.=" crypto/rc2/rc2.h" unless $no_rc2; 91$crypto.=" crypto/bf/blowfish.h" unless $no_bf; 92$crypto.=" crypto/cast/cast.h" unless $no_cast; 93$crypto.=" crypto/md2/md2.h" unless $no_md2; 94$crypto.=" crypto/md5/md5.h" unless $no_md5; 95$crypto.=" crypto/mdc2/mdc2.h" unless $no_mdc2; 96$crypto.=" crypto/sha/sha.h" unless $no_sha; 97$crypto.=" crypto/ripemd/ripemd.h" unless $no_ripemd; 98 99$crypto.=" crypto/bn/bn.h"; 100$crypto.=" crypto/rsa/rsa.h" unless $no_rsa; 101$crypto.=" crypto/dsa/dsa.h" unless $no_dsa; 102$crypto.=" crypto/dh/dh.h" unless $no_dh; 103$crypto.=" crypto/hmac/hmac.h" unless $no_hmac; 104 105$crypto.=" crypto/stack/stack.h"; 106$crypto.=" crypto/buffer/buffer.h"; 107$crypto.=" crypto/bio/bio.h"; 108$crypto.=" crypto/lhash/lhash.h"; 109$crypto.=" crypto/conf/conf.h"; 110$crypto.=" crypto/txt_db/txt_db.h"; 111 112$crypto.=" crypto/evp/evp.h"; 113$crypto.=" crypto/objects/objects.h"; 114$crypto.=" crypto/pem/pem.h"; 115#$crypto.=" crypto/meth/meth.h"; 116$crypto.=" crypto/asn1/asn1.h"; 117$crypto.=" crypto/asn1/asn1_mac.h"; 118$crypto.=" crypto/err/err.h"; 119$crypto.=" crypto/pkcs7/pkcs7.h"; 120$crypto.=" crypto/pkcs12/pkcs12.h"; 121$crypto.=" crypto/x509/x509.h"; 122$crypto.=" crypto/x509/x509_vfy.h"; 123$crypto.=" crypto/x509v3/x509v3.h"; 124$crypto.=" crypto/rand/rand.h"; 125$crypto.=" crypto/comp/comp.h"; 126$crypto.=" crypto/tmdiff.h"; 127 128my @ssl_func = &do_defs("SSLEAY", $ssl); 129my @crypto_func = &do_defs("LIBEAY", $crypto); 130 131 132if ($do_update) { 133 134if ($do_ssl == 1) { 135 open(OUT, ">>$ssl_num"); 136 &update_numbers(*OUT,"SSLEAY",*ssl_list,$max_ssl, @ssl_func); 137 close OUT; 138} 139 140if($do_crypto == 1) { 141 open(OUT, ">>$crypto_num"); 142 &update_numbers(*OUT,"LIBEAY",*crypto_list,$max_crypto, @crypto_func); 143 close OUT; 144} 145 146} elsif ($do_ctest) { 147 148 print <<"EOF"; 149 150/* Test file to check all DEF file symbols are present by trying 151 * to link to all of them. This is *not* intended to be run! 152 */ 153 154int main() 155{ 156EOF 157 &print_test_file(*STDOUT,"SSLEAY",*ssl_list,@ssl_func) 158 if $do_ssl == 1; 159 160 &print_test_file(*STDOUT,"LIBEAY",*crypto_list,@crypto_func) 161 if $do_crypto == 1; 162 163 print "}\n"; 164 165} else { 166 167 &print_def_file(*STDOUT,"SSLEAY",*ssl_list,@ssl_func) 168 if $do_ssl == 1; 169 170 &print_def_file(*STDOUT,"LIBEAY",*crypto_list,@crypto_func) 171 if $do_crypto == 1; 172 173} 174 175 176sub do_defs 177{ 178 my($name,$files)=@_; 179 my $file; 180 my @ret; 181 my %funcs; 182 my $cpp; 183 184 foreach $file (split(/\s+/,$files)) 185 { 186 open(IN,"<$file") || die "unable to open $file:$!\n"; 187 my $line = "", my $def= ""; 188 my %tag = ( 189 FreeBSD => 0, 190 NOPROTO => 0, 191 WIN16 => 0, 192 PERL5 => 0, 193 _WINDLL => 0, 194 NO_FP_API => 0, 195 CONST_STRICT => 0, 196 TRUE => 1, 197 NO_RC2 => 0, 198 NO_RC4 => 0, 199 NO_RC5 => 0, 200 NO_IDEA => 0, 201 NO_DES => 0, 202 NO_BF => 0, 203 NO_CAST => 0, 204 NO_MD2 => 0, 205 NO_MD5 => 0, 206 NO_SHA => 0, 207 NO_RIPEMD => 0, 208 NO_MDC2 => 0, 209 NO_RSA => 0, 210 NO_DSA => 0, 211 NO_DH => 0, 212 NO_HMAC => 0, 213 ); 214 while(<IN>) { 215 last if (/BEGIN ERROR CODES/); 216 if ($line ne '') { 217 $_ = $line . $_; 218 $line = ''; 219 } 220 221 if (/\\$/) { 222 $line = $_; 223 next; 224 } 225 226 $cpp = 1 if /^#.*ifdef.*cplusplus/; 227 if ($cpp) { 228 $cpp = 0 if /^#.*endif/; 229 next; 230 } 231 232 s/\/\*.*?\*\///gs; # ignore comments 233 s/{[^{}]*}//gs; # ignore {} blocks 234 if (/^\#\s*ifndef (.*)/) { 235 push(@tag,$1); 236 $tag{$1}=-1; 237 next; 238 } elsif (/^\#\s*if !defined\(([^\)]+)\)/) { 239 push(@tag,$1); 240 $tag{$1}=-1; 241 next; 242 } elsif (/^\#\s*ifdef (.*)/) { 243 push(@tag,$1); 244 $tag{$1}=1; 245 next; 246 } elsif (/^\#\s*if defined(.*)/) { 247 push(@tag,$1); 248 $tag{$1}=1; 249 next; 250 } elsif (/^\#\s*endif/) { 251 $tag{$tag[$#tag]}=0; 252 pop(@tag); 253 next; 254 } elsif (/^\#\s*else/) { 255 my $t=$tag[$#tag]; 256 $tag{$t}= -$tag{$t}; 257 next; 258 } elsif (/^\#\s*if\s+1/) { 259 # Dummy tag 260 push(@tag,"TRUE"); 261 $tag{"TRUE"}=1; 262 next; 263 } elsif (/^\#\s*if\s+0/) { 264 # Dummy tag 265 push(@tag,"TRUE"); 266 $tag{"TRUE"}=-1; 267 next; 268 } elsif (/^\#/) { 269 next; 270 } 271 if ($safe_stack_def && 272 /^\s*DECLARE_STACK_OF\s*\(\s*(\w*)\s*\)/) { 273 $funcs{"sk_${1}_new"} = 1; 274 $funcs{"sk_${1}_new_null"} = 1; 275 $funcs{"sk_${1}_free"} = 1; 276 $funcs{"sk_${1}_num"} = 1; 277 $funcs{"sk_${1}_value"} = 1; 278 $funcs{"sk_${1}_set"} = 1; 279 $funcs{"sk_${1}_zero"} = 1; 280 $funcs{"sk_${1}_push"} = 1; 281 $funcs{"sk_${1}_unshift"} = 1; 282 $funcs{"sk_${1}_find"} = 1; 283 $funcs{"sk_${1}_delete"} = 1; 284 $funcs{"sk_${1}_delete_ptr"} = 1; 285 $funcs{"sk_${1}_insert"} = 1; 286 $funcs{"sk_${1}_set_cmp_func"} = 1; 287 $funcs{"sk_${1}_dup"} = 1; 288 $funcs{"sk_${1}_pop_free"} = 1; 289 $funcs{"sk_${1}_shift"} = 1; 290 $funcs{"sk_${1}_pop"} = 1; 291 $funcs{"sk_${1}_sort"} = 1; 292 } elsif ($safe_stack_def && 293 /^\s*DECLARE_ASN1_SET_OF\s*\(\s*(\w*)\s*\)/) { 294 $funcs{"d2i_ASN1_SET_OF_${1}"} = 1; 295 $funcs{"i2d_ASN1_SET_OF_${1}"} = 1; 296 } elsif (/^DECLARE_PEM_rw\s*\(\s*(\w*)\s*,/ || 297 /^DECLARE_PEM_rw_cb\s*\(\s*(\w*)\s*,/ ) { 298 if($W32) { 299 $funcs{"PEM_read_${1}"} = 1; 300 $funcs{"PEM_write_${1}"} = 1; 301 } 302 $funcs{"PEM_read_bio_${1}"} = 1; 303 $funcs{"PEM_write_bio_${1}"} = 1; 304 } elsif (/^DECLARE_PEM_write\s*\(\s*(\w*)\s*,/ || 305 /^DECLARE_PEM_write_cb\s*\(\s*(\w*)\s*,/ ) { 306 if($W32) { 307 $funcs{"PEM_write_${1}"} = 1; 308 } 309 $funcs{"PEM_write_bio_${1}"} = 1; 310 } elsif (/^DECLARE_PEM_read\s*\(\s*(\w*)\s*,/ || 311 /^DECLARE_PEM_read_cb\s*\(\s*(\w*)\s*,/ ) { 312 if($W32) { 313 $funcs{"PEM_read_${1}"} = 1; 314 } 315 $funcs{"PEM_read_bio_${1}"} = 1; 316 } elsif ( 317 ($tag{'TRUE'} != -1) && 318 ($tag{'FreeBSD'} != 1) && 319 ($tag{'CONST_STRICT'} != 1) && 320 (($W32 && ($tag{'WIN16'} != 1)) || 321 (!$W32 && ($tag{'WIN16'} != -1))) && 322 ($tag{'PERL5'} != 1) && 323# ($tag{'_WINDLL'} != -1) && 324 ((!$W32 && $tag{'_WINDLL'} != -1) || 325 ($W32 && $tag{'_WINDLL'} != 1)) && 326 ((($tag{'NO_FP_API'} != 1) && $W32) || 327 (($tag{'NO_FP_API'} != -1) && !$W32)) && 328 ($tag{'NO_RC2'} == 0 || !$no_rc2) && 329 ($tag{'NO_RC4'} == 0 || !$no_rc4) && 330 ($tag{'NO_RC5'} == 0 || !$no_rc5) && 331 ($tag{'NO_IDEA'} == 0 || !$no_idea) && 332 ($tag{'NO_DES'} == 0 || !$no_des) && 333 ($tag{'NO_BF'} == 0 || !$no_bf) && 334 ($tag{'NO_CAST'} == 0 || !$no_cast) && 335 ($tag{'NO_MD2'} == 0 || !$no_md2) && 336 ($tag{'NO_MD5'} == 0 || !$no_md5) && 337 ($tag{'NO_SHA'} == 0 || !$no_sha) && 338 ($tag{'NO_RIPEMD'} == 0 || !$no_ripemd) && 339 ($tag{'NO_MDC2'} == 0 || !$no_mdc2) && 340 ($tag{'NO_RSA'} == 0 || !$no_rsa) && 341 ($tag{'NO_DSA'} == 0 || !$no_dsa) && 342 ($tag{'NO_DH'} == 0 || !$no_dh) && 343 ($tag{'NO_HMAC'} == 0 || !$no_hmac)) 344 { 345 if (/{|\/\*/) { # } 346 $line = $_; 347 } else { 348 $def .= $_; 349 } 350 } 351 } 352 close(IN); 353 354 foreach (split /;/, $def) { 355 s/^[\n\s]*//g; 356 s/[\n\s]*$//g; 357 next if(/typedef\W/); 358 next if(/EVP_bf/ and $no_bf); 359 next if(/EVP_cast/ and $no_cast); 360 next if(/EVP_des/ and $no_des); 361 next if(/EVP_dss/ and $no_dsa); 362 next if(/EVP_idea/ and $no_idea); 363 next if(/EVP_md2/ and $no_md2); 364 next if(/EVP_md5/ and $no_md5); 365 next if(/EVP_rc2/ and $no_rc2); 366 next if(/EVP_rc4/ and $no_rc4); 367 next if(/EVP_rc5/ and $no_rc5); 368 next if(/EVP_ripemd/ and $no_ripemd); 369 next if(/EVP_sha/ and $no_sha); 370 if (/\(\*(\w*)\([^\)]+/) { 371 $funcs{$1} = 1; 372 } elsif (/\w+\W+(\w+)\W*\(\s*\)$/s) { 373 # K&R C 374 next; 375 } elsif (/\w+\W+\w+\W*\(.*\)$/s) { 376 while (not /\(\)$/s) { 377 s/[^\(\)]*\)$/\)/s; 378 s/\([^\(\)]*\)\)$/\)/s; 379 } 380 s/\(void\)//; 381 /(\w+)\W*\(\)/s; 382 $funcs{$1} = 1; 383 } elsif (/\(/ and not (/=/)) { 384 print STDERR "File $file: cannot parse: $_;\n"; 385 } 386 } 387 } 388 389 # Prune the returned functions 390 391 delete $funcs{"SSL_add_dir_cert_subjects_to_stack"}; 392 delete $funcs{"RSA_PKCS1_RSAref"} unless $rsaref; 393 delete $funcs{"bn_dump1"}; 394 395 if($W32) { 396 delete $funcs{"BIO_s_file_internal"}; 397 delete $funcs{"BIO_new_file_internal"}; 398 delete $funcs{"BIO_new_fp_internal"}; 399 } else { 400 if(exists $funcs{"ERR_load_CRYPTO_strings"}) { 401 delete $funcs{"ERR_load_CRYPTO_strings"}; 402 $funcs{"ERR_load_CRYPTOlib_strings"} = 1; 403 } 404 delete $funcs{"BIO_s_file"}; 405 delete $funcs{"BIO_new_file"}; 406 delete $funcs{"BIO_new_fp"}; 407 } 408 if (!$NT) { 409 delete $funcs{"BIO_s_log"}; 410 } 411 412 push @ret, keys %funcs; 413 414 return(@ret); 415} 416 417sub print_test_file 418{ 419 (*OUT,my $name,*nums,my @functions)=@_; 420 my $n = 1; my @e; my @r; 421 my $func; 422 423 (@e)=grep(/^SSLeay/,@functions); 424 (@r)=grep(!/^SSLeay/,@functions); 425 @functions=((sort @e),(sort @r)); 426 427 foreach $func (@functions) { 428 if (!defined($nums{$func})) { 429 printf STDERR "$func does not have a number assigned\n" 430 if(!$do_update); 431 } else { 432 $n=$nums{$func}; 433 print OUT "\t$func();\n"; 434 } 435 } 436} 437 438sub print_def_file 439{ 440 (*OUT,my $name,*nums,my @functions)=@_; 441 my $n = 1; my @e; my @r; 442 443 if ($W32) 444 { $name.="32"; } 445 else 446 { $name.="16"; } 447 448 print OUT <<"EOF"; 449; 450; Definition file for the DLL version of the $name library from OpenSSL 451; 452 453LIBRARY $name 454 455DESCRIPTION 'OpenSSL $name - http://www.openssl.org/' 456 457EOF 458 459 if (!$W32) { 460 print <<"EOF"; 461CODE PRELOAD MOVEABLE 462DATA PRELOAD MOVEABLE SINGLE 463 464EXETYPE WINDOWS 465 466HEAPSIZE 4096 467STACKSIZE 8192 468 469EOF 470 } 471 472 print "EXPORTS\n"; 473 474 475 (@e)=grep(/^SSLeay/,@functions); 476 (@r)=grep(!/^SSLeay/,@functions); 477 @functions=((sort @e),(sort @r)); 478 479 foreach $func (@functions) { 480 if (!defined($nums{$func})) { 481 printf STDERR "$func does not have a number assigned\n" 482 if(!$do_update); 483 } else { 484 $n=$nums{$func}; 485 printf OUT " %s%-40s@%d\n",($W32)?"":"_",$func,$n; 486 } 487 } 488 printf OUT "\n"; 489} 490 491sub load_numbers 492{ 493 my($name)=@_; 494 my(@a,%ret); 495 496 $max_num = 0; 497 498 open(IN,"<$name") || die "unable to open $name:$!\n"; 499 while (<IN>) { 500 chop; 501 s/#.*$//; 502 next if /^\s*$/; 503 @a=split; 504 $ret{$a[0]}=$a[1]; 505 $max_num = $a[1] if $a[1] > $max_num; 506 } 507 close(IN); 508 return(%ret); 509} 510 511sub update_numbers 512{ 513 (*OUT,$name,*nums,my $start_num, my @functions)=@_; 514 my $new_funcs = 0; 515 print STDERR "Updating $name\n"; 516 foreach $func (@functions) { 517 if (!exists $nums{$func}) { 518 $new_funcs++; 519 printf OUT "%s%-40s%d\n","",$func, ++$start_num; 520 } 521 } 522 if($new_funcs) { 523 print STDERR "$new_funcs New Functions added\n"; 524 } else { 525 print STDERR "No New Functions Added\n"; 526 } 527} 528