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