1 #!/usr/local/bin/perl -w
3 my $config = "crypto/err/openssl.ec";
4 my $hprefix = "openssl/";
12 my $staticloader = "";
18 my $year = (localtime)[5] + 1900;
24 $config = shift @ARGV;
25 } elsif($arg eq "-hprefix") {
27 $hprefix = shift @ARGV;
28 } elsif($arg eq "-debug") {
32 } elsif($arg eq "-rebuild") {
35 } elsif($arg eq "-recurse") {
38 } elsif($arg eq "-reindex") {
41 } elsif($arg eq "-nostatic") {
44 } elsif($arg eq "-staticloader") {
45 $staticloader = "static ";
47 } elsif($arg eq "-unref") {
50 } elsif($arg eq "-write") {
53 } elsif($arg eq "-help" || $arg eq "-h" || $arg eq "-?" || $arg eq "--help") {
55 mkerr.pl [options] ...
59 -conf F Use the config file F instead of the default one:
62 -hprefix P Prepend the filenames in generated #include <header>
63 statements with prefix P. Default: 'openssl/' (without
64 the quotes, naturally)
66 -debug Turn on debugging verbose output on stderr.
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!)
74 -recurse scan a preconfigured set of directories / files for error and
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.
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
88 Default: keep previously assigned numbers. (You are warned
89 when collisions are detected.)
91 -nostatic Generates a different source code, where these additional
92 functions are generated for each library specified in the
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,OPENSSL_FILE,OPENSSL_LINE)
98 while the code facilitates the use of these in an environment
99 where the error support routines are dynamically loaded at
101 Default: 'static' code generation.
103 -staticloader Prefix generated functions with the 'static' scope modifier.
104 Default: don't write any scope modifier prefix.
106 -unref Print out unreferenced function and reason codes.
108 -write Actually (over)write the generated code to the header and C
109 source files as assigned to each library through the config
111 Default: don't write.
113 -help / -h / -? / --help Show this help text.
115 ... Additional arguments are added to the file list to scan,
116 assuming '-recurse' was NOT specified on the command line.
126 @source = ( <crypto/*.c>, <crypto/*/*.c>, <ssl/*.c>, <ssl/*/*.c> )
131 # Read in the config file
133 open(IN, "<$config") || die "Can't open config file $config";
139 if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) {
147 $fassigned{$1} = ":";
148 $rassigned{$1} = ":";
152 } elsif (/^F\s+(\S+)/) {
153 # Add extra function with $1
154 } elsif (/^R\s+(\S+)\s+(\S+)/) {
162 # Scan each header file in turn and make a list of error codes
165 while (($hdr, $lib) = each %libinc)
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")) {
174 print STDERR "line: $linenr\r" if $debug;
176 last if(/BEGIN\s+ERROR\s+CODES/);
188 if (not /\*\//) { # multiline comment...
189 $line = $_; # ... just accumulate
192 s/\/\*.*?\*\///gs; # wipe it
198 $cpp-- if /^#\s*endif/;
201 $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration
203 next if (/^\#/); # skip preprocessor directives
205 s/{[^{}]*}//gs; # ignore {} blocks
207 if (/\{|\/\*/) { # Add a } so editor works...
215 print STDERR " \r" if $debug;
217 # Delete any DECLARE_ macros
218 $def =~ s/DECLARE_\w+\([\w,\s]+\)//gs;
219 foreach (split /;/, $def) {
221 print STDERR "def: $defnr\r" if $debug;
223 # The goal is to collect function names from function declarations.
228 # Skip over recognized non-function declarations
229 next if(/typedef\W/ or /DECLARE_STACK_OF/ or /TYPEDEF_.*_OF/);
231 # Remove STACK_OF(foo)
232 s/STACK_OF\(\w+\)/void/;
234 # Reduce argument lists to empty ()
235 # fold round brackets recursively: (t(*v)(t),t) -> (t{}{},t) -> {}
237 s/\([^\(\)]+\)/\{\}/gs;
238 s/\(\s*\*\s*(\w+)\s*\{\}\s*\)/$1/gs; #(*f{}) -> f
240 # pretend as we didn't use curly braces: {} -> ()
243 if (/(\w+)\s*\(\).*/s) { # first token prior [first] () is
244 my $name = $1; # a function name!
245 $name =~ tr/[a-z]/[A-Z]/;
247 } elsif (/[\(\)]/ and not (/=/)) {
248 print STDERR "Header $hdr: cannot parse: $_;\n";
252 print STDERR " \r" if $debug;
256 # Scan function and reason codes and store them: keep a note of the
261 if(/^\#\s*define\s+(\S+)\s+(\S+)/) {
264 next if $name =~ /^${lib}err/;
265 unless($name =~ /^${lib}_([RF])_(\w+)$/) {
266 print STDERR "Invalid error code $name\n";
270 $rcodes{$name} = $code;
271 if ($rassigned{$lib} =~ /:$code:/) {
272 print STDERR "!! ERROR: $lib reason code $code assigned twice (collision at $name)\n";
275 $rassigned{$lib} .= "$code:";
276 if(!(exists $rextra{$name}) &&
277 ($code > $rmax{$lib}) ) {
281 if ($fassigned{$lib} =~ /:$code:/) {
282 print STDERR "!! ERROR: $lib function code $code assigned twice (collision at $name)\n";
285 $fassigned{$lib} .= "$code:";
286 if($code > $fmax{$lib}) {
289 $fcodes{$name} = $code;
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";
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";
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";
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.
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";
341 # skip obsoleted source files entirely!
342 last if(/^#error\s+obsolete/);
344 if (!/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/)
346 /^([^()]*(\([^()]*\)[^()]*)*)\(/;
347 $1 =~ /([A-Za-z_0-9]*)$/;
351 if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) {
352 next unless exists $csrc{$2};
353 next if($1 eq "BIO_F_BUFFER_CTX");
355 if(!exists $fcodes{$1}) {
359 $ftrans{$3} = $func unless exists $ftrans{$3};
360 if (uc $func ne $3) {
361 print STDERR "ERROR: mismatch $file:$linenr $func:$3\n";
364 print STDERR "Function: $1\t= $fcodes{$1} (lib: $2, name: $3)\n" if $debug;
366 if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) {
367 next unless exists $csrc{$2};
369 if(!exists $rcodes{$1}) {
373 print STDERR "Reason: $1\t= $rcodes{$1} (lib: $2)\n" if $debug;
378 print STDERR " \n" if $debug;
380 # Now process each library in turn.
382 foreach $lib (keys %csrc)
384 my $hfile = $hinc{$lib};
385 my $cfile = $csrc{$lib};
386 if(!$fnew{$lib} && !$rnew{$lib}) {
387 next unless $rebuild;
389 print STDERR "$lib:\t\t$fnew{$lib} New Functions,";
390 print STDERR " $rnew{$lib} New Reasons.\n";
391 next unless $dowrite;
394 # If we get here then we have some new error codes so we
395 # need to rebuild the header file and C file.
397 # Make a sorted list of error and reason codes for later use.
399 my @function = sort grep(/^${lib}_/,keys %fcodes);
400 my @reasons = sort grep(/^${lib}_/,keys %rcodes);
402 # Rewrite the header file
404 if (open(IN, "<$hfile")) {
405 # Copy across the old file
408 last if (/BEGIN ERROR CODES/);
413 "/* ====================================================================\n",
414 " * Copyright (c) 2001-$year The OpenSSL Project. All rights reserved.\n",
416 " * Redistribution and use in source and binary forms, with or without\n",
417 " * modification, are permitted provided that the following conditions\n",
420 " * 1. Redistributions of source code must retain the above copyright\n",
421 " * notice, this list of conditions and the following disclaimer. \n",
423 " * 2. Redistributions in binary form must reproduce the above copyright\n",
424 " * notice, this list of conditions and the following disclaimer in\n",
425 " * the documentation and/or other materials provided with the\n",
426 " * distribution.\n",
428 " * 3. All advertising materials mentioning features or use of this\n",
429 " * software must display the following acknowledgment:\n",
430 " * \"This product includes software developed by the OpenSSL Project\n",
431 " * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n",
433 " * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n",
434 " * endorse or promote products derived from this software without\n",
435 " * prior written permission. For written permission, please contact\n",
436 " * openssl-core\@openssl.org.\n",
438 " * 5. Products derived from this software may not be called \"OpenSSL\"\n",
439 " * nor may \"OpenSSL\" appear in their names without prior written\n",
440 " * permission of the OpenSSL Project.\n",
442 " * 6. Redistributions of any form whatsoever must retain the following\n",
443 " * acknowledgment:\n",
444 " * \"This product includes software developed by the OpenSSL Project\n",
445 " * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n",
447 " * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n",
448 " * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n",
449 " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n",
450 " * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n",
451 " * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n",
452 " * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n",
453 " * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n",
454 " * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n",
455 " * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n",
456 " * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n",
457 " * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n",
458 " * OF THE POSSIBILITY OF SUCH DAMAGE.\n",
459 " * ====================================================================\n",
461 " * This product includes cryptographic software written by Eric Young\n",
462 " * (eay\@cryptsoft.com). This product includes software written by Tim\n",
463 " * Hudson (tjh\@cryptsoft.com).\n",
467 "#ifndef HEADER_${lib}_ERR_H\n",
468 "#define HEADER_${lib}_ERR_H\n",
470 "#ifdef __cplusplus\n",
474 "/* BEGIN ERROR CODES */\n";
476 open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n";
482 * The following lines are auto generated by the script mkerr.pl. Any changes
483 * made after this point may be overwritten when the script is next run.
488 ${staticloader}void ERR_load_${lib}_strings(void);
493 ${staticloader}void ERR_load_${lib}_strings(void);
494 ${staticloader}void ERR_unload_${lib}_strings(void);
495 ${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line);
496 # define ${lib}err(f,r) ERR_${lib}_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
501 /* Error codes for the $lib functions. */
503 /* Function codes. */
506 foreach $i (@function) {
508 if($fcodes{$i} eq "X") {
509 $fassigned{$lib} =~ m/^:([^:]*):/;
511 if (!defined($findcode)) {
512 $findcode = $fmax{$lib};
514 while ($fassigned{$lib} =~ m/:$findcode:/) {
517 $fcodes{$i} = $findcode;
518 $fassigned{$lib} .= "$findcode:";
519 print STDERR "New Function code $i\n" if $debug;
521 printf OUT "# define $i%s $fcodes{$i}\n"," " x $z;
524 print OUT "\n/* Reason codes. */\n";
526 foreach $i (@reasons) {
528 if($rcodes{$i} eq "X") {
529 $rassigned{$lib} =~ m/^:([^:]*):/;
531 if (!defined($findcode)) {
532 $findcode = $rmax{$lib};
534 while ($rassigned{$lib} =~ m/:$findcode:/) {
537 $rcodes{$i} = $findcode;
538 $rassigned{$lib} .= "$findcode:";
539 print STDERR "New Reason code $i\n" if $debug;
541 printf OUT "# define $i%s $rcodes{$i}\n"," " x $z;
552 # Rewrite the C source file containing the error details.
554 # First, read any existing reason string definitions:
555 my %err_reason_strings;
556 if (open(IN,"<$cfile")) {
559 s|\R$||; # Better chomp
562 if (/{ERR_(FUNC|REASON)\(/) {
563 if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) {
564 $err_reason_strings{$1} = $2;
565 } elsif (/\b${lib}_F_(\w*)\b.*\"(.*)\"/) {
566 if (!exists $ftrans{$1} && ($1 ne $2)) {
567 print STDERR "WARNING: Mismatched function string $2\n";
581 $hfile =~ /([^\/]+)$/;
582 $hincf = "<${hprefix}$1>";
584 $hincf = "\"$hfile\"";
587 # If static we know the error code at compile time so use it
588 # in error definitions.
592 $pack_errcode = "ERR_LIB_${lib}";
598 $load_errcode = "ERR_LIB_${lib}";
602 open (OUT,">$cfile") || die "Can't open $cfile for writing";
605 /* ====================================================================
606 * Copyright (c) 1999-$year The OpenSSL Project. All rights reserved.
608 * Redistribution and use in source and binary forms, with or without
609 * modification, are permitted provided that the following conditions
612 * 1. Redistributions of source code must retain the above copyright
613 * notice, this list of conditions and the following disclaimer.
615 * 2. Redistributions in binary form must reproduce the above copyright
616 * notice, this list of conditions and the following disclaimer in
617 * the documentation and/or other materials provided with the
620 * 3. All advertising materials mentioning features or use of this
621 * software must display the following acknowledgment:
622 * "This product includes software developed by the OpenSSL Project
623 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
625 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
626 * endorse or promote products derived from this software without
627 * prior written permission. For written permission, please contact
628 * openssl-core\@OpenSSL.org.
630 * 5. Products derived from this software may not be called "OpenSSL"
631 * nor may "OpenSSL" appear in their names without prior written
632 * permission of the OpenSSL Project.
634 * 6. Redistributions of any form whatsoever must retain the following
636 * "This product includes software developed by the OpenSSL Project
637 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
639 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
640 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
641 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
642 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
643 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
644 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
645 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
646 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
647 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
648 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
649 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
650 * OF THE POSSIBILITY OF SUCH DAMAGE.
651 * ====================================================================
653 * This product includes cryptographic software written by Eric Young
654 * (eay\@cryptsoft.com). This product includes software written by Tim
655 * Hudson (tjh\@cryptsoft.com).
660 * NOTE: this file was auto generated by the mkerr.pl script: any changes
661 * made to it will be overwritten when the script next updates this file,
662 * only reason strings will be preserved.
666 #include <openssl/err.h>
669 /* BEGIN ERROR CODES */
670 #ifndef OPENSSL_NO_ERR
672 # define ERR_FUNC(func) ERR_PACK($pack_errcode,func,0)
673 # define ERR_REASON(reason) ERR_PACK($pack_errcode,0,reason)
675 static ERR_STRING_DATA ${lib}_str_functs[] = {
677 # Add each function code: if a function name is found then use it.
678 foreach $i (@function) {
680 $i =~ /^${lib}_F_(\S+)$/;
682 if(exists $ftrans{$fn}) {
685 # print OUT "{ERR_PACK($pack_errcode,$i,0),\t\"$fn\"},\n";
686 if(length($i) + length($fn) > 58) {
687 print OUT " {ERR_FUNC($i),\n \"$fn\"},\n";
689 print OUT " {ERR_FUNC($i), \"$fn\"},\n";
696 static ERR_STRING_DATA ${lib}_str_reasons[] = {
698 # Add each reason code.
699 foreach $i (@reasons) {
701 my $rstr = "ERR_REASON($i)";
702 if (exists $err_reason_strings{$i}) {
703 $rn = $err_reason_strings{$i};
705 $i =~ /^${lib}_R_(\S+)$/;
707 $rn =~ tr/_[A-Z]/ [a-z]/;
709 if(length($i) + length($rn) > 56) {
710 print OUT " {${rstr},\n \"$rn\"},\n";
712 print OUT " {${rstr}, \"$rn\"},\n";
722 ${staticloader}void ERR_load_${lib}_strings(void)
724 #ifndef OPENSSL_NO_ERR
726 if (ERR_func_error_string(${lib}_str_functs[0].error) == NULL) {
727 ERR_load_strings($load_errcode, ${lib}_str_functs);
728 ERR_load_strings($load_errcode, ${lib}_str_reasons);
740 #ifdef ${lib}_LIB_NAME
741 static ERR_STRING_DATA ${lib}_lib_name[] = {
742 {0, ${lib}_LIB_NAME},
747 static int ${lib}_lib_error_code = 0;
748 static int ${lib}_error_init = 1;
750 ${staticloader}void ERR_load_${lib}_strings(void)
752 if (${lib}_lib_error_code == 0)
753 ${lib}_lib_error_code = ERR_get_next_error_library();
755 if (${lib}_error_init) {
756 ${lib}_error_init = 0;
757 #ifndef OPENSSL_NO_ERR
758 ERR_load_strings(${lib}_lib_error_code, ${lib}_str_functs);
759 ERR_load_strings(${lib}_lib_error_code, ${lib}_str_reasons);
762 #ifdef ${lib}_LIB_NAME
763 ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code, 0, 0);
764 ERR_load_strings(0, ${lib}_lib_name);
769 ${staticloader}void ERR_unload_${lib}_strings(void)
771 if (${lib}_error_init == 0) {
772 #ifndef OPENSSL_NO_ERR
773 ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_functs);
774 ERR_unload_strings(${lib}_lib_error_code, ${lib}_str_reasons);
777 #ifdef ${lib}_LIB_NAME
778 ERR_unload_strings(0, ${lib}_lib_name);
780 ${lib}_error_init = 1;
784 ${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line)
786 if (${lib}_lib_error_code == 0)
787 ${lib}_lib_error_code = ERR_get_next_error_library();
788 ERR_PUT_error(${lib}_lib_error_code, function, reason, file, line);
795 undef %err_reason_strings;
798 if($debug && %notrans) {
799 print STDERR "The following function codes were not translated:\n";
800 foreach(sort keys %notrans)
806 # Make a list of unreferenced function and reason codes
808 foreach (keys %fcodes) {
809 push (@funref, $_) unless exists $ufcodes{$_};
812 foreach (keys %rcodes) {
813 push (@runref, $_) unless exists $urcodes{$_};
816 if($unref && @funref) {
817 print STDERR "The following function codes were not referenced:\n";
818 foreach(sort @funref)
824 if($unref && @runref) {
825 print STDERR "The following reason codes were not referenced:\n";
826 foreach(sort @runref)
833 print STDERR "There were errors, failing...\n\n";