mkerr.pl 20.8 KB
Newer Older
R
Rich Salz 已提交
1 2 3 4 5 6 7
#! /usr/bin/env perl
# Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
8

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
use strict;
use warnings;

my $config       = "crypto/err/openssl.ec";
my $debug        = 0;
my $internal     = 0;
my $nowrite      = 0;
my $rebuild      = 0;
my $reindex      = 0;
my $static       = 0;
my $unref        = 0;

my $errors       = 0;
my @t            = localtime();
my $YEAR         = $t[5] + 1900;

sub phase
{
    my $text = uc(shift);
    print STDERR "\n---\n$text\n" if $debug;
}

sub help
{
    print STDERR <<"EOF";
mkerr.pl [options] [files...]
D
Dr. Stephen Henson 已提交
35 36 37

Options:

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
    -conf FILE  Use the named config file FILE instead of the default.

    -debug      Verbose output debugging on stderr.

    -internal   Generate code that is to be built as part of OpenSSL itself.
                Also scans internal list of files.

    -nowrite    Do not write the header/source files, even if changed.

    -rebuild    Rebuild all header and C source files, even if there
                were no changes.

    -reindex    Ignore previously assigned values (except for R records in
                the config file) and renumber everything starting at 100.

    -static     Make the load/unload functions static.

    -unref      List all unreferenced function and reason codes on stderr;
                implies -nowrite.

    -help       Show this help text.

    ...         Additional arguments are added to the file list to scan,
                if '-internal' was NOT specified on the command line.
D
Dr. Stephen Henson 已提交
62 63

EOF
64 65
}

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
while ( @ARGV ) {
    my $arg = $ARGV[0];
    last unless $arg =~ /-.*/;
    $arg = $1 if $arg =~ /-(-.*)/;
    if ( $arg eq "-conf" ) {
        $config = $ARGV[1];
        shift @ARGV;
    } elsif ( $arg eq "-debug" ) {
        $debug = 1;
        $unref = 1;
    } elsif ( $arg eq "-internal" ) {
        $internal = 1;
    } elsif ( $arg eq "-nowrite" ) {
        $nowrite = 1;
    } elsif ( $arg eq "-rebuild" ) {
        $rebuild = 1;
    } elsif ( $arg eq "-reindex" ) {
        $reindex = 1;
    } elsif ( $arg eq "-static" ) {
        $static = 1;
    } elsif ( $arg eq "-unref" ) {
        $unref = 1;
        $nowrite = 1;
    } elsif ( $arg =~ /-*h(elp)?/ ) {
        &help();
        exit;
    } elsif ( $arg =~ /-.*/ ) {
        die "Unknown option $arg; use -h for help.\n";
    }
    shift @ARGV;
96 97
}

98 99 100 101 102 103 104 105 106
my @source;
if ( $internal ) {
    die "Cannot mix -internal and -static\n" if $static;
    die "Extra parameters given.\n" if @ARGV;
    @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
                glob('ssl/*.c'), glob('ssl/*/*.c') );
} else {
    @source = @ARGV;
}
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
# Data parsed out of the config and state files.
my %hinc;       # lib -> header
my %libinc;     # header -> lib
my %cskip;      # error_file -> lib
my %errorfile;  # lib -> error file name
my %fmax;       # lib -> max assigned function code
my %rmax;       # lib -> max assigned reason code
my %fassigned;  # lib -> colon-separated list of assigned function codes
my %rassigned;  # lib -> colon-separated list of assigned reason codes
my %fnew;       # lib -> count of new function codes
my %rnew;       # lib -> count of new reason codes
my %rextra;     # "extra" reason code -> lib
my %rcodes;     # reason-name -> value
my %ftrans;     # old name -> #define-friendly name (all caps)
my %fcodes;     # function-name -> value
my $statefile;  # state file with assigned reason and function codes
R
Rich Salz 已提交
124
my %strings;    # define -> text
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

