X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=util%2Fmkerr.pl;h=28e180a9d46980d10667c568c12fd35c5ac550f2;hp=6c2237d1423e24df2fd65818defe4f097fee1703;hb=964ff301d6b50dabdb9daeb533f337e015f0419f;hpb=f924200e1b211e4f1012455dcd893de06b5df4bb diff --git a/util/mkerr.pl b/util/mkerr.pl old mode 100644 new mode 100755 index 6c2237d142..28e180a9d4 --- a/util/mkerr.pl +++ b/util/mkerr.pl @@ -1,629 +1,732 @@ -#!/usr/local/bin/perl -w - -my $config = "crypto/err/openssl.ec"; -my $debug = 0; -my $rebuild = 0; -my $static = 1; -my $recurse = 0; -my $reindex = 0; -my $dowrite = 0; -my $staticloader = ""; - -while (@ARGV) { - my $arg = $ARGV[0]; - if($arg eq "-conf") { - shift @ARGV; - $config = shift @ARGV; - } elsif($arg eq "-debug") { - $debug = 1; - shift @ARGV; - } elsif($arg eq "-rebuild") { - $rebuild = 1; - shift @ARGV; - } elsif($arg eq "-recurse") { - $recurse = 1; - shift @ARGV; - } elsif($arg eq "-reindex") { - $reindex = 1; - shift @ARGV; - } elsif($arg eq "-nostatic") { - $static = 0; - shift @ARGV; - } elsif($arg eq "-staticloader") { - $staticloader = "static "; - shift @ARGV; - } elsif($arg eq "-write") { - $dowrite = 1; - shift @ARGV; - } else { - last; - } +#! /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 + +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 %modules = (); + +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; } -if($recurse) { - @source = (, , ); -} else { - @source = @ARGV; -} +sub help +{ + print STDERR <<"EOF"; +mkerr.pl [options] [files...] -# Read in the config file +Options: -open(IN, "<$config") || die "Can't open config file $config"; + -conf FILE Use the named config file FILE instead of the default. -# Parse config file + -debug Verbose output debugging on stderr. -while() -{ - if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) { - $hinc{$1} = $2; - $libinc{$2} = $1; - $cskip{$3} = $1; - if($3 ne "NONE") { - $csrc{$1} = $3; - $fmax{$1} = 99; - $rmax{$1} = 99; - $fnew{$1} = 0; - $rnew{$1} = 0; - } - } elsif (/^F\s+(\S+)/) { - # Add extra function with $1 - } elsif (/^R\s+(\S+)\s+(\S+)/) { - $rextra{$1} = $2; - $rcodes{$1} = $2; - } + -internal Generate code that is to be built as part of OpenSSL itself. + Also scans internal list of files. + + -module M Only useful with -internal! + Only write files for library module M. Whether files are + actually written or not depends on other options, such as + -rebuild. + Note: this option is cumulative. If not given at all, all + internal modules will be considered. + + -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. + +EOF +} + +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 eq "-module" ) { + shift @ARGV; + $modules{uc $ARGV[0]} = 1; + } elsif ( $arg =~ /-*h(elp)?/ ) { + &help(); + exit; + } elsif ( $arg =~ /-.*/ ) { + die "Unknown option $arg; use -h for help.\n"; + } + shift @ARGV; } +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 { + die "-module isn't useful without -internal\n" if scalar keys %modules > 0; + @source = @ARGV; +} + +# 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 +my %strings; # define -> text + +# Read and parse the config file +open(IN, "$config") || die "Can't open config file $config, $!,"; +while ( ) { + 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; -# Scan each header file in turn and make a list of error codes -# and function names +my $statefile_prolog = ''; +if ( ! $statefile ) { + $statefile = $config; + $statefile =~ s/.ec/.txt/; +} -while (($hdr, $lib) = each %libinc) -{ - next if($hdr eq "NONE"); - print STDERR "Scanning header file $hdr\n" if $debug; - my $line = "", $def= "", $linenr = 0, $gotfile = 0; - if (open(IN, "<$hdr")) { - $gotfile = 1; - while() { - $linenr++; - print STDERR "line: $linenr\r" if $debug; - - last if(/BEGIN\s+ERROR\s+CODES/); - if ($line ne '') { - $_ = $line . $_; - $line = ''; - } - - if (/\\$/) { - $line = $_; - next; - } - - $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration - if ($cpp) { - $cpp = 0 if /^#.*endif/; - next; - } - - next if (/^\#/); # skip preprocessor directives - - s/\/\*.*?\*\///gs; # ignore comments - s/{[^{}]*}//gs; # ignore {} blocks - - if (/\{|\/\*/) { # Add a } so editor works... - $line = $_; - } else { - $def .= $_; - } - } - } - - print STDERR " \r" if $debug; - $defnr = 0; - foreach (split /;/, $def) { - $defnr++; - print STDERR "def: $defnr\r" if $debug; - - s/^[\n\s]*//g; - s/[\n\s]*$//g; - next if(/typedef\W/); - if (/\(\*(\w*)\([^\)]+/) { - my $name = $1; - $name =~ tr/[a-z]/[A-Z]/; - $ftrans{$name} = $1; - } elsif (/\w+\W+(\w+)\W*\(\s*\)$/s){ - # K&R C - next ; - } elsif (/\w+\W+\w+\W*\(.*\)$/s) { - while (not /\(\)$/s) { - s/[^\(\)]*\)$/\)/s; - s/\([^\(\)]*\)\)$/\)/s; - } - s/\(void\)//; - /(\w+)\W*\(\)/s; - my $name = $1; - $name =~ tr/[a-z]/[A-Z]/; - $ftrans{$name} = $1; - } elsif (/\(/ and not (/=/ or /DECLARE_STACK/)) { - print STDERR "Header $hdr: cannot parse: $_;\n"; - } - } - - print STDERR " \r" if $debug; - - next if $reindex; - - # Scan function and reason codes and store them: keep a note of the - # maximum code used. - - if ($gotfile) { - while() { - if(/^\#define\s+(\S+)\s+(\S+)/) { - $name = $1; - $code = $2; - next if $name =~ /^${lib}err/; - unless($name =~ /^${lib}_([RF])_(\w+)$/) { - print STDERR "Invalid error code $name\n"; - next; - } - if($1 eq "R") { - $rcodes{$name} = $code; - if(!(exists $rextra{$name}) && - ($code > $rmax{$lib}) ) { - $rmax{$lib} = $code; - } - } else { - if($code > $fmax{$lib}) { - $fmax{$lib} = $code; - } - $fcodes{$name} = $code; - } - } - } - } - close IN; +# 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. + my $collecting = 1; + while ( ) { + $statefile_prolog .= $_ if $collecting && ( /^#/ || /^$/ ); + next if /^#/ || /^$/; + my $name; + my $code; + if ( /^(.+):(\d+):\\$/ ) { + $name = $1; + $code = $2; + my $next = ; + $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; + 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"; + } + } + } +} + +# Scan each header file and make a list of error codes +# and function names +&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 ( ) { + $linenr++; + + if ( $line ne '' ) { + $_ = $line . $_; + $line = ''; + } + + if ( /\\$/ ) { + $line = $_; + next; + } + + if ( /\/\*/ ) { + if ( not /\*\// ) { # multiline comment... + $line = $_; # ... just accumulate + next; + } else { + s/\/\*.*?\*\///gs; # wipe it + } + } + + 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; + + # Last token just before the first () is a function name. + if ( /(\w+)\s*\(\).*/s ) { + my $name = $1; + $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; } +print STDERR "\n" if $debug; # 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 -# error library at the start. This seems to work fine except for the +# error library at the start. This seems to work fine except for the # 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. -# Store all function and reason codes found in %ufcodes and %urcodes +# Store all function and reason codes found in %usedfuncs and %usedreasons # so all those unreferenced can be printed out. - - -print STDERR "Files loaded: " if $debug; -foreach $file (@source) { - # Don't parse the error source file. - next if exists $cskip{$file}; - print STDERR $file if $debug; - open(IN, "<$file") || die "Can't open source file $file\n"; - while() { - if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) { - next unless exists $csrc{$2}; - next if($1 eq "BIO_F_BUFFER_CTX"); - $ufcodes{$1} = 1; - if(!exists $fcodes{$1}) { - $fcodes{$1} = "X"; - $fnew{$2}++; - } - $notrans{$1} = 1 unless exists $ftrans{$3}; - } - if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) { - next unless exists $csrc{$2}; - $urcodes{$1} = 1; - if(!exists $rcodes{$1}) { - $rcodes{$1} = "X"; - $rnew{$2}++; - } - } - } - close IN; +&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 ( ) { + + # 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 ) { + print STDERR "ERROR: mismatch $file:$linenr $func:$3\n"; + $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}++; + } + print STDERR " Reason $1 = $rcodes{$1}\n" if $debug; + } + } + close IN; } print STDERR "\n" if $debug; # Now process each library in turn. - -foreach $lib (keys %csrc) -{ - my $hfile = $hinc{$lib}; - my $cfile = $csrc{$lib}; - if(!$fnew{$lib} && !$rnew{$lib}) { - print STDERR "$lib:\t\tNo new error codes\n"; - next unless $rebuild; - } else { - print STDERR "$lib:\t\t$fnew{$lib} New Functions,"; - print STDERR " $rnew{$lib} New Reasons.\n"; - next unless $dowrite; - } - - # 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 - - if (open(IN, "<$hfile")) { - # Copy across the old file - while() { - push @out, $_; - last if (/BEGIN ERROR CODES/); - } - close IN; - } else { - push @out, -"/* ====================================================================\n", -" * Copyright (c) 2001 The OpenSSL Project. All rights reserved.\n", -" *\n", -" * Redistribution and use in source and binary forms, with or without\n", -" * modification, are permitted provided that the following conditions\n", -" * are met:\n", -" *\n", -" * 1. Redistributions of source code must retain the above copyright\n", -" * notice, this list of conditions and the following disclaimer. \n", -" *\n", -" * 2. Redistributions in binary form must reproduce the above copyright\n", -" * notice, this list of conditions and the following disclaimer in\n", -" * the documentation and/or other materials provided with the\n", -" * distribution.\n", -" *\n", -" * 3. All advertising materials mentioning features or use of this\n", -" * software must display the following acknowledgment:\n", -" * \"This product includes software developed by the OpenSSL Project\n", -" * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n", -" *\n", -" * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n", -" * endorse or promote products derived from this software without\n", -" * prior written permission. For written permission, please contact\n", -" * openssl-core\@openssl.org.\n", -" *\n", -" * 5. Products derived from this software may not be called \"OpenSSL\"\n", -" * nor may \"OpenSSL\" appear in their names without prior written\n", -" * permission of the OpenSSL Project.\n", -" *\n", -" * 6. Redistributions of any form whatsoever must retain the following\n", -" * acknowledgment:\n", -" * \"This product includes software developed by the OpenSSL Project\n", -" * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n", -" *\n", -" * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n", -" * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n", -" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n", -" * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n", -" * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n", -" * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n", -" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n", -" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n", -" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n", -" * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n", -" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n", -" * OF THE POSSIBILITY OF SUCH DAMAGE.\n", -" * ====================================================================\n", -" *\n", -" * This product includes cryptographic software written by Eric Young\n", -" * (eay\@cryptsoft.com). This product includes software written by Tim\n", -" * Hudson (tjh\@cryptsoft.com).\n", -" *\n", -" */\n", -"\n", -"#ifndef HEADER_${lib}_ERR_H\n", -"#define HEADER_${lib}_ERR_H\n", -"\n", -"/* BEGIN ERROR CODES */\n"; - } - open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n"; - - print OUT @out; - undef @out; - print OUT <<"EOF"; -/* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. +&phase("Writing files"); +my $newstate = 0; +foreach my $lib ( keys %errorfile ) { + if ( ! $fnew{$lib} && ! $rnew{$lib} ) { + next unless $rebuild; + } + next if scalar keys %modules > 0 && !$modules{$lib}; + 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; + + # 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"; +/* + * 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 */ -EOF - if($static) { - print OUT <<"EOF"; -${staticloader}void ERR_load_${lib}_strings(void); -EOF - } else { - print OUT <<"EOF"; -${staticloader}void ERR_load_${lib}_strings(void); -${staticloader}void ERR_unload_${lib}_strings(void); -${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line); -#define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__) +#ifndef HEADER_${lib}ERR_H +# define HEADER_${lib}ERR_H EOF - } - print OUT <<"EOF"; -/* Error codes for the $lib functions. */ - -/* Function codes. */ + 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 EOF + } else { + print OUT <<"EOF"; +# define ${lib}err(f, r) ERR_${lib}_error((f), (r), OPENSSL_FILE, OPENSSL_LINE) - foreach $i (@function) { - $z=6-int(length($i)/8); - if($fcodes{$i} eq "X") { - $fcodes{$i} = ++$fmax{$lib}; - print STDERR "New Function code $i\n" if $debug; - } - printf OUT "#define $i%s $fcodes{$i}\n","\t" x $z; - } - - print OUT "\n/* Reason codes. */\n"; - - foreach $i (@reasons) { - $z=6-int(length($i)/8); - if($rcodes{$i} eq "X") { - $rcodes{$i} = ++$rmax{$lib}; - print STDERR "New Reason code $i\n" if $debug; - } - printf OUT "#define $i%s $rcodes{$i}\n","\t" x $z; - } - print OUT <<"EOF"; - -#ifdef __cplusplus +EOF + 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 -#endif +# endif EOF - close OUT; - - # Rewrite the C source file containing the error details. - - # First, read any existing reason string definitions: - my %err_reason_strings; - if (open(IN,"<$cfile")) { - while () { - if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) { - $err_reason_strings{$1} = $2; - } - } - close(IN); - } - - my $hincf; - if($static) { - $hfile =~ /([^\/]+)$/; - $hincf = ""; - } else { - $hincf = "\"$hfile\""; - } - - - open (OUT,">$cfile") || die "Can't open $cfile for writing"; - - print OUT <<"EOF"; -/* $cfile */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + } + } + + 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; + } + + 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"; +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core\@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay\@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh\@cryptsoft.com). - * - */ - -/* NOTE: this file was auto generated by the mkerr.pl script: any changes - * made to it will be overwritten when the script next updates this file, - * only reason strings will be preserved. + * 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 */ -#include #include #include $hincf -/* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR -static ERR_STRING_DATA ${lib}_str_functs[]= - { -EOF - # Add each function code: if a function name is found then use it. - foreach $i (@function) { - my $fn; - $i =~ /^${lib}_F_(\S+)$/; - $fn = $1; - if(exists $ftrans{$fn}) { - $fn = $ftrans{$fn}; - } - print OUT "{ERR_PACK(0,$i,0),\t\"$fn\"},\n"; - } - print OUT <<"EOF"; -{0,NULL} - }; - -static ERR_STRING_DATA ${lib}_str_reasons[]= - { + +static ${const}ERR_STRING_DATA ${lib}_str_functs[] = { EOF - # Add each reason code. - foreach $i (@reasons) { - my $rn; - my $nspc = 0; - if (exists $err_reason_strings{$i}) { - $rn = $err_reason_strings{$i}; - } else { - $i =~ /^${lib}_R_(\S+)$/; - $rn = $1; - $rn =~ tr/_[A-Z]/ [a-z]/; - } - $nspc = 40 - length($i) unless length($i) > 40; - $nspc = " " x $nspc; - print OUT "{${i}${nspc},\"$rn\"},\n"; - } -if($static) { - print OUT <<"EOF"; -{0,NULL} - }; -#endif + # Add each function code: if a function name is found then use it. + foreach my $i ( @function ) { + my $fn; + 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; + } + 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"; + {0, NULL} +}; + +static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = { +EOF -${staticloader}void ERR_load_${lib}_strings(void) - { - static int init=1; + # Add each reason code. + foreach my $i ( @reasons ) { + my $rn; + if ( exists $strings{$i} ) { + $rn = $strings{$i}; + $rn = "" if $rn eq '*'; + } else { + $i =~ /^${lib}_R_(\S+)$/; + $rn = $1; + $rn =~ tr/_[A-Z]/ [a-z]/; + $strings{$i} = $rn; + } + 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"; + {0, NULL} +}; - if (init) - { - init=0; -#ifndef OPENSSL_NO_ERR - ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs); - ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons); #endif - - } - } EOF -} else { - print OUT <<"EOF"; -{0,NULL} - }; + if ( $internal ) { + print OUT <<"EOF"; +int ERR_load_${lib}_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) { + ERR_load_strings_const(${lib}_str_functs); + ERR_load_strings_const(${lib}_str_reasons); + } #endif + return 1; +} +EOF + } else { + my $st = $static ? "static " : ""; + print OUT <<"EOF"; -#ifdef ${lib}_LIB_NAME -static ERR_STRING_DATA ${lib}_lib_name[]= - { -{0 ,${lib}_LIB_NAME}, -{0,NULL} - }; -#endif - - -static int ${lib}_lib_error_code=0; -static int ${lib}_error_init=1; +static int lib_code = 0; +static int error_loaded = 0; -${staticloader}void ERR_load_${lib}_strings(void) - { - if (${lib}_lib_error_code == 0) - ${lib}_lib_error_code=ERR_get_next_error_library(); +${st}int ERR_load_${lib}_strings(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); - if (${lib}_error_init) - { - ${lib}_error_init=0; + if (!error_loaded) { #ifndef OPENSSL_NO_ERR - ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs); - ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons); + ERR_load_strings(lib_code, ${lib}_str_functs); + ERR_load_strings(lib_code, ${lib}_str_reasons); #endif + error_loaded = 1; + } + return 1; +} -#ifdef ${lib}_LIB_NAME - ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0); - ERR_load_strings(0,${lib}_lib_name); -#endif - } - } - -${staticloader}void ERR_unload_${lib}_strings(void) - { - if (${lib}_error_init == 0) - { +${st}void ERR_unload_${lib}_strings(void) +{ + if (error_loaded) { #ifndef OPENSSL_NO_ERR - ERR_unload_strings(${lib}_lib_error_code,${lib}_str_functs); - ERR_unload_strings(${lib}_lib_error_code,${lib}_str_reasons); -#endif - -#ifdef ${lib}_LIB_NAME - ERR_unload_strings(0,${lib}_lib_name); + ERR_unload_strings(lib_code, ${lib}_str_functs); + ERR_unload_strings(lib_code, ${lib}_str_reasons); #endif - ${lib}_error_init=1; - } - } - -${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line) - { - if (${lib}_lib_error_code == 0) - ${lib}_lib_error_code=ERR_get_next_error_library(); - ERR_PUT_error(${lib}_lib_error_code,function,reason,file,line); - } -EOF - -} - - close OUT; - undef %err_reason_strings; + error_loaded = 0; + } } -if($debug && defined(%notrans)) { - print STDERR "The following function codes were not translated:\n"; - foreach(sort keys %notrans) - { - print STDERR "$_\n"; - } +${st}void ERR_${lib}_error(int function, int reason, char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_PUT_error(lib_code, function, reason, file, line); } +EOF -# Make a list of unreferenced function and reason codes + } -foreach (keys %fcodes) { - push (@funref, $_) unless exists $ufcodes{$_}; + close OUT; } -foreach (keys %rcodes) { - push (@runref, $_) unless exists $urcodes{$_}; +&phase("Ending"); +# Make a list of unreferenced function and reason codes +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"; + } + } } -if($debug && defined(@funref) ) { - print STDERR "The following function codes were not referenced:\n"; - foreach(sort @funref) - { - print STDERR "$_\n"; - } +die "Found $errors errors, quitting" if $errors; + +# Update the state file +if ( $newstate ) { + open(OUT, ">$statefile.new") + || die "Can't write $statefile.new, $!"; + print OUT $statefile_prolog; + print OUT "# Function codes\n"; + foreach my $i ( sort keys %fcodes ) { + 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"; + } + print OUT "\n#Reason codes\n"; + foreach my $i ( sort keys %rcodes ) { + 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}; + } + 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, $!"; + } } -if($debug && defined(@runref) ) { - print STDERR "The following reason codes were not referenced:\n"; - foreach(sort @runref) - { - print STDERR "$_\n"; - } -} +exit;