2018-12-14 08:33:39 +08:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use File::Find;
|
|
|
|
use File::Basename;
|
|
|
|
|
|
|
|
my @warnings = ();
|
2019-06-07 11:53:17 +08:00
|
|
|
my %aliases = ();
|
|
|
|
my %prefixes = ();
|
2018-12-14 08:33:39 +08:00
|
|
|
my $err = 0;
|
|
|
|
my $nwarn = 0;
|
|
|
|
|
|
|
|
sub quote_for_c($) {
|
|
|
|
my $s = join('', @_);
|
|
|
|
|
2019-08-10 04:30:19 +08:00
|
|
|
$s =~ s/([\"\'\\])/\\$1/g;
|
2018-12-14 08:33:39 +08:00
|
|
|
return $s;
|
|
|
|
}
|
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-14 08:33:39 +08:00
|
|
|
sub find_warnings {
|
|
|
|
my $infile = $_;
|
|
|
|
|
2018-12-14 13:53:31 +08:00
|
|
|
return unless (basename($infile) =~ /^\w.*\.[ch]$/i);
|
2018-12-14 08:33:39 +08:00
|
|
|
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;
|
|
|
|
|
2018-12-14 13:53:31 +08:00
|
|
|
next if ($str eq '');
|
2019-06-07 11:53:17 +08:00
|
|
|
|
2018-12-14 08:33:39 +08:00
|
|
|
if (!defined($this) || ($ws eq '' && $str ne '')) {
|
2019-06-07 11:53:17 +08:00
|
|
|
if ($str =~ /^([\w-]+)\s+\[(\w+)\]\s(.*\S)\s*$/) {
|
2018-12-14 08:33:39 +08:00
|
|
|
my $name = $1;
|
|
|
|
my $def = $2;
|
|
|
|
my $help = $3;
|
|
|
|
|
|
|
|
my $cname = uc($name);
|
|
|
|
$cname =~ s/[^A-Z0-9_]+/_/g;
|
|
|
|
|
|
|
|
$this = {name => $name, cname => $cname,
|
2019-06-07 11:53:17 +08:00
|
|
|
def => $def, help => $help,
|
|
|
|
doc => [], file => $infile, line => $nline};
|
2019-08-07 10:28:57 +08:00
|
|
|
|
|
|
|
if (defined(my $that = $aliases{$name})) {
|
2019-08-07 10:30:36 +08:00
|
|
|
# Duplicate defintion?!
|
2019-08-07 10:28:57 +08:00
|
|
|
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++;
|
|
|
|
}
|
2019-08-10 04:30:19 +08:00
|
|
|
} elsif (defined($this) && $str =~ /^\=([-\w,]+)\s*$/) {
|
2019-06-07 11:53:17 +08:00
|
|
|
# Alias names for warnings
|
|
|
|
for my $a (split(/,+/, $1)) {
|
|
|
|
add_alias($a, $this);
|
|
|
|
}
|
2018-12-14 08:33:39 +08:00
|
|
|
} 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";
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "const char * const warning_name[%d] = {\n",
|
2018-12-14 08:33:39 +08:00
|
|
|
$#warnings + 2;
|
|
|
|
print $out "\tNULL";
|
|
|
|
foreach my $warn (@warnings) {
|
|
|
|
print $out ",\n\t\"", $warn->{name}, "\"";
|
|
|
|
}
|
|
|
|
print $out "\n};\n\n";
|
2019-08-10 04:30:19 +08:00
|
|
|
printf $out "const struct warning_alias warning_alias[%d] = {",
|
2019-08-10 07:20:40 +08:00
|
|
|
scalar(keys %aliases);
|
2019-06-07 11:53:17 +08:00
|
|
|
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";
|
|
|
|
|
2018-12-14 08:33:39 +08:00
|
|
|
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";
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "const uint8_t warning_default[%d] = {\n",
|
2018-12-14 08:33:39 +08:00
|
|
|
$#warn_noall + 2;
|
|
|
|
print $out "\tWARN_INIT_ON"; # for entry 0
|
|
|
|
foreach my $warn (@warn_noall) {
|
|
|
|
print $out ",\n\tWARN_INIT_", uc($warn->{def});
|
|
|
|
}
|
2018-12-14 13:53:31 +08:00
|
|
|
print $out "\n};\n\n";
|
|
|
|
printf $out "uint8_t warning_state[%d];\t/* Current state */\n",
|
|
|
|
$#warn_noall + 2;
|
2018-12-14 08:33:39 +08:00
|
|
|
} elsif ($what eq 'h') {
|
2018-12-14 13:53:31 +08:00
|
|
|
my $filename = basename($outfile);
|
|
|
|
my $guard = $filename;
|
2018-12-14 08:33:39 +08:00
|
|
|
$guard =~ s/[^A-Za-z0-9_]+/_/g;
|
|
|
|
$guard = "NASM_\U$guard";
|
|
|
|
|
|
|
|
print $out "#ifndef $guard\n";
|
|
|
|
print $out "#define $guard\n";
|
|
|
|
print $out "\n";
|
2018-12-14 13:53:31 +08:00
|
|
|
print $out "#ifndef WARN_SHR\n";
|
|
|
|
print $out "# error \"$filename should only be included from within error.h\"\n";
|
|
|
|
print $out "#endif\n\n";
|
2018-12-14 08:33:39 +08:00
|
|
|
print $out "enum warn_index {\n";
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "\tWARN_IDX_%-23s = %3d, /* not suppressible */\n", 'NONE', 0;
|
2018-12-14 08:33:39 +08:00
|
|
|
my $n = 1;
|
|
|
|
foreach my $warn (@warnings) {
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "\tWARN_IDX_%-23s = %3d%s /* %s */\n",
|
|
|
|
$warn->{cname}, $n,
|
|
|
|
($n == $#warnings + 1) ? " " : ",",
|
|
|
|
$warn->{help};
|
|
|
|
$n++;
|
2018-12-14 08:33:39 +08:00
|
|
|
}
|
2018-12-14 13:53:31 +08:00
|
|
|
print $out "};\n\n";
|
2018-12-14 08:33:39 +08:00
|
|
|
|
|
|
|
print $out "enum warn_const {\n";
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "\tWARN_%-27s = %3d << WARN_SHR", 'NONE', 0;
|
2019-08-10 04:30:19 +08:00
|
|
|
$n = 1;
|
2018-12-14 08:33:39 +08:00
|
|
|
foreach my $warn (@warn_noall) {
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out ",\n\tWARN_%-27s = %3d << WARN_SHR", $warn->{cname}, $n++;
|
2018-12-14 08:33:39 +08:00
|
|
|
}
|
|
|
|
print $out "\n};\n\n";
|
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
print $out "struct warning_alias {\n";
|
|
|
|
print $out "\tconst char *name;\n";
|
|
|
|
print $out "\tenum warn_index warning;\n";
|
|
|
|
print $out "};\n\n";
|
warnings.pl: BR 3392585: don't use scalar(%hash)
The idiom scalar(%hash) seems similar to scalar(@array), and in fact
is in current versions of Perl. However, in older versions of Perl,
the former is totally useless:
Prior to Perl 5.25 the value returned was a string consisting
of the number of used buckets and the number of allocated
buckets, separated by a slash. This is pretty much useful only
to find out whether Perl's internal hashing algorithm is
performing poorly on your data set. For example, you stick
10,000 things in a hash, but evaluating %HASH in scalar context
reveals "1/16", which means only one out of sixteen buckets has
been touched, and presumably contains all 10,000 of your items.
This isn't supposed to happen.
As of Perl 5.25 the return was changed to be the count of keys
in the hash. If you need access to the old behavior you can use
"Hash::Util::bucket_ratio()" instead.
Use scalar(keys %hash) instead.
Reported-by: Orkan Sezer <sezeroz@gmail.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
2019-08-10 04:44:16 +08:00
|
|
|
printf $out "#define NUM_WARNING_ALIAS %d\n", scalar(keys %aliases);
|
2019-06-07 11:53:17 +08:00
|
|
|
|
2018-12-14 13:53:31 +08:00
|
|
|
printf $out "extern const char * const warning_name[%d];\n",
|
2018-12-14 08:33:39 +08:00
|
|
|
$#warnings + 2;
|
|
|
|
printf $out "extern const char * const warning_help[%d];\n",
|
|
|
|
$#warnings + 2;
|
2019-06-07 11:53:17 +08:00
|
|
|
print $out "extern const struct warning_alias warning_alias[NUM_WARNING_ALIAS];\n";
|
2018-12-14 13:53:31 +08:00
|
|
|
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;
|
2018-12-14 08:33:39 +08:00
|
|
|
print $out "\n#endif /* $guard */\n";
|
|
|
|
} elsif ($what eq 'doc') {
|
|
|
|
my %whatdef = ( 'on' => 'Enabled',
|
|
|
|
'off' => 'Disabled',
|
|
|
|
'err' => 'Enabled and promoted to error' );
|
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
foreach my $pfx (sort { $a cmp $b } keys(%prefixes)) {
|
|
|
|
my $warn = $aliases{$pfx};
|
|
|
|
my @doc;
|
2018-12-14 08:33:39 +08:00
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
if (!defined($warn)) {
|
|
|
|
my @plist = sort { $a cmp $b } @{$prefixes{$pfx}};
|
|
|
|
next if ( $#plist < 1 );
|
2018-12-14 08:33:39 +08:00
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
@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");
|
|
|
|
}
|
2018-12-14 08:33:39 +08:00
|
|
|
}
|
|
|
|
|
2019-06-07 11:53:17 +08:00
|
|
|
print $out "\\b \\i\\c{", $pfx, "} ", @doc, "\n";
|
2018-12-14 08:33:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
close($out);
|