# Read and parse the config file
open(IN, "$config") || die "Can't open config file $config, $!,";
while ( <IN> ) {
    next if /^#/ || /^$/;
    if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
        my $lib = $1;
        my $hdr = $2;
        my $err = $3;
        $hinc{$lib}   = $hdr;
        $libinc{$hdr} = $lib;
        $cskip{$err}  = $lib;
        next if $err eq 'NONE';
        $errorfile{$lib} = $err;
        $fmax{$lib}      = 100;
        $rmax{$lib}      = 100;
        $fassigned{$lib} = ":";
        $rassigned{$lib} = ":";
        $fnew{$lib}      = 0;
        $rnew{$lib}      = 0;
    } elsif ( /^R\s+(\S+)\s+(\S+)/ ) {
        $rextra{$1} = $2;
        $rcodes{$1} = $2;
    } elsif ( /^S\s+(\S+)/ ) {
        $statefile = $1;
    } else {
        die "Illegal config line $_\n";
    }
}
close IN;
155

R
Rich Salz 已提交
156
my $statefile_prolog = '';
157 158 159
if ( ! $statefile ) {
    $statefile = $config;
    $statefile =~ s/.ec/.txt/;
160 161
}

162 163 164 165 166 167 168 169
# The statefile has all the previous assignments.
&phase("Reading state");
my $skippedstate = 0;
if ( ! $reindex && $statefile ) {
    open(STATE, "<$statefile") || die "Can't open $statefile, $!";

    # Scan function and reason codes and store them: keep a note of the
    # maximum code used.
R
Rich Salz 已提交
170
    my $collecting = 1;
171
    while ( <STATE> ) {
R
Rich Salz 已提交
172
        $statefile_prolog .= $_ if $collecting && ( /^#/ || /^$/ );
173
        next if /^#/ || /^$/;
R
Rich Salz 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
        my $name;
        my $code;
        if ( /^(.+):(\d+):\\$/ ) {
            $name = $1;
            $code = $2;
            my $next = <STATE>;
            $next =~ s/^\s*(.*)\s*$/$1/;
            die "Duplicate define $name" if exists $strings{$name};
            $strings{$name} = $next;
        } elsif ( /^(\S+):(\d+):(.*)$/ ) {
            $name = $1;
            $code = $2;
            die "Duplicate define $name" if exists $strings{$name};
            $strings{$name} = $3;
        } else {
            die "Bad line in $statefile:\n$_\n";
        }
        $collecting = 0;
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
        my $lib = $name;
        $lib =~ s/_.*//;
        $lib = "SSL" if $lib =~ /TLS/;
        if ( !defined $errorfile{$lib} ) {
            print "Skipping $_";
            $skippedstate++;
            next;
        }
        if ( $name =~ /^[A-Z0-9]+_R_/ ) {
            die "$lib reason code $code collision at $name\n"
                if $rassigned{$lib} =~ /:$code:/;
            $rassigned{$lib} .= "$code:";
            if ( !exists $rextra{$name} ) {
                $rmax{$lib} = $code if $code > $rmax{$lib};
            }
            $rcodes{$name} = $code;
        } elsif ( $name =~ /^[A-Z0-9]+_F_/ ) {
            die "$lib function code $code collision at $name\n"
                if $fassigned{$lib} =~ /:$code:/;
            $fassigned{$lib} .= "$code:";
            $fmax{$lib} = $code if $code > $fmax{$lib};
            $fcodes{$name} = $code;
        } else {
            die "Bad line in $statefile:\n$_\n";
        }
    }
    close(STATE);

    if ( $debug ) {
        foreach my $lib ( sort keys %rmax ) {
            print STDERR "Reason codes for ${lib}:\n";
            if ( $rassigned{$lib} =~ m/^:(.*):$/ ) {
                my @rassigned = sort { $a <=> $b } split( ":", $1 );
                print STDERR "  ", join(' ', @rassigned), "\n";
            } else {
                print STDERR "  --none--\n";
            }
        }
        print STDERR "\n";
        foreach my $lib ( sort keys %fmax ) {
            print STDERR "Function codes for ${lib}:\n";
            if ( $fassigned{$lib} =~ m/^:(.*):$/ ) {
                my @fassigned = sort { $a <=> $b } split( ":", $1 );
                print STDERR "  ", join(' ', @fassigned), "\n";
            } else {
                print STDERR "  --none--\n";
            }
        }
    }
}
242

243
# Scan each header file and make a list of error codes
244
# and function names
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
&phase("Scanning headers");
while ( ( my $hdr, my $lib ) = each %libinc ) {
    next if $hdr eq "NONE";
    print STDERR " ." if $debug;
    my $line = "";
    my $def = "";
    my $linenr = 0;
    my $cpp = 0;

    open(IN, "<$hdr") || die "Can't open $hdr, $!,";
    while ( <IN> ) {
        $linenr++;

        if ( $line ne '' ) {
            $_    = $line . $_;
            $line = '';
        }

        if ( /\\$/ ) {
            $line = $_;
            next;
        }

        if ( /\/\*/ ) {
            if ( not /\*\// ) {    # multiline comment...
                $line = $_;        # ... just accumulate
                next;
            } else {
                s/\/\*.*?\*\///gs;    # wipe it
            }
        }
276

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
        if ( $cpp ) {
            $cpp++ if /^#\s*if/;
            $cpp-- if /^#\s*endif/;
            next;
        }
        $cpp = 1 if /^#.*ifdef.*cplusplus/;    # skip "C" declaration

        next if /^\#/;    # skip preprocessor directives

        s/{[^{}]*}//gs;     # ignore {} blocks

        if ( /\{|\/\*/ ) {    # Add a so editor works...
            $line = $_;
        } else {
            $def .= $_;
        }
    }

    # Delete any DECLARE_ macros
    my $defnr = 0;
    $def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
    foreach ( split /;/, $def ) {
        $defnr++;
        # The goal is to collect function names from function declarations.

        s/^[\n\s]*//g;
        s/[\n\s]*$//g;

        # Skip over recognized non-function declarations
        next if /typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/;

        # Remove STACK_OF(foo)
        s/STACK_OF\(\w+\)/void/;

        # Reduce argument lists to empty ()
        # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
        while ( /\(.*\)/s ) {
            s/\([^\(\)]+\)/\{\}/gs;
            s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs;    #(*f{}) -> f
        }

        # pretend as we didn't use curly braces: {} -> ()
        s/\{\}/\(\)/gs;

R
Rich Salz 已提交
321 322 323
        # Last token just before the first () is a function name.
        if ( /(\w+)\s*\(\).*/s ) {
            my $name = $1;
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
            $name =~ tr/[a-z]/[A-Z]/;
            $ftrans{$name} = $1;
        } elsif ( /[\(\)]/ and not(/=/) ) {
            print STDERR "Header $hdr: cannot parse: $_;\n";
        }
    }

    next if $reindex;

    if ( $lib eq "SSL" && $rmax{$lib} >= 1000 ) {
        print STDERR "SSL error codes 1000+ are reserved for alerts.\n";
        print STDERR "Any new alerts must be added to $config.\n";
        $errors++;
    }
    close IN;
339
}
340
print STDERR "\n" if $debug;
341 342 343 344 345

# Scan each C source file and look for function and reason codes
# This is done by looking for strings that "look like" function or
# reason codes: basically anything consisting of all upper case and
# numerics which has _F_ or _R_ in it and which has the name of an
346
# error library at the start.  This seems to work fine except for the
347 348 349
# oddly named structure BIO_F_CTX which needs to be ignored.
# If a code doesn't exist in list compiled from headers then mark it
# with the value "X" as a place holder to give it a value later.
350
# Store all function and reason codes found in %usedfuncs and %usedreasons
351
# so all those unreferenced can be printed out.
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
&phase("Scanning source");
my %usedfuncs;
my %usedreasons;
foreach my $file ( @source ) {
    # Don't parse the error source file.
    next if exists $cskip{$file};
    open( IN, "<$file" ) || die "Can't open $file, $!,";
    my $func;
    my $linenr = 0;
    print STDERR "$file:\n" if $debug;
    while ( <IN> ) {

        # skip obsoleted source files entirely!
        last if /^#error\s+obsolete/;
        $linenr++;
        if ( !/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/ ) {
            /^([^()]*(\([^()]*\)[^()]*)*)\(/;
            $1 =~ /([A-Za-z_0-9]*)$/;
            $func = $1;
        }

        if ( /(([A-Z0-9]+)_F_([A-Z0-9_]+))/ ) {
            next unless exists $errorfile{$2};
            next if $1 eq "BIO_F_BUFFER_CTX";
            $usedfuncs{$1} = 1;
            if ( !exists $fcodes{$1} ) {
                print STDERR "  New function $1\n" if $debug;
                $fcodes{$1} = "X";
                $fnew{$2}++;
            }
            $ftrans{$3} = $func unless exists $ftrans{$3};
            if ( uc($func) ne $3 ) {
384
                print STDERR "ERROR: mismatch $file:$linenr $func:$3\n";
385 386 387 388 389 390 391 392 393 394 395 396
                $errors++;
            }
            print STDERR "  Function $1 = $fcodes{$1}\n"
              if $debug;
        }
        if ( /(([A-Z0-9]+)_R_[A-Z0-9_]+)/ ) {
            next unless exists $errorfile{$2};
            $usedreasons{$1} = 1;
            if ( !exists $rcodes{$1} ) {
                print STDERR "  New reason $1\n" if $debug;
                $rcodes{$1} = "X";
                $rnew{$2}++;
397
            }
398 399 400 401
            print STDERR "  Reason $1 = $rcodes{$1}\n" if $debug;
        }
    }
    close IN;
402
}
403
print STDERR "\n" if $debug;
404 405

# Now process each library in turn.
406 407 408 409 410 411 412 413 414 415
&phase("Writing files");
my $newstate = 0;
foreach my $lib ( keys %errorfile ) {
    if ( ! $fnew{$lib} && ! $rnew{$lib} ) {
        next unless $rebuild;
    }
    next if $nowrite;
    print STDERR "$lib: $fnew{$lib} new functions\n" if $fnew{$lib};
    print STDERR "$lib: $rnew{$lib} new reasons\n" if $rnew{$lib};
    $newstate = 1;
416

417 418 419 420 421 422 423 424 425 426 427 428 429
    # If we get here then we have some new error codes so we
    # need to rebuild the header file and C file.

    # Make a sorted list of error and reason codes for later use.
    my @function = sort grep( /^${lib}_/, keys %fcodes );
    my @reasons  = sort grep( /^${lib}_/, keys %rcodes );

    # Rewrite the header file

    my $hfile = $hinc{$lib};
    $hfile =~ s/.h$/err.h/ if $internal;
    open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,";
    print OUT <<"EOF";
M
Matt Caswell 已提交
430
/*
431 432 433 434 435 436 437
 * Generated by util/mkerr.pl DO NOT EDIT
 * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the \"License\").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
438
 */
R
Richard Levitte 已提交
439

440 441
#ifndef HEADER_${lib}ERR_H
# define HEADER_${lib}ERR_H
R
Richard Levitte 已提交
442

443
EOF
444 445 446 447 448 449 450 451 452 453 454
    if ( $internal ) {
        # Declare the load function because the generate C file
        # includes "fooerr.h" not "foo.h"
        print OUT <<"EOF";
# ifdef  __cplusplus
extern \"C\" {
# endif
int ERR_load_${lib}_strings(void);
# ifdef  __cplusplus
}
# endif
455
EOF
456 457 458
    } else {
        print OUT <<"EOF";
# define ${lib}err(f, r) ERR_${lib}_error((f), (r), OPENSSL_FILE, OPENSSL_LINE)
459 460

EOF
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
        if ( ! $static ) {
            print OUT <<"EOF";

# ifdef  __cplusplus
extern \"C\" {
# endif
int ERR_load_${lib}_strings(void);
void ERR_unload_${lib}_strings(void);
void ERR_${lib}_error(int function, int reason, char *file, int line);
# ifdef  __cplusplus
}
# endif
EOF
        }
    }

    print OUT "\n/*\n * $lib function codes.\n */\n";
    foreach my $i ( @function ) {
        my $z = 48 - length($i);
        if ( $fcodes{$i} eq "X" ) {
            $fassigned{$lib} =~ m/^:([^:]*):/;
            my $findcode = $1;
            $findcode = $fmax{$lib} if !defined $findcode;
            while ( $fassigned{$lib} =~ m/:$findcode:/ ) {
                $findcode++;
            }
            $fcodes{$i} = $findcode;
            $fassigned{$lib} .= "$findcode:";
            print STDERR "New Function code $i\n" if $debug;
        }
        printf OUT "# define $i%s $fcodes{$i}\n", " " x $z;
    }
493

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    print OUT "\n/*\n * $lib reason codes.\n */\n";
    foreach my $i ( @reasons ) {
        my $z = 48 - length($i);
        if ( $rcodes{$i} eq "X" ) {
            $rassigned{$lib} =~ m/^:([^:]*):/;
            my $findcode = $1;
            $findcode = $rmax{$lib} if !defined $findcode;
            while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
                $findcode++;
            }
            $rcodes{$i} = $findcode;
            $rassigned{$lib} .= "$findcode:";
            print STDERR "New Reason code $i\n" if $debug;
        }
        printf OUT "# define $i%s $rcodes{$i}\n", " " x $z;
    }
    print OUT "\n";

    print OUT "#endif\n";

    # Rewrite the C source file containing the error details.

    # First, read any existing reason string definitions:
    my $cfile = $errorfile{$lib};
    my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0";
    my $hincf = $hfile;
    $hincf =~ s|.*include/||;
    if ( $hincf =~ m|^openssl/| ) {
        $hincf = "<${hincf}>";
    } else {
        $hincf = "\"${hincf}\"";
    }

    open( OUT, ">$cfile" )
        || die "Can't open $cfile for writing, $!, stopped";

    my $const = $internal ? 'const ' : '';

    print OUT <<"EOF";
R
Rich Salz 已提交
533
/*
R
Rich Salz 已提交
534 535
 * Generated by util/mkerr.pl DO NOT EDIT
 * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
536
 *
R
Rich Salz 已提交
537 538 539 540
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
541 542 543
 */

#include <openssl/err.h>
544
#include $hincf
545

546
#ifndef OPENSSL_NO_ERR
547

548
static ${const}ERR_STRING_DATA ${lib}_str_functs[] = {
549
EOF
550 551 552 553

    # Add each function code: if a function name is found then use it.
    foreach my $i ( @function ) {
        my $fn;
R
Rich Salz 已提交
554 555 556 557 558 559 560 561 562
        if ( exists $strings{$i} and $strings{$i} ne '' ) {
            $fn = $strings{$i};
            $fn = "" if $fn eq '*';
        } else {
            $i =~ /^${lib}_F_(\S+)$/;
            $fn = $1;
            $fn = $ftrans{$fn} if exists $ftrans{$fn};
            $strings{$i} = $fn;
        }
563 564 565 566 567 568 569 570
        my $short = "    {ERR_PACK($pack_lib, $i, 0), \"$fn\"},";
        if ( length($short) <= 80 ) {
            print OUT "$short\n";
        } else {
            print OUT "    {ERR_PACK($pack_lib, $i, 0),\n     \"$fn\"},\n";
        }
    }
    print OUT <<"EOF";
M
Matt Caswell 已提交
571 572
    {0, NULL}
};
573

574
static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = {
575
EOF
576 577 578 579

    # Add each reason code.
    foreach my $i ( @reasons ) {
        my $rn;
R
Rich Salz 已提交
580 581 582
        if ( exists $strings{$i} ) {
            $rn = $strings{$i};
            $rn = "" if $rn eq '*';
583 584 585 586
        } else {
            $i =~ /^${lib}_R_(\S+)$/;
            $rn = $1;
            $rn =~ tr/_[A-Z]/ [a-z]/;
R
Rich Salz 已提交
587
            $strings{$i} = $rn;
588 589 590 591 592 593 594 595 596
        }
        my $short = "    {ERR_PACK($pack_lib, 0, $i), \"$rn\"},";
        if ( length($short) <= 80 ) {
            print OUT "$short\n";
        } else {
            print OUT "    {ERR_PACK($pack_lib, 0, $i),\n    \"$rn\"},\n";
        }
    }
    print OUT <<"EOF";
M
Matt Caswell 已提交
597 598
    {0, NULL}
};
599 600

#endif
601 602 603
EOF
    if ( $internal ) {
        print OUT <<"EOF";
604

605
int ERR_load_${lib}_strings(void)
M
Matt Caswell 已提交
606
{
607
#ifndef OPENSSL_NO_ERR
M
Matt Caswell 已提交
608
    if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) {
609 610
        ERR_load_strings_const(${lib}_str_functs);
        ERR_load_strings_const(${lib}_str_reasons);
M
Matt Caswell 已提交
611
    }
612
#endif
613
    return 1;
M
Matt Caswell 已提交
614
}
615
EOF
616 617 618
    } else {
        my $st = $static ? "static " : "";
        print OUT <<"EOF";
619

620 621
static int lib_code = 0;
static int error_loaded = 0;
622

623
${st}int ERR_load_${lib}_strings(void)
M
Matt Caswell 已提交
624
{
625 626
    if (lib_code == 0)
        lib_code = ERR_get_next_error_library();
627

628
    if (!error_loaded) {
629
#ifndef OPENSSL_NO_ERR
630 631
        ERR_load_strings(lib_code, ${lib}_str_functs);
        ERR_load_strings(lib_code, ${lib}_str_reasons);
632
#endif
633
        error_loaded = 1;
M
Matt Caswell 已提交
634
    }
635
    return 1;
M
Matt Caswell 已提交
636
}
637

638
${st}void ERR_unload_${lib}_strings(void)
M
Matt Caswell 已提交
639
{
640
    if (error_loaded) {
641
#ifndef OPENSSL_NO_ERR
642 643
        ERR_unload_strings(lib_code, ${lib}_str_functs);
        ERR_unload_strings(lib_code, ${lib}_str_reasons);
644
#endif
645
        error_loaded = 0;
M
Matt Caswell 已提交
646 647
    }
}
648

649
${st}void ERR_${lib}_error(int function, int reason, char *file, int line)
M
Matt Caswell 已提交
650
{
651 652 653
    if (lib_code == 0)
        lib_code = ERR_get_next_error_library();
    ERR_PUT_error(lib_code, function, reason, file, line);
M
Matt Caswell 已提交
654
}
655 656
EOF

657
    }
