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 # First, read any existing reason string definitions: 288 my %err_reason_strings; 289 if (open(IN,"<$cfile")) { 290 while (<IN>) { 291 if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) { 292 $err_reason_strings{$1} = $2; 293 } 294 } 295 close(IN); 296 } 297 298 my $hincf; 299 if($static) { 300 $hfile =~ /([^\/]+)$/; 301 $hincf = "<openssl/$1>"; 302 } else { 303 $hincf = "\"$hfile\""; 304 } 305 306 307 open (OUT,">$cfile") || die "Can't open $cfile for writing"; 308 309 print OUT <<"EOF"; 310/* $cfile */ 311/* ==================================================================== 312 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 313 * 314 * Redistribution and use in source and binary forms, with or without 315 * modification, are permitted provided that the following conditions 316 * are met: 317 * 318 * 1. Redistributions of source code must retain the above copyright 319 * notice, this list of conditions and the following disclaimer. 320 * 321 * 2. Redistributions in binary form must reproduce the above copyright 322 * notice, this list of conditions and the following disclaimer in 323 * the documentation and/or other materials provided with the 324 * distribution. 325 * 326 * 3. All advertising materials mentioning features or use of this 327 * software must display the following acknowledgment: 328 * "This product includes software developed by the OpenSSL Project 329 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 330 * 331 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 332 * endorse or promote products derived from this software without 333 * prior written permission. For written permission, please contact 334 * openssl-core\@OpenSSL.org. 335 * 336 * 5. Products derived from this software may not be called "OpenSSL" 337 * nor may "OpenSSL" appear in their names without prior written 338 * permission of the OpenSSL Project. 339 * 340 * 6. Redistributions of any form whatsoever must retain the following 341 * acknowledgment: 342 * "This product includes software developed by the OpenSSL Project 343 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 344 * 345 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 346 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 347 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 348 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 349 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 350 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 351 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 352 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 353 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 354 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 355 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 356 * OF THE POSSIBILITY OF SUCH DAMAGE. 357 * ==================================================================== 358 * 359 * This product includes cryptographic software written by Eric Young 360 * (eay\@cryptsoft.com). This product includes software written by Tim 361 * Hudson (tjh\@cryptsoft.com). 362 * 363 */ 364 365/* NOTE: this file was auto generated by the mkerr.pl script: any changes 366 * made to it will be overwritten when the script next updates this file, 367 * only reason strings will be preserved. 368 */ 369 370#include <stdio.h> 371#include <openssl/err.h> 372#include $hincf 373 374/* BEGIN ERROR CODES */ 375#ifndef NO_ERR 376static ERR_STRING_DATA ${lib}_str_functs[]= 377 { 378EOF 379 # Add each function code: if a function name is found then use it. 380 foreach $i (@function) { 381 my $fn; 382 $i =~ /^${lib}_F_(\S+)$/; 383 $fn = $1; 384 if(exists $ftrans{$fn}) { 385 $fn = $ftrans{$fn}; 386 } 387 print OUT "{ERR_PACK(0,$i,0),\t\"$fn\"},\n"; 388 } 389 print OUT <<"EOF"; 390{0,NULL} 391 }; 392 393static ERR_STRING_DATA ${lib}_str_reasons[]= 394 { 395EOF 396 # Add each reason code. 397 foreach $i (@reasons) { 398 my $rn; 399 my $nspc = 0; 400 if (exists $err_reason_strings{$i}) { 401 $rn = $err_reason_strings{$i}; 402 } else { 403 $i =~ /^${lib}_R_(\S+)$/; 404 $rn = $1; 405 $rn =~ tr/_[A-Z]/ [a-z]/; 406 } 407 $nspc = 40 - length($i) unless length($i) > 40; 408 $nspc = " " x $nspc; 409 print OUT "{${i}${nspc},\"$rn\"},\n"; 410 } 411if($static) { 412 print OUT <<"EOF"; 413{0,NULL} 414 }; 415 416#endif 417 418void ERR_load_${lib}_strings(void) 419 { 420 static int init=1; 421 422 if (init) 423 { 424 init=0; 425#ifndef NO_ERR 426 ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs); 427 ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons); 428#endif 429 430 } 431 } 432EOF 433} else { 434 print OUT <<"EOF"; 435{0,NULL} 436 }; 437 438#endif 439 440#ifdef ${lib}_LIB_NAME 441static ERR_STRING_DATA ${lib}_lib_name[]= 442 { 443{0 ,${lib}_LIB_NAME}, 444{0,NULL} 445 }; 446#endif 447 448 449int ${lib}_lib_error_code=0; 450 451void ERR_load_${lib}_strings(void) 452 { 453 static int init=1; 454 455 if (${lib}_lib_error_code == 0) 456 ${lib}_lib_error_code=ERR_get_next_error_library(); 457 458 if (init) 459 { 460 init=0; 461#ifndef NO_ERR 462 ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs); 463 ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons); 464#endif 465 466#ifdef ${lib}_LIB_NAME 467 ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0); 468 ERR_load_strings(0,${lib}_lib_name); 469#endif 470 } 471 } 472 473void ERR_${lib}_error(int function, int reason, char *file, int line) 474 { 475 if (${lib}_lib_error_code == 0) 476 ${lib}_lib_error_code=ERR_get_next_error_library(); 477 ERR_PUT_error(${lib}_lib_error_code,function,reason,file,line); 478 } 479EOF 480 481} 482 483 close OUT; 484 undef %err_reason_strings; 485} 486 487if($debug && defined(%notrans)) { 488 print STDERR "The following function codes were not translated:\n"; 489 foreach(sort keys %notrans) 490 { 491 print STDERR "$_\n"; 492 } 493} 494 495# Make a list of unreferenced function and reason codes 496 497foreach (keys %fcodes) { 498 push (@funref, $_) unless exists $ufcodes{$_}; 499} 500 501foreach (keys %rcodes) { 502 push (@runref, $_) unless exists $urcodes{$_}; 503} 504 505if($debug && defined(@funref) ) { 506 print STDERR "The following function codes were not referenced:\n"; 507 foreach(sort @funref) 508 { 509 print STDERR "$_\n"; 510 } 511} 512 513if($debug && defined(@runref) ) { 514 print STDERR "The following reason codes were not referenced:\n"; 515 foreach(sort @runref) 516 { 517 print STDERR "$_\n"; 518 } 519} 520