-#!/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-2022 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 = (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>);
-} 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(<IN>)
-{
- 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 ( <IN> ) {
+ 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(<IN>) {
- $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(<IN>) {
- 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 ( <STATE> ) {
+ next if /^#/ || /^$/;
+ 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";
+ }
+ 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(<IN>) {
- 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 ( <IN> ) {
+
+ # 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(<IN>) {
- 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 <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+# ifdef __cplusplus
+extern \"C\" {
+# endif
+
+EOF
+ $indent = ' ';
+ if ($disablable) {
+ print OUT <<"EOF";
+# ifndef OPENSSL_NO_${lib}
-/* Function codes. */
+EOF
+ $indent = " ";
+ }
+ print OUT <<"EOF";
+int ossl_err_load_${lib}_strings(void);
EOF
- 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
+ # 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 (<IN>) {
- if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
- $err_reason_strings{$1} = $2;
- }
- }
- close(IN);
- }
-
- my $hincf;
- if($static) {
- $hfile =~ /([^\/]+)$/;
- $hincf = "<openssl/$1>";
- } 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 <openssl/cryptoerr_legacy.h>\n"
+ : "# include <openssl/sslerr_legacy.h>\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 <stdio.h>
-#include <openssl/err.h>
-#include $hincf
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+$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 <openssl/err.h>
+$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" 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;