1 #!/usr/local/bin/perl -w
3 my $config = "crypto/err/openssl.ec";
4 my $hprefix = "openssl/";
11 my $staticloader = "";
17 my $year = (localtime)[5] + 1900;
23 $config = shift @ARGV;
24 } elsif($arg eq "-hprefix") {
26 $hprefix = shift @ARGV;
27 } elsif($arg eq "-debug") {
30 } elsif($arg eq "-rebuild") {
33 } elsif($arg eq "-recurse") {
36 } elsif($arg eq "-reindex") {
39 } elsif($arg eq "-nostatic") {
42 } elsif($arg eq "-staticloader") {
43 $staticloader = "static ";
45 } elsif($arg eq "-write") {
48 } elsif($arg eq "-help" || $arg eq "-h" || $arg eq "-?" || $arg eq "--help") {
50 mkerr.pl [options] ...
54 -conf F Use the config file F instead of the default one:
57 -hprefix P Prepend the filenames in generated #include <header>
58 statements with prefix P. Default: 'openssl/' (without
59 the quotes, naturally)
61 -debug Turn on debugging verbose output on stderr.
63 -rebuild Rebuild all header and C source files, irrespective of the
64 fact if any error or function codes have been added/removed.
65 Default: only update files for libraries which saw change
66 (of course, this requires '-write' as well, or no
67 files will be touched!)
69 -recurse scan a preconfigured set of directories / files for error and
71 (<crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>, <apps/*.c>)
72 When this option is NOT specified, the filelist is taken from
73 the commandline instead. Here, wildcards may be embedded. (Be
74 sure to escape those to prevent the shell from expanding them
75 for you when you wish mkerr.pl to do so instead.)
76 Default: take file list to scan from the command line.
78 -reindex Discard the numeric values previously assigned to the error
79 and function codes as extracted from the scanned header files;
80 instead renumber all of them starting from 100. (Note that
81 the numbers assigned through 'R' records in the config file
83 Default: keep previously assigned numbers. (You are warned
84 when collisions are detected.)
86 -nostatic Generates a different source code, where these additional
87 functions are generated for each library specified in the
89 void ERR_load_<LIB>_strings(void);
90 void ERR_unload_<LIB>_strings(void);
91 void ERR_<LIB>_error(int f, int r, char *fn, int ln);
92 #define <LIB>err(f,r) ERR_<LIB>_error(f,r,__FILE__,__LINE__)
93 while the code facilitates the use of these in an environment
94 where the error support routines are dynamically loaded at
96 Default: 'static' code generation.
98 -staticloader Prefix generated functions with the 'static' scope modifier.
99 Default: don't write any scope modifier prefix.
101 -write Actually (over)write the generated code to the header and C
102 source files as assigned to each library through the config
104 Default: don't write.
106 -help / -h / -? / --help Show this help text.
108 ... Additional arguments are added to the file list to scan,
109 assuming '-recurse' was NOT specified on the command line.
119 @source = ( <crypto/*.c>, <crypto/*/*.c>, <ssl/*.c> )
124 # Read in the config file
126 open(IN, "<$config") || die "Can't open config file $config";
132 if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) {
140 $fassigned{$1} = ":";
141 $rassigned{$1} = ":";
145 } elsif (/^F\s+(\S+)/) {
146 # Add extra function with $1
147 } elsif (/^R\s+(\S+)\s+(\S+)/) {
155 # Scan each header file in turn and make a list of error codes
158 while (($hdr, $lib) = each %libinc)
160 next if($hdr eq "NONE");
161 print STDERR "Scanning header file $hdr\n" if $debug;
162 my $line = "", $def= "", $linenr = 0, $gotfile = 0;
163 if (open(IN, "<$hdr")) {
167 print STDERR "line: $linenr\r" if $debug;
169 last if(/BEGIN\s+ERROR\s+CODES/);
181 if (not /\*\//) { # multiline comment...
182 $line = $_; # ... just accumulate
185 s/\/\*.*?\*\///gs; # wipe it
191 $cpp-- if /^#\s*endif/;
194 $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration
196 next if (/^\#/); # skip preprocessor directives
198 s/{[^{}]*}//gs; # ignore {} blocks
200 if (/\{|\/\*/) { # Add a } so editor works...
208 print STDERR " \r" if $debug;
210 # Delete any DECLARE_ macros
211 $def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
212 foreach (split /;/, $def) {
214 print STDERR "def: $defnr\r" if $debug;
216 # The goal is to collect function names from function declarations.
221 # Skip over recognized non-function declarations
222 next if(/typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/);
224 # Remove STACK_OF(foo)
225 s/STACK_OF\(\w+\)/void/;
227 # Reduce argument lists to empty ()
228 # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
230 s/\([^\(\)]+\)/\{\}/gs;
231 s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f
233 # pretend as we didn't use curly braces: {} -> ()
236 if (/(\w+)\s*\(\).*/s) { # first token prior [first] () is
237 my $name = $1; # a function name!
238 $name =~ tr/[a-z]/[A-Z]/;
240 } elsif (/[\(\)]/ and not (/=/)) {
241 print STDERR "Header $hdr: cannot parse: $_;\n";
245 print STDERR " \r" if $debug;
249 # Scan function and reason codes and store them: keep a note of the
254 if(/^\#\s*define\s+(\S+)\s+(\S+)/) {
257 next if $name =~ /^${lib}err/;
258 unless($name =~ /^${lib}_([RF])_(\w+)$/) {
259 print STDERR "Invalid error code $name\n";
263 $rcodes{$name} = $code;
264 if ($rassigned{$lib} =~ /:$code:/) {
265 print STDERR "!! ERROR: $lib reason code $code assigned twice (collision at $name)\n";
268 $rassigned{$lib} .= "$code:";
269 if(!(exists $rextra{$name}) &&
270 ($code > $rmax{$lib}) ) {
274 if ($fassigned{$lib} =~ /:$code:/) {
275 print STDERR "!! ERROR: $lib function code $code assigned twice (collision at $name)\n";
278 $fassigned{$lib} .= "$code:";
279 if($code > $fmax{$lib}) {
282 $fcodes{$name} = $code;
289 if (defined($fmax{$lib})) {
290 print STDERR "Max function code fmax" . "{" . "$lib" . "} = $fmax{$lib}\n";
291 $fassigned{$lib} =~ m/^:(.*):$/;
292 @fassigned = sort {$a <=> $b} split(":", $1);
293 print STDERR " @fassigned\n";
295 if (defined($rmax{$lib})) {
296 print STDERR "Max reason code rmax" . "{" . "$lib" . "} = $rmax{$lib}\n";
297 $rassigned{$lib} =~ m/^:(.*):$/;
298 @rassigned = sort {$a <=> $b} split(":", $1);
299 print STDERR " @rassigned\n";
304 if ($rmax{$lib} >= 1000) {
305 print STDERR "!! ERROR: SSL error codes 1000+ are reserved for alerts.\n";
306 print STDERR "!! Any new alerts must be added to $config.\n";
314 # Scan each C source file and look for function and reason codes
315 # This is done by looking for strings that "look like" function or
316 # reason codes: basically anything consisting of all upper case and
317 # numerics which has _F_ or _R_ in it and which has the name of an
318 # error library at the start. This seems to work fine except for the
319 # oddly named structure BIO_F_CTX which needs to be ignored.
320 # If a code doesn't exist in list compiled from headers then mark it
321 # with the value "X" as a place holder to give it a value later.
322 # Store all function and reason codes found in %ufcodes and %urcodes
323 # so all those unreferenced can be printed out.
326 foreach $file (@source) {
327 # Don't parse the error source file.
328 next if exists $cskip{$file};
329 print STDERR "File loaded: ".$file."\r" if $debug;
330 open(IN, "<$file") || die "Can't open source file $file\n";
332 # skip obsoleted source files entirely!
333 last if(/^#error\s+obsolete/);
335 if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) {
336 next unless exists $csrc{$2};
337 next if($1 eq "BIO_F_BUFFER_CTX");
339 if(!exists $fcodes{$1}) {
343 $notrans{$1} = 1 unless exists $ftrans{$3};
344 print STDERR "Function: $1\t= $fcodes{$1} (lib: $2, name: $3)\n" if $debug;
346 if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) {
347 next unless exists $csrc{$2};
349 if(!exists $rcodes{$1}) {
353 print STDERR "Reason: $1\t= $rcodes{$1} (lib: $2)\n" if $debug;
358 print STDERR " \n" if $debug;
360 # Now process each library in turn.
362 foreach $lib (keys %csrc)
364 my $hfile = $hinc{$lib};
365 my $cfile = $csrc{$lib};
366 if(!$fnew{$lib} && !$rnew{$lib}) {
367 print STDERR "$lib:\t\tNo new error codes\n";
368 next unless $rebuild;
370 print STDERR "$lib:\t\t$fnew{$lib} New Functions,";
371 print STDERR " $rnew{$lib} New Reasons.\n";
372 next unless $dowrite;
375 # If we get here then we have some new error codes so we
376 # need to rebuild the header file and C file.
378 # Make a sorted list of error and reason codes for later use.
380 my @function = sort grep(/^${lib}_/,keys %fcodes);
381 my @reasons = sort grep(/^${lib}_/,keys %rcodes);
383 # Rewrite the header file
385 if (open(IN, "<$hfile")) {
386 # Copy across the old file
389 last if (/BEGIN ERROR CODES/);
394 "/* ====================================================================\n",
395 " * Copyright (c) 2001-$year The OpenSSL Project. All rights reserved.\n",
397 " * Redistribution and use in source and binary forms, with or without\n",
398 " * modification, are permitted provided that the following conditions\n",
401 " * 1. Redistributions of source code must retain the above copyright\n",
402 " * notice, this list of conditions and the following disclaimer. \n",
404 " * 2. Redistributions in binary form must reproduce the above copyright\n",
405 " * notice, this list of conditions and the following disclaimer in\n",
406 " * the documentation and/or other materials provided with the\n",
407 " * distribution.\n",
409 " * 3. All advertising materials mentioning features or use of this\n",
410 " * software must display the following acknowledgment:\n",
411 " * \"This product includes software developed by the OpenSSL Project\n",
412 " * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n",
414 " * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n",
415 " * endorse or promote products derived from this software without\n",
416 " * prior written permission. For written permission, please contact\n",
417 " * openssl-core\@openssl.org.\n",
419 " * 5. Products derived from this software may not be called \"OpenSSL\"\n",
420 " * nor may \"OpenSSL\" appear in their names without prior written\n",
421 " * permission of the OpenSSL Project.\n",
423 " * 6. Redistributions of any form whatsoever must retain the following\n",
424 " * acknowledgment:\n",
425 " * \"This product includes software developed by the OpenSSL Project\n",
426 " * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n",
428 " * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n",
429 " * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n",
430 " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n",
431 " * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n",
432 " * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n",
433 " * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n",
434 " * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n",
435 " * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n",
436 " * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n",
437 " * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n",
438 " * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n",
439 " * OF THE POSSIBILITY OF SUCH DAMAGE.\n",
440 " * ====================================================================\n",
442 " * This product includes cryptographic software written by Eric Young\n",
443 " * (eay\@cryptsoft.com). This product includes software written by Tim\n",
444 " * Hudson (tjh\@cryptsoft.com).\n",
448 "#ifndef HEADER_${lib}_ERR_H\n",
449 "#define HEADER_${lib}_ERR_H\n",
451 "#ifdef __cplusplus\n",
455 "/* BEGIN ERROR CODES */\n";
457 open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n";
463 * The following lines are auto generated by the script mkerr.pl. Any changes
464 * made after this point may be overwritten when the script is next run.
469 ${staticloader}void ERR_load_${lib}_strings(void);
474 ${staticloader}void ERR_load_${lib}_strings(void);
475 ${staticloader}void ERR_unload_${lib}_strings(void);
476 ${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
477 # define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__)
482 /* Error codes for the $lib functions. */
484 /* Function codes. */
487 foreach $i (@function) {
489 if($fcodes{$i} eq "X") {
490 $fassigned{$lib} =~ m/^:([^:]*):/;
492 if (!defined($findcode)) {
493 $findcode = $fmax{$lib};
495 while ($fassigned{$lib} =~ m/:$findcode:/) {
498 $fcodes{$i} = $findcode;
499 $fassigned{$lib} .= "$findcode:";
500 print STDERR "New Function code $i\n" if $debug;
502 printf OUT "# define $i%s $fcodes{$i}\n"," " x $z;
505 print OUT "\n/* Reason codes. */\n";
507 foreach $i (@reasons) {
509 if($rcodes{$i} eq "X") {
510 $rassigned{$lib} =~ m/^:([^:]*):/;
512 if (!defined($findcode)) {
513 $findcode = $rmax{$lib};
515 while ($rassigned{$lib} =~ m/:$findcode:/) {
518 $rcodes{$i} = $findcode;
519 $rassigned{$lib} .= "$findcode:";
520 print STDERR "New Reason code $i\n" if $debug;
522 printf OUT "# define $i%s $rcodes{$i}\n"," " x $z;
533 # Rewrite the C source file containing the error details.
535 # First, read any existing reason string definitions:
536 my %err_reason_strings;
537 if (open(IN,"<$cfile")) {
539 if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
540 $err_reason_strings{$1} = $2;
542 if (/\b${lib}_F_(\w*)\b.*\"(.*)\"/) {
543 if (!exists $ftrans{$1} && ($1 ne $2)) {
544 print STDERR "WARNING: Mismatched function string $2\n";
555 $hfile =~ /([^\/]+)$/;
556 $hincf = "<${hprefix}$1>";
558 $hincf = "\"$hfile\"";
561 # If static we know the error code at compile time so use it
562 # in error definitions.
566 $pack_errcode = "ERR_LIB_${lib}";
572 $load_errcode = "ERR_LIB_${lib}";
576 open (OUT,">$cfile") || die "Can't open $cfile for writing";
580 /* ====================================================================
581 * Copyright (c) 1999-$year The OpenSSL Project. All rights reserved.
583 * Redistribution and use in source and binary forms, with or without
584 * modification, are permitted provided that the following conditions
587 * 1. Redistributions of source code must retain the above copyright
588 * notice, this list of conditions and the following disclaimer.
590 * 2. Redistributions in binary form must reproduce the above copyright
591 * notice, this list of conditions and the following disclaimer in
592 * the documentation and/or other materials provided with the
595 * 3. All advertising materials mentioning features or use of this
596 * software must display the following acknowledgment:
597 * "This product includes software developed by the OpenSSL Project
598 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
600 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
601 * endorse or promote products derived from this software without
602 * prior written permission. For written permission, please contact
603 * openssl-core\@OpenSSL.org.
605 * 5. Products derived from this software may not be called "OpenSSL"
606 * nor may "OpenSSL" appear in their names without prior written
607 * permission of the OpenSSL Project.
609 * 6. Redistributions of any form whatsoever must retain the following
611 * "This product includes software developed by the OpenSSL Project
612 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
614 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
615 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
616 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
617 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
618 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
619 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
620 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
621 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
622 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
623 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
624 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
625 * OF THE POSSIBILITY OF SUCH DAMAGE.
626 * ====================================================================
628 * This product includes cryptographic software written by Eric Young
629 * (eay\@cryptsoft.com). This product includes software written by Tim
630 * Hudson (tjh\@cryptsoft.com).
635 * NOTE: this file was auto generated by the mkerr.pl script: any changes
636 * made to it will be overwritten when the script next updates this file,
637 * only reason strings will be preserved.
641 #include <openssl/err.h>
644 /* BEGIN ERROR CODES */
645 #ifndef OPENSSL_NO_ERR
647 # define ERR_FUNC(func) ERR_PACK($pack_errcode,func,0)
648 # define ERR_REASON(reason) ERR_PACK($pack_errcode,0,reason)
650 static ERR_STRING_DATA ${lib}_str_functs[] = {
652 # Add each function code: if a function name is found then use it.
653 foreach $i (@function) {
655 $i =~ /^${lib}_F_(\S+)$/;
657 if(exists $ftrans{$fn}) {
660 # print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
661 if(length($i) + length($fn) > 58) {
662 print OUT " {ERR_FUNC($i),\n \"$fn\"},\n";
664 print OUT " {ERR_FUNC($i), \"$fn\"},\n";
671 static ERR_STRING_DATA ${lib}_str_reasons[] = {
673 # Add each reason code.
674 foreach $i (@reasons) {
676 my $rstr = "ERR_REASON($i)";
677 if (exists $err_reason_strings{$i}) {
678 $rn = $err_reason_strings{$i};
680 $i =~ /^${lib}_R_(\S+)$/;
682 $rn =~ tr/_[A-Z]/ [a-z]/;
684 if(length($i) + length($rn) > 56) {
685 print OUT " {${rstr},\n \"$rn\"},\n";
687 print OUT " {${rstr}, \"$rn\"},\n";
697 ${staticloader}void ERR_load_${lib}_strings(void)
699 #ifndef OPENSSL_NO_ERR
701 if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) {
702 ERR_load_strings($load_errcode, ${lib}_str_functs);
703 ERR_load_strings($load_errcode, ${lib}_str_reasons);
715 #ifdef ${lib}_LIB_NAME
716 static ERR_STRING_DATA ${lib}_lib_name[] = {
717 {0, ${lib}_LIB_NAME},
722 static int ${lib}_lib_error_code = 0;
723 static int ${lib}_error_init = 1;
725 ${staticloader}void ERR_load_${lib}_strings(void)
727 if (${lib}_lib_error_code == 0)
728 ${lib}_lib_error_code = ERR_get_next_error_library();
730 if (${lib}_error_init) {
731 ${lib}_error_init = 0;
732 #ifndef OPENSSL_NO_ERR
733 ERR_load_strings(${lib}_lib_error_code, ${lib}_str_functs);
734 ERR_load_strings(${lib}_lib_error_code, ${lib}_str_reasons);
737 #ifdef ${lib}_LIB_NAME
738 ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code, 0, 0);
739 ERR_load_strings(0, ${lib}_lib_name);
744 ${staticloader}void ERR_unload_${lib}_strings(void)
746 if (${lib}_error_init == 0) {
747 #ifndef OPENSSL_NO_ERR
748 ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_functs);
749 ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_reasons);
752 #ifdef ${lib}_LIB_NAME
753 ERR_unload_strings(0, ${lib}_lib_name);
755 ${lib}_error_init = 1;
759 ${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line)
761 if (${lib}_lib_error_code == 0)
762 ${lib}_lib_error_code = ERR_get_next_error_library();
763 ERR_PUT_error(${lib}_lib_error_code, function, reason, file, line);
770 undef %err_reason_strings;
773 if($debug && %notrans) {
774 print STDERR "The following function codes were not translated:\n";
775 foreach(sort keys %notrans)
781 # Make a list of unreferenced function and reason codes
783 foreach (keys %fcodes) {
784 push (@funref, $_) unless exists $ufcodes{$_};
787 foreach (keys %rcodes) {
788 push (@runref, $_) unless exists $urcodes{$_};
791 if($debug && @funref) {
792 print STDERR "The following function codes were not referenced:\n";
793 foreach(sort @funref)
799 if($debug && @runref) {
800 print STDERR "The following reason codes were not referenced:\n";
801 foreach(sort @runref)
808 print STDERR "There were errors, failing...\n\n";