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