1*e0c4386eSCy Schubert#! /usr/bin/env perl 2*e0c4386eSCy Schubert# Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3*e0c4386eSCy Schubert# 4*e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License"). You may not use 5*e0c4386eSCy Schubert# this file except in compliance with the License. You can obtain a copy 6*e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at 7*e0c4386eSCy Schubert# https://www.openssl.org/source/license.html 8*e0c4386eSCy Schubert 9*e0c4386eSCy Schubertuse strict; 10*e0c4386eSCy Schubertuse warnings; 11*e0c4386eSCy Schubert 12*e0c4386eSCy Schubertuse File::Basename; 13*e0c4386eSCy Schubertuse File::Spec::Functions qw(abs2rel rel2abs); 14*e0c4386eSCy Schubert 15*e0c4386eSCy Schubertuse lib "."; 16*e0c4386eSCy Schubertuse configdata; 17*e0c4386eSCy Schubert 18*e0c4386eSCy Schubertmy $config = "crypto/err/openssl.ec"; 19*e0c4386eSCy Schubertmy $debug = 0; 20*e0c4386eSCy Schubertmy $internal = 0; 21*e0c4386eSCy Schubertmy $nowrite = 0; 22*e0c4386eSCy Schubertmy $rebuild = 0; 23*e0c4386eSCy Schubertmy $reindex = 0; 24*e0c4386eSCy Schubertmy $static = 0; 25*e0c4386eSCy Schubertmy $unref = 0; 26*e0c4386eSCy Schubertmy %modules = (); 27*e0c4386eSCy Schubert 28*e0c4386eSCy Schubertmy $errors = 0; 29*e0c4386eSCy Schubertmy @t = localtime(); 30*e0c4386eSCy Schubertmy $YEAR = $t[5] + 1900; 31*e0c4386eSCy Schubert 32*e0c4386eSCy Schubertsub phase 33*e0c4386eSCy Schubert{ 34*e0c4386eSCy Schubert my $text = uc(shift); 35*e0c4386eSCy Schubert print STDERR "\n---\n$text\n" if $debug; 36*e0c4386eSCy Schubert} 37*e0c4386eSCy Schubert 38*e0c4386eSCy Schubertsub help 39*e0c4386eSCy Schubert{ 40*e0c4386eSCy Schubert print STDERR <<"EOF"; 41*e0c4386eSCy Schubertmkerr.pl [options] [files...] 42*e0c4386eSCy Schubert 43*e0c4386eSCy SchubertOptions: 44*e0c4386eSCy Schubert 45*e0c4386eSCy Schubert -conf FILE Use the named config file FILE instead of the default. 46*e0c4386eSCy Schubert 47*e0c4386eSCy Schubert -debug Verbose output debugging on stderr. 48*e0c4386eSCy Schubert 49*e0c4386eSCy Schubert -internal Generate code that is to be built as part of OpenSSL itself. 50*e0c4386eSCy Schubert Also scans internal list of files. 51*e0c4386eSCy Schubert 52*e0c4386eSCy Schubert -module M Only useful with -internal! 53*e0c4386eSCy Schubert Only write files for library module M. Whether files are 54*e0c4386eSCy Schubert actually written or not depends on other options, such as 55*e0c4386eSCy Schubert -rebuild. 56*e0c4386eSCy Schubert Note: this option is cumulative. If not given at all, all 57*e0c4386eSCy Schubert internal modules will be considered. 58*e0c4386eSCy Schubert 59*e0c4386eSCy Schubert -nowrite Do not write the header/source files, even if changed. 60*e0c4386eSCy Schubert 61*e0c4386eSCy Schubert -rebuild Rebuild all header and C source files, even if there 62*e0c4386eSCy Schubert were no changes. 63*e0c4386eSCy Schubert 64*e0c4386eSCy Schubert -reindex Ignore previously assigned values (except for R records in 65*e0c4386eSCy Schubert the config file) and renumber everything starting at 100. 66*e0c4386eSCy Schubert 67*e0c4386eSCy Schubert -static Make the load/unload functions static. 68*e0c4386eSCy Schubert 69*e0c4386eSCy Schubert -unref List all unreferenced function and reason codes on stderr; 70*e0c4386eSCy Schubert implies -nowrite. 71*e0c4386eSCy Schubert 72*e0c4386eSCy Schubert -help Show this help text. 73*e0c4386eSCy Schubert 74*e0c4386eSCy Schubert ... Additional arguments are added to the file list to scan, 75*e0c4386eSCy Schubert if '-internal' was NOT specified on the command line. 76*e0c4386eSCy Schubert 77*e0c4386eSCy SchubertEOF 78*e0c4386eSCy Schubert} 79*e0c4386eSCy Schubert 80*e0c4386eSCy Schubertwhile ( @ARGV ) { 81*e0c4386eSCy Schubert my $arg = $ARGV[0]; 82*e0c4386eSCy Schubert last unless $arg =~ /-.*/; 83*e0c4386eSCy Schubert $arg = $1 if $arg =~ /-(-.*)/; 84*e0c4386eSCy Schubert if ( $arg eq "-conf" ) { 85*e0c4386eSCy Schubert $config = $ARGV[1]; 86*e0c4386eSCy Schubert shift @ARGV; 87*e0c4386eSCy Schubert } elsif ( $arg eq "-debug" ) { 88*e0c4386eSCy Schubert $debug = 1; 89*e0c4386eSCy Schubert $unref = 1; 90*e0c4386eSCy Schubert } elsif ( $arg eq "-internal" ) { 91*e0c4386eSCy Schubert $internal = 1; 92*e0c4386eSCy Schubert } elsif ( $arg eq "-nowrite" ) { 93*e0c4386eSCy Schubert $nowrite = 1; 94*e0c4386eSCy Schubert } elsif ( $arg eq "-rebuild" ) { 95*e0c4386eSCy Schubert $rebuild = 1; 96*e0c4386eSCy Schubert } elsif ( $arg eq "-reindex" ) { 97*e0c4386eSCy Schubert $reindex = 1; 98*e0c4386eSCy Schubert } elsif ( $arg eq "-static" ) { 99*e0c4386eSCy Schubert $static = 1; 100*e0c4386eSCy Schubert } elsif ( $arg eq "-unref" ) { 101*e0c4386eSCy Schubert $unref = 1; 102*e0c4386eSCy Schubert $nowrite = 1; 103*e0c4386eSCy Schubert } elsif ( $arg eq "-module" ) { 104*e0c4386eSCy Schubert shift @ARGV; 105*e0c4386eSCy Schubert $modules{uc $ARGV[0]} = 1; 106*e0c4386eSCy Schubert } elsif ( $arg =~ /-*h(elp)?/ ) { 107*e0c4386eSCy Schubert &help(); 108*e0c4386eSCy Schubert exit; 109*e0c4386eSCy Schubert } elsif ( $arg =~ /-.*/ ) { 110*e0c4386eSCy Schubert die "Unknown option $arg; use -h for help.\n"; 111*e0c4386eSCy Schubert } 112*e0c4386eSCy Schubert shift @ARGV; 113*e0c4386eSCy Schubert} 114*e0c4386eSCy Schubert 115*e0c4386eSCy Schubertmy @source; 116*e0c4386eSCy Schubertif ( $internal ) { 117*e0c4386eSCy Schubert die "Cannot mix -internal and -static\n" if $static; 118*e0c4386eSCy Schubert die "Extra parameters given.\n" if @ARGV; 119*e0c4386eSCy Schubert @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'), 120*e0c4386eSCy Schubert glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'), 121*e0c4386eSCy Schubert glob('providers/*/*.c'), glob('providers/*/*/*.c') ); 122*e0c4386eSCy Schubert} else { 123*e0c4386eSCy Schubert die "-module isn't useful without -internal\n" if scalar keys %modules > 0; 124*e0c4386eSCy Schubert @source = @ARGV; 125*e0c4386eSCy Schubert} 126*e0c4386eSCy Schubert 127*e0c4386eSCy Schubert# Data parsed out of the config and state files. 128*e0c4386eSCy Schubertmy %hpubinc; # lib -> public header 129*e0c4386eSCy Schubertmy %libpubinc; # public header -> lib 130*e0c4386eSCy Schubertmy %hprivinc; # lib -> private header 131*e0c4386eSCy Schubertmy %libprivinc; # private header -> lib 132*e0c4386eSCy Schubertmy %cskip; # error_file -> lib 133*e0c4386eSCy Schubertmy %errorfile; # lib -> error file name 134*e0c4386eSCy Schubertmy %rmax; # lib -> max assigned reason code 135*e0c4386eSCy Schubertmy %rassigned; # lib -> colon-separated list of assigned reason codes 136*e0c4386eSCy Schubertmy %rnew; # lib -> count of new reason codes 137*e0c4386eSCy Schubertmy %rextra; # "extra" reason code -> lib 138*e0c4386eSCy Schubertmy %rcodes; # reason-name -> value 139*e0c4386eSCy Schubertmy $statefile; # state file with assigned reason and function codes 140*e0c4386eSCy Schubertmy %strings; # define -> text 141*e0c4386eSCy Schubert 142*e0c4386eSCy Schubert# Read and parse the config file 143*e0c4386eSCy Schubertopen(IN, "$config") || die "Can't open config file $config, $!,"; 144*e0c4386eSCy Schubertwhile ( <IN> ) { 145*e0c4386eSCy Schubert next if /^#/ || /^$/; 146*e0c4386eSCy Schubert if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)(?:\s+(\S+))?\s+$/ ) { 147*e0c4386eSCy Schubert my $lib = $1; 148*e0c4386eSCy Schubert my $pubhdr = $2; 149*e0c4386eSCy Schubert my $err = $3; 150*e0c4386eSCy Schubert my $privhdr = $4 // 'NONE'; 151*e0c4386eSCy Schubert $hpubinc{$lib} = $pubhdr; 152*e0c4386eSCy Schubert $libpubinc{$pubhdr} = $lib; 153*e0c4386eSCy Schubert $hprivinc{$lib} = $privhdr; 154*e0c4386eSCy Schubert $libprivinc{$privhdr} = $lib; 155*e0c4386eSCy Schubert $cskip{$err} = $lib; 156*e0c4386eSCy Schubert $errorfile{$lib} = $err; 157*e0c4386eSCy Schubert next if $err eq 'NONE'; 158*e0c4386eSCy Schubert $rmax{$lib} = 100; 159*e0c4386eSCy Schubert $rassigned{$lib} = ":"; 160*e0c4386eSCy Schubert $rnew{$lib} = 0; 161*e0c4386eSCy Schubert die "Public header file must be in include/openssl ($pubhdr is not)\n" 162*e0c4386eSCy Schubert if ($internal 163*e0c4386eSCy Schubert && $pubhdr ne 'NONE' 164*e0c4386eSCy Schubert && $pubhdr !~ m|^include/openssl/|); 165*e0c4386eSCy Schubert die "Private header file may only be specified with -internal ($privhdr given)\n" 166*e0c4386eSCy Schubert unless ($privhdr eq 'NONE' || $internal); 167*e0c4386eSCy Schubert } elsif ( /^R\s+(\S+)\s+(\S+)/ ) { 168*e0c4386eSCy Schubert $rextra{$1} = $2; 169*e0c4386eSCy Schubert $rcodes{$1} = $2; 170*e0c4386eSCy Schubert } elsif ( /^S\s+(\S+)/ ) { 171*e0c4386eSCy Schubert $statefile = $1; 172*e0c4386eSCy Schubert } else { 173*e0c4386eSCy Schubert die "Illegal config line $_\n"; 174*e0c4386eSCy Schubert } 175*e0c4386eSCy Schubert} 176*e0c4386eSCy Schubertclose IN; 177*e0c4386eSCy Schubert 178*e0c4386eSCy Schubertif ( ! $statefile ) { 179*e0c4386eSCy Schubert $statefile = $config; 180*e0c4386eSCy Schubert $statefile =~ s/.ec/.txt/; 181*e0c4386eSCy Schubert} 182*e0c4386eSCy Schubert 183*e0c4386eSCy Schubert# The statefile has all the previous assignments. 184*e0c4386eSCy Schubert&phase("Reading state"); 185*e0c4386eSCy Schubertmy $skippedstate = 0; 186*e0c4386eSCy Schubertif ( ! $reindex && $statefile ) { 187*e0c4386eSCy Schubert open(STATE, "<$statefile") || die "Can't open $statefile, $!"; 188*e0c4386eSCy Schubert 189*e0c4386eSCy Schubert # Scan function and reason codes and store them: keep a note of the 190*e0c4386eSCy Schubert # maximum code used. 191*e0c4386eSCy Schubert while ( <STATE> ) { 192*e0c4386eSCy Schubert next if /^#/ || /^$/; 193*e0c4386eSCy Schubert my $name; 194*e0c4386eSCy Schubert my $code; 195*e0c4386eSCy Schubert if ( /^(.+):(\d+):\\$/ ) { 196*e0c4386eSCy Schubert $name = $1; 197*e0c4386eSCy Schubert $code = $2; 198*e0c4386eSCy Schubert my $next = <STATE>; 199*e0c4386eSCy Schubert $next =~ s/^\s*(.*)\s*$/$1/; 200*e0c4386eSCy Schubert die "Duplicate define $name" if exists $strings{$name}; 201*e0c4386eSCy Schubert $strings{$name} = $next; 202*e0c4386eSCy Schubert } elsif ( /^(\S+):(\d+):(.*)$/ ) { 203*e0c4386eSCy Schubert $name = $1; 204*e0c4386eSCy Schubert $code = $2; 205*e0c4386eSCy Schubert die "Duplicate define $name" if exists $strings{$name}; 206*e0c4386eSCy Schubert $strings{$name} = $3; 207*e0c4386eSCy Schubert } else { 208*e0c4386eSCy Schubert die "Bad line in $statefile:\n$_\n"; 209*e0c4386eSCy Schubert } 210*e0c4386eSCy Schubert my $lib = $name; 211*e0c4386eSCy Schubert $lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/; 212*e0c4386eSCy Schubert $lib = "SSL" if $lib =~ /TLS/; 213*e0c4386eSCy Schubert if ( !defined $errorfile{$lib} ) { 214*e0c4386eSCy Schubert print "Skipping $_"; 215*e0c4386eSCy Schubert $skippedstate++; 216*e0c4386eSCy Schubert next; 217*e0c4386eSCy Schubert } 218*e0c4386eSCy Schubert next if $errorfile{$lib} eq 'NONE'; 219*e0c4386eSCy Schubert if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_R_/ ) { 220*e0c4386eSCy Schubert die "$lib reason code $code collision at $name\n" 221*e0c4386eSCy Schubert if $rassigned{$lib} =~ /:$code:/; 222*e0c4386eSCy Schubert $rassigned{$lib} .= "$code:"; 223*e0c4386eSCy Schubert if ( !exists $rextra{$name} ) { 224*e0c4386eSCy Schubert $rmax{$lib} = $code if $code > $rmax{$lib}; 225*e0c4386eSCy Schubert } 226*e0c4386eSCy Schubert $rcodes{$name} = $code; 227*e0c4386eSCy Schubert } elsif ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) { 228*e0c4386eSCy Schubert # We do nothing with the function codes, just let them go away 229*e0c4386eSCy Schubert } else { 230*e0c4386eSCy Schubert die "Bad line in $statefile:\n$_\n"; 231*e0c4386eSCy Schubert } 232*e0c4386eSCy Schubert } 233*e0c4386eSCy Schubert close(STATE); 234*e0c4386eSCy Schubert 235*e0c4386eSCy Schubert if ( $debug ) { 236*e0c4386eSCy Schubert foreach my $lib ( sort keys %rmax ) { 237*e0c4386eSCy Schubert print STDERR "Reason codes for ${lib}:\n"; 238*e0c4386eSCy Schubert if ( $rassigned{$lib} =~ m/^:(.*):$/ ) { 239*e0c4386eSCy Schubert my @rassigned = sort { $a <=> $b } split( ":", $1 ); 240*e0c4386eSCy Schubert print STDERR " ", join(' ', @rassigned), "\n"; 241*e0c4386eSCy Schubert } else { 242*e0c4386eSCy Schubert print STDERR " --none--\n"; 243*e0c4386eSCy Schubert } 244*e0c4386eSCy Schubert } 245*e0c4386eSCy Schubert } 246*e0c4386eSCy Schubert} 247*e0c4386eSCy Schubert 248*e0c4386eSCy Schubert# Scan each C source file and look for reason codes. This is done by 249*e0c4386eSCy Schubert# looking for strings that "look like" reason codes: basically anything 250*e0c4386eSCy Schubert# consisting of all upper case and numerics which _R_ in it and which has 251*e0c4386eSCy Schubert# the name of an error library at the start. Should there be anything else, 252*e0c4386eSCy Schubert# such as a type name, we add exceptions here. 253*e0c4386eSCy Schubert# If a code doesn't exist in list compiled from headers then mark it 254*e0c4386eSCy Schubert# with the value "X" as a place holder to give it a value later. 255*e0c4386eSCy Schubert# Store all reason codes found in and %usedreasons so all those unreferenced 256*e0c4386eSCy Schubert# can be printed out. 257*e0c4386eSCy Schubert&phase("Scanning source"); 258*e0c4386eSCy Schubertmy %usedreasons; 259*e0c4386eSCy Schubertforeach my $file ( @source ) { 260*e0c4386eSCy Schubert # Don't parse the error source file. 261*e0c4386eSCy Schubert next if exists $cskip{$file}; 262*e0c4386eSCy Schubert open( IN, "<$file" ) || die "Can't open $file, $!,"; 263*e0c4386eSCy Schubert my $func; 264*e0c4386eSCy Schubert my $linenr = 0; 265*e0c4386eSCy Schubert print STDERR "$file:\n" if $debug; 266*e0c4386eSCy Schubert while ( <IN> ) { 267*e0c4386eSCy Schubert 268*e0c4386eSCy Schubert # skip obsoleted source files entirely! 269*e0c4386eSCy Schubert last if /^#error\s+obsolete/; 270*e0c4386eSCy Schubert $linenr++; 271*e0c4386eSCy Schubert 272*e0c4386eSCy Schubert if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) { 273*e0c4386eSCy Schubert next unless exists $errorfile{$2}; 274*e0c4386eSCy Schubert next if $errorfile{$2} eq 'NONE'; 275*e0c4386eSCy Schubert $usedreasons{$1} = 1; 276*e0c4386eSCy Schubert if ( !exists $rcodes{$1} ) { 277*e0c4386eSCy Schubert print STDERR " New reason $1\n" if $debug; 278*e0c4386eSCy Schubert $rcodes{$1} = "X"; 279*e0c4386eSCy Schubert $rnew{$2}++; 280*e0c4386eSCy Schubert } 281*e0c4386eSCy Schubert print STDERR " Reason $1 = $rcodes{$1}\n" if $debug; 282*e0c4386eSCy Schubert } 283*e0c4386eSCy Schubert } 284*e0c4386eSCy Schubert close IN; 285*e0c4386eSCy Schubert} 286*e0c4386eSCy Schubertprint STDERR "\n" if $debug; 287*e0c4386eSCy Schubert 288*e0c4386eSCy Schubert# Now process each library in turn. 289*e0c4386eSCy Schubert&phase("Writing files"); 290*e0c4386eSCy Schubertmy $newstate = 0; 291*e0c4386eSCy Schubertforeach my $lib ( keys %errorfile ) { 292*e0c4386eSCy Schubert next if ! $rnew{$lib} && ! $rebuild; 293*e0c4386eSCy Schubert next if scalar keys %modules > 0 && !$modules{$lib}; 294*e0c4386eSCy Schubert next if $nowrite; 295*e0c4386eSCy Schubert print STDERR "$lib: $rnew{$lib} new reasons\n" if $rnew{$lib}; 296*e0c4386eSCy Schubert $newstate = 1; 297*e0c4386eSCy Schubert 298*e0c4386eSCy Schubert # If we get here then we have some new error codes so we 299*e0c4386eSCy Schubert # need to rebuild the header file and C file. 300*e0c4386eSCy Schubert 301*e0c4386eSCy Schubert # Make a sorted list of error and reason codes for later use. 302*e0c4386eSCy Schubert my @reasons = sort grep( /^${lib}_/, keys %rcodes ); 303*e0c4386eSCy Schubert 304*e0c4386eSCy Schubert # indent level for innermost preprocessor lines 305*e0c4386eSCy Schubert my $indent = " "; 306*e0c4386eSCy Schubert 307*e0c4386eSCy Schubert # Flag if the sub-library is disablable 308*e0c4386eSCy Schubert # There are a few exceptions, where disabling the sub-library 309*e0c4386eSCy Schubert # doesn't actually remove the whole sub-library, but rather implements 310*e0c4386eSCy Schubert # it with a NULL backend. 311*e0c4386eSCy Schubert my $disablable = 312*e0c4386eSCy Schubert ($lib ne "SSL" && $lib ne "ASYNC" && $lib ne "DSO" 313*e0c4386eSCy Schubert && (grep { $lib eq uc $_ } @disablables, @disablables_int)); 314*e0c4386eSCy Schubert 315*e0c4386eSCy Schubert # Rewrite the internal header file if there is one ($internal only!) 316*e0c4386eSCy Schubert 317*e0c4386eSCy Schubert if ($hprivinc{$lib} ne 'NONE') { 318*e0c4386eSCy Schubert my $hfile = $hprivinc{$lib}; 319*e0c4386eSCy Schubert my $guard = $hfile; 320*e0c4386eSCy Schubert 321*e0c4386eSCy Schubert if ($guard =~ m|^include/|) { 322*e0c4386eSCy Schubert $guard = $'; 323*e0c4386eSCy Schubert } else { 324*e0c4386eSCy Schubert $guard = basename($guard); 325*e0c4386eSCy Schubert } 326*e0c4386eSCy Schubert $guard = "OSSL_" . join('_', split(m|[./]|, uc $guard)); 327*e0c4386eSCy Schubert 328*e0c4386eSCy Schubert open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,"; 329*e0c4386eSCy Schubert print OUT <<"EOF"; 330*e0c4386eSCy Schubert/* 331*e0c4386eSCy Schubert * Generated by util/mkerr.pl DO NOT EDIT 332*e0c4386eSCy Schubert * Copyright 2020-$YEAR The OpenSSL Project Authors. All Rights Reserved. 333*e0c4386eSCy Schubert * 334*e0c4386eSCy Schubert * Licensed under the Apache License 2.0 (the \"License\"). You may not use 335*e0c4386eSCy Schubert * this file except in compliance with the License. You can obtain a copy 336*e0c4386eSCy Schubert * in the file LICENSE in the source distribution or at 337*e0c4386eSCy Schubert * https://www.openssl.org/source/license.html 338*e0c4386eSCy Schubert */ 339*e0c4386eSCy Schubert 340*e0c4386eSCy Schubert#ifndef $guard 341*e0c4386eSCy Schubert# define $guard 342*e0c4386eSCy Schubert# pragma once 343*e0c4386eSCy Schubert 344*e0c4386eSCy Schubert# include <openssl/opensslconf.h> 345*e0c4386eSCy Schubert# include <openssl/symhacks.h> 346*e0c4386eSCy Schubert 347*e0c4386eSCy Schubert# ifdef __cplusplus 348*e0c4386eSCy Schubertextern \"C\" { 349*e0c4386eSCy Schubert# endif 350*e0c4386eSCy Schubert 351*e0c4386eSCy SchubertEOF 352*e0c4386eSCy Schubert $indent = ' '; 353*e0c4386eSCy Schubert if ($disablable) { 354*e0c4386eSCy Schubert print OUT <<"EOF"; 355*e0c4386eSCy Schubert# ifndef OPENSSL_NO_${lib} 356*e0c4386eSCy Schubert 357*e0c4386eSCy SchubertEOF 358*e0c4386eSCy Schubert $indent = " "; 359*e0c4386eSCy Schubert } 360*e0c4386eSCy Schubert print OUT <<"EOF"; 361*e0c4386eSCy Schubertint ossl_err_load_${lib}_strings(void); 362*e0c4386eSCy SchubertEOF 363*e0c4386eSCy Schubert 364*e0c4386eSCy Schubert # If this library doesn't have a public header file, we write all 365*e0c4386eSCy Schubert # definitions that would end up there here instead 366*e0c4386eSCy Schubert if ($hpubinc{$lib} eq 'NONE') { 367*e0c4386eSCy Schubert print OUT "\n/*\n * $lib reason codes.\n */\n"; 368*e0c4386eSCy Schubert foreach my $i ( @reasons ) { 369*e0c4386eSCy Schubert my $z = 48 - length($i); 370*e0c4386eSCy Schubert $z = 0 if $z < 0; 371*e0c4386eSCy Schubert if ( $rcodes{$i} eq "X" ) { 372*e0c4386eSCy Schubert $rassigned{$lib} =~ m/^:([^:]*):/; 373*e0c4386eSCy Schubert my $findcode = $1; 374*e0c4386eSCy Schubert $findcode = $rmax{$lib} if !defined $findcode; 375*e0c4386eSCy Schubert while ( $rassigned{$lib} =~ m/:$findcode:/ ) { 376*e0c4386eSCy Schubert $findcode++; 377*e0c4386eSCy Schubert } 378*e0c4386eSCy Schubert $rcodes{$i} = $findcode; 379*e0c4386eSCy Schubert $rassigned{$lib} .= "$findcode:"; 380*e0c4386eSCy Schubert print STDERR "New Reason code $i\n" if $debug; 381*e0c4386eSCy Schubert } 382*e0c4386eSCy Schubert printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z; 383*e0c4386eSCy Schubert } 384*e0c4386eSCy Schubert print OUT "\n"; 385*e0c4386eSCy Schubert } 386*e0c4386eSCy Schubert 387*e0c4386eSCy Schubert # This doesn't go all the way down to zero, to allow for the ending 388*e0c4386eSCy Schubert # brace for 'extern "C" {'. 389*e0c4386eSCy Schubert while (length($indent) > 1) { 390*e0c4386eSCy Schubert $indent = substr $indent, 0, -1; 391*e0c4386eSCy Schubert print OUT "#${indent}endif\n"; 392*e0c4386eSCy Schubert } 393*e0c4386eSCy Schubert 394*e0c4386eSCy Schubert print OUT <<"EOF"; 395*e0c4386eSCy Schubert 396*e0c4386eSCy Schubert# ifdef __cplusplus 397*e0c4386eSCy Schubert} 398*e0c4386eSCy Schubert# endif 399*e0c4386eSCy Schubert#endif 400*e0c4386eSCy SchubertEOF 401*e0c4386eSCy Schubert close OUT; 402*e0c4386eSCy Schubert } 403*e0c4386eSCy Schubert 404*e0c4386eSCy Schubert # Rewrite the public header file 405*e0c4386eSCy Schubert 406*e0c4386eSCy Schubert if ($hpubinc{$lib} ne 'NONE') { 407*e0c4386eSCy Schubert my $extra_include = 408*e0c4386eSCy Schubert $internal 409*e0c4386eSCy Schubert ? ($lib ne 'SSL' 410*e0c4386eSCy Schubert ? "# include <openssl/cryptoerr_legacy.h>\n" 411*e0c4386eSCy Schubert : "# include <openssl/sslerr_legacy.h>\n") 412*e0c4386eSCy Schubert : ''; 413*e0c4386eSCy Schubert my $hfile = $hpubinc{$lib}; 414*e0c4386eSCy Schubert my $guard = $hfile; 415*e0c4386eSCy Schubert $guard =~ s|^include/||; 416*e0c4386eSCy Schubert $guard = join('_', split(m|[./]|, uc $guard)); 417*e0c4386eSCy Schubert $guard = "OSSL_" . $guard unless $internal; 418*e0c4386eSCy Schubert 419*e0c4386eSCy Schubert open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,"; 420*e0c4386eSCy Schubert print OUT <<"EOF"; 421*e0c4386eSCy Schubert/* 422*e0c4386eSCy Schubert * Generated by util/mkerr.pl DO NOT EDIT 423*e0c4386eSCy Schubert * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. 424*e0c4386eSCy Schubert * 425*e0c4386eSCy Schubert * Licensed under the Apache License 2.0 (the \"License\"). You may not use 426*e0c4386eSCy Schubert * this file except in compliance with the License. You can obtain a copy 427*e0c4386eSCy Schubert * in the file LICENSE in the source distribution or at 428*e0c4386eSCy Schubert * https://www.openssl.org/source/license.html 429*e0c4386eSCy Schubert */ 430*e0c4386eSCy Schubert 431*e0c4386eSCy Schubert#ifndef $guard 432*e0c4386eSCy Schubert# define $guard 433*e0c4386eSCy Schubert# pragma once 434*e0c4386eSCy Schubert 435*e0c4386eSCy Schubert# include <openssl/opensslconf.h> 436*e0c4386eSCy Schubert# include <openssl/symhacks.h> 437*e0c4386eSCy Schubert$extra_include 438*e0c4386eSCy Schubert 439*e0c4386eSCy SchubertEOF 440*e0c4386eSCy Schubert $indent = ' '; 441*e0c4386eSCy Schubert if ( $internal ) { 442*e0c4386eSCy Schubert if ($disablable) { 443*e0c4386eSCy Schubert print OUT <<"EOF"; 444*e0c4386eSCy Schubert# ifndef OPENSSL_NO_${lib} 445*e0c4386eSCy Schubert 446*e0c4386eSCy SchubertEOF 447*e0c4386eSCy Schubert $indent .= ' '; 448*e0c4386eSCy Schubert } 449*e0c4386eSCy Schubert } else { 450*e0c4386eSCy Schubert print OUT <<"EOF"; 451*e0c4386eSCy Schubert# define ${lib}err(f, r) ERR_${lib}_error(0, (r), OPENSSL_FILE, OPENSSL_LINE) 452*e0c4386eSCy Schubert 453*e0c4386eSCy SchubertEOF 454*e0c4386eSCy Schubert if ( ! $static ) { 455*e0c4386eSCy Schubert print OUT <<"EOF"; 456*e0c4386eSCy Schubert 457*e0c4386eSCy Schubert# ifdef __cplusplus 458*e0c4386eSCy Schubertextern \"C\" { 459*e0c4386eSCy Schubert# endif 460*e0c4386eSCy Schubertint ERR_load_${lib}_strings(void); 461*e0c4386eSCy Schubertvoid ERR_unload_${lib}_strings(void); 462*e0c4386eSCy Schubertvoid ERR_${lib}_error(int function, int reason, const char *file, int line); 463*e0c4386eSCy Schubert# ifdef __cplusplus 464*e0c4386eSCy Schubert} 465*e0c4386eSCy Schubert# endif 466*e0c4386eSCy SchubertEOF 467*e0c4386eSCy Schubert } 468*e0c4386eSCy Schubert } 469*e0c4386eSCy Schubert 470*e0c4386eSCy Schubert print OUT "\n/*\n * $lib reason codes.\n */\n"; 471*e0c4386eSCy Schubert foreach my $i ( @reasons ) { 472*e0c4386eSCy Schubert my $z = 48 - length($i); 473*e0c4386eSCy Schubert $z = 0 if $z < 0; 474*e0c4386eSCy Schubert if ( $rcodes{$i} eq "X" ) { 475*e0c4386eSCy Schubert $rassigned{$lib} =~ m/^:([^:]*):/; 476*e0c4386eSCy Schubert my $findcode = $1; 477*e0c4386eSCy Schubert $findcode = $rmax{$lib} if !defined $findcode; 478*e0c4386eSCy Schubert while ( $rassigned{$lib} =~ m/:$findcode:/ ) { 479*e0c4386eSCy Schubert $findcode++; 480*e0c4386eSCy Schubert } 481*e0c4386eSCy Schubert $rcodes{$i} = $findcode; 482*e0c4386eSCy Schubert $rassigned{$lib} .= "$findcode:"; 483*e0c4386eSCy Schubert print STDERR "New Reason code $i\n" if $debug; 484*e0c4386eSCy Schubert } 485*e0c4386eSCy Schubert printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z; 486*e0c4386eSCy Schubert } 487*e0c4386eSCy Schubert print OUT "\n"; 488*e0c4386eSCy Schubert 489*e0c4386eSCy Schubert while (length($indent) > 0) { 490*e0c4386eSCy Schubert $indent = substr $indent, 0, -1; 491*e0c4386eSCy Schubert print OUT "#${indent}endif\n"; 492*e0c4386eSCy Schubert } 493*e0c4386eSCy Schubert close OUT; 494*e0c4386eSCy Schubert } 495*e0c4386eSCy Schubert 496*e0c4386eSCy Schubert # Rewrite the C source file containing the error details. 497*e0c4386eSCy Schubert 498*e0c4386eSCy Schubert if ($errorfile{$lib} ne 'NONE') { 499*e0c4386eSCy Schubert # First, read any existing reason string definitions: 500*e0c4386eSCy Schubert my $cfile = $errorfile{$lib}; 501*e0c4386eSCy Schubert my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0"; 502*e0c4386eSCy Schubert my $hpubincf = $hpubinc{$lib}; 503*e0c4386eSCy Schubert my $hprivincf = $hprivinc{$lib}; 504*e0c4386eSCy Schubert my $includes = ''; 505*e0c4386eSCy Schubert if ($internal) { 506*e0c4386eSCy Schubert if ($hpubincf ne 'NONE') { 507*e0c4386eSCy Schubert $hpubincf =~ s|^include/||; 508*e0c4386eSCy Schubert $includes .= "#include <${hpubincf}>\n"; 509*e0c4386eSCy Schubert } 510*e0c4386eSCy Schubert if ($hprivincf =~ m|^include/|) { 511*e0c4386eSCy Schubert $hprivincf = $'; 512*e0c4386eSCy Schubert } else { 513*e0c4386eSCy Schubert $hprivincf = abs2rel(rel2abs($hprivincf), 514*e0c4386eSCy Schubert rel2abs(dirname($cfile))); 515*e0c4386eSCy Schubert } 516*e0c4386eSCy Schubert $includes .= "#include \"${hprivincf}\"\n"; 517*e0c4386eSCy Schubert } else { 518*e0c4386eSCy Schubert $includes .= "#include \"${hpubincf}\"\n"; 519*e0c4386eSCy Schubert } 520*e0c4386eSCy Schubert 521*e0c4386eSCy Schubert open( OUT, ">$cfile" ) 522*e0c4386eSCy Schubert || die "Can't open $cfile for writing, $!, stopped"; 523*e0c4386eSCy Schubert 524*e0c4386eSCy Schubert my $const = $internal ? 'const ' : ''; 525*e0c4386eSCy Schubert 526*e0c4386eSCy Schubert print OUT <<"EOF"; 527*e0c4386eSCy Schubert/* 528*e0c4386eSCy Schubert * Generated by util/mkerr.pl DO NOT EDIT 529*e0c4386eSCy Schubert * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. 530*e0c4386eSCy Schubert * 531*e0c4386eSCy Schubert * Licensed under the Apache License 2.0 (the "License"). You may not use 532*e0c4386eSCy Schubert * this file except in compliance with the License. You can obtain a copy 533*e0c4386eSCy Schubert * in the file LICENSE in the source distribution or at 534*e0c4386eSCy Schubert * https://www.openssl.org/source/license.html 535*e0c4386eSCy Schubert */ 536*e0c4386eSCy Schubert 537*e0c4386eSCy Schubert#include <openssl/err.h> 538*e0c4386eSCy Schubert$includes 539*e0c4386eSCy SchubertEOF 540*e0c4386eSCy Schubert $indent = ''; 541*e0c4386eSCy Schubert if ( $internal ) { 542*e0c4386eSCy Schubert if ($disablable) { 543*e0c4386eSCy Schubert print OUT <<"EOF"; 544*e0c4386eSCy Schubert#ifndef OPENSSL_NO_${lib} 545*e0c4386eSCy Schubert 546*e0c4386eSCy SchubertEOF 547*e0c4386eSCy Schubert $indent .= ' '; 548*e0c4386eSCy Schubert } 549*e0c4386eSCy Schubert } 550*e0c4386eSCy Schubert print OUT <<"EOF"; 551*e0c4386eSCy Schubert#${indent}ifndef OPENSSL_NO_ERR 552*e0c4386eSCy Schubert 553*e0c4386eSCy Schubertstatic ${const}ERR_STRING_DATA ${lib}_str_reasons[] = { 554*e0c4386eSCy SchubertEOF 555*e0c4386eSCy Schubert 556*e0c4386eSCy Schubert # Add each reason code. 557*e0c4386eSCy Schubert foreach my $i ( @reasons ) { 558*e0c4386eSCy Schubert my $rn; 559*e0c4386eSCy Schubert if ( exists $strings{$i} ) { 560*e0c4386eSCy Schubert $rn = $strings{$i}; 561*e0c4386eSCy Schubert $rn = "" if $rn eq '*'; 562*e0c4386eSCy Schubert } else { 563*e0c4386eSCy Schubert $i =~ /^${lib}_R_(\S+)$/; 564*e0c4386eSCy Schubert $rn = $1; 565*e0c4386eSCy Schubert $rn =~ tr/_[A-Z]/ [a-z]/; 566*e0c4386eSCy Schubert $strings{$i} = $rn; 567*e0c4386eSCy Schubert } 568*e0c4386eSCy Schubert my $short = " {ERR_PACK($pack_lib, 0, $i), \"$rn\"},"; 569*e0c4386eSCy Schubert if ( length($short) <= 80 ) { 570*e0c4386eSCy Schubert print OUT "$short\n"; 571*e0c4386eSCy Schubert } else { 572*e0c4386eSCy Schubert print OUT " {ERR_PACK($pack_lib, 0, $i),\n \"$rn\"},\n"; 573*e0c4386eSCy Schubert } 574*e0c4386eSCy Schubert } 575*e0c4386eSCy Schubert print OUT <<"EOF"; 576*e0c4386eSCy Schubert {0, NULL} 577*e0c4386eSCy Schubert}; 578*e0c4386eSCy Schubert 579*e0c4386eSCy Schubert#${indent}endif 580*e0c4386eSCy SchubertEOF 581*e0c4386eSCy Schubert if ( $internal ) { 582*e0c4386eSCy Schubert print OUT <<"EOF"; 583*e0c4386eSCy Schubert 584*e0c4386eSCy Schubertint ossl_err_load_${lib}_strings(void) 585*e0c4386eSCy Schubert{ 586*e0c4386eSCy Schubert#${indent}ifndef OPENSSL_NO_ERR 587*e0c4386eSCy Schubert if (ERR_reason_error_string(${lib}_str_reasons[0].error) == NULL) 588*e0c4386eSCy Schubert ERR_load_strings_const(${lib}_str_reasons); 589*e0c4386eSCy Schubert#${indent}endif 590*e0c4386eSCy Schubert return 1; 591*e0c4386eSCy Schubert} 592*e0c4386eSCy SchubertEOF 593*e0c4386eSCy Schubert } else { 594*e0c4386eSCy Schubert my $st = $static ? "static " : ""; 595*e0c4386eSCy Schubert print OUT <<"EOF"; 596*e0c4386eSCy Schubert 597*e0c4386eSCy Schubertstatic int lib_code = 0; 598*e0c4386eSCy Schubertstatic int error_loaded = 0; 599*e0c4386eSCy Schubert 600*e0c4386eSCy Schubert${st}int ERR_load_${lib}_strings(void) 601*e0c4386eSCy Schubert{ 602*e0c4386eSCy Schubert if (lib_code == 0) 603*e0c4386eSCy Schubert lib_code = ERR_get_next_error_library(); 604*e0c4386eSCy Schubert 605*e0c4386eSCy Schubert if (!error_loaded) { 606*e0c4386eSCy Schubert#ifndef OPENSSL_NO_ERR 607*e0c4386eSCy Schubert ERR_load_strings(lib_code, ${lib}_str_reasons); 608*e0c4386eSCy Schubert#endif 609*e0c4386eSCy Schubert error_loaded = 1; 610*e0c4386eSCy Schubert } 611*e0c4386eSCy Schubert return 1; 612*e0c4386eSCy Schubert} 613*e0c4386eSCy Schubert 614*e0c4386eSCy Schubert${st}void ERR_unload_${lib}_strings(void) 615*e0c4386eSCy Schubert{ 616*e0c4386eSCy Schubert if (error_loaded) { 617*e0c4386eSCy Schubert#ifndef OPENSSL_NO_ERR 618*e0c4386eSCy Schubert ERR_unload_strings(lib_code, ${lib}_str_reasons); 619*e0c4386eSCy Schubert#endif 620*e0c4386eSCy Schubert error_loaded = 0; 621*e0c4386eSCy Schubert } 622*e0c4386eSCy Schubert} 623*e0c4386eSCy Schubert 624*e0c4386eSCy Schubert${st}void ERR_${lib}_error(int function, int reason, const char *file, int line) 625*e0c4386eSCy Schubert{ 626*e0c4386eSCy Schubert if (lib_code == 0) 627*e0c4386eSCy Schubert lib_code = ERR_get_next_error_library(); 628*e0c4386eSCy Schubert ERR_raise(lib_code, reason); 629*e0c4386eSCy Schubert ERR_set_debug(file, line, NULL); 630*e0c4386eSCy Schubert} 631*e0c4386eSCy SchubertEOF 632*e0c4386eSCy Schubert 633*e0c4386eSCy Schubert } 634*e0c4386eSCy Schubert 635*e0c4386eSCy Schubert while (length($indent) > 1) { 636*e0c4386eSCy Schubert $indent = substr $indent, 0, -1; 637*e0c4386eSCy Schubert print OUT "#${indent}endif\n"; 638*e0c4386eSCy Schubert } 639*e0c4386eSCy Schubert if ($internal && $disablable) { 640*e0c4386eSCy Schubert print OUT <<"EOF"; 641*e0c4386eSCy Schubert#else 642*e0c4386eSCy SchubertNON_EMPTY_TRANSLATION_UNIT 643*e0c4386eSCy Schubert#endif 644*e0c4386eSCy SchubertEOF 645*e0c4386eSCy Schubert } 646*e0c4386eSCy Schubert close OUT; 647*e0c4386eSCy Schubert } 648*e0c4386eSCy Schubert} 649*e0c4386eSCy Schubert 650*e0c4386eSCy Schubert&phase("Ending"); 651*e0c4386eSCy Schubert# Make a list of unreferenced reason codes 652*e0c4386eSCy Schubertif ( $unref ) { 653*e0c4386eSCy Schubert my @runref; 654*e0c4386eSCy Schubert foreach ( keys %rcodes ) { 655*e0c4386eSCy Schubert push( @runref, $_ ) unless exists $usedreasons{$_}; 656*e0c4386eSCy Schubert } 657*e0c4386eSCy Schubert if ( @runref ) { 658*e0c4386eSCy Schubert print STDERR "The following reason codes were not referenced:\n"; 659*e0c4386eSCy Schubert foreach ( sort @runref ) { 660*e0c4386eSCy Schubert print STDERR " $_\n"; 661*e0c4386eSCy Schubert } 662*e0c4386eSCy Schubert } 663*e0c4386eSCy Schubert} 664*e0c4386eSCy Schubert 665*e0c4386eSCy Schubertdie "Found $errors errors, quitting" if $errors; 666*e0c4386eSCy Schubert 667*e0c4386eSCy Schubert# Update the state file 668*e0c4386eSCy Schubertif ( $newstate ) { 669*e0c4386eSCy Schubert open(OUT, ">$statefile.new") 670*e0c4386eSCy Schubert || die "Can't write $statefile.new, $!"; 671*e0c4386eSCy Schubert print OUT <<"EOF"; 672*e0c4386eSCy Schubert# Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved. 673*e0c4386eSCy Schubert# 674*e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License"). You may not use 675*e0c4386eSCy Schubert# this file except in compliance with the License. You can obtain a copy 676*e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at 677*e0c4386eSCy Schubert# https://www.openssl.org/source/license.html 678*e0c4386eSCy SchubertEOF 679*e0c4386eSCy Schubert print OUT "\n#Reason codes\n"; 680*e0c4386eSCy Schubert foreach my $i ( sort keys %rcodes ) { 681*e0c4386eSCy Schubert my $short = "$i:$rcodes{$i}:"; 682*e0c4386eSCy Schubert my $t = exists $strings{$i} ? "$strings{$i}" : ""; 683*e0c4386eSCy Schubert $t = "\\\n\t" . $t if length($short) + length($t) > 80; 684*e0c4386eSCy Schubert print OUT "$short$t\n" if !exists $rextra{$i}; 685*e0c4386eSCy Schubert } 686*e0c4386eSCy Schubert close(OUT); 687*e0c4386eSCy Schubert if ( $skippedstate ) { 688*e0c4386eSCy Schubert print "Skipped state, leaving update in $statefile.new"; 689*e0c4386eSCy Schubert } else { 690*e0c4386eSCy Schubert rename "$statefile", "$statefile.old" 691*e0c4386eSCy Schubert || die "Can't backup $statefile to $statefile.old, $!"; 692*e0c4386eSCy Schubert rename "$statefile.new", "$statefile" 693*e0c4386eSCy Schubert || die "Can't rename $statefile to $statefile.new, $!"; 694*e0c4386eSCy Schubert } 695*e0c4386eSCy Schubert} 696*e0c4386eSCy Schubert 697*e0c4386eSCy Schubertexit; 698