1#!/usr/local/bin/perl -w 2 3my $config = "crypto/err/openssl.ec"; 4my $debug = 0; 5my $rebuild = 0; 6my $static = 1; 7my $recurse = 0; 8my $reindex = 0; 9my $dowrite = 0; 10my $staticloader = ""; 11 12while (@ARGV) { 13 my $arg = $ARGV[0]; 14 if($arg eq "-conf") { 15 shift @ARGV; 16 $config = shift @ARGV; 17 } elsif($arg eq "-debug") { 18 $debug = 1; 19 shift @ARGV; 20 } elsif($arg eq "-rebuild") { 21 $rebuild = 1; 22 shift @ARGV; 23 } elsif($arg eq "-recurse") { 24 $recurse = 1; 25 shift @ARGV; 26 } elsif($arg eq "-reindex") { 27 $reindex = 1; 28 shift @ARGV; 29 } elsif($arg eq "-nostatic") { 30 $static = 0; 31 shift @ARGV; 32 } elsif($arg eq "-staticloader") { 33 $staticloader = "static "; 34 shift @ARGV; 35 } elsif($arg eq "-write") { 36 $dowrite = 1; 37 shift @ARGV; 38 } else { 39 last; 40 } 41} 42 43if($recurse) { 44 @source = (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>); 45} else { 46 @source = @ARGV; 47} 48 49# Read in the config file 50 51open(IN, "<$config") || die "Can't open config file $config"; 52 53# Parse config file 54 55while(<IN>) 56{ 57 if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) { 58 $hinc{$1} = $2; 59 $libinc{$2} = $1; 60 $cskip{$3} = $1; 61 if($3 ne "NONE") { 62 $csrc{$1} = $3; 63 $fmax{$1} = 99; 64 $rmax{$1} = 99; 65 $fnew{$1} = 0; 66 $rnew{$1} = 0; 67 } 68 } elsif (/^F\s+(\S+)/) { 69 # Add extra function with $1 70 } elsif (/^R\s+(\S+)\s+(\S+)/) { 71 $rextra{$1} = $2; 72 $rcodes{$1} = $2; 73 } 74} 75 76close IN; 77 78# Scan each header file in turn and make a list of error codes 79# and function names 80 81while (($hdr, $lib) = each %libinc) 82{ 83 next if($hdr eq "NONE"); 84 print STDERR "Scanning header file $hdr\n" if $debug; 85 my $line = "", $def= "", $linenr = 0, $gotfile = 0; 86 if (open(IN, "<$hdr")) { 87 $gotfile = 1; 88 while(<IN>) { 89 $linenr++; 90 print STDERR "line: $linenr\r" if $debug; 91 92 last if(/BEGIN\s+ERROR\s+CODES/); 93 if ($line ne '') { 94 $_ = $line . $_; 95 $line = ''; 96 } 97 98 if (/\\$/) { 99 $line = $_; 100 next; 101 } 102 103 $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration 104 if ($cpp) { 105 $cpp = 0 if /^#.*endif/; 106 next; 107 } 108 109 next if (/^\#/); # skip preprocessor directives 110 111 s/\/\*.*?\*\///gs; # ignore comments 112 s/{[^{}]*}//gs; # ignore {} blocks 113 114 if (/\{|\/\*/) { # Add a } so editor works... 115 $line = $_; 116 } else { 117 $def .= $_; 118 } 119 } 120 } 121 122 print STDERR " \r" if $debug; 123 $defnr = 0; 124 foreach (split /;/, $def) { 125 $defnr++; 126 print STDERR "def: $defnr\r" if $debug; 127 128 s/^[\n\s]*//g; 129 s/[\n\s]*$//g; 130 next if(/typedef\W/); 131 if (/\(\*(\w*)\([^\)]+/) { 132 my $name = $1; 133 $name =~ tr/[a-z]/[A-Z]/; 134 $ftrans{$name} = $1; 135 } elsif (/\w+\W+(\w+)\W*\(\s*\)$/s){ 136 # K&R C 137 next ; 138 } elsif (/\w+\W+\w+\W*\(.*\)$/s) { 139 while (not /\(\)$/s) { 140 s/[^\(\)]*\)$/\)/s; 141 s/\([^\(\)]*\)\)$/\)/s; 142 } 143 s/\(void\)//; 144 /(\w+)\W*\(\)/s; 145 my $name = $1; 146 $name =~ tr/[a-z]/[A-Z]/; 147 $ftrans{$name} = $1; 148 } elsif (/\(/ and not (/=/ or /DECLARE_STACK/)) { 149 print STDERR "Header $hdr: cannot parse: $_;\n"; 150 } 151 } 152 153 print STDERR " \r" if $debug; 154 155 next if $reindex; 156 157 # Scan function and reason codes and store them: keep a note of the 158 # maximum code used. 159 160 if ($gotfile) { 161 while(<IN>) { 162 if(/^\#define\s+(\S+)\s+(\S+)/) { 163 $name = $1; 164 $code = $2; 165 next if $name =~ /^${lib}err/; 166 unless($name =~ /^${lib}_([RF])_(\w+)$/) { 167 print STDERR "Invalid error code $name\n"; 168 next; 169 } 170 if($1 eq "R") { 171 $rcodes{$name} = $code; 172 if(!(exists $rextra{$name}) && 173 ($code > $rmax{$lib}) ) { 174 $rmax{$lib} = $code; 175 } 176 } else { 177 if($code > $fmax{$lib}) { 178 $fmax{$lib} = $code; 179 } 180 $fcodes{$name} = $code; 181 } 182 } 183 } 184 } 185 close IN; 186} 187 188# Scan each C source file and look for function and reason codes 189# This is done by looking for strings that "look like" function or 190# reason codes: basically anything consisting of all upper case and 191# numerics which has _F_ or _R_ in it and which has the name of an 192# error library at the start. This seems to work fine except for the 193# oddly named structure BIO_F_CTX which needs to be ignored. 194# If a code doesn't exist in list compiled from headers then mark it 195# with the value "X" as a place holder to give it a value later. 196# Store all function and reason codes found in %ufcodes and %urcodes 197# so all those unreferenced can be printed out. 198 199 200print STDERR "Files loaded: " if $debug; 201foreach $file (@source) { 202 # Don't parse the error source file. 203 next if exists $cskip{$file}; 204 print STDERR $file if $debug; 205 open(IN, "<$file") || die "Can't open source file $file\n"; 206 while(<IN>) { 207 if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) { 208 next unless exists $csrc{$2}; 209 next if($1 eq "BIO_F_BUFFER_CTX"); 210 $ufcodes{$1} = 1; 211 if(!exists $fcodes{$1}) { 212 $fcodes{$1} = "X"; 213 $fnew{$2}++; 214 } 215 $notrans{$1} = 1 unless exists $ftrans{$3}; 216 } 217 if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) { 218 next unless exists $csrc{$2}; 219 $urcodes{$1} = 1; 220 if(!exists $rcodes{$1}) { 221 $rcodes{$1} = "X"; 222 $rnew{$2}++; 223 } 224 } 225 } 226 close IN; 227} 228print STDERR "\n" if $debug; 229 230# Now process each library in turn. 231 232foreach $lib (keys %csrc) 233{ 234 my $hfile = $hinc{$lib}; 235 my $cfile = $csrc{$lib}; 236 if(!$fnew{$lib} && !$rnew{$lib}) { 237 print STDERR "$lib:\t\tNo new error codes\n"; 238 next unless $rebuild; 239 } else { 240 print STDERR "$lib:\t\t$fnew{$lib} New Functions,"; 241 print STDERR " $rnew{$lib} New Reasons.\n"; 242 next unless $dowrite; 243 } 244 245 # If we get here then we have some new error codes so we 246 # need to rebuild the header file and C file. 247 248 # Make a sorted list of error and reason codes for later use. 249 250 my @function = sort grep(/^${lib}_/,keys %fcodes); 251 my @reasons = sort grep(/^${lib}_/,keys %rcodes); 252 253 # Rewrite the header file 254 255 if (open(IN, "<$hfile")) { 256 # Copy across the old file 257 while(<IN>) { 258 push @out, $_; 259 last if (/BEGIN ERROR CODES/); 260 } 261 close IN; 262 } else { 263 push @out, 264"/* ====================================================================\n", 265" * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.\n", 266" *\n", 267" * Redistribution and use in source and binary forms, with or without\n", 268" * modification, are permitted provided that the following conditions\n", 269" * are met:\n", 270" *\n", 271" * 1. Redistributions of source code must retain the above copyright\n", 272" * notice, this list of conditions and the following disclaimer. \n", 273" *\n", 274" * 2. Redistributions in binary form must reproduce the above copyright\n", 275" * notice, this list of conditions and the following disclaimer in\n", 276" * the documentation and/or other materials provided with the\n", 277" * distribution.\n", 278" *\n", 279" * 3. All advertising materials mentioning features or use of this\n", 280" * software must display the following acknowledgment:\n", 281" * \"This product includes software developed by the OpenSSL Project\n", 282" * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n", 283" *\n", 284" * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n", 285" * endorse or promote products derived from this software without\n", 286" * prior written permission. For written permission, please contact\n", 287" * openssl-core\@openssl.org.\n", 288" *\n", 289" * 5. Products derived from this software may not be called \"OpenSSL\"\n", 290" * nor may \"OpenSSL\" appear in their names without prior written\n", 291" * permission of the OpenSSL Project.\n", 292" *\n", 293" * 6. Redistributions of any form whatsoever must retain the following\n", 294" * acknowledgment:\n", 295" * \"This product includes software developed by the OpenSSL Project\n", 296" * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n", 297" *\n", 298" * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n", 299" * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n", 300" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n", 301" * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n", 302" * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n", 303" * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n", 304" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n", 305" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n", 306" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n", 307" * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n", 308" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n", 309" * OF THE POSSIBILITY OF SUCH DAMAGE.\n", 310" * ====================================================================\n", 311" *\n", 312" * This product includes cryptographic software written by Eric Young\n", 313" * (eay\@cryptsoft.com). This product includes software written by Tim\n", 314" * Hudson (tjh\@cryptsoft.com).\n", 315" *\n", 316" */\n", 317"\n", 318"#ifndef HEADER_${lib}_ERR_H\n", 319"#define HEADER_${lib}_ERR_H\n", 320"\n", 321"/* BEGIN ERROR CODES */\n"; 322 } 323 open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n"; 324 325 print OUT @out; 326 undef @out; 327 print OUT <<"EOF"; 328/* The following lines are auto generated by the script mkerr.pl. Any changes 329 * made after this point may be overwritten when the script is next run. 330 */ 331EOF 332 if($static) { 333 print OUT <<"EOF"; 334${staticloader}void ERR_load_${lib}_strings(void); 335 336EOF 337 } else { 338 print OUT <<"EOF"; 339${staticloader}void ERR_load_${lib}_strings(void); 340${staticloader}void ERR_unload_${lib}_strings(void); 341${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line); 342#define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__) 343 344EOF 345 } 346 print OUT <<"EOF"; 347/* Error codes for the $lib functions. */ 348 349/* Function codes. */ 350EOF 351 352 foreach $i (@function) { 353 $z=6-int(length($i)/8); 354 if($fcodes{$i} eq "X") { 355 $fcodes{$i} = ++$fmax{$lib}; 356 print STDERR "New Function code $i\n" if $debug; 357 } 358 printf OUT "#define $i%s $fcodes{$i}\n","\t" x $z; 359 } 360 361 print OUT "\n/* Reason codes. */\n"; 362 363 foreach $i (@reasons) { 364 $z=6-int(length($i)/8); 365 if($rcodes{$i} eq "X") { 366 $rcodes{$i} = ++$rmax{$lib}; 367 print STDERR "New Reason code $i\n" if $debug; 368 } 369 printf OUT "#define $i%s $rcodes{$i}\n","\t" x $z; 370 } 371 print OUT <<"EOF"; 372 373#ifdef __cplusplus 374} 375#endif 376#endif 377EOF 378 close OUT; 379 380 # Rewrite the C source file containing the error details. 381 382 # First, read any existing reason string definitions: 383 my %err_reason_strings; 384 if (open(IN,"<$cfile")) { 385 while (<IN>) { 386 if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) { 387 $err_reason_strings{$1} = $2; 388 } 389 } 390 close(IN); 391 } 392 393 my $hincf; 394 if($static) { 395 $hfile =~ /([^\/]+)$/; 396 $hincf = "<openssl/$1>"; 397 } else { 398 $hincf = "\"$hfile\""; 399 } 400 401 402 open (OUT,">$cfile") || die "Can't open $cfile for writing"; 403 404 print OUT <<"EOF"; 405/* $cfile */ 406/* ==================================================================== 407 * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. 408 * 409 * Redistribution and use in source and binary forms, with or without 410 * modification, are permitted provided that the following conditions 411 * are met: 412 * 413 * 1. Redistributions of source code must retain the above copyright 414 * notice, this list of conditions and the following disclaimer. 415 * 416 * 2. Redistributions in binary form must reproduce the above copyright 417 * notice, this list of conditions and the following disclaimer in 418 * the documentation and/or other materials provided with the 419 * distribution. 420 * 421 * 3. All advertising materials mentioning features or use of this 422 * software must display the following acknowledgment: 423 * "This product includes software developed by the OpenSSL Project 424 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 425 * 426 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 427 * endorse or promote products derived from this software without 428 * prior written permission. For written permission, please contact 429 * openssl-core\@OpenSSL.org. 430 * 431 * 5. Products derived from this software may not be called "OpenSSL" 432 * nor may "OpenSSL" appear in their names without prior written 433 * permission of the OpenSSL Project. 434 * 435 * 6. Redistributions of any form whatsoever must retain the following 436 * acknowledgment: 437 * "This product includes software developed by the OpenSSL Project 438 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 439 * 440 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 441 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 442 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 444 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 445 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 446 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 447 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 448 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 449 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 450 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 451 * OF THE POSSIBILITY OF SUCH DAMAGE. 452 * ==================================================================== 453 * 454 * This product includes cryptographic software written by Eric Young 455 * (eay\@cryptsoft.com). This product includes software written by Tim 456 * Hudson (tjh\@cryptsoft.com). 457 * 458 */ 459 460/* NOTE: this file was auto generated by the mkerr.pl script: any changes 461 * made to it will be overwritten when the script next updates this file, 462 * only reason strings will be preserved. 463 */ 464 465#include <stdio.h> 466#include <openssl/err.h> 467#include $hincf 468 469/* BEGIN ERROR CODES */ 470#ifndef OPENSSL_NO_ERR 471static ERR_STRING_DATA ${lib}_str_functs[]= 472 { 473EOF 474 # Add each function code: if a function name is found then use it. 475 foreach $i (@function) { 476 my $fn; 477 $i =~ /^${lib}_F_(\S+)$/; 478 $fn = $1; 479 if(exists $ftrans{$fn}) { 480 $fn = $ftrans{$fn}; 481 } 482 print OUT "{ERR_PACK(0,$i,0),\t\"$fn\"},\n"; 483 } 484 print OUT <<"EOF"; 485{0,NULL} 486 }; 487 488static ERR_STRING_DATA ${lib}_str_reasons[]= 489 { 490EOF 491 # Add each reason code. 492 foreach $i (@reasons) { 493 my $rn; 494 my $nspc = 0; 495 if (exists $err_reason_strings{$i}) { 496 $rn = $err_reason_strings{$i}; 497 } else { 498 $i =~ /^${lib}_R_(\S+)$/; 499 $rn = $1; 500 $rn =~ tr/_[A-Z]/ [a-z]/; 501 } 502 $nspc = 40 - length($i) unless length($i) > 40; 503 $nspc = " " x $nspc; 504 print OUT "{${i}${nspc},\"$rn\"},\n"; 505 } 506if($static) { 507 print OUT <<"EOF"; 508{0,NULL} 509 }; 510 511#endif 512 513${staticloader}void ERR_load_${lib}_strings(void) 514 { 515 static int init=1; 516 517 if (init) 518 { 519 init=0; 520#ifndef OPENSSL_NO_ERR 521 ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs); 522 ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons); 523#endif 524 525 } 526 } 527EOF 528} else { 529 print OUT <<"EOF"; 530{0,NULL} 531 }; 532 533#endif 534 535#ifdef ${lib}_LIB_NAME 536static ERR_STRING_DATA ${lib}_lib_name[]= 537 { 538{0 ,${lib}_LIB_NAME}, 539{0,NULL} 540 }; 541#endif 542 543 544static int ${lib}_lib_error_code=0; 545static int ${lib}_error_init=1; 546 547${staticloader}void ERR_load_${lib}_strings(void) 548 { 549 if (${lib}_lib_error_code == 0) 550 ${lib}_lib_error_code=ERR_get_next_error_library(); 551 552 if (${lib}_error_init) 553 { 554 ${lib}_error_init=0; 555#ifndef OPENSSL_NO_ERR 556 ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs); 557 ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons); 558#endif 559 560#ifdef ${lib}_LIB_NAME 561 ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0); 562 ERR_load_strings(0,${lib}_lib_name); 563#endif 564 } 565 } 566 567${staticloader}void ERR_unload_${lib}_strings(void) 568 { 569 if (${lib}_error_init == 0) 570 { 571#ifndef OPENSSL_NO_ERR 572 ERR_unload_strings(${lib}_lib_error_code,${lib}_str_functs); 573 ERR_unload_strings(${lib}_lib_error_code,${lib}_str_reasons); 574#endif 575 576#ifdef ${lib}_LIB_NAME 577 ERR_unload_strings(0,${lib}_lib_name); 578#endif 579 ${lib}_error_init=1; 580 } 581 } 582 583${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line) 584 { 585 if (${lib}_lib_error_code == 0) 586 ${lib}_lib_error_code=ERR_get_next_error_library(); 587 ERR_PUT_error(${lib}_lib_error_code,function,reason,file,line); 588 } 589EOF 590 591} 592 593 close OUT; 594 undef %err_reason_strings; 595} 596 597if($debug && defined(%notrans)) { 598 print STDERR "The following function codes were not translated:\n"; 599 foreach(sort keys %notrans) 600 { 601 print STDERR "$_\n"; 602 } 603} 604 605# Make a list of unreferenced function and reason codes 606 607foreach (keys %fcodes) { 608 push (@funref, $_) unless exists $ufcodes{$_}; 609} 610 611foreach (keys %rcodes) { 612 push (@runref, $_) unless exists $urcodes{$_}; 613} 614 615if($debug && defined(@funref) ) { 616 print STDERR "The following function codes were not referenced:\n"; 617 foreach(sort @funref) 618 { 619 print STDERR "$_\n"; 620 } 621} 622 623if($debug && defined(@runref) ) { 624 print STDERR "The following reason codes were not referenced:\n"; 625 foreach(sort @runref) 626 { 627 print STDERR "$_\n"; 628 } 629} 630