658

659
    close OUT;
660 661
}

662
&phase("Ending");
663
# Make a list of unreferenced function and reason codes
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
if ( $unref ) {
    my @funref;
    foreach ( keys %fcodes ) {
        push( @funref, $_ ) unless exists $usedfuncs{$_};
    }
    my @runref;
    foreach ( keys %rcodes ) {
        push( @runref, $_ ) unless exists $usedreasons{$_};
    }
    if ( @funref ) {
        print STDERR "The following function codes were not referenced:\n";
        foreach ( sort @funref ) {
            print STDERR "  $_\n";
        }
    }
    if ( @runref ) {
        print STDERR "The following reason codes were not referenced:\n";
        foreach ( sort @runref ) {
            print STDERR "  $_\n";
        }
    }
685 686
}

687
die "Found $errors errors, quitting" if $errors;
B
Ben Laurie 已提交
688

689 690 691 692
# Update the state file
if ( $newstate )  {
    open(OUT, ">$statefile.new")
        || die "Can't write $statefile.new, $!";
R
Rich Salz 已提交
693 694
    print OUT $statefile_prolog;
    print OUT "# Function codes\n";
695
    foreach my $i ( sort keys %fcodes ) {
R
Rich Salz 已提交
696 697 698 699
        my $short = "$i:$fcodes{$i}:";
        my $t = exists $strings{$i} ? $strings{$i} : "";
        $t = "\\\n\t" . $t if length($short) + length($t) > 80;
        print OUT "$short$t\n";
700
    }
R
Rich Salz 已提交
701
    print OUT "\n#Reason codes\n";
702
    foreach my $i ( sort keys %rcodes ) {
R
Rich Salz 已提交
703 704 705 706
        my $short = "$i:$rcodes{$i}:";
        my $t = exists $strings{$i} ? "$strings{$i}" : "";
        $t = "\\\n\t" . $t if length($short) + length($t) > 80;
        print OUT "$short$t\n" if !exists $rextra{$i};
707 708 709 710 711 712 713 714 715 716
    }
    close(OUT);
    if ( $skippedstate ) {
        print "Skipped state, leaving update in $statefile.new";
    } else {
        rename "$statefile", "$statefile.old"
            || die "Can't backup $statefile to $statefile.old, $!";
        rename "$statefile.new", "$statefile"
            || die "Can't rename $statefile to $statefile.new, $!";
    }
B
Ben Laurie 已提交
717
}
R
Rich Salz 已提交
718

719
exit;