155714Skris#!/usr/local/bin/perl -w
255714Skris
355714Skrismy $config = "crypto/err/openssl.ec";
4238405Sjkimmy $hprefix = "openssl/";
555714Skrismy $debug = 0;
655714Skrismy $rebuild = 0;
755714Skrismy $static = 1;
855714Skrismy $recurse = 0;
955714Skrismy $reindex = 0;
1055714Skrismy $dowrite = 0;
11109998Smarkmmy $staticloader = "";
1255714Skris
13160814Ssimonmy $pack_errcode;
14160814Ssimonmy $load_errcode;
15160814Ssimon
16238405Sjkimmy $errcount;
17238405Sjkim
1855714Skriswhile (@ARGV) {
1955714Skris	my $arg = $ARGV[0];
2055714Skris	if($arg eq "-conf") {
2155714Skris		shift @ARGV;
2255714Skris		$config = shift @ARGV;
23238405Sjkim	} elsif($arg eq "-hprefix") {
24238405Sjkim		shift @ARGV;
25238405Sjkim		$hprefix = shift @ARGV;
2655714Skris	} elsif($arg eq "-debug") {
2755714Skris		$debug = 1;
2855714Skris		shift @ARGV;
2955714Skris	} elsif($arg eq "-rebuild") {
3055714Skris		$rebuild = 1;
3155714Skris		shift @ARGV;
3255714Skris	} elsif($arg eq "-recurse") {
3355714Skris		$recurse = 1;
3455714Skris		shift @ARGV;
3555714Skris	} elsif($arg eq "-reindex") {
3655714Skris		$reindex = 1;
3755714Skris		shift @ARGV;
3855714Skris	} elsif($arg eq "-nostatic") {
3955714Skris		$static = 0;
4055714Skris		shift @ARGV;
41109998Smarkm	} elsif($arg eq "-staticloader") {
42109998Smarkm		$staticloader = "static ";
43109998Smarkm		shift @ARGV;
4455714Skris	} elsif($arg eq "-write") {
4555714Skris		$dowrite = 1;
4655714Skris		shift @ARGV;
47238405Sjkim	} elsif($arg eq "-help" || $arg eq "-h" || $arg eq "-?" || $arg eq "--help") {
48238405Sjkim		print STDERR <<"EOF";
49238405Sjkimmkerr.pl [options] ...
50238405Sjkim
51238405SjkimOptions:
52238405Sjkim
53238405Sjkim  -conf F       Use the config file F instead of the default one:
54238405Sjkim                  crypto/err/openssl.ec
55238405Sjkim
56238405Sjkim  -hprefix P    Prepend the filenames in generated #include <header>
57238405Sjkim                statements with prefix P. Default: 'openssl/' (without
58238405Sjkim                the quotes, naturally)
59238405Sjkim
60238405Sjkim  -debug        Turn on debugging verbose output on stderr.
61238405Sjkim
62238405Sjkim  -rebuild      Rebuild all header and C source files, irrespective of the
63238405Sjkim                fact if any error or function codes have been added/removed.
64238405Sjkim                Default: only update files for libraries which saw change
65238405Sjkim                         (of course, this requires '-write' as well, or no
66238405Sjkim                          files will be touched!)
67238405Sjkim
68238405Sjkim  -recurse      scan a preconfigured set of directories / files for error and
69238405Sjkim                function codes:
70238405Sjkim                  (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>, <apps/*.c>)
71238405Sjkim                When this option is NOT specified, the filelist is taken from
72238405Sjkim                the commandline instead. Here, wildcards may be embedded. (Be
73238405Sjkim                sure to escape those to prevent the shell from expanding them
74238405Sjkim                for you when you wish mkerr.pl to do so instead.)
75238405Sjkim                Default: take file list to scan from the command line.
76238405Sjkim
77238405Sjkim  -reindex      Discard the numeric values previously assigned to the error
78238405Sjkim                and function codes as extracted from the scanned header files;
79238405Sjkim                instead renumber all of them starting from 100. (Note that
80238405Sjkim                the numbers assigned through 'R' records in the config file
81238405Sjkim                remain intact.)
82238405Sjkim                Default: keep previously assigned numbers. (You are warned
83238405Sjkim                         when collisions are detected.)
84238405Sjkim
85238405Sjkim  -nostatic     Generates a different source code, where these additional
86238405Sjkim                functions are generated for each library specified in the
87238405Sjkim                config file:
88238405Sjkim                  void ERR_load_<LIB>_strings(void);
89238405Sjkim                  void ERR_unload_<LIB>_strings(void);
90238405Sjkim                  void ERR_<LIB>_error(int f, int r, char *fn, int ln);
91238405Sjkim                  #define <LIB>err(f,r) ERR_<LIB>_error(f,r,__FILE__,__LINE__)
92238405Sjkim                while the code facilitates the use of these in an environment
93238405Sjkim                where the error support routines are dynamically loaded at
94238405Sjkim                runtime.
95238405Sjkim                Default: 'static' code generation.
96238405Sjkim
97238405Sjkim  -staticloader Prefix generated functions with the 'static' scope modifier.
98238405Sjkim                Default: don't write any scope modifier prefix.
99238405Sjkim
100238405Sjkim  -write        Actually (over)write the generated code to the header and C
101238405Sjkim                source files as assigned to each library through the config
102238405Sjkim                file.
103238405Sjkim                Default: don't write.
104238405Sjkim
105238405Sjkim  -help / -h / -? / --help            Show this help text.
106238405Sjkim
107238405Sjkim  ...           Additional arguments are added to the file list to scan,
108238405Sjkim                assuming '-recurse' was NOT specified on the command line.
109238405Sjkim
110238405SjkimEOF
111238405Sjkim		exit 1;
11255714Skris	} else {
11355714Skris		last;
11455714Skris	}
11555714Skris}
11655714Skris
11755714Skrisif($recurse) {
118238405Sjkim	@source = (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>);
11955714Skris} else {
12055714Skris	@source = @ARGV;
12155714Skris}
12255714Skris
12355714Skris# Read in the config file
12455714Skris
12555714Skrisopen(IN, "<$config") || die "Can't open config file $config";
12655714Skris
12755714Skris# Parse config file
12855714Skris
12955714Skriswhile(<IN>)
13055714Skris{
13155714Skris	if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) {
13255714Skris		$hinc{$1} = $2;
13389837Skris		$libinc{$2} = $1;
13455714Skris		$cskip{$3} = $1;
13555714Skris		if($3 ne "NONE") {
13655714Skris			$csrc{$1} = $3;
137238405Sjkim			$fmax{$1} = 100;
138238405Sjkim			$rmax{$1} = 100;
139160814Ssimon			$fassigned{$1} = ":";
140160814Ssimon			$rassigned{$1} = ":";
14155714Skris			$fnew{$1} = 0;
14255714Skris			$rnew{$1} = 0;
14355714Skris		}
14455714Skris	} elsif (/^F\s+(\S+)/) {
14555714Skris	# Add extra function with $1
14655714Skris	} elsif (/^R\s+(\S+)\s+(\S+)/) {
14755714Skris		$rextra{$1} = $2;
14855714Skris		$rcodes{$1} = $2;
14955714Skris	}
15055714Skris}
15155714Skris
15255714Skrisclose IN;
15355714Skris
15455714Skris# Scan each header file in turn and make a list of error codes
15555714Skris# and function names
15655714Skris
15789837Skriswhile (($hdr, $lib) = each %libinc)
15855714Skris{
15955714Skris	next if($hdr eq "NONE");
16055714Skris	print STDERR "Scanning header file $hdr\n" if $debug;
161109998Smarkm	my $line = "", $def= "", $linenr = 0, $gotfile = 0;
162109998Smarkm	if (open(IN, "<$hdr")) {
163109998Smarkm	    $gotfile = 1;
164109998Smarkm	    while(<IN>) {
165109998Smarkm		$linenr++;
166109998Smarkm		print STDERR "line: $linenr\r" if $debug;
16768651Skris
168109998Smarkm		last if(/BEGIN\s+ERROR\s+CODES/);
169109998Smarkm		if ($line ne '') {
170109998Smarkm		    $_ = $line . $_;
171109998Smarkm		    $line = '';
172109998Smarkm		}
17355714Skris
174109998Smarkm		if (/\\$/) {
175109998Smarkm		    $line = $_;
176109998Smarkm		    next;
177109998Smarkm		}
17855714Skris
179160814Ssimon		if(/\/\*/) {
180160814Ssimon		    if (not /\*\//) {		# multiline comment...
181160814Ssimon			$line = $_;		# ... just accumulate
182160814Ssimon			next;
183160814Ssimon		    } else {
184160814Ssimon			s/\/\*.*?\*\///gs;	# wipe it
185160814Ssimon		    }
186160814Ssimon		}
187160814Ssimon
188109998Smarkm		if ($cpp) {
189160814Ssimon		    $cpp++ if /^#\s*if/;
190160814Ssimon		    $cpp-- if /^#\s*endif/;
191109998Smarkm		    next;
192109998Smarkm		}
193160814Ssimon		$cpp = 1 if /^#.*ifdef.*cplusplus/;  # skip "C" declaration
19455714Skris
195109998Smarkm		next if (/^\#/);                      # skip preprocessor directives
19655714Skris
197109998Smarkm		s/{[^{}]*}//gs;                      # ignore {} blocks
19855714Skris
199109998Smarkm		if (/\{|\/\*/) { # Add a } so editor works...
200109998Smarkm		    $line = $_;
201109998Smarkm		} else {
202109998Smarkm		    $def .= $_;
203109998Smarkm		}
20455714Skris	    }
20555714Skris	}
20655714Skris
20768651Skris	print STDERR "                                  \r" if $debug;
20868651Skris        $defnr = 0;
209167612Ssimon	# Delete any DECLARE_ macros
210167612Ssimon	$def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
21155714Skris	foreach (split /;/, $def) {
21268651Skris	    $defnr++;
21368651Skris	    print STDERR "def: $defnr\r" if $debug;
21468651Skris
215160814Ssimon	    # The goal is to collect function names from function declarations.
216160814Ssimon
21755714Skris	    s/^[\n\s]*//g;
21855714Skris	    s/[\n\s]*$//g;
219160814Ssimon
220160814Ssimon	    # Skip over recognized non-function declarations
221160814Ssimon	    next if(/typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/);
222160814Ssimon
223167612Ssimon	    # Remove STACK_OF(foo)
224167612Ssimon	    s/STACK_OF\(\w+\)/void/;
225167612Ssimon
226160814Ssimon	    # Reduce argument lists to empty ()
227160814Ssimon	    # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
228160814Ssimon	    while(/\(.*\)/s) {
229160814Ssimon		s/\([^\(\)]+\)/\{\}/gs;
230160814Ssimon		s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs;	#(*f{}) -> f
231160814Ssimon	    }
232160814Ssimon	    # pretend as we didn't use curly braces: {} -> ()
233160814Ssimon	    s/\{\}/\(\)/gs;
234160814Ssimon
235160814Ssimon	    if (/(\w+)\s*\(\).*/s) {	# first token prior [first] () is
236160814Ssimon		my $name = $1;		# a function name!
23755714Skris		$name =~ tr/[a-z]/[A-Z]/;
23855714Skris		$ftrans{$name} = $1;
239160814Ssimon	    } elsif (/[\(\)]/ and not (/=/)) {
24055714Skris		print STDERR "Header $hdr: cannot parse: $_;\n";
24155714Skris	    }
24255714Skris	}
24355714Skris
24468651Skris	print STDERR "                                  \r" if $debug;
24568651Skris
24655714Skris	next if $reindex;
24755714Skris
24855714Skris	# Scan function and reason codes and store them: keep a note of the
24955714Skris	# maximum code used.
25055714Skris
251109998Smarkm	if ($gotfile) {
252160814Ssimon	  while(<IN>) {
253280304Sjkim		if(/^\#\s*define\s+(\S+)\s+(\S+)/) {
25455714Skris			$name = $1;
25555714Skris			$code = $2;
256109998Smarkm			next if $name =~ /^${lib}err/;
25755714Skris			unless($name =~ /^${lib}_([RF])_(\w+)$/) {
25855714Skris				print STDERR "Invalid error code $name\n";
25955714Skris				next;
26055714Skris			}
26155714Skris			if($1 eq "R") {
26255714Skris				$rcodes{$name} = $code;
263160814Ssimon				if ($rassigned{$lib} =~ /:$code:/) {
264238405Sjkim					print STDERR "!! ERROR: $lib reason code $code assigned twice (collision at $name)\n";
265238405Sjkim					++$errcount;
266160814Ssimon				}
267160814Ssimon				$rassigned{$lib} .= "$code:";
26855714Skris				if(!(exists $rextra{$name}) &&
26955714Skris					 ($code > $rmax{$lib}) ) {
27055714Skris					$rmax{$lib} = $code;
27155714Skris				}
27255714Skris			} else {
273160814Ssimon				if ($fassigned{$lib} =~ /:$code:/) {
274238405Sjkim					print STDERR "!! ERROR: $lib function code $code assigned twice (collision at $name)\n";
275238405Sjkim					++$errcount;
276160814Ssimon				}
277160814Ssimon				$fassigned{$lib} .= "$code:";
27855714Skris				if($code > $fmax{$lib}) {
27955714Skris					$fmax{$lib} = $code;
28055714Skris				}
28155714Skris				$fcodes{$name} = $code;
28255714Skris			}
28355714Skris		}
284160814Ssimon	  }
28555714Skris	}
286160814Ssimon
287160814Ssimon	if ($debug) {
288160814Ssimon		if (defined($fmax{$lib})) {
289160814Ssimon			print STDERR "Max function code fmax" . "{" . "$lib" . "} = $fmax{$lib}\n";
290160814Ssimon			$fassigned{$lib} =~ m/^:(.*):$/;
291160814Ssimon			@fassigned = sort {$a <=> $b} split(":", $1);
292160814Ssimon			print STDERR "  @fassigned\n";
293160814Ssimon		}
294160814Ssimon		if (defined($rmax{$lib})) {
295160814Ssimon			print STDERR "Max reason code rmax" . "{" . "$lib" . "} = $rmax{$lib}\n";
296160814Ssimon			$rassigned{$lib} =~ m/^:(.*):$/;
297160814Ssimon			@rassigned = sort {$a <=> $b} split(":", $1);
298160814Ssimon			print STDERR "  @rassigned\n";
299160814Ssimon		}
300160814Ssimon	}
301160814Ssimon
302160814Ssimon	if ($lib eq "SSL") {
303160814Ssimon		if ($rmax{$lib} >= 1000) {
304160814Ssimon			print STDERR "!! ERROR: SSL error codes 1000+ are reserved for alerts.\n";
305160814Ssimon			print STDERR "!!        Any new alerts must be added to $config.\n";
306238405Sjkim			++$errcount;
307160814Ssimon			print STDERR "\n";
308160814Ssimon		}
309160814Ssimon	}
31055714Skris	close IN;
31155714Skris}
31255714Skris
31355714Skris# Scan each C source file and look for function and reason codes
31455714Skris# This is done by looking for strings that "look like" function or
31555714Skris# reason codes: basically anything consisting of all upper case and
31655714Skris# numerics which has _F_ or _R_ in it and which has the name of an
31755714Skris# error library at the start. This seems to work fine except for the
31855714Skris# oddly named structure BIO_F_CTX which needs to be ignored.
31955714Skris# If a code doesn't exist in list compiled from headers then mark it
32055714Skris# with the value "X" as a place holder to give it a value later.
32155714Skris# Store all function and reason codes found in %ufcodes and %urcodes
32255714Skris# so all those unreferenced can be printed out.
32355714Skris
32455714Skris
32555714Skrisforeach $file (@source) {
32655714Skris	# Don't parse the error source file.
32755714Skris	next if exists $cskip{$file};
328160814Ssimon	print STDERR "File loaded: ".$file."\r" if $debug;
32955714Skris	open(IN, "<$file") || die "Can't open source file $file\n";
33055714Skris	while(<IN>) {
331238405Sjkim		# skip obsoleted source files entirely!
332238405Sjkim		last if(/^#error\s+obsolete/);
333238405Sjkim
33455714Skris		if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) {
33555714Skris			next unless exists $csrc{$2};
33655714Skris			next if($1 eq "BIO_F_BUFFER_CTX");
33755714Skris			$ufcodes{$1} = 1;
33855714Skris			if(!exists $fcodes{$1}) {
33955714Skris				$fcodes{$1} = "X";
34055714Skris				$fnew{$2}++;
34155714Skris			}
34255714Skris			$notrans{$1} = 1 unless exists $ftrans{$3};
343238405Sjkim			print STDERR "Function: $1\t= $fcodes{$1} (lib: $2, name: $3)\n" if $debug;
34455714Skris		}
34555714Skris		if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) {
34655714Skris			next unless exists $csrc{$2};
34755714Skris			$urcodes{$1} = 1;
34855714Skris			if(!exists $rcodes{$1}) {
34955714Skris				$rcodes{$1} = "X";
35055714Skris				$rnew{$2}++;
35155714Skris			}
352238405Sjkim			print STDERR "Reason: $1\t= $rcodes{$1} (lib: $2)\n" if $debug;
35355714Skris		}
35455714Skris	}
35555714Skris	close IN;
35655714Skris}
357160814Ssimonprint STDERR "                                  \n" if $debug;
35855714Skris
35955714Skris# Now process each library in turn.
36055714Skris
36155714Skrisforeach $lib (keys %csrc)
36255714Skris{
36355714Skris	my $hfile = $hinc{$lib};
36455714Skris	my $cfile = $csrc{$lib};
36555714Skris	if(!$fnew{$lib} && !$rnew{$lib}) {
36655714Skris		print STDERR "$lib:\t\tNo new error codes\n";
36755714Skris		next unless $rebuild;
36855714Skris	} else {
36955714Skris		print STDERR "$lib:\t\t$fnew{$lib} New Functions,";
37055714Skris		print STDERR " $rnew{$lib} New Reasons.\n";
37155714Skris		next unless $dowrite;
37255714Skris	}
37355714Skris
37455714Skris	# If we get here then we have some new error codes so we
37555714Skris	# need to rebuild the header file and C file.
37655714Skris
37755714Skris	# Make a sorted list of error and reason codes for later use.
37855714Skris
37955714Skris	my @function = sort grep(/^${lib}_/,keys %fcodes);
38055714Skris	my @reasons = sort grep(/^${lib}_/,keys %rcodes);
38155714Skris
38255714Skris	# Rewrite the header file
38355714Skris
384109998Smarkm	if (open(IN, "<$hfile")) {
385109998Smarkm	    # Copy across the old file
386109998Smarkm	    while(<IN>) {
38755714Skris		push @out, $_;
38855714Skris		last if (/BEGIN ERROR CODES/);
389109998Smarkm	    }
390109998Smarkm	    close IN;
391109998Smarkm	} else {
392109998Smarkm	    push @out,
393109998Smarkm"/* ====================================================================\n",
394237657Sjkim" * Copyright (c) 2001-2011 The OpenSSL Project.  All rights reserved.\n",
395109998Smarkm" *\n",
396109998Smarkm" * Redistribution and use in source and binary forms, with or without\n",
397109998Smarkm" * modification, are permitted provided that the following conditions\n",
398109998Smarkm" * are met:\n",
399109998Smarkm" *\n",
400109998Smarkm" * 1. Redistributions of source code must retain the above copyright\n",
401109998Smarkm" *    notice, this list of conditions and the following disclaimer. \n",
402109998Smarkm" *\n",
403109998Smarkm" * 2. Redistributions in binary form must reproduce the above copyright\n",
404109998Smarkm" *    notice, this list of conditions and the following disclaimer in\n",
405109998Smarkm" *    the documentation and/or other materials provided with the\n",
406109998Smarkm" *    distribution.\n",
407109998Smarkm" *\n",
408109998Smarkm" * 3. All advertising materials mentioning features or use of this\n",
409109998Smarkm" *    software must display the following acknowledgment:\n",
410109998Smarkm" *    \"This product includes software developed by the OpenSSL Project\n",
411109998Smarkm" *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n",
412109998Smarkm" *\n",
413109998Smarkm" * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n",
414109998Smarkm" *    endorse or promote products derived from this software without\n",
415109998Smarkm" *    prior written permission. For written permission, please contact\n",
416109998Smarkm" *    openssl-core\@openssl.org.\n",
417109998Smarkm" *\n",
418109998Smarkm" * 5. Products derived from this software may not be called \"OpenSSL\"\n",
419109998Smarkm" *    nor may \"OpenSSL\" appear in their names without prior written\n",
420109998Smarkm" *    permission of the OpenSSL Project.\n",
421109998Smarkm" *\n",
422109998Smarkm" * 6. Redistributions of any form whatsoever must retain the following\n",
423109998Smarkm" *    acknowledgment:\n",
424109998Smarkm" *    \"This product includes software developed by the OpenSSL Project\n",
425109998Smarkm" *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n",
426109998Smarkm" *\n",
427109998Smarkm" * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n",
428109998Smarkm" * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n",
429109998Smarkm" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n",
430109998Smarkm" * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n",
431109998Smarkm" * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n",
432109998Smarkm" * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n",
433109998Smarkm" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n",
434109998Smarkm" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n",
435109998Smarkm" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n",
436109998Smarkm" * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n",
437109998Smarkm" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n",
438109998Smarkm" * OF THE POSSIBILITY OF SUCH DAMAGE.\n",
439109998Smarkm" * ====================================================================\n",
440109998Smarkm" *\n",
441109998Smarkm" * This product includes cryptographic software written by Eric Young\n",
442109998Smarkm" * (eay\@cryptsoft.com).  This product includes software written by Tim\n",
443109998Smarkm" * Hudson (tjh\@cryptsoft.com).\n",
444109998Smarkm" *\n",
445109998Smarkm" */\n",
446109998Smarkm"\n",
447109998Smarkm"#ifndef HEADER_${lib}_ERR_H\n",
448109998Smarkm"#define HEADER_${lib}_ERR_H\n",
449109998Smarkm"\n",
450238405Sjkim"#ifdef  __cplusplus\n",
451238405Sjkim"extern \"C\" {\n",
452238405Sjkim"#endif\n",
453238405Sjkim"\n",
454109998Smarkm"/* BEGIN ERROR CODES */\n";
45555714Skris	}
45655714Skris	open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n";
45755714Skris
45855714Skris	print OUT @out;
45955714Skris	undef @out;
46055714Skris	print OUT <<"EOF";
461280304Sjkim/*
462280304Sjkim * The following lines are auto generated by the script mkerr.pl. Any changes
46355714Skris * made after this point may be overwritten when the script is next run.
46455714Skris */
465109998SmarkmEOF
466109998Smarkm	if($static) {
467109998Smarkm		print OUT <<"EOF";
468109998Smarkm${staticloader}void ERR_load_${lib}_strings(void);
46955714Skris
470109998SmarkmEOF
471109998Smarkm	} else {
472109998Smarkm		print OUT <<"EOF";
473109998Smarkm${staticloader}void ERR_load_${lib}_strings(void);
474109998Smarkm${staticloader}void ERR_unload_${lib}_strings(void);
475109998Smarkm${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
476280304Sjkim# define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__)
477109998Smarkm
478109998SmarkmEOF
479109998Smarkm	}
480109998Smarkm	print OUT <<"EOF";
48155714Skris/* Error codes for the $lib functions. */
48255714Skris
48355714Skris/* Function codes. */
48455714SkrisEOF
48555714Skris
48655714Skris	foreach $i (@function) {
487280304Sjkim		$z=48 - length($i);
48855714Skris		if($fcodes{$i} eq "X") {
489160814Ssimon			$fassigned{$lib} =~ m/^:([^:]*):/;
490160814Ssimon			$findcode = $1;
491160814Ssimon			if (!defined($findcode)) {
492160814Ssimon				$findcode = $fmax{$lib};
493160814Ssimon			}
494160814Ssimon			while ($fassigned{$lib} =~ m/:$findcode:/) {
495160814Ssimon				$findcode++;
496160814Ssimon			}
497160814Ssimon			$fcodes{$i} = $findcode;
498160814Ssimon			$fassigned{$lib} .= "$findcode:";
49955714Skris			print STDERR "New Function code $i\n" if $debug;
50055714Skris		}
501280304Sjkim		printf OUT "# define $i%s $fcodes{$i}\n"," " x $z;
50255714Skris	}
50355714Skris
50455714Skris	print OUT "\n/* Reason codes. */\n";
50555714Skris
50655714Skris	foreach $i (@reasons) {
507280304Sjkim		$z=48 - length($i);
50855714Skris		if($rcodes{$i} eq "X") {
509160814Ssimon			$rassigned{$lib} =~ m/^:([^:]*):/;
510160814Ssimon			$findcode = $1;
511160814Ssimon			if (!defined($findcode)) {
512160814Ssimon				$findcode = $rmax{$lib};
513160814Ssimon			}
514160814Ssimon			while ($rassigned{$lib} =~ m/:$findcode:/) {
515160814Ssimon				$findcode++;
516160814Ssimon			}
517160814Ssimon			$rcodes{$i} = $findcode;
518160814Ssimon			$rassigned{$lib} .= "$findcode:";
51955714Skris			print STDERR "New Reason code   $i\n" if $debug;
52055714Skris		}
521280304Sjkim		printf OUT "# define $i%s $rcodes{$i}\n"," " x $z;
52255714Skris	}
52355714Skris	print OUT <<"EOF";
52455714Skris
52555714Skris#ifdef  __cplusplus
52655714Skris}
52755714Skris#endif
52855714Skris#endif
52955714SkrisEOF
53055714Skris	close OUT;
53155714Skris
53255714Skris	# Rewrite the C source file containing the error details.
53355714Skris
53459191Skris	# First, read any existing reason string definitions:
53559191Skris	my %err_reason_strings;
53659191Skris	if (open(IN,"<$cfile")) {
537284285Sjkim		my $line = "";
53859191Skris		while (<IN>) {
539284285Sjkim			chomp;
540284285Sjkim			$_ = $line . $_;
541284285Sjkim			$line = "";
542284285Sjkim			if (/{ERR_(FUNC|REASON)\(/) {
543284285Sjkim				if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
544284285Sjkim					$err_reason_strings{$1} = $2;
545284285Sjkim				} elsif (/\b${lib}_F_(\w*)\b.*\"(.*)\"/) {
546284285Sjkim					if (!exists $ftrans{$1} && ($1 ne $2)) {
547284285Sjkim						print STDERR "WARNING: Mismatched function string $2\n";
548284285Sjkim						$ftrans{$1} = $2;
549284285Sjkim					}
550284285Sjkim				} else {
551284285Sjkim					$line = $_;
552238405Sjkim				}
553238405Sjkim			}
55459191Skris		}
55559191Skris		close(IN);
55659191Skris	}
55759191Skris
558238405Sjkim
55955714Skris	my $hincf;
56055714Skris	if($static) {
56155714Skris		$hfile =~ /([^\/]+)$/;
562238405Sjkim		$hincf = "<${hprefix}$1>";
56355714Skris	} else {
56455714Skris		$hincf = "\"$hfile\"";
56555714Skris	}
56655714Skris
567160814Ssimon	# If static we know the error code at compile time so use it
568160814Ssimon	# in error definitions.
56955714Skris
570160814Ssimon	if ($static)
571160814Ssimon		{
572160814Ssimon		$pack_errcode = "ERR_LIB_${lib}";
573160814Ssimon		$load_errcode = "0";
574160814Ssimon		}
575160814Ssimon	else
576160814Ssimon		{
577160814Ssimon		$pack_errcode = "0";
578160814Ssimon		$load_errcode = "ERR_LIB_${lib}";
579160814Ssimon		}
580160814Ssimon
581160814Ssimon
58255714Skris	open (OUT,">$cfile") || die "Can't open $cfile for writing";
58355714Skris
58455714Skris	print OUT <<"EOF";
58555714Skris/* $cfile */
58655714Skris/* ====================================================================
587237657Sjkim * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
58855714Skris *
58955714Skris * Redistribution and use in source and binary forms, with or without
59055714Skris * modification, are permitted provided that the following conditions
59155714Skris * are met:
59255714Skris *
59355714Skris * 1. Redistributions of source code must retain the above copyright
594280304Sjkim *    notice, this list of conditions and the following disclaimer.
59555714Skris *
59655714Skris * 2. Redistributions in binary form must reproduce the above copyright
59755714Skris *    notice, this list of conditions and the following disclaimer in
59855714Skris *    the documentation and/or other materials provided with the
59955714Skris *    distribution.
60055714Skris *
60155714Skris * 3. All advertising materials mentioning features or use of this
60255714Skris *    software must display the following acknowledgment:
60355714Skris *    "This product includes software developed by the OpenSSL Project
60455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
60555714Skris *
60655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
60755714Skris *    endorse or promote products derived from this software without
60855714Skris *    prior written permission. For written permission, please contact
60955714Skris *    openssl-core\@OpenSSL.org.
61055714Skris *
61155714Skris * 5. Products derived from this software may not be called "OpenSSL"
61255714Skris *    nor may "OpenSSL" appear in their names without prior written
61355714Skris *    permission of the OpenSSL Project.
61455714Skris *
61555714Skris * 6. Redistributions of any form whatsoever must retain the following
61655714Skris *    acknowledgment:
61755714Skris *    "This product includes software developed by the OpenSSL Project
61855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
61955714Skris *
62055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
62155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
62455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
62555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
62755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
63155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
63255714Skris * ====================================================================
63355714Skris *
63455714Skris * This product includes cryptographic software written by Eric Young
63555714Skris * (eay\@cryptsoft.com).  This product includes software written by Tim
63655714Skris * Hudson (tjh\@cryptsoft.com).
63755714Skris *
63855714Skris */
63955714Skris
640280304Sjkim/*
641280304Sjkim * NOTE: this file was auto generated by the mkerr.pl script: any changes
64259191Skris * made to it will be overwritten when the script next updates this file,
64359191Skris * only reason strings will be preserved.
64455714Skris */
64555714Skris
64655714Skris#include <stdio.h>
64755714Skris#include <openssl/err.h>
64855714Skris#include $hincf
64955714Skris
65055714Skris/* BEGIN ERROR CODES */
651109998Smarkm#ifndef OPENSSL_NO_ERR
652160814Ssimon
653280304Sjkim# define ERR_FUNC(func) ERR_PACK($pack_errcode,func,0)
654280304Sjkim# define ERR_REASON(reason) ERR_PACK($pack_errcode,0,reason)
655160814Ssimon
656280304Sjkimstatic ERR_STRING_DATA ${lib}_str_functs[] = {
65755714SkrisEOF
65855714Skris	# Add each function code: if a function name is found then use it.
65955714Skris	foreach $i (@function) {
66055714Skris		my $fn;
66155714Skris		$i =~ /^${lib}_F_(\S+)$/;
66255714Skris		$fn = $1;
66355714Skris		if(exists $ftrans{$fn}) {
66455714Skris			$fn = $ftrans{$fn};
66555714Skris		}
666160814Ssimon#		print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
667280304Sjkim		if(length($i) + length($fn) > 58) {
668280304Sjkim			print OUT "    {ERR_FUNC($i),\n     \"$fn\"},\n";
669280304Sjkim		} else {
670280304Sjkim			print OUT "    {ERR_FUNC($i), \"$fn\"},\n";
671280304Sjkim		}
67255714Skris	}
67355714Skris	print OUT <<"EOF";
674280304Sjkim    {0, NULL}
675280304Sjkim};
67655714Skris
677280304Sjkimstatic ERR_STRING_DATA ${lib}_str_reasons[] = {
67855714SkrisEOF
67955714Skris	# Add each reason code.
68055714Skris	foreach $i (@reasons) {
68155714Skris		my $rn;
682160814Ssimon		my $rstr = "ERR_REASON($i)";
68359191Skris		if (exists $err_reason_strings{$i}) {
68459191Skris			$rn = $err_reason_strings{$i};
68559191Skris		} else {
68659191Skris			$i =~ /^${lib}_R_(\S+)$/;
68759191Skris			$rn = $1;
68859191Skris			$rn =~ tr/_[A-Z]/ [a-z]/;
68959191Skris		}
690280304Sjkim		if(length($i) + length($rn) > 56) {
691280304Sjkim			print OUT "    {${rstr},\n     \"$rn\"},\n";
692280304Sjkim		} else {
693280304Sjkim			print OUT "    {${rstr}, \"$rn\"},\n";
694280304Sjkim		}
69555714Skris	}
69655714Skrisif($static) {
69755714Skris	print OUT <<"EOF";
698280304Sjkim    {0, NULL}
699280304Sjkim};
70055714Skris
70155714Skris#endif
70255714Skris
703109998Smarkm${staticloader}void ERR_load_${lib}_strings(void)
704280304Sjkim{
705167612Ssimon#ifndef OPENSSL_NO_ERR
70655714Skris
707280304Sjkim    if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) {
708280304Sjkim        ERR_load_strings($load_errcode, ${lib}_str_functs);
709280304Sjkim        ERR_load_strings($load_errcode, ${lib}_str_reasons);
710280304Sjkim    }
71155714Skris#endif
712280304Sjkim}
71355714SkrisEOF
71455714Skris} else {
71555714Skris	print OUT <<"EOF";
716280304Sjkim    {0, NULL}
717280304Sjkim};
71855714Skris
71955714Skris#endif
72055714Skris
72155714Skris#ifdef ${lib}_LIB_NAME
722280304Sjkimstatic ERR_STRING_DATA ${lib}_lib_name[] = {
723280304Sjkim    {0, ${lib}_LIB_NAME},
724280304Sjkim    {0, NULL}
725280304Sjkim};
72655714Skris#endif
72755714Skris
728280304Sjkimstatic int ${lib}_lib_error_code = 0;
729280304Sjkimstatic int ${lib}_error_init = 1;
73055714Skris
731109998Smarkm${staticloader}void ERR_load_${lib}_strings(void)
732280304Sjkim{
733280304Sjkim    if (${lib}_lib_error_code == 0)
734280304Sjkim        ${lib}_lib_error_code = ERR_get_next_error_library();
73555714Skris
736280304Sjkim    if (${lib}_error_init) {
737280304Sjkim        ${lib}_error_init = 0;
738109998Smarkm#ifndef OPENSSL_NO_ERR
739280304Sjkim        ERR_load_strings(${lib}_lib_error_code, ${lib}_str_functs);
740280304Sjkim        ERR_load_strings(${lib}_lib_error_code, ${lib}_str_reasons);
74155714Skris#endif
74255714Skris
74355714Skris#ifdef ${lib}_LIB_NAME
744280304Sjkim        ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code, 0, 0);
745280304Sjkim        ERR_load_strings(0, ${lib}_lib_name);
74659191Skris#endif
747280304Sjkim    }
748280304Sjkim}
74955714Skris
750109998Smarkm${staticloader}void ERR_unload_${lib}_strings(void)
751280304Sjkim{
752280304Sjkim    if (${lib}_error_init == 0) {
753109998Smarkm#ifndef OPENSSL_NO_ERR
754280304Sjkim        ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_functs);
755280304Sjkim        ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_reasons);
756109998Smarkm#endif
757109998Smarkm
758109998Smarkm#ifdef ${lib}_LIB_NAME
759280304Sjkim        ERR_unload_strings(0, ${lib}_lib_name);
760109998Smarkm#endif
761280304Sjkim        ${lib}_error_init = 1;
762280304Sjkim    }
763280304Sjkim}
764109998Smarkm
765109998Smarkm${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line)
766280304Sjkim{
767280304Sjkim    if (${lib}_lib_error_code == 0)
768280304Sjkim        ${lib}_lib_error_code = ERR_get_next_error_library();
769280304Sjkim    ERR_PUT_error(${lib}_lib_error_code, function, reason, file, line);
770280304Sjkim}
77155714SkrisEOF
77255714Skris
77355714Skris}
77455714Skris
77555714Skris	close OUT;
77659191Skris	undef %err_reason_strings;
77755714Skris}
77855714Skris
779237657Sjkimif($debug && %notrans) {
78055714Skris	print STDERR "The following function codes were not translated:\n";
78155714Skris	foreach(sort keys %notrans)
78255714Skris	{
78355714Skris		print STDERR "$_\n";
78455714Skris	}
78555714Skris}
78655714Skris
78755714Skris# Make a list of unreferenced function and reason codes
78855714Skris
78955714Skrisforeach (keys %fcodes) {
79055714Skris	push (@funref, $_) unless exists $ufcodes{$_};
79155714Skris}
79255714Skris
79355714Skrisforeach (keys %rcodes) {
79455714Skris	push (@runref, $_) unless exists $urcodes{$_};
79555714Skris}
79655714Skris
797269686Sjkimif($debug && @funref) {
79855714Skris	print STDERR "The following function codes were not referenced:\n";
79955714Skris	foreach(sort @funref)
80055714Skris	{
80155714Skris		print STDERR "$_\n";
80255714Skris	}
80355714Skris}
80455714Skris
805269686Sjkimif($debug && @runref) {
80655714Skris	print STDERR "The following reason codes were not referenced:\n";
80755714Skris	foreach(sort @runref)
80855714Skris	{
80955714Skris		print STDERR "$_\n";
81055714Skris	}
81155714Skris}
812238405Sjkim
813238405Sjkimif($errcount) {
814238405Sjkim	print STDERR "There were errors, failing...\n\n";
815238405Sjkim	exit $errcount;
816238405Sjkim}
817238405Sjkim
818