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