X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=util%2Fmkerr.pl;h=e297797b6a88fc1efa0e4b78d649c06726791cf2;hb=HEAD;hp=b744c81d6b970a359b0012808420a102cf7dae77;hpb=226cc7ded421041f561215a8e3f25e48a0574d6c;p=openssl.git diff --git a/util/mkerr.pl b/util/mkerr.pl old mode 100644 new mode 100755 index b744c81d6b..6f22bbd582 --- a/util/mkerr.pl +++ b/util/mkerr.pl @@ -1,528 +1,706 @@ -#!/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; - - -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 "-write") { - $dowrite = 1; - shift @ARGV; - } else { - last; - } +#! /usr/bin/env perl +# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (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; + +use File::Basename; +use File::Spec::Functions qw(abs2rel rel2abs); + +use lib "."; +use configdata; + +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; - $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'), glob('ssl/*/*/*.c'), + glob('providers/*.c'), glob('providers/*/*.c'), + glob('providers/*/*/*.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 %hpubinc; # lib -> public header +my %libpubinc; # public header -> lib +my %hprivinc; # lib -> private header +my %libprivinc; # private header -> lib +my %cskip; # error_file -> lib +my %errorfile; # lib -> error file name +my %rmax; # lib -> max assigned reason code +my %rassigned; # lib -> colon-separated list of assigned reason codes +my %rnew; # lib -> count of new reason codes +my %rextra; # "extra" reason code -> lib +my %rcodes; # reason-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+)(?:\s+(\S+))?\s+$/ ) { + my $lib = $1; + my $pubhdr = $2; + my $err = $3; + my $privhdr = $4 // 'NONE'; + $hpubinc{$lib} = $pubhdr; + $libpubinc{$pubhdr} = $lib; + $hprivinc{$lib} = $privhdr; + $libprivinc{$privhdr} = $lib; + $cskip{$err} = $lib; + $errorfile{$lib} = $err; + next if $err eq 'NONE'; + $rmax{$lib} = 100; + $rassigned{$lib} = ":"; + $rnew{$lib} = 0; + die "Public header file must be in include/openssl ($pubhdr is not)\n" + if ($internal + && $pubhdr ne 'NONE' + && $pubhdr !~ m|^include/openssl/|); + die "Private header file may only be specified with -internal ($privhdr given)\n" + unless ($privhdr eq 'NONE' || $internal); + } 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 +if ( ! $statefile ) { + $statefile = $config; + $statefile =~ s/.ec/.txt/; +} -while (($lib, $hdr) = each %hinc) -{ - next if($hdr eq "NONE"); - print STDERR "Scanning header file $hdr\n" if $debug; - open(IN, "<$hdr") || die "Can't open Header file $hdr\n"; - my $line = "", $def= "", $linenr = 0; - 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. - - while() { - if(/^#define\s+(\S+)\s+(\S+)/) { - $name = $1; - $code = $2; - 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. + while ( ) { + 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"; + } + my $lib = $name; + $lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/; + $lib = "SSL" if $lib =~ /TLS/; + if ( !defined $errorfile{$lib} ) { + print "Skipping $_"; + $skippedstate++; + next; + } + next if $errorfile{$lib} eq 'NONE'; + if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_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 =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) { + # We do nothing with the function codes, just let them go away + } 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"; + } + } + } } -# 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 -# oddly named structure BIO_F_CTX which needs to be ignored. +# Scan each C source file and look for reason codes. This is done by +# looking for strings that "look like" reason codes: basically anything +# consisting of all uppercase and numerics which _R_ in it and which has +# the name of an error library at the start. Should there be anything else, +# such as a type name, we add exceptions here. # 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 -# so all those unreferenced can be printed out. - - -foreach $file (@source) { - # Don't parse the error source file. - next if exists $cskip{$file}; - 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; +# Store all reason codes found in and %usedreasons so all those unreferenced +# can be printed out. +&phase("Scanning source"); +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 ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) { + next unless exists $errorfile{$2}; + next if $errorfile{$2} eq 'NONE'; + $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 - - open(IN, "<$hfile") || die "Can't Open Header File $hfile\n"; - - # Copy across the old file - while() { - push @out, $_; - last if (/BEGIN ERROR CODES/); - } - close IN; - - 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 ) { + next if ! $rnew{$lib} && ! $rebuild; + next if scalar keys %modules > 0 && !$modules{$lib}; + next if $nowrite; + 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 @reasons = sort grep( /^${lib}_/, keys %rcodes ); + + # indent level for innermost preprocessor lines + my $indent = " "; + + # Flag if the sub-library is disablable + # There are a few exceptions, where disabling the sub-library + # doesn't actually remove the whole sub-library, but rather implements + # it with a NULL backend. + my $disablable = + ($lib ne "SSL" && $lib ne "ASYNC" && $lib ne "DSO" + && (grep { $lib eq uc $_ } @disablables, @disablables_int)); + + # Rewrite the internal header file if there is one ($internal only!) + + if ($hprivinc{$lib} ne 'NONE') { + my $hfile = $hprivinc{$lib}; + my $guard = $hfile; + + if ($guard =~ m|^include/|) { + $guard = $'; + } else { + $guard = basename($guard); + } + $guard = "OSSL_" . join('_', split(m|[./]|, uc $guard)); + + open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,"; + print OUT <<"EOF"; +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 2020-$YEAR The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 */ -/* Error codes for the $lib functions. */ +#ifndef $guard +# define $guard +# pragma once + +# include +# include + +# ifdef __cplusplus +extern \"C\" { +# endif -/* Function codes. */ EOF + $indent = ' '; + if ($disablable) { + print OUT <<"EOF"; +# ifndef OPENSSL_NO_${lib} - 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 + $indent = " "; + } + print OUT <<"EOF"; +int ossl_err_load_${lib}_strings(void); +EOF + + # If this library doesn't have a public header file, we write all + # definitions that would end up there here instead + if ($hpubinc{$lib} eq 'NONE') { + print OUT "\n/*\n * $lib reason codes.\n */\n"; + foreach my $i ( @reasons ) { + my $z = 48 - length($i); + $z = 0 if $z < 0; + 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 "#${indent}define $i%s $rcodes{$i}\n", " " x $z; + } + print OUT "\n"; + } + + # This doesn't go all the way down to zero, to allow for the ending + # brace for 'extern "C" {'. + while (length($indent) > 1) { + $indent = substr $indent, 0, -1; + print OUT "#${indent}endif\n"; + } + + print OUT <<"EOF"; + +# 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: - * - * 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). + close OUT; + } + + # Rewrite the public header file + + if ($hpubinc{$lib} ne 'NONE') { + my $extra_include = + $internal + ? ($lib ne 'SSL' + ? "# include \n" + : "# include \n") + : ''; + my $hfile = $hpubinc{$lib}; + my $guard = $hfile; + $guard =~ s|^include/||; + $guard = join('_', split(m|[./]|, uc $guard)); + $guard = "OSSL_" . $guard unless $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 Apache License 2.0 (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 */ -/* 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. - */ +#ifndef $guard +# define $guard +# pragma once -#include -#include -#include $hincf +# include +# include +$extra_include -/* 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[]= - { -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 + $indent = ' '; + if ( $internal ) { + if ($disablable) { + print OUT <<"EOF"; +# ifndef OPENSSL_NO_${lib} -void ERR_load_${lib}_strings(void) - { - static int init=1; +EOF + $indent .= ' '; + } + } else { + print OUT <<"EOF"; +# define ${lib}err(f, r) ERR_${lib}_error(0, (r), OPENSSL_FILE, OPENSSL_LINE) +# define ERR_R_${lib}_LIB ERR_${lib}_lib() - 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 + 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, const char *file, int line); +# ifdef __cplusplus +} +# endif +EOF + } + } + + print OUT "\n/*\n * $lib reason codes.\n */\n"; + foreach my $i ( @reasons ) { + my $z = 48 - length($i); + $z = 0 if $z < 0; + 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 "#${indent}define $i%s $rcodes{$i}\n", " " x $z; + } + print OUT "\n"; + + while (length($indent) > 0) { + $indent = substr $indent, 0, -1; + print OUT "#${indent}endif\n"; + } + close OUT; + } + + # Rewrite the C source file containing the error details. + + if ($errorfile{$lib} ne 'NONE') { + # First, read any existing reason string definitions: + my $cfile = $errorfile{$lib}; + my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0"; + my $hpubincf = $hpubinc{$lib}; + my $hprivincf = $hprivinc{$lib}; + my $includes = ''; + if ($internal) { + if ($hpubincf ne 'NONE') { + $hpubincf =~ s|^include/||; + $includes .= "#include <${hpubincf}>\n"; + } + if ($hprivincf =~ m|^include/|) { + $hprivincf = $'; + } else { + $hprivincf = abs2rel(rel2abs($hprivincf), + rel2abs(dirname($cfile))); + } + $includes .= "#include \"${hprivincf}\"\n"; + } else { + $includes .= "#include \"${hpubincf}\"\n"; + } + + 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. + * + * Licensed under the Apache License 2.0 (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 +$includes EOF -} else { - print OUT <<"EOF"; -{0,NULL} - }; + $indent = ''; + if ( $internal ) { + if ($disablable) { + print OUT <<"EOF"; +#ifndef OPENSSL_NO_${lib} -#endif +EOF + $indent .= ' '; + } + } + print OUT <<"EOF"; +#${indent}ifndef OPENSSL_NO_ERR -#ifdef ${lib}_LIB_NAME -static ERR_STRING_DATA ${lib}_lib_name[]= - { -{0 ,${lib}_LIB_NAME}, -{0,NULL} - }; -#endif +static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = { +EOF + # 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} +}; + +#${indent}endif +EOF + if ( $internal ) { + print OUT <<"EOF"; -int ${lib}_lib_error_code=0; +int ossl_err_load_${lib}_strings(void) +{ +#${indent}ifndef OPENSSL_NO_ERR + if (ERR_reason_error_string(${lib}_str_reasons[0].error) == NULL) + ERR_load_strings_const(${lib}_str_reasons); +#${indent}endif + return 1; +} +EOF + } else { + my $st = $static ? "static " : ""; + print OUT <<"EOF"; -void ERR_load_${lib}_strings(void) - { - static int init=1; +static int lib_code = 0; +static int error_loaded = 0; - 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 (init) - { - 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_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); +${st}void ERR_unload_${lib}_strings(void) +{ + if (error_loaded) { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(lib_code, ${lib}_str_reasons); #endif - } - } - -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 - + error_loaded = 0; + } } - close OUT; - undef %err_reason_strings; +${st}void ERR_${lib}_error(int function, int reason, const char *file, int line) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + ERR_raise(lib_code, reason); + ERR_set_debug(file, line, NULL); } -if($debug && defined(%notrans)) { - print STDERR "The following function codes were not translated:\n"; - foreach(sort keys %notrans) - { - print STDERR "$_\n"; - } +${st}int ERR_${lib}_lib(void) +{ + if (lib_code == 0) + lib_code = ERR_get_next_error_library(); + return lib_code; } +EOF -# Make a list of unreferenced function and reason codes + } -foreach (keys %fcodes) { - push (@funref, $_) unless exists $ufcodes{$_}; + while (length($indent) > 1) { + $indent = substr $indent, 0, -1; + print OUT "#${indent}endif\n"; + } + if ($internal && $disablable) { + print OUT <<"EOF"; +#else +NON_EMPTY_TRANSLATION_UNIT +#endif +EOF + } + close OUT; + } } -foreach (keys %rcodes) { - push (@runref, $_) unless exists $urcodes{$_}; +&phase("Ending"); +# Make a list of unreferenced reason codes +if ( $unref ) { + my @runref; + foreach ( keys %rcodes ) { + push( @runref, $_ ) unless exists $usedreasons{$_}; + } + 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 <<"EOF"; +# Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (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 + 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"; + } + 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;