nasm/asm/warnings.pl
H. Peter Anvin (Intel) 177a05d0ce perl files: clean up warnings
Clean up some perl warnings, some of which were legitimate (apparently
undef doesn't actually take a list of arguments, a common enough
mistake that it is mentioned in the man page!, and a list of variables
after "my" can be cantankerous), and some of which were nuisance but
were easy enough to clean up.

Maybe this can resolve the problems with very old version of Perl?

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
2019-08-09 13:30:19 -07:00

270 lines
7.0 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use File::Find;
use File::Basename;
my @warnings = ();
my %aliases = ();
my %prefixes = ();
my $err = 0;
my $nwarn = 0;
sub quote_for_c($) {
my $s = join('', @_);
$s =~ s/([\"\'\\])/\\$1/g;
return $s;
}
sub add_alias($$) {
my($a, $this) = @_;
my @comp = split(/-/, $a);
$aliases{$a} = $this;
# All names are prefixes in their own right, although we only
# list the ones that are either prefixes of "proper names" or
# the complete alias name.
for (my $i = ($a eq $this->{name}) ? 0 : $#comp; $i <= $#comp; $i++) {
my $prefix = join('-', @comp[0..$i]);
$prefixes{$prefix} = [] unless defined($prefixes{$prefix});
push(@{$prefixes{$prefix}}, $a);
}
}
sub find_warnings {
my $infile = $_;
return unless (basename($infile) =~ /^\w.*\.[ch]$/i);
open(my $in, '<', $infile)
or die "$0: cannot open input file $infile: $!\n";
my $in_comment = 0;
my $nline = 0;
my $this;
my @doc;
while (defined(my $l = <$in>)) {
$nline++;
chomp $l;
if (!$in_comment) {
$l =~ s/^.*?\/\*.*?\*\///g; # Remove single-line comments
if ($l =~ /^.*?(\/\*.*)$/) {
# Begin block comment
$l = $1;
$in_comment = 1;
}
}
if ($in_comment) {
if ($l =~ /\*\//) {
# End block comment
$in_comment = 0;
undef $this;
} elsif ($l =~ /^\s*\/?\*\!(\s*)(.*?)\s*$/) {
my $ws = $1;
my $str = $2;
next if ($str eq '');
if (!defined($this) || ($ws eq '' && $str ne '')) {
if ($str =~ /^([\w-]+)\s+\[(\w+)\]\s(.*\S)\s*$/) {
my $name = $1;
my $def = $2;
my $help = $3;
my $cname = uc($name);
$cname =~ s/[^A-Z0-9_]+/_/g;
$this = {name => $name, cname => $cname,
def => $def, help => $help,
doc => [], file => $infile, line => $nline};
if (defined(my $that = $aliases{$name})) {
# Duplicate defintion?!
printf STDERR "%s:%s: warning %s previously defined at %s:%s\n",
$infile, $nline, $name, $that->{file}, $that->{line};
} else {
push(@warnings, $this);
# Every warning name is also a valid warning alias
add_alias($name, $this);
$nwarn++;
}
} elsif (defined($this) && $str =~ /^\=([-\w,]+)\s*$/) {
# Alias names for warnings
for my $a (split(/,+/, $1)) {
add_alias($a, $this);
}
} else {
print STDERR "$infile:$nline: malformed warning definition\n";
print STDERR " $l\n";
$err++;
}
} else {
push(@{$this->{doc}}, "$str\n");
}
} else {
undef $this;
}
}
}
close($in);
}
my($what, $outfile, @indirs) = @ARGV;
if (!defined($outfile)) {
die "$0: usage: [c|h|doc] outfile indir...\n";
}
find({ wanted => \&find_warnings, no_chdir => 1, follow => 1 }, @indirs);
exit(1) if ($err);
my %sort_special = ( 'other' => 1, 'all' => 2 );
sub sort_warnings {
my $an = $a->{name};
my $bn = $b->{name};
return ($sort_special{$an} <=> $sort_special{$bn}) || ($an cmp $bn);
}
@warnings = sort sort_warnings @warnings;
my @warn_noall = @warnings;
pop @warn_noall if ($warn_noall[$#warn_noall]->{name} eq 'all');
open(my $out, '>', $outfile)
or die "$0: cannot open output file $outfile: $!\n";
if ($what eq 'c') {
print $out "#include \"error.h\"\n\n";
printf $out "const char * const warning_name[%d] = {\n",
$#warnings + 2;
print $out "\tNULL";
foreach my $warn (@warnings) {
print $out ",\n\t\"", $warn->{name}, "\"";
}
print $out "\n};\n\n";
printf $out "const struct warning_alias warning_alias[%d] = {",
scalar(%aliases);
my $sep = '';
foreach my $alias (sort { $a cmp $b } keys(%aliases)) {
printf $out "%s\n\t{ %-27s WARN_IDX_%s }",
$sep, "\"$alias\",", $aliases{$alias}->{cname};
$sep = ',';
}
print $out "\n};\n\n";
printf $out "const char * const warning_help[%d] = {\n",
$#warnings + 2;
print $out "\tNULL";
foreach my $warn (@warnings) {
my $help = quote_for_c($warn->{help});
print $out ",\n\t\"", $help, "\"";
}
print $out "\n};\n\n";
printf $out "const uint8_t warning_default[%d] = {\n",
$#warn_noall + 2;
print $out "\tWARN_INIT_ON"; # for entry 0
foreach my $warn (@warn_noall) {
print $out ",\n\tWARN_INIT_", uc($warn->{def});
}
print $out "\n};\n\n";
printf $out "uint8_t warning_state[%d];\t/* Current state */\n",
$#warn_noall + 2;
} elsif ($what eq 'h') {
my $filename = basename($outfile);
my $guard = $filename;
$guard =~ s/[^A-Za-z0-9_]+/_/g;
$guard = "NASM_\U$guard";
print $out "#ifndef $guard\n";
print $out "#define $guard\n";
print $out "\n";
print $out "#ifndef WARN_SHR\n";
print $out "# error \"$filename should only be included from within error.h\"\n";
print $out "#endif\n\n";
print $out "enum warn_index {\n";
printf $out "\tWARN_IDX_%-23s = %3d, /* not suppressible */\n", 'NONE', 0;
my $n = 1;
foreach my $warn (@warnings) {
printf $out "\tWARN_IDX_%-23s = %3d%s /* %s */\n",
$warn->{cname}, $n,
($n == $#warnings + 1) ? " " : ",",
$warn->{help};
$n++;
}
print $out "};\n\n";
print $out "enum warn_const {\n";
printf $out "\tWARN_%-27s = %3d << WARN_SHR", 'NONE', 0;
$n = 1;
foreach my $warn (@warn_noall) {
printf $out ",\n\tWARN_%-27s = %3d << WARN_SHR", $warn->{cname}, $n++;
}
print $out "\n};\n\n";
print $out "struct warning_alias {\n";
print $out "\tconst char *name;\n";
print $out "\tenum warn_index warning;\n";
print $out "};\n\n";
printf $out "#define NUM_WARNING_ALIAS %d\n", scalar(%aliases);
printf $out "extern const char * const warning_name[%d];\n",
$#warnings + 2;
printf $out "extern const char * const warning_help[%d];\n",
$#warnings + 2;
print $out "extern const struct warning_alias warning_alias[NUM_WARNING_ALIAS];\n";
printf $out "extern const uint8_t warning_default[%d];\n",
$#warn_noall + 2;
printf $out "extern uint8_t warning_state[%d];\n",
$#warn_noall + 2;
print $out "\n#endif /* $guard */\n";
} elsif ($what eq 'doc') {
my %whatdef = ( 'on' => 'Enabled',
'off' => 'Disabled',
'err' => 'Enabled and promoted to error' );
foreach my $pfx (sort { $a cmp $b } keys(%prefixes)) {
my $warn = $aliases{$pfx};
my @doc;
if (!defined($warn)) {
my @plist = sort { $a cmp $b } @{$prefixes{$pfx}};
next if ( $#plist < 1 );
@doc = ("is a group alias for all warning classes prefixed by ".
"\\c{".$pfx."-}; currently\n");
for (my $i = 0; $i <= $#plist; $i++) {
if ($i > 0) {
if ($i < $#plist) {
push(@doc, ", ");
} else {
push(@doc, ($i == 1) ? " and " : ", and ");
}
}
push(@doc, '\c{'.$plist[$i].'}');
}
push(@doc, ".\n");
} elsif ($pfx ne $warn->{name}) {
@doc = ("is a backwards compatibility alias for \\c{",
$warn->{name}, "}.\n");
} else {
my $docdef = $whatdef{$warn->{def}};
@doc = @{$warn->{doc}};
shift @doc while ($doc[0] =~ /^\s*$/);
pop @doc while ($doc[$#doc] =~ /^\s*$/);
if (defined($docdef)) {
push(@doc, "$docdef by default.\n");
}
}
print $out "\\b \\i\\c{", $pfx, "} ", @doc, "\n";
}
}
close($out);