mkerr.pl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. #! /usr/bin/env perl
  2. # Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License 2.0 (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. use strict;
  9. use warnings;
  10. use File::Basename;
  11. use File::Spec::Functions qw(abs2rel rel2abs);
  12. use lib ".";
  13. use configdata;
  14. my $config = "crypto/err/openssl.ec";
  15. my $debug = 0;
  16. my $internal = 0;
  17. my $nowrite = 0;
  18. my $rebuild = 0;
  19. my $reindex = 0;
  20. my $static = 0;
  21. my $unref = 0;
  22. my %modules = ();
  23. my $errors = 0;
  24. my @t = localtime();
  25. my $YEAR = $t[5] + 1900;
  26. sub phase
  27. {
  28. my $text = uc(shift);
  29. print STDERR "\n---\n$text\n" if $debug;
  30. }
  31. sub help
  32. {
  33. print STDERR <<"EOF";
  34. mkerr.pl [options] [files...]
  35. Options:
  36. -conf FILE Use the named config file FILE instead of the default.
  37. -debug Verbose output debugging on stderr.
  38. -internal Generate code that is to be built as part of OpenSSL itself.
  39. Also scans internal list of files.
  40. -module M Only useful with -internal!
  41. Only write files for library module M. Whether files are
  42. actually written or not depends on other options, such as
  43. -rebuild.
  44. Note: this option is cumulative. If not given at all, all
  45. internal modules will be considered.
  46. -nowrite Do not write the header/source files, even if changed.
  47. -rebuild Rebuild all header and C source files, even if there
  48. were no changes.
  49. -reindex Ignore previously assigned values (except for R records in
  50. the config file) and renumber everything starting at 100.
  51. -static Make the load/unload functions static.
  52. -unref List all unreferenced function and reason codes on stderr;
  53. implies -nowrite.
  54. -help Show this help text.
  55. ... Additional arguments are added to the file list to scan,
  56. if '-internal' was NOT specified on the command line.
  57. EOF
  58. }
  59. while ( @ARGV ) {
  60. my $arg = $ARGV[0];
  61. last unless $arg =~ /-.*/;
  62. $arg = $1 if $arg =~ /-(-.*)/;
  63. if ( $arg eq "-conf" ) {
  64. $config = $ARGV[1];
  65. shift @ARGV;
  66. } elsif ( $arg eq "-debug" ) {
  67. $debug = 1;
  68. $unref = 1;
  69. } elsif ( $arg eq "-internal" ) {
  70. $internal = 1;
  71. } elsif ( $arg eq "-nowrite" ) {
  72. $nowrite = 1;
  73. } elsif ( $arg eq "-rebuild" ) {
  74. $rebuild = 1;
  75. } elsif ( $arg eq "-reindex" ) {
  76. $reindex = 1;
  77. } elsif ( $arg eq "-static" ) {
  78. $static = 1;
  79. } elsif ( $arg eq "-unref" ) {
  80. $unref = 1;
  81. $nowrite = 1;
  82. } elsif ( $arg eq "-module" ) {
  83. shift @ARGV;
  84. $modules{uc $ARGV[0]} = 1;
  85. } elsif ( $arg =~ /-*h(elp)?/ ) {
  86. &help();
  87. exit;
  88. } elsif ( $arg =~ /-.*/ ) {
  89. die "Unknown option $arg; use -h for help.\n";
  90. }
  91. shift @ARGV;
  92. }
  93. my @source;
  94. if ( $internal ) {
  95. die "Cannot mix -internal and -static\n" if $static;
  96. die "Extra parameters given.\n" if @ARGV;
  97. @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
  98. glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'),
  99. glob('providers/*/*.c'), glob('providers/*/*/*.c') );
  100. } else {
  101. die "-module isn't useful without -internal\n" if scalar keys %modules > 0;
  102. @source = @ARGV;
  103. }
  104. # Data parsed out of the config and state files.
  105. my %hpubinc; # lib -> public header
  106. my %libpubinc; # public header -> lib
  107. my %hprivinc; # lib -> private header
  108. my %libprivinc; # private header -> lib
  109. my %cskip; # error_file -> lib
  110. my %errorfile; # lib -> error file name
  111. my %rmax; # lib -> max assigned reason code
  112. my %rassigned; # lib -> colon-separated list of assigned reason codes
  113. my %rnew; # lib -> count of new reason codes
  114. my %rextra; # "extra" reason code -> lib
  115. my %rcodes; # reason-name -> value
  116. my $statefile; # state file with assigned reason and function codes
  117. my %strings; # define -> text
  118. # Read and parse the config file
  119. open(IN, "$config") || die "Can't open config file $config, $!,";
  120. while ( <IN> ) {
  121. next if /^#/ || /^$/;
  122. if ( /^L\s+(\S+)\s+(\S+)\s+(\S+)(?:\s+(\S+))?\s+$/ ) {
  123. my $lib = $1;
  124. my $pubhdr = $2;
  125. my $err = $3;
  126. my $privhdr = $4 // 'NONE';
  127. $hpubinc{$lib} = $pubhdr;
  128. $libpubinc{$pubhdr} = $lib;
  129. $hprivinc{$lib} = $privhdr;
  130. $libprivinc{$privhdr} = $lib;
  131. $cskip{$err} = $lib;
  132. $errorfile{$lib} = $err;
  133. next if $err eq 'NONE';
  134. $rmax{$lib} = 100;
  135. $rassigned{$lib} = ":";
  136. $rnew{$lib} = 0;
  137. die "Public header file must be in include/openssl ($pubhdr is not)\n"
  138. if ($internal
  139. && $pubhdr ne 'NONE'
  140. && $pubhdr !~ m|^include/openssl/|);
  141. die "Private header file may only be specified with -internal ($privhdr given)\n"
  142. unless ($privhdr eq 'NONE' || $internal);
  143. } elsif ( /^R\s+(\S+)\s+(\S+)/ ) {
  144. $rextra{$1} = $2;
  145. $rcodes{$1} = $2;
  146. } elsif ( /^S\s+(\S+)/ ) {
  147. $statefile = $1;
  148. } else {
  149. die "Illegal config line $_\n";
  150. }
  151. }
  152. close IN;
  153. if ( ! $statefile ) {
  154. $statefile = $config;
  155. $statefile =~ s/.ec/.txt/;
  156. }
  157. # The statefile has all the previous assignments.
  158. &phase("Reading state");
  159. my $skippedstate = 0;
  160. if ( ! $reindex && $statefile ) {
  161. open(STATE, "<$statefile") || die "Can't open $statefile, $!";
  162. # Scan function and reason codes and store them: keep a note of the
  163. # maximum code used.
  164. while ( <STATE> ) {
  165. next if /^#/ || /^$/;
  166. my $name;
  167. my $code;
  168. if ( /^(.+):(\d+):\\$/ ) {
  169. $name = $1;
  170. $code = $2;
  171. my $next = <STATE>;
  172. $next =~ s/^\s*(.*)\s*$/$1/;
  173. die "Duplicate define $name" if exists $strings{$name};
  174. $strings{$name} = $next;
  175. } elsif ( /^(\S+):(\d+):(.*)$/ ) {
  176. $name = $1;
  177. $code = $2;
  178. die "Duplicate define $name" if exists $strings{$name};
  179. $strings{$name} = $3;
  180. } else {
  181. die "Bad line in $statefile:\n$_\n";
  182. }
  183. my $lib = $name;
  184. $lib =~ s/^((?:OSSL_|OPENSSL_)?[^_]{2,}).*$/$1/;
  185. $lib = "SSL" if $lib =~ /TLS/;
  186. if ( !defined $errorfile{$lib} ) {
  187. print "Skipping $_";
  188. $skippedstate++;
  189. next;
  190. }
  191. next if $errorfile{$lib} eq 'NONE';
  192. if ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_R_/ ) {
  193. die "$lib reason code $code collision at $name\n"
  194. if $rassigned{$lib} =~ /:$code:/;
  195. $rassigned{$lib} .= "$code:";
  196. if ( !exists $rextra{$name} ) {
  197. $rmax{$lib} = $code if $code > $rmax{$lib};
  198. }
  199. $rcodes{$name} = $code;
  200. } elsif ( $name =~ /^(?:OSSL_|OPENSSL_)?[A-Z0-9]{2,}_F_/ ) {
  201. # We do nothing with the function codes, just let them go away
  202. } else {
  203. die "Bad line in $statefile:\n$_\n";
  204. }
  205. }
  206. close(STATE);
  207. if ( $debug ) {
  208. foreach my $lib ( sort keys %rmax ) {
  209. print STDERR "Reason codes for ${lib}:\n";
  210. if ( $rassigned{$lib} =~ m/^:(.*):$/ ) {
  211. my @rassigned = sort { $a <=> $b } split( ":", $1 );
  212. print STDERR " ", join(' ', @rassigned), "\n";
  213. } else {
  214. print STDERR " --none--\n";
  215. }
  216. }
  217. }
  218. }
  219. # Scan each C source file and look for reason codes. This is done by
  220. # looking for strings that "look like" reason codes: basically anything
  221. # consisting of all upper case and numerics which _R_ in it and which has
  222. # the name of an error library at the start. Should there be anything else,
  223. # such as a type name, we add exceptions here.
  224. # If a code doesn't exist in list compiled from headers then mark it
  225. # with the value "X" as a place holder to give it a value later.
  226. # Store all reason codes found in and %usedreasons so all those unreferenced
  227. # can be printed out.
  228. &phase("Scanning source");
  229. my %usedreasons;
  230. foreach my $file ( @source ) {
  231. # Don't parse the error source file.
  232. next if exists $cskip{$file};
  233. open( IN, "<$file" ) || die "Can't open $file, $!,";
  234. my $func;
  235. my $linenr = 0;
  236. print STDERR "$file:\n" if $debug;
  237. while ( <IN> ) {
  238. # skip obsoleted source files entirely!
  239. last if /^#error\s+obsolete/;
  240. $linenr++;
  241. if ( /(((?:OSSL_|OPENSSL_)?[A-Z0-9]{2,})_R_[A-Z0-9_]+)/ ) {
  242. next unless exists $errorfile{$2};
  243. next if $errorfile{$2} eq 'NONE';
  244. $usedreasons{$1} = 1;
  245. if ( !exists $rcodes{$1} ) {
  246. print STDERR " New reason $1\n" if $debug;
  247. $rcodes{$1} = "X";
  248. $rnew{$2}++;
  249. }
  250. print STDERR " Reason $1 = $rcodes{$1}\n" if $debug;
  251. }
  252. }
  253. close IN;
  254. }
  255. print STDERR "\n" if $debug;
  256. # Now process each library in turn.
  257. &phase("Writing files");
  258. my $newstate = 0;
  259. foreach my $lib ( keys %errorfile ) {
  260. next if ! $rnew{$lib} && ! $rebuild;
  261. next if scalar keys %modules > 0 && !$modules{$lib};
  262. next if $nowrite;
  263. print STDERR "$lib: $rnew{$lib} new reasons\n" if $rnew{$lib};
  264. $newstate = 1;
  265. # If we get here then we have some new error codes so we
  266. # need to rebuild the header file and C file.
  267. # Make a sorted list of error and reason codes for later use.
  268. my @reasons = sort grep( /^${lib}_/, keys %rcodes );
  269. # indent level for innermost preprocessor lines
  270. my $indent = " ";
  271. # Flag if the sub-library is disablable
  272. # There are a few exceptions, where disabling the sub-library
  273. # doesn't actually remove the whole sub-library, but rather implements
  274. # it with a NULL backend.
  275. my $disablable =
  276. ($lib ne "SSL" && $lib ne "ASYNC" && $lib ne "DSO"
  277. && (grep { $lib eq uc $_ } @disablables, @disablables_int));
  278. # Rewrite the internal header file if there is one ($internal only!)
  279. if ($hprivinc{$lib} ne 'NONE') {
  280. my $hfile = $hprivinc{$lib};
  281. my $guard = $hfile;
  282. if ($guard =~ m|^include/|) {
  283. $guard = $';
  284. } else {
  285. $guard = basename($guard);
  286. }
  287. $guard = "OSSL_" . join('_', split(m|[./]|, uc $guard));
  288. open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,";
  289. print OUT <<"EOF";
  290. /*
  291. * Generated by util/mkerr.pl DO NOT EDIT
  292. * Copyright 2020-$YEAR The OpenSSL Project Authors. All Rights Reserved.
  293. *
  294. * Licensed under the Apache License 2.0 (the \"License\"). You may not use
  295. * this file except in compliance with the License. You can obtain a copy
  296. * in the file LICENSE in the source distribution or at
  297. * https://www.openssl.org/source/license.html
  298. */
  299. #ifndef $guard
  300. # define $guard
  301. # pragma once
  302. # include <openssl/opensslconf.h>
  303. # include <openssl/symhacks.h>
  304. # ifdef __cplusplus
  305. extern \"C\" {
  306. # endif
  307. EOF
  308. $indent = ' ';
  309. if ($disablable) {
  310. print OUT <<"EOF";
  311. # ifndef OPENSSL_NO_${lib}
  312. EOF
  313. $indent = " ";
  314. }
  315. print OUT <<"EOF";
  316. int ossl_err_load_${lib}_strings(void);
  317. EOF
  318. # If this library doesn't have a public header file, we write all
  319. # definitions that would end up there here instead
  320. if ($hpubinc{$lib} eq 'NONE') {
  321. print OUT "\n/*\n * $lib reason codes.\n */\n";
  322. foreach my $i ( @reasons ) {
  323. my $z = 48 - length($i);
  324. $z = 0 if $z < 0;
  325. if ( $rcodes{$i} eq "X" ) {
  326. $rassigned{$lib} =~ m/^:([^:]*):/;
  327. my $findcode = $1;
  328. $findcode = $rmax{$lib} if !defined $findcode;
  329. while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
  330. $findcode++;
  331. }
  332. $rcodes{$i} = $findcode;
  333. $rassigned{$lib} .= "$findcode:";
  334. print STDERR "New Reason code $i\n" if $debug;
  335. }
  336. printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z;
  337. }
  338. print OUT "\n";
  339. }
  340. # This doesn't go all the way down to zero, to allow for the ending
  341. # brace for 'extern "C" {'.
  342. while (length($indent) > 1) {
  343. $indent = substr $indent, 0, -1;
  344. print OUT "#${indent}endif\n";
  345. }
  346. print OUT <<"EOF";
  347. # ifdef __cplusplus
  348. }
  349. # endif
  350. #endif
  351. EOF
  352. close OUT;
  353. }
  354. # Rewrite the public header file
  355. if ($hpubinc{$lib} ne 'NONE') {
  356. my $extra_include =
  357. $internal
  358. ? ($lib ne 'SSL'
  359. ? "# include <openssl/cryptoerr_legacy.h>\n"
  360. : "# include <openssl/sslerr_legacy.h>\n")
  361. : '';
  362. my $hfile = $hpubinc{$lib};
  363. my $guard = $hfile;
  364. $guard =~ s|^include/||;
  365. $guard = join('_', split(m|[./]|, uc $guard));
  366. $guard = "OSSL_" . $guard unless $internal;
  367. open( OUT, ">$hfile" ) || die "Can't write to $hfile, $!,";
  368. print OUT <<"EOF";
  369. /*
  370. * Generated by util/mkerr.pl DO NOT EDIT
  371. * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
  372. *
  373. * Licensed under the Apache License 2.0 (the \"License\"). You may not use
  374. * this file except in compliance with the License. You can obtain a copy
  375. * in the file LICENSE in the source distribution or at
  376. * https://www.openssl.org/source/license.html
  377. */
  378. #ifndef $guard
  379. # define $guard
  380. # pragma once
  381. # include <openssl/opensslconf.h>
  382. # include <openssl/symhacks.h>
  383. $extra_include
  384. EOF
  385. $indent = ' ';
  386. if ( $internal ) {
  387. if ($disablable) {
  388. print OUT <<"EOF";
  389. # ifndef OPENSSL_NO_${lib}
  390. EOF
  391. $indent .= ' ';
  392. }
  393. } else {
  394. print OUT <<"EOF";
  395. # define ${lib}err(f, r) ERR_${lib}_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
  396. EOF
  397. if ( ! $static ) {
  398. print OUT <<"EOF";
  399. # ifdef __cplusplus
  400. extern \"C\" {
  401. # endif
  402. int ERR_load_${lib}_strings(void);
  403. void ERR_unload_${lib}_strings(void);
  404. void ERR_${lib}_error(int function, int reason, const char *file, int line);
  405. # ifdef __cplusplus
  406. }
  407. # endif
  408. EOF
  409. }
  410. }
  411. print OUT "\n/*\n * $lib reason codes.\n */\n";
  412. foreach my $i ( @reasons ) {
  413. my $z = 48 - length($i);
  414. $z = 0 if $z < 0;
  415. if ( $rcodes{$i} eq "X" ) {
  416. $rassigned{$lib} =~ m/^:([^:]*):/;
  417. my $findcode = $1;
  418. $findcode = $rmax{$lib} if !defined $findcode;
  419. while ( $rassigned{$lib} =~ m/:$findcode:/ ) {
  420. $findcode++;
  421. }
  422. $rcodes{$i} = $findcode;
  423. $rassigned{$lib} .= "$findcode:";
  424. print STDERR "New Reason code $i\n" if $debug;
  425. }
  426. printf OUT "#${indent}define $i%s $rcodes{$i}\n", " " x $z;
  427. }
  428. print OUT "\n";
  429. while (length($indent) > 0) {
  430. $indent = substr $indent, 0, -1;
  431. print OUT "#${indent}endif\n";
  432. }
  433. close OUT;
  434. }
  435. # Rewrite the C source file containing the error details.
  436. if ($errorfile{$lib} ne 'NONE') {
  437. # First, read any existing reason string definitions:
  438. my $cfile = $errorfile{$lib};
  439. my $pack_lib = $internal ? "ERR_LIB_${lib}" : "0";
  440. my $hpubincf = $hpubinc{$lib};
  441. my $hprivincf = $hprivinc{$lib};
  442. my $includes = '';
  443. if ($internal) {
  444. if ($hpubincf ne 'NONE') {
  445. $hpubincf =~ s|^include/||;
  446. $includes .= "#include <${hpubincf}>\n";
  447. }
  448. if ($hprivincf =~ m|^include/|) {
  449. $hprivincf = $';
  450. } else {
  451. $hprivincf = abs2rel(rel2abs($hprivincf),
  452. rel2abs(dirname($cfile)));
  453. }
  454. $includes .= "#include \"${hprivincf}\"\n";
  455. } else {
  456. $includes .= "#include \"${hpubincf}\"\n";
  457. }
  458. open( OUT, ">$cfile" )
  459. || die "Can't open $cfile for writing, $!, stopped";
  460. my $const = $internal ? 'const ' : '';
  461. print OUT <<"EOF";
  462. /*
  463. * Generated by util/mkerr.pl DO NOT EDIT
  464. * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved.
  465. *
  466. * Licensed under the Apache License 2.0 (the "License"). You may not use
  467. * this file except in compliance with the License. You can obtain a copy
  468. * in the file LICENSE in the source distribution or at
  469. * https://www.openssl.org/source/license.html
  470. */
  471. #include <openssl/err.h>
  472. $includes
  473. EOF
  474. $indent = '';
  475. if ( $internal ) {
  476. if ($disablable) {
  477. print OUT <<"EOF";
  478. #ifndef OPENSSL_NO_${lib}
  479. EOF
  480. $indent .= ' ';
  481. }
  482. }
  483. print OUT <<"EOF";
  484. #${indent}ifndef OPENSSL_NO_ERR
  485. static ${const}ERR_STRING_DATA ${lib}_str_reasons[] = {
  486. EOF
  487. # Add each reason code.
  488. foreach my $i ( @reasons ) {
  489. my $rn;
  490. if ( exists $strings{$i} ) {
  491. $rn = $strings{$i};
  492. $rn = "" if $rn eq '*';
  493. } else {
  494. $i =~ /^${lib}_R_(\S+)$/;
  495. $rn = $1;
  496. $rn =~ tr/_[A-Z]/ [a-z]/;
  497. $strings{$i} = $rn;
  498. }
  499. my $short = " {ERR_PACK($pack_lib, 0, $i), \"$rn\"},";
  500. if ( length($short) <= 80 ) {
  501. print OUT "$short\n";
  502. } else {
  503. print OUT " {ERR_PACK($pack_lib, 0, $i),\n \"$rn\"},\n";
  504. }
  505. }
  506. print OUT <<"EOF";
  507. {0, NULL}
  508. };
  509. #${indent}endif
  510. EOF
  511. if ( $internal ) {
  512. print OUT <<"EOF";
  513. int ossl_err_load_${lib}_strings(void)
  514. {
  515. #${indent}ifndef OPENSSL_NO_ERR
  516. if (ERR_reason_error_string(${lib}_str_reasons[0].error) == NULL)
  517. ERR_load_strings_const(${lib}_str_reasons);
  518. #${indent}endif
  519. return 1;
  520. }
  521. EOF
  522. } else {
  523. my $st = $static ? "static " : "";
  524. print OUT <<"EOF";
  525. static int lib_code = 0;
  526. static int error_loaded = 0;
  527. ${st}int ERR_load_${lib}_strings(void)
  528. {
  529. if (lib_code == 0)
  530. lib_code = ERR_get_next_error_library();
  531. if (!error_loaded) {
  532. #ifndef OPENSSL_NO_ERR
  533. ERR_load_strings(lib_code, ${lib}_str_reasons);
  534. #endif
  535. error_loaded = 1;
  536. }
  537. return 1;
  538. }
  539. ${st}void ERR_unload_${lib}_strings(void)
  540. {
  541. if (error_loaded) {
  542. #ifndef OPENSSL_NO_ERR
  543. ERR_unload_strings(lib_code, ${lib}_str_reasons);
  544. #endif
  545. error_loaded = 0;
  546. }
  547. }
  548. ${st}void ERR_${lib}_error(int function, int reason, const char *file, int line)
  549. {
  550. if (lib_code == 0)
  551. lib_code = ERR_get_next_error_library();
  552. ERR_raise(lib_code, reason);
  553. ERR_set_debug(file, line, NULL);
  554. }
  555. EOF
  556. }
  557. while (length($indent) > 1) {
  558. $indent = substr $indent, 0, -1;
  559. print OUT "#${indent}endif\n";
  560. }
  561. if ($internal && $disablable) {
  562. print OUT <<"EOF";
  563. #else
  564. NON_EMPTY_TRANSLATION_UNIT
  565. #endif
  566. EOF
  567. }
  568. close OUT;
  569. }
  570. }
  571. &phase("Ending");
  572. # Make a list of unreferenced reason codes
  573. if ( $unref ) {
  574. my @runref;
  575. foreach ( keys %rcodes ) {
  576. push( @runref, $_ ) unless exists $usedreasons{$_};
  577. }
  578. if ( @runref ) {
  579. print STDERR "The following reason codes were not referenced:\n";
  580. foreach ( sort @runref ) {
  581. print STDERR " $_\n";
  582. }
  583. }
  584. }
  585. die "Found $errors errors, quitting" if $errors;
  586. # Update the state file
  587. if ( $newstate ) {
  588. open(OUT, ">$statefile.new")
  589. || die "Can't write $statefile.new, $!";
  590. print OUT <<"EOF";
  591. # Copyright 1999-$YEAR The OpenSSL Project Authors. All Rights Reserved.
  592. #
  593. # Licensed under the Apache License 2.0 (the "License"). You may not use
  594. # this file except in compliance with the License. You can obtain a copy
  595. # in the file LICENSE in the source distribution or at
  596. # https://www.openssl.org/source/license.html
  597. EOF
  598. print OUT "\n#Reason codes\n";
  599. foreach my $i ( sort keys %rcodes ) {
  600. my $short = "$i:$rcodes{$i}:";
  601. my $t = exists $strings{$i} ? "$strings{$i}" : "";
  602. $t = "\\\n\t" . $t if length($short) + length($t) > 80;
  603. print OUT "$short$t\n" if !exists $rextra{$i};
  604. }
  605. close(OUT);
  606. if ( $skippedstate ) {
  607. print "Skipped state, leaving update in $statefile.new";
  608. } else {
  609. rename "$statefile", "$statefile.old"
  610. || die "Can't backup $statefile to $statefile.old, $!";
  611. rename "$statefile.new", "$statefile"
  612. || die "Can't rename $statefile to $statefile.new, $!";
  613. }
  614. }
  615. exit;