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