blob: 8a79568a459e147235c77d2bc5d9166b96ff9dc2 [file] [log] [blame]
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -08001#!/usr/bin/perl
2
3use strict;
4use File::Find;
5use File::Basename;
6
7my @warnings = ();
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -07008my %aliases = ();
9my %prefixes = ();
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080010my $err = 0;
11my $nwarn = 0;
12
13sub quote_for_c($) {
14 my $s = join('', @_);
15
H. Peter Anvin (Intel)177a05d2019-08-09 13:30:19 -070016 $s =~ s/([\"\'\\])/\\$1/g;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080017 return $s;
18}
19
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -070020sub add_alias($$) {
21 my($a, $this) = @_;
22 my @comp = split(/-/, $a);
23
24 $aliases{$a} = $this;
25
26 # All names are prefixes in their own right, although we only
27 # list the ones that are either prefixes of "proper names" or
28 # the complete alias name.
29 for (my $i = ($a eq $this->{name}) ? 0 : $#comp; $i <= $#comp; $i++) {
30 my $prefix = join('-', @comp[0..$i]);
31 $prefixes{$prefix} = [] unless defined($prefixes{$prefix});
32 push(@{$prefixes{$prefix}}, $a);
33 }
34}
35
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080036sub find_warnings {
37 my $infile = $_;
38
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -080039 return unless (basename($infile) =~ /^\w.*\.[ch]$/i);
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080040 open(my $in, '<', $infile)
41 or die "$0: cannot open input file $infile: $!\n";
42
43 my $in_comment = 0;
44 my $nline = 0;
45 my $this;
46 my @doc;
47
48 while (defined(my $l = <$in>)) {
49 $nline++;
50 chomp $l;
51
52 if (!$in_comment) {
53 $l =~ s/^.*?\/\*.*?\*\///g; # Remove single-line comments
54
55 if ($l =~ /^.*?(\/\*.*)$/) {
56 # Begin block comment
57 $l = $1;
58 $in_comment = 1;
59 }
60 }
61
62 if ($in_comment) {
63 if ($l =~ /\*\//) {
64 # End block comment
65 $in_comment = 0;
66 undef $this;
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070067 } elsif ($l =~ /^\s*\/?\*\!(\-|\=|\s*)(.*?)\s*$/) {
68 my $opr = $1;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080069 my $str = $2;
70
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070071 if ($opr eq '' && $str eq '') {
72 next;
73 } elsif ((!defined($this) || ($opr eq '')) &&
74 ($str =~ /^([\w\-]+)\s+\[(\w+)\]\s(.*\S)\s*$/)) {
75 my $name = $1;
76 my $def = $2;
77 my $help = $3;
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -070078
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070079 my $cname = uc($name);
80 $cname =~ s/[^A-Z0-9_]+/_/g;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080081
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070082 $this = {name => $name, cname => $cname,
83 def => $def, help => $help,
84 doc => [], file => $infile, line => $nline};
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080085
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070086 if (defined(my $that = $aliases{$name})) {
87 # Duplicate defintion?!
88 printf STDERR "%s:%s: warning %s previously defined at %s:%s\n",
89 $infile, $nline, $name, $that->{file}, $that->{line};
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080090 } else {
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070091 push(@warnings, $this);
92 # Every warning name is also a valid warning alias
93 add_alias($name, $this);
94 $nwarn++;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -080095 }
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070096 } elsif ($opr eq '=') {
97 # Alias names for warnings
H. Peter Anvin58bd8e62019-10-07 21:11:13 -070098 for my $a (split(/,+/, $str)) {
H. Peter Anvin7ad824b2019-10-03 22:18:35 -070099 add_alias($a, $this);
100 }
101 } elsif ($opr =~ /^[\-\s]/) {
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800102 push(@{$this->{doc}}, "$str\n");
H. Peter Anvin7ad824b2019-10-03 22:18:35 -0700103 } else {
104 print STDERR "$infile:$nline: malformed warning definition\n";
105 print STDERR " $l\n";
106 $err++;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800107 }
108 } else {
109 undef $this;
110 }
111 }
112 }
113 close($in);
114}
115
116my($what, $outfile, @indirs) = @ARGV;
117
118if (!defined($outfile)) {
119 die "$0: usage: [c|h|doc] outfile indir...\n";
120}
121
122find({ wanted => \&find_warnings, no_chdir => 1, follow => 1 }, @indirs);
123
124exit(1) if ($err);
125
126my %sort_special = ( 'other' => 1, 'all' => 2 );
127sub sort_warnings {
128 my $an = $a->{name};
129 my $bn = $b->{name};
130 return ($sort_special{$an} <=> $sort_special{$bn}) || ($an cmp $bn);
131}
132
133@warnings = sort sort_warnings @warnings;
134my @warn_noall = @warnings;
135pop @warn_noall if ($warn_noall[$#warn_noall]->{name} eq 'all');
136
137open(my $out, '>', $outfile)
138 or die "$0: cannot open output file $outfile: $!\n";
139
140if ($what eq 'c') {
141 print $out "#include \"error.h\"\n\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800142 printf $out "const char * const warning_name[%d] = {\n",
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800143 $#warnings + 2;
144 print $out "\tNULL";
145 foreach my $warn (@warnings) {
146 print $out ",\n\t\"", $warn->{name}, "\"";
147 }
148 print $out "\n};\n\n";
H. Peter Anvin (Intel)177a05d2019-08-09 13:30:19 -0700149 printf $out "const struct warning_alias warning_alias[%d] = {",
H. Peter Anvin (Intel)ad1f50a2019-08-09 16:20:40 -0700150 scalar(keys %aliases);
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700151 my $sep = '';
152 foreach my $alias (sort { $a cmp $b } keys(%aliases)) {
153 printf $out "%s\n\t{ %-27s WARN_IDX_%s }",
154 $sep, "\"$alias\",", $aliases{$alias}->{cname};
155 $sep = ',';
156 }
157 print $out "\n};\n\n";
158
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800159 printf $out "const char * const warning_help[%d] = {\n",
160 $#warnings + 2;
161 print $out "\tNULL";
162 foreach my $warn (@warnings) {
163 my $help = quote_for_c($warn->{help});
164 print $out ",\n\t\"", $help, "\"";
165 }
166 print $out "\n};\n\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800167 printf $out "const uint8_t warning_default[%d] = {\n",
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800168 $#warn_noall + 2;
169 print $out "\tWARN_INIT_ON"; # for entry 0
170 foreach my $warn (@warn_noall) {
171 print $out ",\n\tWARN_INIT_", uc($warn->{def});
172 }
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800173 print $out "\n};\n\n";
174 printf $out "uint8_t warning_state[%d];\t/* Current state */\n",
175 $#warn_noall + 2;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800176} elsif ($what eq 'h') {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800177 my $filename = basename($outfile);
178 my $guard = $filename;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800179 $guard =~ s/[^A-Za-z0-9_]+/_/g;
180 $guard = "NASM_\U$guard";
181
182 print $out "#ifndef $guard\n";
183 print $out "#define $guard\n";
184 print $out "\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800185 print $out "#ifndef WARN_SHR\n";
186 print $out "# error \"$filename should only be included from within error.h\"\n";
187 print $out "#endif\n\n";
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800188 print $out "enum warn_index {\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800189 printf $out "\tWARN_IDX_%-23s = %3d, /* not suppressible */\n", 'NONE', 0;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800190 my $n = 1;
191 foreach my $warn (@warnings) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800192 printf $out "\tWARN_IDX_%-23s = %3d%s /* %s */\n",
193 $warn->{cname}, $n,
194 ($n == $#warnings + 1) ? " " : ",",
195 $warn->{help};
196 $n++;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800197 }
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800198 print $out "};\n\n";
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800199
200 print $out "enum warn_const {\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800201 printf $out "\tWARN_%-27s = %3d << WARN_SHR", 'NONE', 0;
H. Peter Anvin (Intel)177a05d2019-08-09 13:30:19 -0700202 $n = 1;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800203 foreach my $warn (@warn_noall) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800204 printf $out ",\n\tWARN_%-27s = %3d << WARN_SHR", $warn->{cname}, $n++;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800205 }
206 print $out "\n};\n\n";
207
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700208 print $out "struct warning_alias {\n";
209 print $out "\tconst char *name;\n";
210 print $out "\tenum warn_index warning;\n";
211 print $out "};\n\n";
H. Peter Anvin (Intel)d73b10a2019-08-09 13:44:16 -0700212 printf $out "#define NUM_WARNING_ALIAS %d\n", scalar(keys %aliases);
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700213
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800214 printf $out "extern const char * const warning_name[%d];\n",
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800215 $#warnings + 2;
216 printf $out "extern const char * const warning_help[%d];\n",
217 $#warnings + 2;
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700218 print $out "extern const struct warning_alias warning_alias[NUM_WARNING_ALIAS];\n";
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -0800219 printf $out "extern const uint8_t warning_default[%d];\n",
220 $#warn_noall + 2;
221 printf $out "extern uint8_t warning_state[%d];\n",
222 $#warn_noall + 2;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800223 print $out "\n#endif /* $guard */\n";
224} elsif ($what eq 'doc') {
225 my %whatdef = ( 'on' => 'Enabled',
226 'off' => 'Disabled',
227 'err' => 'Enabled and promoted to error' );
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800228
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700229 foreach my $pfx (sort { $a cmp $b } keys(%prefixes)) {
230 my $warn = $aliases{$pfx};
231 my @doc;
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800232
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700233 if (!defined($warn)) {
234 my @plist = sort { $a cmp $b } @{$prefixes{$pfx}};
235 next if ( $#plist < 1 );
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800236
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700237 @doc = ("is a group alias for all warning classes prefixed by ".
238 "\\c{".$pfx."-}; currently\n");
239 for (my $i = 0; $i <= $#plist; $i++) {
240 if ($i > 0) {
241 if ($i < $#plist) {
242 push(@doc, ", ");
243 } else {
244 push(@doc, ($i == 1) ? " and " : ", and ");
245 }
246 }
247 push(@doc, '\c{'.$plist[$i].'}');
248 }
249 push(@doc, ".\n");
250 } elsif ($pfx ne $warn->{name}) {
251 @doc = ("is a backwards compatibility alias for \\c{",
252 $warn->{name}, "}.\n");
253 } else {
254 my $docdef = $whatdef{$warn->{def}};
255
H. Peter Anvin (Intel)de8817d2020-06-27 22:30:50 -0700256 my $newpara = 0;
257 foreach my $l (@{$warn->{doc}}) {
258 if ($l =~ /^\s*$/) {
259 $newpara = 1;
260 } else {
261 if ($newpara && $l !~ /^\\c\s+/) {
262 $l = '\> ' . $l;
263 }
264 $newpara = 0;
265 }
266 push(@doc, $l);
267 }
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700268 if (defined($docdef)) {
H. Peter Anvinbef71a82019-10-03 23:47:08 -0700269 push(@doc, "\n", "\\> $docdef by default.\n");
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700270 }
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800271 }
272
H. Peter Anvinfdeb3b02019-06-06 20:53:17 -0700273 print $out "\\b \\i\\c{", $pfx, "} ", @doc, "\n";
H. Peter Anvin (Intel)3c896de2018-12-13 16:33:39 -0800274 }
275}
276close($out);