blob: bd018eb3815b73378cbb17599a3be4b337de9ae8 [file] [log] [blame]
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -03001#!/usr/bin/perl
Mauro Carvalho Chehabecb351f2019-06-20 14:23:10 -03002# SPDX-License-Identifier: GPL-2.0
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -03003
4use strict;
5use Pod::Usage;
6use Getopt::Long;
7use File::Find;
8use Fcntl ':mode';
9
10my $help;
11my $man;
12my $debug;
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +010013my $enable_lineno;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030014my $prefix="Documentation/ABI";
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030015
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +010016#
17# If true, assumes that the description is formatted with ReST
18#
19my $description_is_rst = 0;
20
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030021GetOptions(
22 "debug|d+" => \$debug,
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +010023 "enable-lineno" => \$enable_lineno,
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +010024 "rst-source!" => \$description_is_rst,
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030025 "dir=s" => \$prefix,
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030026 'help|?' => \$help,
27 man => \$man
28) or pod2usage(2);
29
30pod2usage(1) if $help;
31pod2usage(-exitstatus => 0, -verbose => 2) if $man;
32
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030033pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2);
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030034
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030035my ($cmd, $arg) = @ARGV;
36
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -030037pod2usage(2) if ($cmd ne "search" && $cmd ne "rest" && $cmd ne "validate");
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030038pod2usage(2) if ($cmd eq "search" && !$arg);
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030039
40require Data::Dumper if ($debug);
41
42my %data;
43
44#
45# Displays an error message, printing file name and line
46#
47sub parse_error($$$$) {
48 my ($file, $ln, $msg, $data) = @_;
49
50 print STDERR "file $file#$ln: $msg at\n\t$data";
51}
52
53#
54# Parse an ABI file, storing its contents at %data
55#
56sub parse_abi {
57 my $file = $File::Find::name;
58
59 my $mode = (stat($file))[2];
60 return if ($mode & S_IFDIR);
61 return if ($file =~ m,/README,);
62
63 my $name = $file;
64 $name =~ s,.*/,,;
65
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030066 my $nametag = "File $name";
67 $data{$nametag}->{what} = "File $name";
68 $data{$nametag}->{type} = "File";
69 $data{$nametag}->{file} = $name;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030070 $data{$nametag}->{filepath} = $file;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030071 $data{$nametag}->{is_file} = 1;
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +010072 $data{$nametag}->{line_no} = 1;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030073
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030074 my $type = $file;
75 $type =~ s,.*/(.*)/.*,$1,;
76
77 my $what;
78 my $new_what;
79 my $tag;
80 my $ln;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -030081 my $xrefs;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -030082 my $space;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030083 my @labels;
84 my $label;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030085
86 print STDERR "Opening $file\n" if ($debug > 1);
87 open IN, $file;
88 while(<IN>) {
89 $ln++;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -030090 if (m/^(\S+)(:\s*)(.*)/i) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030091 my $new_tag = lc($1);
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -030092 my $sep = $2;
93 my $content = $3;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030094
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -030095 if (!($new_tag =~ m/(what|where|date|kernelversion|contact|description|users)/)) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030096 if ($tag eq "description") {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -030097 # New "tag" is actually part of
98 # description. Don't consider it a tag
99 $new_tag = "";
Mauro Carvalho Chehab7d7ea8d2019-06-20 14:23:01 -0300100 } elsif ($tag ne "") {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300101 parse_error($file, $ln, "tag '$tag' is invalid", $_);
102 }
103 }
104
Mauro Carvalho Chehab2c0700e2019-06-20 14:23:03 -0300105 # Invalid, but it is a common mistake
106 if ($new_tag eq "where") {
107 parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", $_);
108 $new_tag = "what";
109 }
110
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300111 if ($new_tag =~ m/what/) {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300112 $space = "";
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300113 if ($tag =~ m/what/) {
114 $what .= ", " . $content;
115 } else {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300116 parse_error($file, $ln, "What '$what' doesn't have a description", "") if ($what && !$data{$what}->{description});
117
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300118 $what = $content;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300119 $label = $content;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300120 $new_what = 1;
121 }
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300122 push @labels, [($content, $label)];
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300123 $tag = $new_tag;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300124
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300125 push @{$data{$nametag}->{xrefs}}, [($content, $label)] if ($data{$nametag}->{what});
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300126 next;
127 }
128
Mauro Carvalho Chehab7d7ea8d2019-06-20 14:23:01 -0300129 if ($tag ne "" && $new_tag) {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300130 $tag = $new_tag;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300131
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100132 $data{$what}->{line_no} = $ln;
133
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300134 if ($new_what) {
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300135 @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what});
136 @labels = ();
137 $label = "";
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300138 $new_what = 0;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300139
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300140 $data{$what}->{type} = $type;
141 $data{$what}->{file} = $name;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300142 $data{$what}->{filepath} = $file;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300143 print STDERR "\twhat: $what\n" if ($debug > 1);
144 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300145
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300146 if (!$what) {
147 parse_error($file, $ln, "'What:' should come first:", $_);
148 next;
149 }
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100150 if ($new_tag eq "description") {
151 $sep =~ s,:, ,;
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100152 $content = ' ' x length($new_tag) . $sep . $content;
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100153 while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
154 if ($content =~ m/^(\s*)(\S.*)$/) {
155 # Preserve initial spaces for the first line
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100156 $space = $1;
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100157 $content = "$2\n";
158 $data{$what}->{$tag} .= $content;
159 } else {
160 undef($space);
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300161 }
Mauro Carvalho Chehabe9bca892020-10-30 08:40:21 +0100162
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300163 } else {
164 $data{$what}->{$tag} = $content;
165 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300166 next;
167 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300168 }
169
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300170 # Store any contents before tags at the database
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300171 if (!$tag && $data{$nametag}->{what}) {
172 $data{$nametag}->{description} .= $_;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300173 next;
174 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300175
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300176 if ($tag eq "description") {
Mauro Carvalho Chehabe9bca892020-10-30 08:40:21 +0100177 my $content = $_;
178 while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100179 if (m/^\s*\n/) {
180 $data{$what}->{$tag} .= "\n";
181 next;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300182 }
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100183
184 if (!defined($space)) {
185 # Preserve initial spaces for the first line
186 if ($content =~ m/^(\s*)(\S.*)$/) {
187 $space = $1;
188 $content = "$2\n";
189 }
190 } else {
191 $space = "" if (!($content =~ s/^($space)//));
192 }
193 $data{$what}->{$tag} .= $content;
194
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300195 next;
196 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300197 if (m/^\s*(.*)/) {
198 $data{$what}->{$tag} .= "\n$1";
199 $data{$what}->{$tag} =~ s/\n+$//;
200 next;
201 }
202
203 # Everything else is error
204 parse_error($file, $ln, "Unexpected line:", $_);
205 }
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300206 $data{$nametag}->{description} =~ s/^\n+//;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300207 close IN;
208}
209
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300210#
211# Outputs the book on ReST format
212#
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300213
Mauro Carvalho Chehab2e7ce052019-06-20 14:23:02 -0300214my %labels;
215
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300216sub output_rest {
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300217 foreach my $what (sort {
218 ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
219 $a cmp $b
220 } keys %data) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300221 my $type = $data{$what}->{type};
222 my $file = $data{$what}->{file};
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300223 my $filepath = $data{$what}->{filepath};
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300224
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100225 if ($enable_lineno) {
226 printf "#define LINENO %s%s#%s\n\n",
227 $prefix, $data{$what}->{file},
228 $data{$what}->{line_no};
229 }
230
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300231 my $w = $what;
232 $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g;
233
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300234
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300235 foreach my $p (@{$data{$what}->{label}}) {
236 my ($content, $label) = @{$p};
237 $label = "abi_" . $label . " ";
238 $label =~ tr/A-Z/a-z/;
239
240 # Convert special chars to "_"
241 $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
242 $label =~ s,_+,_,g;
243 $label =~ s,_$,,;
244
Mauro Carvalho Chehab2e7ce052019-06-20 14:23:02 -0300245 # Avoid duplicated labels
246 while (defined($labels{$label})) {
247 my @chars = ("A".."Z", "a".."z");
248 $label .= $chars[rand @chars];
249 }
250 $labels{$label} = 1;
251
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300252 $data{$what}->{label} .= $label;
253
254 printf ".. _%s:\n\n", $label;
255
256 # only one label is enough
257 last;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300258 }
259
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300260
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300261 $filepath =~ s,.*/(.*/.*),\1,;;
262 $filepath =~ s,[/\-],_,g;;
263 my $fileref = "abi_file_".$filepath;
264
265 if ($type eq "File") {
266 my $bar = $w;
267 $bar =~ s/./-/g;
268
269 print ".. _$fileref:\n\n";
270 print "$w\n$bar\n\n";
271 } else {
272 my @names = split /\s*,\s*/,$w;
273
274 my $len = 0;
275
276 foreach my $name (@names) {
277 $len = length($name) if (length($name) > $len);
278 }
279
280 print "What:\n\n";
281
282 print "+-" . "-" x $len . "-+\n";
283 foreach my $name (@names) {
284 printf "| %s", $name . " " x ($len - length($name)) . " |\n";
285 print "+-" . "-" x $len . "-+\n";
286 }
287 print "\n";
288 }
289
290 print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File");
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300291
292 my $desc = $data{$what}->{description};
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300293
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300294 if (!($desc =~ /^\s*$/)) {
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100295 if ($description_is_rst) {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300296 print "$desc\n\n";
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100297 } else {
298 $desc =~ s/^\s+//;
299
300 # Remove title markups from the description, as they won't work
301 $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
302
303 if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
304 # put everything inside a code block
305 $desc =~ s/\n/\n /g;
306
307 print "::\n\n";
308 print " $desc\n\n";
309 } else {
310 # Escape any special chars from description
311 $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
312 print "$desc\n\n";
313 }
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300314 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300315 } else {
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300316 print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300317 }
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300318
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300319 if ($data{$what}->{xrefs}) {
320 printf "Has the following ABI:\n\n";
321
322 foreach my $p(@{$data{$what}->{xrefs}}) {
323 my ($content, $label) = @{$p};
324 $label = "abi_" . $label . " ";
325 $label =~ tr/A-Z/a-z/;
326
327 # Convert special chars to "_"
328 $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
329 $label =~ s,_+,_,g;
330 $label =~ s,_$,,;
331
332 # Escape special chars from content
333 $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
334
335 print "- :ref:`$content <$label>`\n\n";
336 }
337 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300338 }
339}
340
341#
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300342# Searches for ABI symbols
343#
344sub search_symbols {
345 foreach my $what (sort keys %data) {
346 next if (!($what =~ m/($arg)/));
347
348 my $type = $data{$what}->{type};
349 next if ($type eq "File");
350
351 my $file = $data{$what}->{filepath};
352
353 my $bar = $what;
354 $bar =~ s/./-/g;
355
356 print "\n$what\n$bar\n\n";
357
358 my $kernelversion = $data{$what}->{kernelversion};
359 my $contact = $data{$what}->{contact};
360 my $users = $data{$what}->{users};
361 my $date = $data{$what}->{date};
362 my $desc = $data{$what}->{description};
363 $kernelversion =~ s/^\s+//;
364 $contact =~ s/^\s+//;
365 $users =~ s/^\s+//;
366 $users =~ s/\n//g;
367 $date =~ s/^\s+//;
368 $desc =~ s/^\s+//;
369
370 printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion);
371 printf "Date:\t\t\t%s\n", $date if ($date);
372 printf "Contact:\t\t%s\n", $contact if ($contact);
373 printf "Users:\t\t\t%s\n", $users if ($users);
374 print "Defined on file:\t$file\n\n";
375 print "Description:\n\n$desc";
376 }
377}
378
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100379# Ensure that the prefix will always end with a slash
380# While this is not needed for find, it makes the patch nicer
381# with --enable-lineno
382$prefix =~ s,/?$,/,;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300383
384#
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300385# Parses all ABI files located at $prefix dir
386#
387find({wanted =>\&parse_abi, no_chdir => 1}, $prefix);
388
389print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
390
391#
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300392# Handles the command
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300393#
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300394if ($cmd eq "rest") {
395 output_rest;
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300396} elsif ($cmd eq "search") {
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300397 search_symbols;
398}
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300399
400
401__END__
402
403=head1 NAME
404
405abi_book.pl - parse the Linux ABI files and produce a ReST book.
406
407=head1 SYNOPSIS
408
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100409B<abi_book.pl> [--debug] [--enable-lineno] [--man] [--help]
410 [--(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300411
412Where <COMMAND> can be:
413
414=over 8
415
416B<search> [SEARCH_REGEX] - search for [SEARCH_REGEX] inside ABI
417
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300418B<rest> - output the ABI in ReST markup language
419
420B<validate> - validate the ABI contents
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300421
422=back
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300423
424=head1 OPTIONS
425
426=over 8
427
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300428=item B<--dir>
429
430Changes the location of the ABI search. By default, it uses
431the Documentation/ABI directory.
432
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100433=item B<--rst-source> and B<--no-rst-source>
434
435The input file may be using ReST syntax or not. Those two options allow
436selecting between a rst-compliant source ABI (--rst-source), or a
437plain text that may be violating ReST spec, so it requres some escaping
438logic (--no-rst-source).
439
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100440=item B<--enable-lineno>
441
442Enable output of #define LINENO lines.
443
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300444=item B<--debug>
445
446Put the script in verbose mode, useful for debugging. Can be called multiple
447times, to increase verbosity.
448
449=item B<--help>
450
451Prints a brief help message and exits.
452
453=item B<--man>
454
455Prints the manual page and exits.
456
457=back
458
459=head1 DESCRIPTION
460
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300461Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI),
462allowing to search for ABI symbols or to produce a ReST book containing
463the Linux ABI documentation.
464
465=head1 EXAMPLES
466
467Search for all stable symbols with the word "usb":
468
469=over 8
470
471$ scripts/get_abi.pl search usb --dir Documentation/ABI/stable
472
473=back
474
475Search for all symbols that match the regex expression "usb.*cap":
476
477=over 8
478
479$ scripts/get_abi.pl search usb.*cap
480
481=back
482
483Output all obsoleted symbols in ReST format
484
485=over 8
486
487$ scripts/get_abi.pl rest --dir Documentation/ABI/obsolete
488
489=back
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300490
491=head1 BUGS
492
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300493Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300494
495=head1 COPYRIGHT
496
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300497Copyright (c) 2016-2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300498
499License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
500
501This is free software: you are free to change and redistribute it.
502There is NO WARRANTY, to the extent permitted by law.
503
504=cut