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>) {
253109998Smarkm		if(/^\#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";
46155714Skris/* The following lines are auto generated by the script mkerr.pl. Any changes
46255714Skris * made after this point may be overwritten when the script is next run.
46355714Skris */
464109998SmarkmEOF
465109998Smarkm	if($static) {
466109998Smarkm		print OUT <<"EOF";
467109998Smarkm${staticloader}void ERR_load_${lib}_strings(void);
46855714Skris
469109998SmarkmEOF
470109998Smarkm	} else {
471109998Smarkm		print OUT <<"EOF";
472109998Smarkm${staticloader}void ERR_load_${lib}_strings(void);
473109998Smarkm${staticloader}void ERR_unload_${lib}_strings(void);
474109998Smarkm${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
475109998Smarkm#define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__)
476109998Smarkm
477109998SmarkmEOF
478109998Smarkm	}
479109998Smarkm	print OUT <<"EOF";
48055714Skris/* Error codes for the $lib functions. */
48155714Skris
48255714Skris/* Function codes. */
48355714SkrisEOF
48455714Skris
48555714Skris	foreach $i (@function) {
48655714Skris		$z=6-int(length($i)/8);
48755714Skris		if($fcodes{$i} eq "X") {
488160814Ssimon			$fassigned{$lib} =~ m/^:([^:]*):/;
489160814Ssimon			$findcode = $1;
490160814Ssimon			if (!defined($findcode)) {
491160814Ssimon				$findcode = $fmax{$lib};
492160814Ssimon			}
493160814Ssimon			while ($fassigned{$lib} =~ m/:$findcode:/) {
494160814Ssimon				$findcode++;
495160814Ssimon			}
496160814Ssimon			$fcodes{$i} = $findcode;
497160814Ssimon			$fassigned{$lib} .= "$findcode:";
49855714Skris			print STDERR "New Function code $i\n" if $debug;
49955714Skris		}
50055714Skris		printf OUT "#define $i%s $fcodes{$i}\n","\t" x $z;
50155714Skris	}
50255714Skris
50355714Skris	print OUT "\n/* Reason codes. */\n";
50455714Skris
50555714Skris	foreach $i (@reasons) {
50655714Skris		$z=6-int(length($i)/8);
50755714Skris		if($rcodes{$i} eq "X") {
508160814Ssimon			$rassigned{$lib} =~ m/^:([^:]*):/;
509160814Ssimon			$findcode = $1;
510160814Ssimon			if (!defined($findcode)) {
511160814Ssimon				$findcode = $rmax{$lib};
512160814Ssimon			}
513160814Ssimon			while ($rassigned{$lib} =~ m/:$findcode:/) {
514160814Ssimon				$findcode++;
515160814Ssimon			}
516160814Ssimon			$rcodes{$i} = $findcode;
517160814Ssimon			$rassigned{$lib} .= "$findcode:";
51855714Skris			print STDERR "New Reason code   $i\n" if $debug;
51955714Skris		}
52055714Skris		printf OUT "#define $i%s $rcodes{$i}\n","\t" x $z;
52155714Skris	}
52255714Skris	print OUT <<"EOF";
52355714Skris
52455714Skris#ifdef  __cplusplus
52555714Skris}
52655714Skris#endif
52755714Skris#endif
52855714SkrisEOF
52955714Skris	close OUT;
53055714Skris
53155714Skris	# Rewrite the C source file containing the error details.
53255714Skris
53359191Skris	# First, read any existing reason string definitions:
53459191Skris	my %err_reason_strings;
53559191Skris	if (open(IN,"<$cfile")) {
53659191Skris		while (<IN>) {
53759191Skris			if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
53859191Skris				$err_reason_strings{$1} = $2;
53959191Skris			}
540238405Sjkim			if (/\b${lib}_F_(\w*)\b.*\"(.*)\"/) {
541238405Sjkim				if (!exists $ftrans{$1} && ($1 ne $2)) {
542238405Sjkim					print STDERR "WARNING: Mismatched function string $2\n";
543238405Sjkim					$ftrans{$1} = $2;
544238405Sjkim				}
545238405Sjkim			}
54659191Skris		}
54759191Skris		close(IN);
54859191Skris	}
54959191Skris
550238405Sjkim
55155714Skris	my $hincf;
55255714Skris	if($static) {
55355714Skris		$hfile =~ /([^\/]+)$/;
554238405Sjkim		$hincf = "<${hprefix}$1>";
55555714Skris	} else {
55655714Skris		$hincf = "\"$hfile\"";
55755714Skris	}
55855714Skris
559160814Ssimon	# If static we know the error code at compile time so use it
560160814Ssimon	# in error definitions.
56155714Skris
562160814Ssimon	if ($static)
563160814Ssimon		{
564160814Ssimon		$pack_errcode = "ERR_LIB_${lib}";
565160814Ssimon		$load_errcode = "0";
566160814Ssimon		}
567160814Ssimon	else
568160814Ssimon		{
569160814Ssimon		$pack_errcode = "0";
570160814Ssimon		$load_errcode = "ERR_LIB_${lib}";
571160814Ssimon		}
572160814Ssimon
573160814Ssimon
57455714Skris	open (OUT,">$cfile") || die "Can't open $cfile for writing";
57555714Skris
57655714Skris	print OUT <<"EOF";
57755714Skris/* $cfile */
57855714Skris/* ====================================================================
579237657Sjkim * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
58055714Skris *
58155714Skris * Redistribution and use in source and binary forms, with or without
58255714Skris * modification, are permitted provided that the following conditions
58355714Skris * are met:
58455714Skris *
58555714Skris * 1. Redistributions of source code must retain the above copyright
58655714Skris *    notice, this list of conditions and the following disclaimer.
58755714Skris *
58855714Skris * 2. Redistributions in binary form must reproduce the above copyright
58955714Skris *    notice, this list of conditions and the following disclaimer in
59055714Skris *    the documentation and/or other materials provided with the
59155714Skris *    distribution.
59255714Skris *
59355714Skris * 3. All advertising materials mentioning features or use of this
59455714Skris *    software must display the following acknowledgment:
59555714Skris *    "This product includes software developed by the OpenSSL Project
59655714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
59755714Skris *
59855714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
59955714Skris *    endorse or promote products derived from this software without
60055714Skris *    prior written permission. For written permission, please contact
60155714Skris *    openssl-core\@OpenSSL.org.
60255714Skris *
60355714Skris * 5. Products derived from this software may not be called "OpenSSL"
60455714Skris *    nor may "OpenSSL" appear in their names without prior written
60555714Skris *    permission of the OpenSSL Project.
60655714Skris *
60755714Skris * 6. Redistributions of any form whatsoever must retain the following
60855714Skris *    acknowledgment:
60955714Skris *    "This product includes software developed by the OpenSSL Project
61055714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
61155714Skris *
61255714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
61355714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61455714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61555714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
61655714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61755714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
61855714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
61955714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62055714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62155714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62255714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
62355714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
62455714Skris * ====================================================================
62555714Skris *
62655714Skris * This product includes cryptographic software written by Eric Young
62755714Skris * (eay\@cryptsoft.com).  This product includes software written by Tim
62855714Skris * Hudson (tjh\@cryptsoft.com).
62955714Skris *
63055714Skris */
63155714Skris
63255714Skris/* NOTE: this file was auto generated by the mkerr.pl script: any changes
63359191Skris * made to it will be overwritten when the script next updates this file,
63459191Skris * only reason strings will be preserved.
63555714Skris */
63655714Skris
63755714Skris#include <stdio.h>
63855714Skris#include <openssl/err.h>
63955714Skris#include $hincf
64055714Skris
64155714Skris/* BEGIN ERROR CODES */
642109998Smarkm#ifndef OPENSSL_NO_ERR
643160814Ssimon
644160814Ssimon#define ERR_FUNC(func) ERR_PACK($pack_errcode,func,0)
645160814Ssimon#define ERR_REASON(reason) ERR_PACK($pack_errcode,0,reason)
646160814Ssimon
64755714Skrisstatic ERR_STRING_DATA ${lib}_str_functs[]=
64855714Skris	{
64955714SkrisEOF
65055714Skris	# Add each function code: if a function name is found then use it.
65155714Skris	foreach $i (@function) {
65255714Skris		my $fn;
65355714Skris		$i =~ /^${lib}_F_(\S+)$/;
65455714Skris		$fn = $1;
65555714Skris		if(exists $ftrans{$fn}) {
65655714Skris			$fn = $ftrans{$fn};
65755714Skris		}
658160814Ssimon#		print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
659160814Ssimon		print OUT "{ERR_FUNC($i),\t\"$fn\"},\n";
66055714Skris	}
66155714Skris	print OUT <<"EOF";
66255714Skris{0,NULL}
66355714Skris	};
66455714Skris
66555714Skrisstatic ERR_STRING_DATA ${lib}_str_reasons[]=
66655714Skris	{
66755714SkrisEOF
66855714Skris	# Add each reason code.
66955714Skris	foreach $i (@reasons) {
67055714Skris		my $rn;
671160814Ssimon		my $rstr = "ERR_REASON($i)";
67255714Skris		my $nspc = 0;
67359191Skris		if (exists $err_reason_strings{$i}) {
67459191Skris			$rn = $err_reason_strings{$i};
67559191Skris		} else {
67659191Skris			$i =~ /^${lib}_R_(\S+)$/;
67759191Skris			$rn = $1;
67859191Skris			$rn =~ tr/_[A-Z]/ [a-z]/;
67959191Skris		}
680160814Ssimon		$nspc = 40 - length($rstr) unless length($rstr) > 40;
68155714Skris		$nspc = " " x $nspc;
682160814Ssimon		print OUT "{${rstr}${nspc},\"$rn\"},\n";
68355714Skris	}
68455714Skrisif($static) {
68555714Skris	print OUT <<"EOF";
68655714Skris{0,NULL}
68755714Skris	};
68855714Skris
68955714Skris#endif
69055714Skris
691109998Smarkm${staticloader}void ERR_load_${lib}_strings(void)
69255714Skris	{
693167612Ssimon#ifndef OPENSSL_NO_ERR
69455714Skris
695167612Ssimon	if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL)
69655714Skris		{
697160814Ssimon		ERR_load_strings($load_errcode,${lib}_str_functs);
698160814Ssimon		ERR_load_strings($load_errcode,${lib}_str_reasons);
699167612Ssimon		}
70055714Skris#endif
70155714Skris	}
70255714SkrisEOF
70355714Skris} else {
70455714Skris	print OUT <<"EOF";
70555714Skris{0,NULL}
70655714Skris	};
70755714Skris
70855714Skris#endif
70955714Skris
71055714Skris#ifdef ${lib}_LIB_NAME
71155714Skrisstatic ERR_STRING_DATA ${lib}_lib_name[]=
71255714Skris        {
71355714Skris{0	,${lib}_LIB_NAME},
71455714Skris{0,NULL}
71555714Skris	};
71655714Skris#endif
71755714Skris
71855714Skris
719109998Smarkmstatic int ${lib}_lib_error_code=0;
720109998Smarkmstatic int ${lib}_error_init=1;
72155714Skris
722109998Smarkm${staticloader}void ERR_load_${lib}_strings(void)
72355714Skris	{
72455714Skris	if (${lib}_lib_error_code == 0)
72555714Skris		${lib}_lib_error_code=ERR_get_next_error_library();
72655714Skris
727109998Smarkm	if (${lib}_error_init)
72855714Skris		{
729109998Smarkm		${lib}_error_init=0;
730109998Smarkm#ifndef OPENSSL_NO_ERR
73155714Skris		ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs);
73255714Skris		ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons);
73355714Skris#endif
73455714Skris
73555714Skris#ifdef ${lib}_LIB_NAME
73655714Skris		${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0);
73755714Skris		ERR_load_strings(0,${lib}_lib_name);
73859191Skris#endif
73955714Skris		}
74055714Skris	}
74155714Skris
742109998Smarkm${staticloader}void ERR_unload_${lib}_strings(void)
74355714Skris	{
744109998Smarkm	if (${lib}_error_init == 0)
745109998Smarkm		{
746109998Smarkm#ifndef OPENSSL_NO_ERR
747109998Smarkm		ERR_unload_strings(${lib}_lib_error_code,${lib}_str_functs);
748109998Smarkm		ERR_unload_strings(${lib}_lib_error_code,${lib}_str_reasons);
749109998Smarkm#endif
750109998Smarkm
751109998Smarkm#ifdef ${lib}_LIB_NAME
752109998Smarkm		ERR_unload_strings(0,${lib}_lib_name);
753109998Smarkm#endif
754109998Smarkm		${lib}_error_init=1;
755109998Smarkm		}
756109998Smarkm	}
757109998Smarkm
758109998Smarkm${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line)
759109998Smarkm	{
76055714Skris	if (${lib}_lib_error_code == 0)
76155714Skris		${lib}_lib_error_code=ERR_get_next_error_library();
76255714Skris	ERR_PUT_error(${lib}_lib_error_code,function,reason,file,line);
76355714Skris	}
76455714SkrisEOF
76555714Skris
76655714Skris}
76755714Skris
76855714Skris	close OUT;
76959191Skris	undef %err_reason_strings;
77055714Skris}
77155714Skris
772237657Sjkimif($debug && %notrans) {
77355714Skris	print STDERR "The following function codes were not translated:\n";
77455714Skris	foreach(sort keys %notrans)
77555714Skris	{
77655714Skris		print STDERR "$_\n";
77755714Skris	}
77855714Skris}
77955714Skris
78055714Skris# Make a list of unreferenced function and reason codes
78155714Skris
78255714Skrisforeach (keys %fcodes) {
78355714Skris	push (@funref, $_) unless exists $ufcodes{$_};
78455714Skris}
78555714Skris
78655714Skrisforeach (keys %rcodes) {
78755714Skris	push (@runref, $_) unless exists $urcodes{$_};
78855714Skris}
78955714Skris
790279264Sdelphijif($debug && @funref) {
79155714Skris	print STDERR "The following function codes were not referenced:\n";
79255714Skris	foreach(sort @funref)
79355714Skris	{
79455714Skris		print STDERR "$_\n";
79555714Skris	}
79655714Skris}
79755714Skris
798279264Sdelphijif($debug && @runref) {
79955714Skris	print STDERR "The following reason codes were not referenced:\n";
80055714Skris	foreach(sort @runref)
80155714Skris	{
80255714Skris		print STDERR "$_\n";
80355714Skris	}
80455714Skris}
805238405Sjkim
806238405Sjkimif($errcount) {
807238405Sjkim	print STDERR "There were errors, failing...\n\n";
808238405Sjkim	exit $errcount;
809238405Sjkim}
810238405Sjkim
811