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