blob: aa0a751563ba8eaf91fc73f0572c36a8031faa00 [file] [log] [blame]
Finn Behrensc25ce582020-11-23 15:15:33 +01001#!/usr/bin/env 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;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +01005use warnings;
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +01006use utf8;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -03007use Pod::Usage;
8use Getopt::Long;
9use File::Find;
10use Fcntl ':mode';
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +020011use Cwd 'abs_path';
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030012
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +010013my $help = 0;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +020014my $hint = 0;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +010015my $man = 0;
16my $debug = 0;
17my $enable_lineno = 0;
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +020018my $show_warnings = 1;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030019my $prefix="Documentation/ABI";
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +020020my $sysfs_prefix="/sys";
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +020021my $search_string;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030022
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +010023#
24# If true, assumes that the description is formatted with ReST
25#
Mauro Carvalho Chehab2fcce372020-10-30 08:40:58 +010026my $description_is_rst = 1;
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +010027
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030028GetOptions(
29 "debug|d+" => \$debug,
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +010030 "enable-lineno" => \$enable_lineno,
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +010031 "rst-source!" => \$description_is_rst,
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030032 "dir=s" => \$prefix,
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030033 'help|?' => \$help,
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +020034 "show-hints" => \$hint,
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +020035 "search-string=s" => \$search_string,
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030036 man => \$man
37) or pod2usage(2);
38
39pod2usage(1) if $help;
40pod2usage(-exitstatus => 0, -verbose => 2) if $man;
41
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030042pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2);
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030043
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030044my ($cmd, $arg) = @ARGV;
45
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +020046pod2usage(2) if ($cmd ne "search" && $cmd ne "rest" && $cmd ne "validate" && $cmd ne "undefined");
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030047pod2usage(2) if ($cmd eq "search" && !$arg);
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030048
49require Data::Dumper if ($debug);
50
51my %data;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +010052my %symbols;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030053
54#
55# Displays an error message, printing file name and line
56#
57sub parse_error($$$$) {
58 my ($file, $ln, $msg, $data) = @_;
59
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +020060 return if (!$show_warnings);
61
Mauro Carvalho Chehab75442fb2020-10-30 08:40:45 +010062 $data =~ s/\s+$/\n/;
63
64 print STDERR "Warning: file $file#$ln:\n\t$msg";
65
66 if ($data ne "") {
67 print STDERR ". Line\n\t\t$data";
68 } else {
69 print STDERR "\n";
70 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030071}
72
73#
74# Parse an ABI file, storing its contents at %data
75#
76sub parse_abi {
77 my $file = $File::Find::name;
78
79 my $mode = (stat($file))[2];
80 return if ($mode & S_IFDIR);
81 return if ($file =~ m,/README,);
82
83 my $name = $file;
84 $name =~ s,.*/,,;
85
Mauro Carvalho Chehaba4ea67b2020-10-30 08:40:27 +010086 my $fn = $file;
87 $fn =~ s,Documentation/ABI/,,;
88
89 my $nametag = "File $fn";
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030090 $data{$nametag}->{what} = "File $name";
91 $data{$nametag}->{type} = "File";
92 $data{$nametag}->{file} = $name;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -030093 $data{$nametag}->{filepath} = $file;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030094 $data{$nametag}->{is_file} = 1;
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +010095 $data{$nametag}->{line_no} = 1;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -030096
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -030097 my $type = $file;
98 $type =~ s,.*/(.*)/.*,$1,;
99
100 my $what;
101 my $new_what;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100102 my $tag = "";
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300103 my $ln;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300104 my $xrefs;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300105 my $space;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300106 my @labels;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100107 my $label = "";
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300108
109 print STDERR "Opening $file\n" if ($debug > 1);
110 open IN, $file;
111 while(<IN>) {
112 $ln++;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300113 if (m/^(\S+)(:\s*)(.*)/i) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300114 my $new_tag = lc($1);
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300115 my $sep = $2;
116 my $content = $3;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300117
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300118 if (!($new_tag =~ m/(what|where|date|kernelversion|contact|description|users)/)) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300119 if ($tag eq "description") {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300120 # New "tag" is actually part of
121 # description. Don't consider it a tag
122 $new_tag = "";
Mauro Carvalho Chehab7d7ea8d2019-06-20 14:23:01 -0300123 } elsif ($tag ne "") {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300124 parse_error($file, $ln, "tag '$tag' is invalid", $_);
125 }
126 }
127
Mauro Carvalho Chehab2c0700e2019-06-20 14:23:03 -0300128 # Invalid, but it is a common mistake
129 if ($new_tag eq "where") {
Mauro Carvalho Chehab75442fb2020-10-30 08:40:45 +0100130 parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", "");
Mauro Carvalho Chehab2c0700e2019-06-20 14:23:03 -0300131 $new_tag = "what";
132 }
133
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300134 if ($new_tag =~ m/what/) {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300135 $space = "";
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100136 $content =~ s/[,.;]$//;
137
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100138 push @{$symbols{$content}->{file}}, " $file:" . ($ln - 1);
139
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300140 if ($tag =~ m/what/) {
Mauro Carvalho Chehabab9c1482021-09-18 11:52:11 +0200141 $what .= "\xac" . $content;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300142 } else {
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100143 if ($what) {
144 parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
145
Mauro Carvalho Chehabab9c1482021-09-18 11:52:11 +0200146 foreach my $w(split /\xac/, $what) {
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100147 $symbols{$w}->{xref} = $what;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100148 };
149 }
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300150
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300151 $what = $content;
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300152 $label = $content;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300153 $new_what = 1;
154 }
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300155 push @labels, [($content, $label)];
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300156 $tag = $new_tag;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300157
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100158 push @{$data{$nametag}->{symbols}}, $content if ($data{$nametag}->{what});
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300159 next;
160 }
161
Mauro Carvalho Chehab7d7ea8d2019-06-20 14:23:01 -0300162 if ($tag ne "" && $new_tag) {
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300163 $tag = $new_tag;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300164
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300165 if ($new_what) {
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100166 @{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what});
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300167 @labels = ();
168 $label = "";
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300169 $new_what = 0;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300170
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300171 $data{$what}->{type} = $type;
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100172 if (!defined($data{$what}->{file})) {
173 $data{$what}->{file} = $name;
174 $data{$what}->{filepath} = $file;
175 } else {
176 if ($name ne $data{$what}->{file}) {
177 $data{$what}->{file} .= " " . $name;
178 $data{$what}->{filepath} .= " " . $file;
179 }
180 }
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300181 print STDERR "\twhat: $what\n" if ($debug > 1);
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100182 $data{$what}->{line_no} = $ln;
183 } else {
184 $data{$what}->{line_no} = $ln if (!defined($data{$what}->{line_no}));
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300185 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300186
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300187 if (!$what) {
188 parse_error($file, $ln, "'What:' should come first:", $_);
189 next;
190 }
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100191 if ($new_tag eq "description") {
192 $sep =~ s,:, ,;
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100193 $content = ' ' x length($new_tag) . $sep . $content;
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100194 while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
195 if ($content =~ m/^(\s*)(\S.*)$/) {
196 # Preserve initial spaces for the first line
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100197 $space = $1;
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100198 $content = "$2\n";
199 $data{$what}->{$tag} .= $content;
200 } else {
201 undef($space);
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300202 }
Mauro Carvalho Chehabe9bca892020-10-30 08:40:21 +0100203
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300204 } else {
205 $data{$what}->{$tag} = $content;
206 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300207 next;
208 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300209 }
210
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300211 # Store any contents before tags at the database
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300212 if (!$tag && $data{$nametag}->{what}) {
213 $data{$nametag}->{description} .= $_;
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300214 next;
215 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300216
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300217 if ($tag eq "description") {
Mauro Carvalho Chehabe9bca892020-10-30 08:40:21 +0100218 my $content = $_;
219 while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100220 if (m/^\s*\n/) {
221 $data{$what}->{$tag} .= "\n";
222 next;
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300223 }
Mauro Carvalho Chehabf82a8a72020-10-30 08:40:23 +0100224
225 if (!defined($space)) {
226 # Preserve initial spaces for the first line
227 if ($content =~ m/^(\s*)(\S.*)$/) {
228 $space = $1;
229 $content = "$2\n";
230 }
231 } else {
232 $space = "" if (!($content =~ s/^($space)//));
233 }
234 $data{$what}->{$tag} .= $content;
235
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300236 next;
237 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300238 if (m/^\s*(.*)/) {
239 $data{$what}->{$tag} .= "\n$1";
240 $data{$what}->{$tag} =~ s/\n+$//;
241 next;
242 }
243
244 # Everything else is error
Mauro Carvalho Chehab75442fb2020-10-30 08:40:45 +0100245 parse_error($file, $ln, "Unexpected content", $_);
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300246 }
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100247 $data{$nametag}->{description} =~ s/^\n+// if ($data{$nametag}->{description});
248 if ($what) {
249 parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
250
Mauro Carvalho Chehabab9c1482021-09-18 11:52:11 +0200251 foreach my $w(split /\xac/,$what) {
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100252 $symbols{$w}->{xref} = $what;
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100253 };
254 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300255 close IN;
256}
257
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100258sub create_labels {
259 my %labels;
260
261 foreach my $what (keys %data) {
262 next if ($data{$what}->{file} eq "File");
263
264 foreach my $p (@{$data{$what}->{label_list}}) {
265 my ($content, $label) = @{$p};
266 $label = "abi_" . $label . " ";
267 $label =~ tr/A-Z/a-z/;
268
269 # Convert special chars to "_"
270 $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
271 $label =~ s,_+,_,g;
272 $label =~ s,_$,,;
273
274 # Avoid duplicated labels
275 while (defined($labels{$label})) {
276 my @chars = ("A".."Z", "a".."z");
277 $label .= $chars[rand @chars];
278 }
279 $labels{$label} = 1;
280
281 $data{$what}->{label} = $label;
282
283 # only one label is enough
284 last;
285 }
286 }
287}
288
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300289#
290# Outputs the book on ReST format
291#
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300292
Mauro Carvalho Chehab50ebf8f2021-03-25 11:38:24 +0100293# \b doesn't work well with paths. So, we need to define something else:
294# Boundaries are punct characters, spaces and end-of-line
295my $start = qr {(^|\s|\() }x;
296my $bondary = qr { ([,.:;\)\s]|\z) }x;
Mauro Carvalho Chehab87ec9ea12021-03-25 11:38:25 +0100297my $xref_match = qr { $start(\/(sys|config|proc|dev|kvd)\/[^,.:;\)\s]+)$bondary }x;
Mauro Carvalho Chehabb0f95802021-03-25 11:38:22 +0100298my $symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x2f\x3a-\x40\x7b-\xff]) }x;
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +0100299
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300300sub output_rest {
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100301 create_labels();
302
Mauro Carvalho Chehab9d4fdda2020-11-02 11:32:16 +0100303 my $part = "";
304
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300305 foreach my $what (sort {
306 ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
307 $a cmp $b
308 } keys %data) {
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300309 my $type = $data{$what}->{type};
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100310
311 my @file = split / /, $data{$what}->{file};
312 my @filepath = split / /, $data{$what}->{filepath};
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300313
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100314 if ($enable_lineno) {
315 printf "#define LINENO %s%s#%s\n\n",
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100316 $prefix, $file[0],
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100317 $data{$what}->{line_no};
318 }
319
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300320 my $w = $what;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300321
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100322 if ($type ne "File") {
Mauro Carvalho Chehab9d4fdda2020-11-02 11:32:16 +0100323 my $cur_part = $what;
324 if ($what =~ '/') {
325 if ($what =~ m#^(\/?(?:[\w\-]+\/?){1,2})#) {
326 $cur_part = "Symbols under $1";
327 $cur_part =~ s,/$,,;
328 }
329 }
330
331 if ($cur_part ne "" && $part ne $cur_part) {
332 $part = $cur_part;
333 my $bar = $part;
334 $bar =~ s/./-/g;
335 print "$part\n$bar\n\n";
336 }
337
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100338 printf ".. _%s:\n\n", $data{$what}->{label};
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300339
Mauro Carvalho Chehabab9c1482021-09-18 11:52:11 +0200340 my @names = split /\xac/,$w;
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300341 my $len = 0;
342
343 foreach my $name (@names) {
Mauro Carvalho Chehabb0f95802021-03-25 11:38:22 +0100344 $name =~ s/$symbols/\\$1/g;
Mauro Carvalho Chehabc01d62d2020-10-30 08:40:28 +0100345 $name = "**$name**";
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300346 $len = length($name) if (length($name) > $len);
347 }
348
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300349 print "+-" . "-" x $len . "-+\n";
350 foreach my $name (@names) {
351 printf "| %s", $name . " " x ($len - length($name)) . " |\n";
352 print "+-" . "-" x $len . "-+\n";
353 }
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100354
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100355 print "\n";
356 }
357
358 for (my $i = 0; $i < scalar(@filepath); $i++) {
359 my $path = $filepath[$i];
360 my $f = $file[$i];
361
362 $path =~ s,.*/(.*/.*),$1,;;
363 $path =~ s,[/\-],_,g;;
364 my $fileref = "abi_file_".$path;
365
366 if ($type eq "File") {
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100367 print ".. _$fileref:\n\n";
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100368 } else {
369 print "Defined on file :ref:`$f <$fileref>`\n\n";
370 }
Mauro Carvalho Chehab45f96512019-06-20 14:23:00 -0300371 }
372
Mauro Carvalho Chehaba4ea67b2020-10-30 08:40:27 +0100373 if ($type eq "File") {
374 my $bar = $w;
375 $bar =~ s/./-/g;
376 print "$w\n$bar\n\n";
377 }
378
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100379 my $desc = "";
380 $desc = $data{$what}->{description} if (defined($data{$what}->{description}));
381 $desc =~ s/\s+$/\n/;
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300382
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300383 if (!($desc =~ /^\s*$/)) {
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100384 if ($description_is_rst) {
Mauro Carvalho Chehabdaaaf582020-11-02 11:32:15 +0100385 # Remove title markups from the description
386 # Having titles inside ABI files will only work if extra
387 # care would be taken in order to strictly follow the same
388 # level order for each markup.
389 $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
390
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +0100391 # Enrich text by creating cross-references
392
Mauro Carvalho Chehabc27c2e32021-03-25 11:38:26 +0100393 my $new_desc = "";
Mauro Carvalho Chehab2ae7bb52021-03-25 11:38:27 +0100394 my $init_indent = -1;
395 my $literal_indent = -1;
396
Mauro Carvalho Chehabc27c2e32021-03-25 11:38:26 +0100397 open(my $fh, "+<", \$desc);
398 while (my $d = <$fh>) {
Mauro Carvalho Chehab2ae7bb52021-03-25 11:38:27 +0100399 my $indent = $d =~ m/^(\s+)/;
400 my $spaces = length($indent);
401 $init_indent = $indent if ($init_indent < 0);
402 if ($literal_indent >= 0) {
403 if ($spaces > $literal_indent) {
404 $new_desc .= $d;
405 next;
406 } else {
407 $literal_indent = -1;
408 }
409 } else {
410 if ($d =~ /()::$/ && !($d =~ /^\s*\.\./)) {
411 $literal_indent = $spaces;
412 }
413 }
414
Mauro Carvalho Chehabc27c2e32021-03-25 11:38:26 +0100415 $d =~ s,Documentation/(?!devicetree)(\S+)\.rst,:doc:`/$1`,g;
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +0100416
Mauro Carvalho Chehabc27c2e32021-03-25 11:38:26 +0100417 my @matches = $d =~ m,Documentation/ABI/([\w\/\-]+),g;
418 foreach my $f (@matches) {
419 my $xref = $f;
420 my $path = $f;
421 $path =~ s,.*/(.*/.*),$1,;;
422 $path =~ s,[/\-],_,g;;
423 $xref .= " <abi_file_" . $path . ">";
424 $d =~ s,\bDocumentation/ABI/$f\b,:ref:`$xref`,g;
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +0100425 }
Mauro Carvalho Chehab55e54142020-10-30 08:40:29 +0100426
Mauro Carvalho Chehabc27c2e32021-03-25 11:38:26 +0100427 # Seek for cross reference symbols like /sys/...
428 @matches = $d =~ m/$xref_match/g;
429
430 foreach my $s (@matches) {
431 next if (!($s =~ m,/,));
432 if (defined($data{$s}) && defined($data{$s}->{label})) {
433 my $xref = $s;
434
435 $xref =~ s/$symbols/\\$1/g;
436 $xref = ":ref:`$xref <" . $data{$s}->{label} . ">`";
437
438 $d =~ s,$start$s$bondary,$1$xref$2,g;
439 }
440 }
441 $new_desc .= $d;
442 }
443 close $fh;
444
445
446 print "$new_desc\n\n";
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100447 } else {
448 $desc =~ s/^\s+//;
449
450 # Remove title markups from the description, as they won't work
451 $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g;
452
453 if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
454 # put everything inside a code block
455 $desc =~ s/\n/\n /g;
456
457 print "::\n\n";
458 print " $desc\n\n";
459 } else {
460 # Escape any special chars from description
461 $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
462 print "$desc\n\n";
463 }
Mauro Carvalho Chehab4e6a6232019-06-20 14:22:57 -0300464 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300465 } else {
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300466 print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file});
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300467 }
Mauro Carvalho Chehab6619c662019-06-20 14:22:56 -0300468
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100469 if ($data{$what}->{symbols}) {
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300470 printf "Has the following ABI:\n\n";
471
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100472 foreach my $content(@{$data{$what}->{symbols}}) {
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100473 my $label = $data{$symbols{$content}->{xref}}->{label};
Mauro Carvalho Chehabd0ebaf52019-06-20 14:22:58 -0300474
475 # Escape special chars from content
476 $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
477
478 print "- :ref:`$content <$label>`\n\n";
479 }
480 }
Mauro Carvalho Chehaba16ab142020-10-30 08:40:26 +0100481
482 if (defined($data{$what}->{users})) {
483 my $users = $data{$what}->{users};
484
485 $users =~ s/\n/\n\t/g;
486 printf "Users:\n\t%s\n\n", $users if ($users ne "");
487 }
488
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300489 }
490}
491
492#
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300493# Searches for ABI symbols
494#
495sub search_symbols {
496 foreach my $what (sort keys %data) {
497 next if (!($what =~ m/($arg)/));
498
499 my $type = $data{$what}->{type};
500 next if ($type eq "File");
501
502 my $file = $data{$what}->{filepath};
503
504 my $bar = $what;
505 $bar =~ s/./-/g;
506
507 print "\n$what\n$bar\n\n";
508
Mauro Carvalho Chehab234948b2020-10-30 08:40:24 +0100509 my $kernelversion = $data{$what}->{kernelversion} if (defined($data{$what}->{kernelversion}));
510 my $contact = $data{$what}->{contact} if (defined($data{$what}->{contact}));
511 my $users = $data{$what}->{users} if (defined($data{$what}->{users}));
512 my $date = $data{$what}->{date} if (defined($data{$what}->{date}));
513 my $desc = $data{$what}->{description} if (defined($data{$what}->{description}));
514
515 $kernelversion =~ s/^\s+// if ($kernelversion);
516 $contact =~ s/^\s+// if ($contact);
517 if ($users) {
518 $users =~ s/^\s+//;
519 $users =~ s/\n//g;
520 }
521 $date =~ s/^\s+// if ($date);
522 $desc =~ s/^\s+// if ($desc);
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300523
524 printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion);
525 printf "Date:\t\t\t%s\n", $date if ($date);
526 printf "Contact:\t\t%s\n", $contact if ($contact);
527 printf "Users:\t\t\t%s\n", $users if ($users);
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100528 print "Defined on file(s):\t$file\n\n";
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300529 print "Description:\n\n$desc";
530 }
531}
532
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200533# Exclude /sys/kernel/debug and /sys/kernel/tracing from the search path
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200534sub dont_parse_special_attributes {
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200535 if (($File::Find::dir =~ m,^/sys/kernel,)) {
536 return grep {!/(debug|tracing)/ } @_;
537 }
538
539 if (($File::Find::dir =~ m,^/sys/fs,)) {
540 return grep {!/(pstore|bpf|fuse)/ } @_;
541 }
542
543 return @_
544}
545
546my %leaf;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200547my %aliases;
548my @files;
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200549
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200550my $escape_symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x29\x2b-\x2d\x3a-\x40\x7b-\xfe]) }x;
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200551sub parse_existing_sysfs {
552 my $file = $File::Find::name;
Mauro Carvalho Chehab0b87a1b2021-09-18 11:52:16 +0200553
554 # Ignore cgroup and firmware
555 return if ($file =~ m#^/sys/(fs/cgroup|firmware)/#);
556
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200557 my $mode = (lstat($file))[2];
558 my $abs_file = abs_path($file);
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200559
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200560 if (S_ISLNK($mode)) {
561 $aliases{$file} = $abs_file;
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200562 return;
563 }
564
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200565 return if (S_ISDIR($mode));
566
567 # Trivial: file is defined exactly the same way at ABI What:
568 return if (defined($data{$file}));
569 return if (defined($data{$abs_file}));
570
571 push @files, $abs_file;
572}
573
574sub check_undefined_symbols {
575 foreach my $file (sort @files) {
576
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200577 my $defined = 0;
578 my $exact = 0;
579 my $whats = "";
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200580 my $found_string;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200581
582 my $leave = $file;
583 $leave =~ s,.*/,,;
584
585 my $path = $file;
586 $path =~ s,(.*/).*,$1,;
587
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200588 if ($search_string) {
589 next if (!($file =~ m#$search_string#));
590 $found_string = 1;
591 }
592
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200593 if ($leave =~ /^\d+$/ || !defined($leaf{$leave})) {
594 $leave = "others";
595 }
596
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200597 print "--> $file\n" if ($found_string && $hint);
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200598 my $what = $leaf{$leave};
599 $whats .= " $what" if (!($whats =~ m/$what/));
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200600
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200601 foreach my $w (split / /, $what) {
602 if ($file =~ m#^$w$#) {
603 $exact = 1;
604 last;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200605 }
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200606 }
607 # Check for aliases
608 #
609 # TODO: this algorithm is O(w * n²). It can be
610 # improved in the future in order to handle it
611 # faster, by changing parse_existing_sysfs to
612 # store the sysfs inside a tree, at the expense
613 # on making the code less readable and/or using some
614 # additional perl library.
615 foreach my $a (keys %aliases) {
616 my $new = $aliases{$a};
617 my $len = length($new);
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200618
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200619 if (substr($file, 0, $len) eq $new) {
620 my $newf = $a . substr($file, $len);
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200621
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200622 print " $newf\n" if ($found_string && $hint);
623 foreach my $w (split / /, $what) {
624 if ($newf =~ m#^$w$#) {
625 $exact = 1;
626 last;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200627 }
628 }
629 }
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200630 }
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200631
632 $defined++;
633
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200634 next if ($exact);
635
636 # Ignore some sysfs nodes
637 next if ($file =~ m#/(sections|notes)/#);
638
639 # Would need to check at
640 # Documentation/admin-guide/kernel-parameters.txt, but this
641 # is not easily parseable.
642 next if ($file =~ m#/parameters/#);
643
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200644 if ($hint && $defined && $leave ne "others") {
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200645 print "$leave at $path might be one of:$whats\n" if (!$search_string || $found_string);
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200646 next;
647 }
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200648 print "$file not found.\n" if (!$search_string || $found_string);
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200649 }
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200650}
651
652sub undefined_symbols {
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200653 find({
654 wanted =>\&parse_existing_sysfs,
655 preprocess =>\&dont_parse_special_attributes,
656 no_chdir => 1
657 }, $sysfs_prefix);
658
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200659 foreach my $w (sort keys %data) {
660 foreach my $what (split /\xac /,$w) {
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200661 next if (!($what =~ m/^$sysfs_prefix/));
662
663 # Convert what into regular expressions
664
665 $what =~ s,/\.\.\./,/*/,g;
666 $what =~ s,\*,.*,g;
667
668 # Temporarily change [0-9]+ type of patterns
669 $what =~ s/\[0\-9\]\+/\xff/g;
670
671 # Temporarily change [\d+-\d+] type of patterns
672 $what =~ s/\[0\-\d+\]/\xff/g;
673 $what =~ s/\[(\d+)\]/\xf4$1\xf5/g;
674
675 # Temporarily change [0-9] type of patterns
676 $what =~ s/\[(\d)\-(\d)\]/\xf4$1-$2\xf5/g;
677
678 # Handle multiple option patterns
679 $what =~ s/[\{\<\[]([\w_]+)(?:[,|]+([\w_]+)){1,}[\}\>\]]/($1|$2)/g;
680
681 # Handle wildcards
682 $what =~ s/\<[^\>]+\>/.*/g;
683 $what =~ s/\{[^\}]+\}/.*/g;
684 $what =~ s/\[[^\]]+\]/.*/g;
685
686 $what =~ s/[XYZ]/.*/g;
687
688 # Recover [0-9] type of patterns
689 $what =~ s/\xf4/[/g;
690 $what =~ s/\xf5/]/g;
691
692 # Remove duplicated spaces
693 $what =~ s/\s+/ /g;
694
695 # Special case: this ABI has a parenthesis on it
696 $what =~ s/sqrt\(x^2\+y^2\+z^2\)/sqrt\(x^2\+y^2\+z^2\)/;
697
698 # Special case: drop comparition as in:
699 # What: foo = <something>
700 # (this happens on a few IIO definitions)
701 $what =~ s,\s*\=.*$,,;
702
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200703 my $leave = $what;
704 $leave =~ s,.*/,,;
705
Mauro Carvalho Chehab50116ae2021-09-18 11:52:15 +0200706 # $leave is used to improve search performance at
707 # check_undefined_symbols, as the algorithm there can seek
708 # for a small number of "what". It also allows giving a
709 # hint about a leave with the same name somewhere else.
710 # However, there are a few occurences where the leave is
711 # either a wildcard or a number. Just group such cases
712 # altogether.
713 if ($leave =~ m/^\.\*/ || $leave eq "" || $leave =~ /^\d+$/) {
714 $leave = "others" ;
715 }
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200716
717 # Escape all other symbols
718 $what =~ s/$escape_symbols/\\$1/g;
719 $what =~ s/\\\\/\\/g;
720 $what =~ s/\\([\[\]\(\)\|])/$1/g;
721 $what =~ s/(\d+)\\(-\d+)/$1$2/g;
722
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200723 $what =~ s/\xff/\\d+/g;
724
725
726 # Special case: IIO ABI which a parenthesis.
727 $what =~ s/sqrt(.*)/sqrt\(.*\)/;
728
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200729 $leave =~ s/[\(\)]//g;
730
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200731 my $added = 0;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200732 foreach my $l (split /\|/, $leave) {
733 if (defined($leaf{$l})) {
734 next if ($leaf{$l} =~ m/$what/);
735 $leaf{$l} .= " " . $what;
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200736 $added = 1;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200737 } else {
738 $leaf{$l} = $what;
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200739 $added = 1;
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200740 }
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200741 }
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200742 if ($search_string && $added) {
743 print "What: $what\n" if ($what =~ m#$search_string#);
744 }
745
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200746 }
747 }
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200748 check_undefined_symbols;
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200749}
750
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100751# Ensure that the prefix will always end with a slash
752# While this is not needed for find, it makes the patch nicer
753# with --enable-lineno
754$prefix =~ s,/?$,/,;
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300755
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200756if ($cmd eq "undefined" || $cmd eq "search") {
757 $show_warnings = 0;
758}
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300759#
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300760# Parses all ABI files located at $prefix dir
761#
762find({wanted =>\&parse_abi, no_chdir => 1}, $prefix);
763
764print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
765
766#
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300767# Handles the command
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300768#
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200769if ($cmd eq "undefined") {
770 undefined_symbols;
771} elsif ($cmd eq "search") {
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300772 search_symbols;
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100773} else {
774 if ($cmd eq "rest") {
775 output_rest;
776 }
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300777
Mauro Carvalho Chehabc7ba3332020-10-30 08:40:25 +0100778 # Warn about duplicated ABI entries
779 foreach my $what(sort keys %symbols) {
780 my @files = @{$symbols{$what}->{file}};
781
782 next if (scalar(@files) == 1);
783
784 printf STDERR "Warning: $what is defined %d times: @files\n",
785 scalar(@files);
786 }
787}
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300788
789__END__
790
791=head1 NAME
792
793abi_book.pl - parse the Linux ABI files and produce a ReST book.
794
795=head1 SYNOPSIS
796
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100797B<abi_book.pl> [--debug] [--enable-lineno] [--man] [--help]
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200798 [--(no-)rst-source] [--dir=<dir>] [--show-hints]
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200799 [--search-string <regex>]
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200800 <COMAND> [<ARGUMENT>]
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300801
802Where <COMMAND> can be:
803
804=over 8
805
806B<search> [SEARCH_REGEX] - search for [SEARCH_REGEX] inside ABI
807
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300808B<rest> - output the ABI in ReST markup language
809
810B<validate> - validate the ABI contents
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300811
Mauro Carvalho Chehabf090db42021-09-18 11:52:12 +0200812B<undefined> - existing symbols at the system that aren't
813 defined at Documentation/ABI
814
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300815=back
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300816
817=head1 OPTIONS
818
819=over 8
820
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300821=item B<--dir>
822
823Changes the location of the ABI search. By default, it uses
824the Documentation/ABI directory.
825
Mauro Carvalho Chehab11ce90a2020-10-30 08:40:20 +0100826=item B<--rst-source> and B<--no-rst-source>
827
828The input file may be using ReST syntax or not. Those two options allow
829selecting between a rst-compliant source ABI (--rst-source), or a
830plain text that may be violating ReST spec, so it requres some escaping
831logic (--no-rst-source).
832
Mauro Carvalho Chehab61439c42020-10-30 08:40:22 +0100833=item B<--enable-lineno>
834
835Enable output of #define LINENO lines.
836
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300837=item B<--debug>
838
839Put the script in verbose mode, useful for debugging. Can be called multiple
840times, to increase verbosity.
841
Mauro Carvalho Chehabab02c512021-09-18 11:52:13 +0200842=item B<--show-hints>
843
844Show hints about possible definitions for the missing ABI symbols.
845Used only when B<undefined>.
846
Mauro Carvalho Chehab14c94252021-09-18 11:52:14 +0200847=item B<--search-string> [regex string]
848
849Show only occurences that match a search string.
850Used only when B<undefined>.
851
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300852=item B<--help>
853
854Prints a brief help message and exits.
855
856=item B<--man>
857
858Prints the manual page and exits.
859
860=back
861
862=head1 DESCRIPTION
863
Mauro Carvalho Chehab33e3e992019-06-20 14:22:59 -0300864Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI),
865allowing to search for ABI symbols or to produce a ReST book containing
866the Linux ABI documentation.
867
868=head1 EXAMPLES
869
870Search for all stable symbols with the word "usb":
871
872=over 8
873
874$ scripts/get_abi.pl search usb --dir Documentation/ABI/stable
875
876=back
877
878Search for all symbols that match the regex expression "usb.*cap":
879
880=over 8
881
882$ scripts/get_abi.pl search usb.*cap
883
884=back
885
886Output all obsoleted symbols in ReST format
887
888=over 8
889
890$ scripts/get_abi.pl rest --dir Documentation/ABI/obsolete
891
892=back
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300893
894=head1 BUGS
895
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300896Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300897
898=head1 COPYRIGHT
899
Mauro Carvalho Chehab7ce7b892019-06-20 14:23:04 -0300900Copyright (c) 2016-2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
Mauro Carvalho Chehabbbc249f2019-06-20 14:22:55 -0300901
902License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
903
904This is free software: you are free to change and redistribute it.
905There is NO WARRANTY, to the extent permitted by law.
906
907=cut