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