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