comparison libtommath/helper.pl @ 1692:1051e4eea25a

Update LibTomMath to 1.2.0 (#84) * update C files * update other files * update headers * update makefiles * remove mp_set/get_double() * use ltm 1.2.0 API * update ltm_desc * use bundled tommath if system-tommath is too old * XMALLOC etc. were changed to MP_MALLOC etc.
author Steffen Jaeckel <s@jaeckel.eu>
date Tue, 26 May 2020 17:36:47 +0200
parents f52919ffd3b1
children
comparison
equal deleted inserted replaced
1691:2d3745d58843 1692:1051e4eea25a
23 print $fh $data or die "FATAL: write_file() cannot write to '$f': $!"; 23 print $fh $data or die "FATAL: write_file() cannot write to '$f': $!";
24 close $fh or die "FATAL: write_file() cannot close '$f': $!"; 24 close $fh or die "FATAL: write_file() cannot close '$f': $!";
25 return; 25 return;
26 } 26 }
27 27
28 sub sanitize_comments {
29 my($content) = @_;
30 $content =~ s{/\*(.*?)\*/}{my $x=$1; $x =~ s/\w/x/g; "/*$x*/";}egs;
31 return $content;
32 }
33
28 sub check_source { 34 sub check_source {
29 my @all_files = ( 35 my @all_files = (
30 bsd_glob("makefile*"), 36 bsd_glob("Makefile*"),
31 bsd_glob("*.{h,c,sh,pl}"), 37 bsd_glob("*.{h,c,sh,pl}"),
32 bsd_glob("*/*.{h,c,sh,pl}"), 38 bsd_glob("*/*.{h,c,sh,pl}"),
33 ); 39 );
34 40
35 my $fails = 0; 41 my $fails = 0;
36 for my $file (sort @all_files) { 42 for my $file (sort @all_files) {
37 my $troubles = {}; 43 my $troubles = {};
38 my $lineno = 1; 44 my $lineno = 1;
39 my $content = read_file($file); 45 my $content = read_file($file);
46 $content = sanitize_comments $content;
40 push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/; 47 push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/;
41 for my $l (split /\n/, $content) { 48 for my $l (split /\n/, $content) {
42 push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/; 49 push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/;
43 push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/; 50 push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/;
44 push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; 51 push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i;
79 } 86 }
80 87
81 sub check_comments { 88 sub check_comments {
82 my $fails = 0; 89 my $fails = 0;
83 my $first_comment = <<'MARKER'; 90 my $first_comment = <<'MARKER';
84 /* LibTomMath, multiple-precision integer library -- Tom St Denis 91 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
85 * 92 /* SPDX-License-Identifier: Unlicense */
86 * LibTomMath is a library that provides multiple-precision
87 * integer arithmetic as well as number theoretic functionality.
88 *
89 * The library was designed directly after the MPI library by
90 * Michael Fromberger but has been written from scratch with
91 * additional optimizations in place.
92 *
93 * SPDX-License-Identifier: Unlicense
94 */
95 MARKER
96 my $last_comment = <<'MARKER';
97 /* ref: HEAD -> master, tag: v1.1.0 */
98 /* git commit: 08549ad6bc8b0cede0b357a9c341c5c6473a9c55 */
99 /* commit time: 2019-01-28 20:32:32 +0100 */
100 MARKER 93 MARKER
101 #my @all_files = (bsd_glob("*.{h,c}"), bsd_glob("*/*.{h,c}")); 94 #my @all_files = (bsd_glob("*.{h,c}"), bsd_glob("*/*.{h,c}"));
102 my @all_files = (bsd_glob("*.{h,c}")); 95 my @all_files = (bsd_glob("*.{h,c}"));
103 for my $f (@all_files) { 96 for my $f (@all_files) {
104 my $txt = read_file($f); 97 my $txt = read_file($f);
105 if ($txt !~ /\Q$first_comment\E/s) { 98 if ($txt !~ /\Q$first_comment\E/s) {
106 warn "[first_comment] $f\n"; 99 warn "[first_comment] $f\n";
107 $fails++; 100 $fails++;
108 } 101 }
109 if ($txt !~ /\Q$last_comment\E\s*$/s) {
110 warn "[last_comment] $f\n";
111 $fails++;
112 }
113 } 102 }
114 warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" ); 103 warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" );
104 return $fails;
105 }
106
107 sub check_doc {
108 my $fails = 0;
109 my $tex = read_file('doc/bn.tex');
110 my $tmh = read_file('tommath.h');
111 my @functions = $tmh =~ /\n\s*[a-zA-Z0-9_* ]+?(mp_[a-z0-9_]+)\s*\([^\)]+\)\s*;/sg;
112 my @macros = $tmh =~ /\n\s*#define\s+([a-z0-9_]+)\s*\([^\)]+\)/sg;
113 for my $n (sort @functions) {
114 (my $nn = $n) =~ s/_/\\_/g; # mp_sub_d >> mp\_sub\_d
115 if ($tex !~ /index\Q{$nn}\E/) {
116 warn "[missing_doc_for_function] $n\n";
117 $fails++
118 }
119 }
120 for my $n (sort @macros) {
121 (my $nn = $n) =~ s/_/\\_/g; # mp_iszero >> mp\_iszero
122 if ($tex !~ /index\Q{$nn}\E/) {
123 warn "[missing_doc_for_macro] $n\n";
124 $fails++
125 }
126 }
127 warn( $fails > 0 ? "check_doc: FAIL $fails\n" : "check-doc: PASS\n" );
115 return $fails; 128 return $fails;
116 } 129 }
117 130
118 sub prepare_variable { 131 sub prepare_variable {
119 my ($varname, @list) = @_; 132 my ($varname, @list) = @_;
207 } 220 }
208 } 221 }
209 return $content; 222 return $content;
210 } 223 }
211 224
212 sub version_from_tomcrypt_h {
213 my $h = read_file(shift);
214 if ($h =~ /\n#define\s*SCRYPT\s*"([0-9]+)\.([0-9]+)\.([0-9]+)(.*)"/s) {
215 return "VERSION_PC=$1.$2.$3", "VERSION_LT=1:1", "VERSION=$1.$2.$3$4", "PROJECT_NUMBER=$1.$2.$3$4";
216 }
217 else {
218 die "#define SCRYPT not found in tomcrypt.h";
219 }
220 }
221
222 sub process_makefiles { 225 sub process_makefiles {
223 my $write = shift; 226 my $write = shift;
224 my $changed_count = 0; 227 my $changed_count = 0;
225 my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c"); 228 my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c");
226 my @all = bsd_glob("*.{c,h}"); 229 my @all = bsd_glob("*.{c,h}");
247 warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" ); 250 warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" );
248 return $changed_count; 251 return $changed_count;
249 } 252 }
250 } 253 }
251 254
255 sub draw_func
256 {
257 my ($deplist, $depmap, $out, $indent, $funcslist) = @_;
258 my @funcs = split ',', $funcslist;
259 # try this if you want to have a look at a minimized version of the callgraph without all the trivial functions
260 #if ($deplist =~ /$funcs[0]/ || $funcs[0] =~ /BN_MP_(ADD|SUB|CLEAR|CLEAR_\S+|DIV|MUL|COPY|ZERO|GROW|CLAMP|INIT|INIT_\S+|SET|ABS|CMP|CMP_D|EXCH)_C/) {
261 if ($deplist =~ /$funcs[0]/) {
262 return $deplist;
263 } else {
264 $deplist = $deplist . $funcs[0];
265 }
266 if ($indent == 0) {
267 } elsif ($indent >= 1) {
268 print {$out} '| ' x ($indent - 1) . '+--->';
269 }
270 print {$out} $funcs[0] . "\n";
271 shift @funcs;
272 my $olddeplist = $deplist;
273 foreach my $i (@funcs) {
274 $deplist = draw_func($deplist, $depmap, $out, $indent + 1, ${$depmap}{$i}) if exists ${$depmap}{$i};
275 }
276 return $olddeplist;
277 }
278
279 sub update_dep
280 {
281 #open class file and write preamble
282 open(my $class, '>', 'tommath_class.h') or die "Couldn't open tommath_class.h for writing\n";
283 print {$class} << 'EOS';
284 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
285 /* SPDX-License-Identifier: Unlicense */
286
287 #if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
288 #define LTM_INSIDE
289 #if defined(LTM2)
290 # define LTM3
291 #endif
292 #if defined(LTM1)
293 # define LTM2
294 #endif
295 #define LTM1
296 #if defined(LTM_ALL)
297 EOS
298
299 foreach my $filename (glob 'bn*.c') {
300 my $define = $filename;
301
302 print "Processing $filename\n";
303
304 # convert filename to upper case so we can use it as a define
305 $define =~ tr/[a-z]/[A-Z]/;
306 $define =~ tr/\./_/;
307 print {$class} "# define $define\n";
308
309 # now copy text and apply #ifdef as required
310 my $apply = 0;
311 open(my $src, '<', $filename);
312 open(my $out, '>', 'tmp');
313
314 # first line will be the #ifdef
315 my $line = <$src>;
316 if ($line =~ /include/) {
317 print {$out} $line;
318 } else {
319 print {$out} << "EOS";
320 #include "tommath_private.h"
321 #ifdef $define
322 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
323 /* SPDX-License-Identifier: Unlicense */
324 $line
325 EOS
326 $apply = 1;
327 }
328 while (<$src>) {
329 if ($_ !~ /tommath\.h/) {
330 print {$out} $_;
331 }
332 }
333 if ($apply == 1) {
334 print {$out} "#endif\n";
335 }
336 close $src;
337 close $out;
338
339 unlink $filename;
340 rename 'tmp', $filename;
341 }
342 print {$class} "#endif\n#endif\n";
343
344 # now do classes
345 my %depmap;
346 foreach my $filename (glob 'bn*.c') {
347 my $content;
348 if ($filename =~ "bn_deprecated.c") {
349 open(my $src, '<', $filename) or die "Can't open source file!\n";
350 read $src, $content, -s $src;
351 close $src;
352 } else {
353 my $cc = $ENV{'CC'} || 'gcc';
354 $content = `$cc -E -x c -DLTM_ALL $filename`;
355 $content =~ s/^# 1 "$filename".*?^# 2 "$filename"//ms;
356 }
357
358 # convert filename to upper case so we can use it as a define
359 $filename =~ tr/[a-z]/[A-Z]/;
360 $filename =~ tr/\./_/;
361
362 print {$class} "#if defined($filename)\n";
363 my $list = $filename;
364
365 # strip comments
366 $content =~ s{/\*.*?\*/}{}gs;
367
368 # scan for mp_* and make classes
369 my @deps = ();
370 foreach my $line (split /\n/, $content) {
371 while ($line =~ /(fast_)?(s_)?mp\_[a-z_0-9]*((?=\;)|(?=\())|(?<=\()mp\_[a-z_0-9]*(?=\()/g) {
372 my $a = $&;
373 next if $a eq "mp_err";
374 $a =~ tr/[a-z]/[A-Z]/;
375 $a = 'BN_' . $a . '_C';
376 push @deps, $a;
377 }
378 }
379 @deps = sort(@deps);
380 foreach my $a (@deps) {
381 if ($list !~ /$a/) {
382 print {$class} "# define $a\n";
383 }
384 $list = $list . ',' . $a;
385 }
386 $depmap{$filename} = $list;
387
388 print {$class} "#endif\n\n";
389 }
390
391 print {$class} << 'EOS';
392 #ifdef LTM_INSIDE
393 #undef LTM_INSIDE
394 #ifdef LTM3
395 # define LTM_LAST
396 #endif
397
398 #include "tommath_superclass.h"
399 #include "tommath_class.h"
400 #else
401 # define LTM_LAST
402 #endif
403 EOS
404 close $class;
405
406 #now let's make a cool call graph...
407
408 open(my $out, '>', 'callgraph.txt');
409 foreach (sort keys %depmap) {
410 draw_func("", \%depmap, $out, 0, $depmap{$_});
411 print {$out} "\n\n";
412 }
413 close $out;
414
415 return 0;
416 }
417
418 sub generate_def {
419 my @files = split /\n/, `git ls-files`;
420 @files = grep(/\.c/, @files);
421 @files = map { my $x = $_; $x =~ s/^bn_|\.c$//g; $x; } @files;
422 @files = grep(!/mp_radix_smap/, @files);
423
424 push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int));
425
426 my $files = join("\n ", sort(grep(/^mp_/, @files)));
427 write_file "tommath.def", "; libtommath
428 ;
429 ; Use this command to produce a 32-bit .lib file, for use in any MSVC version
430 ; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib
431 ; Use this command to produce a 64-bit .lib file, for use in any MSVC version
432 ; lib -machine:X64 -name:libtommath.dll -def:tommath.def -out:tommath.lib
433 ;
434 EXPORTS
435 $files
436 ";
437 return 0;
438 }
439
252 sub die_usage { 440 sub die_usage {
253 die <<"MARKER"; 441 die <<"MARKER";
254 usage: $0 -s OR $0 --check-source 442 usage: $0 -s OR $0 --check-source
255 $0 -o OR $0 --check-comments 443 $0 -o OR $0 --check-comments
256 $0 -m OR $0 --check-makefiles 444 $0 -m OR $0 --check-makefiles
257 $0 -a OR $0 --check-all 445 $0 -a OR $0 --check-all
258 $0 -u OR $0 --update-makefiles 446 $0 -u OR $0 --update-files
259 MARKER 447 MARKER
260 } 448 }
261 449
262 GetOptions( "s|check-source" => \my $check_source, 450 GetOptions( "s|check-source" => \my $check_source,
263 "o|check-comments" => \my $check_comments, 451 "o|check-comments" => \my $check_comments,
264 "m|check-makefiles" => \my $check_makefiles, 452 "m|check-makefiles" => \my $check_makefiles,
453 "d|check-doc" => \my $check_doc,
265 "a|check-all" => \my $check_all, 454 "a|check-all" => \my $check_all,
266 "u|update-makefiles" => \my $update_makefiles, 455 "u|update-files" => \my $update_files,
267 "h|help" => \my $help 456 "h|help" => \my $help
268 ) or die_usage; 457 ) or die_usage;
269 458
270 my $failure; 459 my $failure;
271 $failure ||= check_source() if $check_all || $check_source; 460 $failure ||= check_source() if $check_all || $check_source;
272 $failure ||= check_comments() if $check_all || $check_comments; 461 $failure ||= check_comments() if $check_all || $check_comments;
462 $failure ||= check_doc() if $check_doc; # temporarily excluded from --check-all
273 $failure ||= process_makefiles(0) if $check_all || $check_makefiles; 463 $failure ||= process_makefiles(0) if $check_all || $check_makefiles;
274 $failure ||= process_makefiles(1) if $update_makefiles; 464 $failure ||= process_makefiles(1) if $update_files;
465 $failure ||= update_dep() if $update_files;
466 $failure ||= generate_def() if $update_files;
275 467
276 die_usage unless defined $failure; 468 die_usage unless defined $failure;
277 exit $failure ? 1 : 0; 469 exit $failure ? 1 : 0;
278
279 # ref: HEAD -> master, tag: v1.1.0
280 # git commit: 08549ad6bc8b0cede0b357a9c341c5c6473a9c55
281 # commit time: 2019-01-28 20:32:32 +0100