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