scripts/get_abi.pl: split label naming from xref logic
[linux-2.6-block.git] / scripts / get_abi.pl
CommitLineData
bbc249f2
MCC
1#!/usr/bin/perl
2
3use strict;
4use Pod::Usage;
5use Getopt::Long;
6use File::Find;
7use Fcntl ':mode';
8
9my $help;
10my $man;
11my $debug;
12
13GetOptions(
14 "debug|d+" => \$debug,
15 'help|?' => \$help,
16 man => \$man
17) or pod2usage(2);
18
19pod2usage(1) if $help;
20pod2usage(-exitstatus => 0, -verbose => 2) if $man;
21
22pod2usage(2) if (scalar @ARGV != 1);
23
24my ($prefix) = @ARGV;
25
26require Data::Dumper if ($debug);
27
28my %data;
29
30#
31# Displays an error message, printing file name and line
32#
33sub parse_error($$$$) {
34 my ($file, $ln, $msg, $data) = @_;
35
36 print STDERR "file $file#$ln: $msg at\n\t$data";
37}
38
39#
40# Parse an ABI file, storing its contents at %data
41#
42sub parse_abi {
43 my $file = $File::Find::name;
44
45 my $mode = (stat($file))[2];
46 return if ($mode & S_IFDIR);
47 return if ($file =~ m,/README,);
48
49 my $name = $file;
50 $name =~ s,.*/,,;
51
d0ebaf51
MCC
52 my $nametag = "File $name";
53 $data{$nametag}->{what} = "File $name";
54 $data{$nametag}->{type} = "File";
55 $data{$nametag}->{file} = $name;
56 $data{$nametag}->{is_file} = 1;
57
bbc249f2
MCC
58 my $type = $file;
59 $type =~ s,.*/(.*)/.*,$1,;
60
61 my $what;
62 my $new_what;
63 my $tag;
64 my $ln;
6619c661 65 my $xrefs;
4e6a6234 66 my $space;
d0ebaf51
MCC
67 my @labels;
68 my $label;
bbc249f2
MCC
69
70 print STDERR "Opening $file\n" if ($debug > 1);
71 open IN, $file;
72 while(<IN>) {
73 $ln++;
4e6a6234 74 if (m/^(\S+)(:\s*)(.*)/i) {
bbc249f2 75 my $new_tag = lc($1);
4e6a6234
MCC
76 my $sep = $2;
77 my $content = $3;
bbc249f2
MCC
78
79 if (!($new_tag =~ m/(what|date|kernelversion|contact|description|users)/)) {
80 if ($tag eq "description") {
4e6a6234
MCC
81 # New "tag" is actually part of
82 # description. Don't consider it a tag
83 $new_tag = "";
bbc249f2
MCC
84 } else {
85 parse_error($file, $ln, "tag '$tag' is invalid", $_);
86 }
87 }
88
89 if ($new_tag =~ m/what/) {
4e6a6234 90 $space = "";
bbc249f2
MCC
91 if ($tag =~ m/what/) {
92 $what .= ", " . $content;
93 } else {
4e6a6234
MCC
94 parse_error($file, $ln, "What '$what' doesn't have a description", "") if ($what && !$data{$what}->{description});
95
bbc249f2 96 $what = $content;
d0ebaf51 97 $label = $content;
bbc249f2
MCC
98 $new_what = 1;
99 }
d0ebaf51 100 push @labels, [($content, $label)];
bbc249f2 101 $tag = $new_tag;
6619c661 102
d0ebaf51 103 push @{$data{$nametag}->{xrefs}}, [($content, $label)] if ($data{$nametag}->{what});
bbc249f2
MCC
104 next;
105 }
106
4e6a6234
MCC
107 if ($new_tag) {
108 $tag = $new_tag;
bbc249f2 109
4e6a6234 110 if ($new_what) {
d0ebaf51
MCC
111 @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what});
112 @labels = ();
113 $label = "";
4e6a6234 114 $new_what = 0;
bbc249f2 115
4e6a6234
MCC
116 $data{$what}->{type} = $type;
117 $data{$what}->{file} = $name;
118 print STDERR "\twhat: $what\n" if ($debug > 1);
119 }
bbc249f2 120
4e6a6234
MCC
121 if (!$what) {
122 parse_error($file, $ln, "'What:' should come first:", $_);
123 next;
124 }
125 if ($tag eq "description") {
126 next if ($content =~ m/^\s*$/);
127 if ($content =~ m/^(\s*)(.*)/) {
128 my $new_content = $2;
129 $space = $new_tag . $sep . $1;
130 while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
131 $space =~ s/./ /g;
132 $data{$what}->{$tag} .= "$new_content\n";
133 }
134 } else {
135 $data{$what}->{$tag} = $content;
136 }
bbc249f2
MCC
137 next;
138 }
bbc249f2
MCC
139 }
140
4e6a6234 141 # Store any contents before tags at the database
d0ebaf51
MCC
142 if (!$tag && $data{$nametag}->{what}) {
143 $data{$nametag}->{description} .= $_;
6619c661
MCC
144 next;
145 }
bbc249f2 146
4e6a6234
MCC
147 if ($tag eq "description") {
148 if (!$data{$what}->{description}) {
149 next if (m/^\s*\n/);
150 if (m/^(\s*)(.*)/) {
151 $space = $1;
152 while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
153 $data{$what}->{$tag} .= "$2\n";
154 }
155 } else {
156 my $content = $_;
157 if (m/^\s*\n/) {
158 $data{$what}->{$tag} .= $content;
159 next;
160 }
161
162 while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
163 $space = "" if (!($content =~ s/^($space)//));
164
165 # Compress spaces with tabs
166 $content =~ s<^ {8}> <\t>;
167 $content =~ s<^ {1,7}\t> <\t>;
168 $content =~ s< {1,7}\t> <\t>;
169 $data{$what}->{$tag} .= $content;
170 }
171 next;
172 }
bbc249f2
MCC
173 if (m/^\s*(.*)/) {
174 $data{$what}->{$tag} .= "\n$1";
175 $data{$what}->{$tag} =~ s/\n+$//;
176 next;
177 }
178
179 # Everything else is error
180 parse_error($file, $ln, "Unexpected line:", $_);
181 }
d0ebaf51 182 $data{$nametag}->{description} =~ s/^\n+//;
bbc249f2
MCC
183 close IN;
184}
185
186# Outputs the output on ReST format
187sub output_rest {
188 foreach my $what (sort keys %data) {
189 my $type = $data{$what}->{type};
190 my $file = $data{$what}->{file};
191
192 my $w = $what;
193 $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
194
4e6a6234
MCC
195 my $bar = $w;
196 $bar =~ s/./-/g;
197
d0ebaf51
MCC
198 foreach my $p (@{$data{$what}->{label}}) {
199 my ($content, $label) = @{$p};
200 $label = "abi_" . $label . " ";
201 $label =~ tr/A-Z/a-z/;
202
203 # Convert special chars to "_"
204 $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
205 $label =~ s,_+,_,g;
206 $label =~ s,_$,,;
207
208 $data{$what}->{label} .= $label;
209
210 printf ".. _%s:\n\n", $label;
211
212 # only one label is enough
213 last;
6619c661
MCC
214 }
215
4e6a6234 216 print "$w\n$bar\n\n";
6619c661
MCC
217
218 print "- defined on file $file (type: $type)\n\n" if ($type ne "File");
bbc249f2
MCC
219
220 my $desc = $data{$what}->{description};
221 $desc =~ s/^\s+//;
222
223 # Remove title markups from the description, as they won't work
224 $desc =~ s/\n[\-\*\=\^\~]+\n/\n/g;
225
4e6a6234
MCC
226 if (!($desc =~ /^\s*$/)) {
227 if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
228 # put everything inside a code block
229 $desc =~ s/\n/\n /g;
bbc249f2 230
4e6a6234
MCC
231 print "::\n\n";
232 print " $desc\n\n";
233 } else {
234 # Escape any special chars from description
235 $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
bbc249f2 236
4e6a6234
MCC
237 print "$desc\n\n";
238 }
bbc249f2 239 } else {
d0ebaf51 240 print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
bbc249f2 241 }
6619c661 242
d0ebaf51
MCC
243 if ($data{$what}->{xrefs}) {
244 printf "Has the following ABI:\n\n";
245
246 foreach my $p(@{$data{$what}->{xrefs}}) {
247 my ($content, $label) = @{$p};
248 $label = "abi_" . $label . " ";
249 $label =~ tr/A-Z/a-z/;
250
251 # Convert special chars to "_"
252 $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
253 $label =~ s,_+,_,g;
254 $label =~ s,_$,,;
255
256 # Escape special chars from content
257 $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
258
259 print "- :ref:`$content <$label>`\n\n";
260 }
261 }
bbc249f2
MCC
262 }
263}
264
265#
266# Parses all ABI files located at $prefix dir
267#
268find({wanted =>\&parse_abi, no_chdir => 1}, $prefix);
269
270print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
271
272#
273# Outputs an ReST file with the ABI contents
274#
275output_rest
276
277
278__END__
279
280=head1 NAME
281
282abi_book.pl - parse the Linux ABI files and produce a ReST book.
283
284=head1 SYNOPSIS
285
286B<abi_book.pl> [--debug] <ABI_DIR>]
287
288=head1 OPTIONS
289
290=over 8
291
292=item B<--debug>
293
294Put the script in verbose mode, useful for debugging. Can be called multiple
295times, to increase verbosity.
296
297=item B<--help>
298
299Prints a brief help message and exits.
300
301=item B<--man>
302
303Prints the manual page and exits.
304
305=back
306
307=head1 DESCRIPTION
308
309Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI)
310and produce a ReST book containing the Linux ABI.
311
312=head1 BUGS
313
314Report bugs to Mauro Carvalho Chehab <mchehab@s-opensource.com>
315
316=head1 COPYRIGHT
317
318Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
319
320License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
321
322This is free software: you are free to change and redistribute it.
323There is NO WARRANTY, to the extent permitted by law.
324
325=cut