]>
git.ipfire.org Git - thirdparty/openssl.git/blob - util/mkerr.pl
2 # Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
4 # Licensed under the Apache License 2.0 (the "License"). You may not use
5 # this file except in compliance with the License. You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
13 use File
::Spec
::Functions
qw(abs2rel rel2abs);
18 my $config = "crypto/err/openssl.ec";
30 my $YEAR = $t[5] + 1900;
35 print STDERR
"\n---\n$text\n" if $debug;
41 mkerr.pl [options] [files...]
45 -conf FILE Use the named config file FILE instead of the default.
47 -debug Verbose output debugging on stderr.
49 -internal Generate code that is to be built as part of OpenSSL itself.
50 Also scans internal list of files.
52 -module M Only useful with -internal!
53 Only write files for library module M. Whether files are
54 actually written or not depends on other options, such as
56 Note: this option is cumulative. If not given at all, all
57 internal modules will be considered.
59 -nowrite Do not write the header/source files, even if changed.
61 -rebuild Rebuild all header and C source files, even if there
64 -reindex Ignore previously assigned values (except for R records in
65 the config file) and renumber everything starting at 100.
67 -static Make the load/unload functions static.
69 -unref List all unreferenced function and reason codes on stderr;
72 -help Show this help text.
74 ... Additional arguments are added to the file list to scan,
75 if '-internal' was NOT specified on the command line.
82 last unless $arg =~ /-.*/;
83 $arg = $1 if $arg =~ /-(-.*)/;
84 if ( $arg eq "-conf" ) {
87 } elsif ( $arg eq "-debug" ) {
90 } elsif ( $arg eq "-internal" ) {
92 } elsif ( $arg eq "-nowrite" ) {
94 } elsif ( $arg eq "-rebuild" ) {
96 } elsif ( $arg eq "-reindex" ) {
98 } elsif ( $arg eq "-static" ) {
100 } elsif ( $arg eq "-unref" ) {
103 } elsif ( $arg eq "-module" ) {
105 $modules{uc $ARGV[0]} = 1;
106 } elsif ( $arg =~ /-*h(elp)?/ ) {
109 } elsif ( $arg =~ /-.*/ ) {
110 die "Unknown option $arg; use -h for help.\n";
117 die "Cannot mix -internal and -static\n" if $static;
118 die "Extra parameters given.\n" if @ARGV;
119 @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
120 glob('ssl/*.c'), glob('ssl/*/*.c'), glob('ssl/*/*/*.c'),
121 glob('providers/*.c'), glob('providers/*/*.c'),
122 glob('providers/*/*/*.c') );
124 die "-module isn't useful without -internal\n" if scalar keys %modules > 0;
128 # Data parsed out of the config and state files.
129 my %hpubinc; # lib -> public header
130 my %libpubinc; # public header -> lib
131 my %hprivinc; # lib -> private header
132 my %libprivinc; # private header -> lib
133 my %cskip; # error_file -> lib
134 my %errorfile; # lib -> error file name
135 my %rmax; # lib -> max assigned reason code
136 my %rassigned; # lib -> colon-separated list of assigned reason codes
137 my %rnew; # lib -> count of new reason codes
138 my %rextra; # "extra" reason code -> lib
139 my %rcodes; # reason-name -> value
140 my $statefile; # state file with assigned reason and function codes
141 my %strings; # define -> text
143 # Read and parse the config file
144 open(IN
, "$config") || die "Can't open config file $config, $!,";
146 next if /^#/ || /^$/;
147 if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)(?:\s+(\S+))?\s+$/ ) {
151 my $privhdr = $4 // 'NONE';
152 $hpubinc{$lib} = $pubhdr;
153 $libpubinc{$pubhdr} = $lib;
154 $hprivinc{$lib} = $privhdr;
155 $libprivinc{$privhdr} = $lib;
157 $errorfile{$lib} = $err;
158 next if $err eq 'NONE';
160 $rassigned{$lib} = ":";
162 die "Public header file must be in include/openssl ($pubhdr is not)\n"
165 && $pubhdr !~ m
|^include
/openssl/|);
166 die "Private header file may only be specified with -internal ($privhdr given)\n"
167 unless ($privhdr eq 'NONE' || $internal);
168 } elsif ( /^R\s+(\S+)\s+(\S+)/ ) {
171 } elsif ( /^S\s+(\S+)/ ) {
174 die "Illegal config line $_\n";
179 if ( ! $statefile ) {
180 $statefile = $config;
181 $statefile =~ s/.ec/.txt/;
184 # The statefile has all the previous assignments.
185 &phase
("Reading state");
186 my $skippedstate = 0;
187 if ( ! $reindex && $statefile ) {
188 open(STATE
, "<$statefile") || die "Can't open $statefile, $!";
190 # Scan function and reason codes and store them: keep a note of the
193 next if /^#/ || /^$/;
196 if ( /^(.+):(\d+):\\$/ ) {
200 $next =~ s/^\s*(.*)\s*$/$1/;
201 die "Duplicate define $name" if exists $strings{$name};
202 $strings{$name} = $next;
203 } elsif ( /^(\S+):(\d+):(.*)$/ ) {
206 die "Duplicate define $name" if exists $strings{$name};
207 $strings{$name} = $3;
209 die "Bad line in $statefile:\n$_\n";
212 $lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/;
213 $lib = "SSL" if $lib =~ /TLS/;
214 if ( !defined $errorfile{$lib} ) {
219 next if $errorfile{$lib} eq 'NONE';
220 if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_R_/ ) {
221 die "$lib reason code $code collision at $name\n"
222 if $rassigned{$lib} =~ /:$code:/;
223 $rassigned{$lib} .= "$code:";
224 if ( !exists $rextra{$name} ) {
225 $rmax{$lib} = $code if $code > $rmax{$lib};
227 $rcodes{$name} = $code;
228 } elsif ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) {
229 # We do nothing with the function codes, just let them go away
231 die "Bad line in $statefile:\n$_\n";
237 foreach my $lib ( sort keys %rmax ) {
238 print STDERR
"Reason codes for ${lib}:\n";
239 if ( $rassigned{$lib} =~ m/^:(.*):$/ ) {
240 my @rassigned = sort { $a <=> $b } split( ":", $1 );
241 print STDERR
" ", join(' ', @rassigned), "\n";
243 print STDERR
" --none--\n";
249 # Scan each C source file and look for reason codes. This is done by
250 # looking for strings that "look like" reason codes: basically anything
251 # consisting of all uppercase and numerics which _R_ in it and which has
252 # the name of an error library at the start. Should there be anything else,
253 # such as a type name, we add exceptions here.
254 # If a code doesn't exist in list compiled from headers then mark it
255 # with the value "X" as a place holder to give it a value later.
256 # Store all reason codes found in and %usedreasons so all those unreferenced
257 # can be printed out.
258 &phase
("Scanning source");
260 foreach my $file ( @source ) {
261 # Don't parse the error source file.
262 next if exists $cskip{$file};
263 open( IN
, "<$file" ) || die "Can't open $file, $!,";
266 print STDERR
"$file:\n" if $debug;
269 # skip obsoleted source files entirely!
270 last if /^#error\s+obsolete/;
273 if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) {
274 next unless exists $errorfile{$2};
275 next if $errorfile{$2} eq 'NONE';
276 $usedreasons{$1} = 1;
277 if ( !exists $rcodes{$1} ) {
278 print STDERR
" New reason $1\n" if $debug;
282 print STDERR
" Reason $1 = $rcodes{$1}\n" if $debug;
287 print STDERR
"\n" if $debug;
289 # Now process each library in turn.
290 &phase
("Writing files");
292 foreach my $lib ( keys %errorfile ) {
293 next if ! $rnew{$lib} && ! $rebuild;
294 next if scalar keys %modules > 0 && !$modules{$lib};
296 print STDERR
"$lib: $rnew{$lib} new reasons\n" if $rnew{$lib};
299 # If we get here then we have some new error codes so we
300 # need to rebuild the header file and C file.
302 # Make a sorted list of error and reason codes for later use.
303 my @reasons = sort grep( /^${lib}_/, keys %rcodes );
305 # indent level for innermost preprocessor lines
308 # Flag if the sub-library is disablable
309 # There are a few exceptions, where disabling the sub-library
310 # doesn't actually remove the whole sub-library, but rather implements
311 # it with a NULL backend.
313 ($lib ne "SSL" && $lib ne "ASYNC" && $lib ne "DSO"
314 && (grep { $lib eq uc $_ } @disablables, @disablables_int));
316 # Rewrite the internal header file if there is one ($internal only!)
318 if ($hprivinc{$lib} ne 'NONE') {
319 my $hfile = $hprivinc{$lib};
322 if ($guard =~ m
|^include
/|) {
325 $guard = basename($guard);
327 $guard = "OSSL_" . join('_
', split(m|[./]|, uc $guard));
329 open( OUT, ">$hfile" ) || die "Can't
write to
$hfile, $!,";
332 * Generated by util/mkerr.pl DO NOT EDIT
333 * Copyright 2020-$YEAR The OpenSSL Project Authors. All Rights Reserved.
335 * Licensed under the Apache License 2.0 (the \"License\"). You may not use
336 * this file except in compliance with the License. You can obtain a copy
337 * in the file LICENSE in the source distribution or at
338 * https://www.openssl.org/source/license.html
345 # include <openssl/opensslconf.h>
346 # include <openssl/symhacks.h>
356 # ifndef OPENSSL_NO_${lib}
362 int ossl_err_load_${lib}_strings(void);
365 # If this library doesn't have a public header file, we write all
366 # definitions that would end up there here instead
367 if ($hpubinc{$lib} eq 'NONE') {
368 print OUT
"\n/*\n * $lib reason codes.\n */\n";
369 foreach my $i ( @reasons ) {
370 my $z = 48 - length($i);
372 if ( $rcodes{$i} eq "X" ) {
373 $rassigned{$lib} =~ m/^:([^:]*):/;
375 $findcode = $rmax{$lib} if !defined $findcode;
376 while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
379 $rcodes{$i} = $findcode;
380 $rassigned{$lib} .= "$findcode:";
381 print STDERR
"New Reason code $i\n" if $debug;
383 printf OUT
"#${indent}define $i%s $rcodes{$i}\n", " " x
$z;
388 # This doesn't go all the way down to zero, to allow for the ending
389 # brace for 'extern "C" {'.
390 while (length($indent) > 1) {
391 $indent = substr $indent, 0, -1;
392 print OUT
"#${indent}endif\n";
405 # Rewrite the public header file
407 if ($hpubinc{$lib} ne 'NONE') {
411 ?
"# include <openssl/cryptoerr_legacy.h>\n"
412 : "# include <openssl/sslerr_legacy.h>\n")
414 my $hfile = $hpubinc{$lib};
416 $guard =~ s
|^include
/||;
417 $guard = join('_', split(m
|[./]|, uc $guard));
418 $guard = "OSSL_" . $guard unless $internal;
420 open( OUT
, ">$hfile" ) || die "Can't write to $hfile, $!,";
423 * Generated by util/mkerr.pl DO NOT EDIT
424 * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
426 * Licensed under the Apache License 2.0 (the \"License\"). You may not use
427 * this file except in compliance with the License. You can obtain a copy
428 * in the file LICENSE in the source distribution or at
429 * https://www.openssl.org/source/license.html
436 # include <openssl/opensslconf.h>
437 # include <openssl/symhacks.h>
445 # ifndef OPENSSL_NO_${lib}
452 # define ${lib}err(f, r) ERR_${lib}_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
453 # define ERR_R_${lib}_LIB ERR_${lib}_lib()
462 int ERR_load_${lib}_strings(void);
463 void ERR_unload_${lib}_strings(void);
464 void ERR_${lib}_error(int function, int reason, const char *file, int line);
472 print OUT
"\n/*\n * $lib reason codes.\n */\n";
473 foreach my $i ( @reasons ) {
474 my $z = 48 - length($i);
476 if ( $rcodes{$i} eq "X" ) {
477 $rassigned{$lib} =~ m/^:([^:]*):/;
479 $findcode = $rmax{$lib} if !defined $findcode;
480 while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
483 $rcodes{$i} = $findcode;
484 $rassigned{$lib} .= "$findcode:";
485 print STDERR
"New Reason code $i\n" if $debug;
487 printf OUT
"#${indent}define $i%s $rcodes{$i}\n", " " x
$z;
491 while (length($indent) > 0) {
492 $indent = substr $indent, 0, -1;
493 print OUT
"#${indent}endif\n";
498 # Rewrite the C source file containing the error details.
500 if ($errorfile{$lib} ne 'NONE') {
501 # First, read any existing reason string definitions:
502 my $cfile = $errorfile{$lib};
503 my $pack_lib = $internal ?
"ERR_LIB_${lib}" : "0";
504 my $hpubincf = $hpubinc{$lib};
505 my $hprivincf = $hprivinc{$lib};
508 if ($hpubincf ne 'NONE') {
509 $hpubincf =~ s
|^include
/||;
510 $includes .= "#include <${hpubincf}>\n";
512 if ($hprivincf =~ m
|^include
/|) {
515 $hprivincf = abs2rel(rel2abs($hprivincf),
516 rel2abs(dirname($cfile)));
518 $includes .= "#include \"${hprivincf}\"\n";
520 $includes .= "#include \"${hpubincf}\"\n";
523 open( OUT, ">$cfile" )
524 || die "Can't
open $cfile for writing
, $!, stopped
";
526 my $const = $internal ? 'const ' : '';
530 * Generated by util/mkerr.pl DO NOT EDIT
531 * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
533 * Licensed under the Apache License 2.0 (the "License
"). You may not use
534 * this file except in compliance with the License. You can obtain a copy
535 * in the file LICENSE in the source distribution or at
536 * https://www.openssl.org/source/license.html
539 #include <openssl/err.h>
546 #ifndef OPENSSL_NO_${lib}
553 #${indent}ifndef OPENSSL_NO_ERR
555 static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = {
558 # Add each reason code.
559 foreach my $i ( @reasons ) {
561 if ( exists $strings{$i} ) {
563 $rn = "" if $rn eq '*';
565 $i =~ /^${lib}_R_(\S+)$/;
567 $rn =~ tr/_[A-Z]/ [a-z]/;
570 my $short = " {ERR_PACK($pack_lib, 0, $i), \"$rn\"},";
571 if ( length($short) <= 80 ) {
572 print OUT
"$short\n";
574 print OUT
" {ERR_PACK($pack_lib, 0, $i),\n \"$rn\"},\n";
586 int ossl_err_load_${lib}_strings(void)
588 #${indent}ifndef OPENSSL_NO_ERR
589 if (ERR_reason_error_string(${lib}_str_reasons[0].error) == NULL)
590 ERR_load_strings_const(${lib}_str_reasons);
596 my $st = $static ?
"static " : "";
599 static int lib_code = 0;
600 static int error_loaded = 0;
602 ${st}int ERR_load_${lib}_strings(void)
605 lib_code = ERR_get_next_error_library();
608 #ifndef OPENSSL_NO_ERR
609 ERR_load_strings(lib_code, ${lib}_str_reasons);
616 ${st}void ERR_unload_${lib}_strings(void)
619 #ifndef OPENSSL_NO_ERR
620 ERR_unload_strings(lib_code, ${lib}_str_reasons);
626 ${st}void ERR_${lib}_error(int function, int reason, const char *file, int line)
629 lib_code = ERR_get_next_error_library();
630 ERR_raise(lib_code, reason);
631 ERR_set_debug(file, line, NULL);
634 ${st}int ERR_${lib}_lib(void)
637 lib_code = ERR_get_next_error_library();
644 while (length($indent) > 1) {
645 $indent = substr $indent, 0, -1;
646 print OUT
"#${indent}endif\n";
648 if ($internal && $disablable) {
651 NON_EMPTY_TRANSLATION_UNIT
660 # Make a list of unreferenced reason codes
663 foreach ( keys %rcodes ) {
664 push( @runref, $_ ) unless exists $usedreasons{$_};
667 print STDERR
"The following reason codes were not referenced:\n";
668 foreach ( sort @runref ) {
669 print STDERR
" $_\n";
674 die "Found $errors errors, quitting" if $errors;
676 # Update the state file
678 open(OUT
, ">$statefile.new")
679 || die "Can't write $statefile.new, $!";
681 # Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved.
683 # Licensed under the Apache License 2.0 (the "License"). You may not use
684 # this file except in compliance with the License. You can obtain a copy
685 # in the file LICENSE in the source distribution or at
686 # https://www.openssl.org/source/license.html
688 print OUT
"\n#Reason codes\n";
689 foreach my $i ( sort keys %rcodes ) {
690 my $short = "$i:$rcodes{$i}:";
691 my $t = exists $strings{$i} ?
"$strings{$i}" : "";
692 $t = "\\\n\t" . $t if length($short) + length($t) > 80;
693 print OUT
"$short$t\n";
696 if ( $skippedstate ) {
697 print "Skipped state, leaving update in $statefile.new";
699 rename "$statefile", "$statefile.old"
700 || die "Can't backup $statefile to $statefile.old, $!";
701 rename "$statefile.new", "$statefile"
702 || die "Can't rename $statefile to $statefile.new, $!";