Blame view

scripts/get_abi.pl 15.1 KB
c25ce589d   Finn Behrens   tweewide: Fix mos...
1
  #!/usr/bin/env perl
ecb351f1c   Mauro Carvalho Chehab   doc: ABI scripts:...
2
  # SPDX-License-Identifier: GPL-2.0
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
3
4
  
  use strict;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
5
  use warnings;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
6
  use utf8;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
7
8
9
10
  use Pod::Usage;
  use Getopt::Long;
  use File::Find;
  use Fcntl ':mode';
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
11
12
13
14
  my $help = 0;
  my $man = 0;
  my $debug = 0;
  my $enable_lineno = 0;
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
15
  my $prefix="Documentation/ABI";
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
16

11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
17
18
19
  #
  # If true, assumes that the description is formatted with ReST
  #
2fcce37a3   Mauro Carvalho Chehab   scripts: get_abi....
20
  my $description_is_rst = 1;
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
21

bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
22
23
  GetOptions(
  	"debug|d+" => \$debug,
61439c4ad   Mauro Carvalho Chehab   scripts: get_abi....
24
  	"enable-lineno" => \$enable_lineno,
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
25
  	"rst-source!" => \$description_is_rst,
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
26
  	"dir=s" => \$prefix,
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
27
28
29
30
31
32
  	'help|?' => \$help,
  	man => \$man
  ) or pod2usage(2);
  
  pod2usage(1) if $help;
  pod2usage(-exitstatus => 0, -verbose => 2) if $man;
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
33
  pod2usage(2) if (scalar @ARGV < 1 || @ARGV > 2);
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
34

33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
35
  my ($cmd, $arg) = @ARGV;
7ce7b89bf   Mauro Carvalho Chehab   scripts/get_abi.p...
36
  pod2usage(2) if ($cmd ne "search" && $cmd ne "rest" && $cmd ne "validate");
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
37
  pod2usage(2) if ($cmd eq "search" && !$arg);
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
38
39
40
41
  
  require Data::Dumper if ($debug);
  
  my %data;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
42
  my %symbols;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
43
44
45
46
47
48
  
  #
  # Displays an error message, printing file name and line
  #
  sub parse_error($$$$) {
  	my ($file, $ln, $msg, $data) = @_;
75442fb0c   Mauro Carvalho Chehab   docs: Kconfig/Mak...
49
50
51
52
53
54
55
56
57
58
59
60
61
  	$data =~ s/\s+$/
  /;
  
  	print STDERR "Warning: file $file#$ln:
  \t$msg";
  
  	if ($data ne "") {
  		print STDERR ". Line
  \t\t$data";
  	} else {
  	    print STDERR "
  ";
  	}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  }
  
  #
  # Parse an ABI file, storing its contents at %data
  #
  sub parse_abi {
  	my $file = $File::Find::name;
  
  	my $mode = (stat($file))[2];
  	return if ($mode & S_IFDIR);
  	return if ($file =~ m,/README,);
  
  	my $name = $file;
  	$name =~ s,.*/,,;
a4ea67bc6   Mauro Carvalho Chehab   scripts: get_abi....
76
77
78
79
  	my $fn = $file;
  	$fn =~ s,Documentation/ABI/,,;
  
  	my $nametag = "File $fn";
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
80
81
82
  	$data{$nametag}->{what} = "File $name";
  	$data{$nametag}->{type} = "File";
  	$data{$nametag}->{file} = $name;
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
83
  	$data{$nametag}->{filepath} = $file;
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
84
  	$data{$nametag}->{is_file} = 1;
61439c4ad   Mauro Carvalho Chehab   scripts: get_abi....
85
  	$data{$nametag}->{line_no} = 1;
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
86

bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
87
88
89
90
91
  	my $type = $file;
  	$type =~ s,.*/(.*)/.*,$1,;
  
  	my $what;
  	my $new_what;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
92
  	my $tag = "";
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
93
  	my $ln;
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
94
  	my $xrefs;
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
95
  	my $space;
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
96
  	my @labels;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
97
  	my $label = "";
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
98
99
100
101
102
103
  
  	print STDERR "Opening $file
  " if ($debug > 1);
  	open IN, $file;
  	while(<IN>) {
  		$ln++;
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
104
  		if (m/^(\S+)(:\s*)(.*)/i) {
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
105
  			my $new_tag = lc($1);
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
106
107
  			my $sep = $2;
  			my $content = $3;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
108

7ce7b89bf   Mauro Carvalho Chehab   scripts/get_abi.p...
109
  			if (!($new_tag =~ m/(what|where|date|kernelversion|contact|description|users)/)) {
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
110
  				if ($tag eq "description") {
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
111
112
113
  					# New "tag" is actually part of
  					# description. Don't consider it a tag
  					$new_tag = "";
7d7ea8d24   Mauro Carvalho Chehab   scripts/get_abi.p...
114
  				} elsif ($tag ne "") {
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
115
116
117
  					parse_error($file, $ln, "tag '$tag' is invalid", $_);
  				}
  			}
2c0700e7a   Mauro Carvalho Chehab   scripts/get_abi.p...
118
119
  			# Invalid, but it is a common mistake
  			if ($new_tag eq "where") {
75442fb0c   Mauro Carvalho Chehab   docs: Kconfig/Mak...
120
  				parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", "");
2c0700e7a   Mauro Carvalho Chehab   scripts/get_abi.p...
121
122
  				$new_tag = "what";
  			}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
123
  			if ($new_tag =~ m/what/) {
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
124
  				$space = "";
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
125
  				$content =~ s/[,.;]$//;
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
126
  				push @{$symbols{$content}->{file}}, " $file:" . ($ln - 1);
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
127
128
129
  				if ($tag =~ m/what/) {
  					$what .= ", " . $content;
  				} else {
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
130
131
132
133
  					if ($what) {
  						parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
  
  						foreach my $w(split /, /, $what) {
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
134
  							$symbols{$w}->{xref} = $what;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
135
136
  						};
  					}
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
137

bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
138
  					$what = $content;
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
139
  					$label = $content;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
140
141
  					$new_what = 1;
  				}
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
142
  				push @labels, [($content, $label)];
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
143
  				$tag = $new_tag;
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
144

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
145
  				push @{$data{$nametag}->{symbols}}, $content if ($data{$nametag}->{what});
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
146
147
  				next;
  			}
7d7ea8d24   Mauro Carvalho Chehab   scripts/get_abi.p...
148
  			if ($tag ne "" && $new_tag) {
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
149
  				$tag = $new_tag;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
150

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
151
  				if ($new_what) {
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
152
  					@{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what});
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
153
154
  					@labels = ();
  					$label = "";
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
155
  					$new_what = 0;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
156

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
157
  					$data{$what}->{type} = $type;
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
158
159
160
161
162
163
164
165
166
  					if (!defined($data{$what}->{file})) {
  						$data{$what}->{file} = $name;
  						$data{$what}->{filepath} = $file;
  					} else {
  						if ($name ne $data{$what}->{file}) {
  							$data{$what}->{file} .= " " . $name;
  							$data{$what}->{filepath} .= " " . $file;
  						}
  					}
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
167
168
  					print STDERR "\twhat: $what
  " if ($debug > 1);
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
169
170
171
  					$data{$what}->{line_no} = $ln;
  				} else {
  					$data{$what}->{line_no} = $ln if (!defined($data{$what}->{line_no}));
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
172
  				}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
173

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
174
175
176
177
  				if (!$what) {
  					parse_error($file, $ln, "'What:' should come first:", $_);
  					next;
  				}
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
178
179
  				if ($new_tag eq "description") {
  					$sep =~ s,:, ,;
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
180
  					$content = ' ' x length($new_tag) . $sep . $content;
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
181
182
183
  					while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
  					if ($content =~ m/^(\s*)(\S.*)$/) {
  						# Preserve initial spaces for the first line
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
184
  						$space = $1;
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
185
186
187
188
189
  						$content = "$2
  ";
  						$data{$what}->{$tag} .= $content;
  					} else {
  						undef($space);
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
190
  					}
e9bca8918   Mauro Carvalho Chehab   scripts: get_abi....
191

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
192
193
194
  				} else {
  					$data{$what}->{$tag} = $content;
  				}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
195
196
  				next;
  			}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
197
  		}
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
198
  		# Store any contents before tags at the database
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
199
200
  		if (!$tag && $data{$nametag}->{what}) {
  			$data{$nametag}->{description} .= $_;
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
201
202
  			next;
  		}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
203

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
204
  		if ($tag eq "description") {
e9bca8918   Mauro Carvalho Chehab   scripts: get_abi....
205
206
  			my $content = $_;
  			while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
207
208
209
210
211
212
213
214
  			if (m/^\s*
  /) {
  				$data{$what}->{$tag} .= "
  ";
  				next;
  			}
  
  			if (!defined($space)) {
e9bca8918   Mauro Carvalho Chehab   scripts: get_abi....
215
  				# Preserve initial spaces for the first line
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
216
  				if ($content =~ m/^(\s*)(\S.*)$/) {
e9bca8918   Mauro Carvalho Chehab   scripts: get_abi....
217
  					$space = $1;
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
218
219
  					$content = "$2
  ";
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
220
221
  				}
  			} else {
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
222
  				$space = "" if (!($content =~ s/^($space)//));
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
223
  			}
f82a8a74e   Mauro Carvalho Chehab   scripts: get_abi....
224
  			$data{$what}->{$tag} .= $content;
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
225
226
  			next;
  		}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
227
228
229
230
231
232
233
234
235
  		if (m/^\s*(.*)/) {
  			$data{$what}->{$tag} .= "
  $1";
  			$data{$what}->{$tag} =~ s/
  +$//;
  			next;
  		}
  
  		# Everything else is error
75442fb0c   Mauro Carvalho Chehab   docs: Kconfig/Mak...
236
  		parse_error($file, $ln, "Unexpected content", $_);
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
237
  	}
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
238
239
240
241
242
243
  	$data{$nametag}->{description} =~ s/^
  +// if ($data{$nametag}->{description});
  	if ($what) {
  		parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description});
  
  		foreach my $w(split /, /,$what) {
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
244
  			$symbols{$w}->{xref} = $what;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
245
246
  		};
  	}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
247
248
  	close IN;
  }
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
249
250
  sub create_labels {
  	my %labels;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
251

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
252
253
  	foreach my $what (keys %data) {
  		next if ($data{$what}->{file} eq "File");
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
254

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
255
  		foreach my $p (@{$data{$what}->{label_list}}) {
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
256
257
258
259
260
261
262
263
  			my ($content, $label) = @{$p};
  			$label = "abi_" . $label . " ";
  			$label =~ tr/A-Z/a-z/;
  
  			# Convert special chars to "_"
  			$label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g;
  			$label =~ s,_+,_,g;
  			$label =~ s,_$,,;
2e7ce0559   Mauro Carvalho Chehab   scripts/get_abi.p...
264
265
266
267
268
269
  			# Avoid duplicated labels
  			while (defined($labels{$label})) {
  			    my @chars = ("A".."Z", "a".."z");
  			    $label .= $chars[rand @chars];
  			}
  			$labels{$label} = 1;
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
270
  			$data{$what}->{label} = $label;
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
271
272
273
  
  			# only one label is enough
  			last;
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
274
  		}
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
275
276
277
278
279
280
  	}
  }
  
  #
  # Outputs the book on ReST format
  #
50ebf8f49   Mauro Carvalho Chehab   get_abi.pl: fix x...
281
282
283
284
  # \b doesn't work well with paths. So, we need to define something else:
  # Boundaries are punct characters, spaces and end-of-line
  my $start = qr {(^|\s|\() }x;
  my $bondary = qr { ([,.:;\)\s]|\z) }x;
87ec9ea1f   Mauro Carvalho Chehab   scripts: get_abi....
285
  my $xref_match = qr { $start(\/(sys|config|proc|dev|kvd)\/[^,.:;\)\s]+)$bondary }x;
b0f9580a8   Mauro Carvalho Chehab   scripts: get_abi....
286
  my $symbols = qr { ([\x01-\x08\x0e-\x1f\x21-\x2f\x3a-\x40\x7b-\xff]) }x;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
287

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
288
289
  sub output_rest {
  	create_labels();
9d4fdda33   Mauro Carvalho Chehab   scripts: get_api....
290
  	my $part = "";
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
291
292
293
294
295
  	foreach my $what (sort {
  				($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") ||
  				$a cmp $b
  			       } keys %data) {
  		my $type = $data{$what}->{type};
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
296
297
298
  
  		my @file = split / /, $data{$what}->{file};
  		my @filepath = split / /, $data{$what}->{filepath};
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
299
300
301
302
303
  
  		if ($enable_lineno) {
  			printf "#define LINENO %s%s#%s
  
  ",
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
304
  			       $prefix, $file[0],
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
305
306
  			       $data{$what}->{line_no};
  		}
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
307

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
308
  		my $w = $what;
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
309

c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
310
  		if ($type ne "File") {
9d4fdda33   Mauro Carvalho Chehab   scripts: get_api....
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  			my $cur_part = $what;
  			if ($what =~ '/') {
  				if ($what =~ m#^(\/?(?:[\w\-]+\/?){1,2})#) {
  					$cur_part = "Symbols under $1";
  					$cur_part =~ s,/$,,;
  				}
  			}
  
  			if ($cur_part ne "" && $part ne $cur_part) {
  			    $part = $cur_part;
  			    my $bar = $part;
  			    $bar =~ s/./-/g;
  			    print "$part
  $bar
  
  ";
  			}
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
328
329
330
  			printf ".. _%s:
  
  ", $data{$what}->{label};
45f965179   Mauro Carvalho Chehab   scripts/get_abi.p...
331

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
332
  			my @names = split /, /,$w;
45f965179   Mauro Carvalho Chehab   scripts/get_abi.p...
333
334
335
  			my $len = 0;
  
  			foreach my $name (@names) {
b0f9580a8   Mauro Carvalho Chehab   scripts: get_abi....
336
  				$name =~ s/$symbols/\\$1/g;
c01d62d3f   Mauro Carvalho Chehab   scripts: get_abi....
337
  				$name = "**$name**";
45f965179   Mauro Carvalho Chehab   scripts/get_abi.p...
338
339
  				$len = length($name) if (length($name) > $len);
  			}
45f965179   Mauro Carvalho Chehab   scripts/get_abi.p...
340
341
342
343
344
345
346
347
  			print "+-" . "-" x $len . "-+
  ";
  			foreach my $name (@names) {
  				printf "| %s", $name . " " x ($len - length($name)) . " |
  ";
  				print "+-" . "-" x $len . "-+
  ";
  			}
45f965179   Mauro Carvalho Chehab   scripts/get_abi.p...
348

c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
349
350
351
352
353
354
355
356
357
358
359
360
361
  			print "
  ";
  		}
  
  		for (my $i = 0; $i < scalar(@filepath); $i++) {
  			my $path = $filepath[$i];
  			my $f = $file[$i];
  
  			$path =~ s,.*/(.*/.*),$1,;;
  			$path =~ s,[/\-],_,g;;
  			my $fileref = "abi_file_".$path;
  
  			if ($type eq "File") {
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
362
363
364
  				print ".. _$fileref:
  
  ";
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
365
366
367
368
369
  			} else {
  				print "Defined on file :ref:`$f <$fileref>`
  
  ";
  			}
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
370
  		}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
371

a4ea67bc6   Mauro Carvalho Chehab   scripts: get_abi....
372
373
374
375
376
377
378
379
  		if ($type eq "File") {
  			my $bar = $w;
  			$bar =~ s/./-/g;
  			print "$w
  $bar
  
  ";
  		}
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
380
381
382
383
  		my $desc = "";
  		$desc = $data{$what}->{description} if (defined($data{$what}->{description}));
  		$desc =~ s/\s+$/
  /;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
384

4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
385
  		if (!($desc =~ /^\s*$/)) {
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
386
  			if ($description_is_rst) {
daaaf58a2   Mauro Carvalho Chehab   scripts: get_abi....
387
388
389
390
391
392
393
394
395
  				# Remove title markups from the description
  				# Having titles inside ABI files will only work if extra
  				# care would be taken in order to strictly follow the same
  				# level order for each markup.
  				$desc =~ s/
  [\-\*\=\^\~]+
  /
  
  /g;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
396
  				# Enrich text by creating cross-references
c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
397
  				my $new_desc = "";
2ae7bb570   Mauro Carvalho Chehab   scripts: get_abi:...
398
399
  				my $init_indent = -1;
  				my $literal_indent = -1;
c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
400
401
  				open(my $fh, "+<", \$desc);
  				while (my $d = <$fh>) {
2ae7bb570   Mauro Carvalho Chehab   scripts: get_abi:...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
  					my $indent = $d =~ m/^(\s+)/;
  					my $spaces = length($indent);
  					$init_indent = $indent if ($init_indent < 0);
  					if ($literal_indent >= 0) {
  						if ($spaces > $literal_indent) {
  							$new_desc .= $d;
  							next;
  						} else {
  							$literal_indent = -1;
  						}
  					} else {
  						if ($d =~ /()::$/ && !($d =~ /^\s*\.\./)) {
  							$literal_indent = $spaces;
  						}
  					}
c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
417
418
419
420
421
422
423
424
425
426
427
  					$d =~ s,Documentation/(?!devicetree)(\S+)\.rst,:doc:`/$1`,g;
  
  					my @matches = $d =~ m,Documentation/ABI/([\w\/\-]+),g;
  					foreach my $f (@matches) {
  						my $xref = $f;
  						my $path = $f;
  						$path =~ s,.*/(.*/.*),$1,;;
  						$path =~ s,[/\-],_,g;;
  						$xref .= " <abi_file_" . $path . ">";
  						$d =~ s,\bDocumentation/ABI/$f\b,:ref:`$xref`,g;
  					}
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
428

c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
429
430
  					# Seek for cross reference symbols like /sys/...
  					@matches = $d =~ m/$xref_match/g;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
431

c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
432
433
434
435
  					foreach my $s (@matches) {
  						next if (!($s =~ m,/,));
  						if (defined($data{$s}) && defined($data{$s}->{label})) {
  							my $xref = $s;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
436

c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
437
438
  							$xref =~ s/$symbols/\\$1/g;
  							$xref = ":ref:`$xref <" . $data{$s}->{label} . ">`";
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
439

c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
440
441
  							$d =~ s,$start$s$bondary,$1$xref$2,g;
  						}
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
442
  					}
c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
443
  					$new_desc .= $d;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
444
  				}
c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
445
  				close $fh;
55e5414f2   Mauro Carvalho Chehab   scripts: get_abi....
446

c27c2e344   Mauro Carvalho Chehab   scripts: get_abi....
447
448
449
  				print "$new_desc
  
  ";
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
450
  			} else {
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
451
  				$desc =~ s/^\s+//;
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
452

11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
  				# Remove title markups from the description, as they won't work
  				$desc =~ s/
  [\-\*\=\^\~]+
  /
  
  /g;
  
  				if ($desc =~ m/\:
  / || $desc =~ m/
  [\t ]+/  || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) {
  					# put everything inside a code block
  					$desc =~ s/
  /
   /g;
  
  					print "::
  
  ";
  					print " $desc
  
  ";
  				} else {
  					# Escape any special chars from description
  					$desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g;
  					print "$desc
  
  ";
  				}
4e6a6234d   Mauro Carvalho Chehab   scripts/get_abi.p...
481
  			}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
482
  		} else {
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
483
484
485
  			print "DESCRIPTION MISSING for $what
  
  " if (!$data{$what}->{is_file});
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
486
  		}
6619c6617   Mauro Carvalho Chehab   scripts/get_abi.p...
487

234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
488
  		if ($data{$what}->{symbols}) {
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
489
490
491
  			printf "Has the following ABI:
  
  ";
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
492
  			foreach my $content(@{$data{$what}->{symbols}}) {
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
493
  				my $label = $data{$symbols{$content}->{xref}}->{label};
d0ebaf51d   Mauro Carvalho Chehab   scripts/get_abi.p...
494
495
496
497
498
499
500
501
502
  
  				# Escape special chars from content
  				$content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g;
  
  				print "- :ref:`$content <$label>`
  
  ";
  			}
  		}
a16ab14eb   Mauro Carvalho Chehab   scripts: get_abi....
503
504
505
506
507
508
509
510
511
512
513
514
  
  		if (defined($data{$what}->{users})) {
  			my $users = $data{$what}->{users};
  
  			$users =~ s/
  /
  \t/g;
  			printf "Users:
  \t%s
  
  ", $users if ($users ne "");
  		}
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
515
516
517
518
  	}
  }
  
  #
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
  # Searches for ABI symbols
  #
  sub search_symbols {
  	foreach my $what (sort keys %data) {
  		next if (!($what =~ m/($arg)/));
  
  		my $type = $data{$what}->{type};
  		next if ($type eq "File");
  
  		my $file = $data{$what}->{filepath};
  
  		my $bar = $what;
  		$bar =~ s/./-/g;
  
  		print "
  $what
  $bar
  
  ";
234948bf3   Mauro Carvalho Chehab   scripts: get_abi....
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  		my $kernelversion = $data{$what}->{kernelversion} if (defined($data{$what}->{kernelversion}));
  		my $contact = $data{$what}->{contact} if (defined($data{$what}->{contact}));
  		my $users = $data{$what}->{users} if (defined($data{$what}->{users}));
  		my $date = $data{$what}->{date} if (defined($data{$what}->{date}));
  		my $desc = $data{$what}->{description} if (defined($data{$what}->{description}));
  
  		$kernelversion =~ s/^\s+// if ($kernelversion);
  		$contact =~ s/^\s+// if ($contact);
  		if ($users) {
  			$users =~ s/^\s+//;
  			$users =~ s/
  //g;
  		}
  		$date =~ s/^\s+// if ($date);
  		$desc =~ s/^\s+// if ($desc);
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
553
554
555
556
557
558
559
560
561
  
  		printf "Kernel version:\t\t%s
  ", $kernelversion if ($kernelversion);
  		printf "Date:\t\t\t%s
  ", $date if ($date);
  		printf "Contact:\t\t%s
  ", $contact if ($contact);
  		printf "Users:\t\t\t%s
  ", $users if ($users);
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
562
563
564
  		print "Defined on file(s):\t$file
  
  ";
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
565
566
567
568
569
  		print "Description:
  
  $desc";
  	}
  }
61439c4ad   Mauro Carvalho Chehab   scripts: get_abi....
570
571
572
573
  # Ensure that the prefix will always end with a slash
  # While this is not needed for find, it makes the patch nicer
  # with --enable-lineno
  $prefix =~ s,/?$,/,;
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
574
575
  
  #
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
576
577
578
579
580
581
582
  # Parses all ABI files located at $prefix dir
  #
  find({wanted =>\&parse_abi, no_chdir => 1}, $prefix);
  
  print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug);
  
  #
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
583
  # Handles the command
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
584
  #
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
585
  if ($cmd eq "search") {
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
586
  	search_symbols;
c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
587
588
589
590
591
592
593
594
595
596
  } else {
  	if ($cmd eq "rest") {
  		output_rest;
  	}
  
  	# Warn about duplicated ABI entries
  	foreach my $what(sort keys %symbols) {
  		my @files = @{$symbols{$what}->{file}};
  
  		next if (scalar(@files) == 1);
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
597

c7ba33342   Mauro Carvalho Chehab   scripts: get_abi....
598
599
600
601
602
  		printf STDERR "Warning: $what is defined %d times: @files
  ",
  		    scalar(@files);
  	}
  }
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
603
604
605
606
607
608
609
610
  
  __END__
  
  =head1 NAME
  
  abi_book.pl - parse the Linux ABI files and produce a ReST book.
  
  =head1 SYNOPSIS
61439c4ad   Mauro Carvalho Chehab   scripts: get_abi....
611
612
  B<abi_book.pl> [--debug] [--enable-lineno] [--man] [--help]
  	       [--(no-)rst-source] [--dir=<dir>] <COMAND> [<ARGUMENT>]
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
613
614
615
616
617
618
  
  Where <COMMAND> can be:
  
  =over 8
  
  B<search> [SEARCH_REGEX] - search for [SEARCH_REGEX] inside ABI
7ce7b89bf   Mauro Carvalho Chehab   scripts/get_abi.p...
619
620
621
  B<rest>                  - output the ABI in ReST markup language
  
  B<validate>              - validate the ABI contents
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
622
623
  
  =back
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
624
625
626
627
  
  =head1 OPTIONS
  
  =over 8
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
628
629
630
631
  =item B<--dir>
  
  Changes the location of the ABI search. By default, it uses
  the Documentation/ABI directory.
11ce90a45   Mauro Carvalho Chehab   scripts: get_abi....
632
633
634
635
636
637
  =item B<--rst-source> and B<--no-rst-source>
  
  The input file may be using ReST syntax or not. Those two options allow
  selecting between a rst-compliant source ABI (--rst-source), or a
  plain text that may be violating ReST spec, so it requres some escaping
  logic (--no-rst-source).
61439c4ad   Mauro Carvalho Chehab   scripts: get_abi....
638
639
640
  =item B<--enable-lineno>
  
  Enable output of #define LINENO lines.
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  =item B<--debug>
  
  Put the script in verbose mode, useful for debugging. Can be called multiple
  times, to increase verbosity.
  
  =item B<--help>
  
  Prints a brief help message and exits.
  
  =item B<--man>
  
  Prints the manual page and exits.
  
  =back
  
  =head1 DESCRIPTION
33e3e9913   Mauro Carvalho Chehab   scripts/get_abi.p...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
  Parse the Linux ABI files from ABI DIR (usually located at Documentation/ABI),
  allowing to search for ABI symbols or to produce a ReST book containing
  the Linux ABI documentation.
  
  =head1 EXAMPLES
  
  Search for all stable symbols with the word "usb":
  
  =over 8
  
  $ scripts/get_abi.pl search usb --dir Documentation/ABI/stable
  
  =back
  
  Search for all symbols that match the regex expression "usb.*cap":
  
  =over 8
  
  $ scripts/get_abi.pl search usb.*cap
  
  =back
  
  Output all obsoleted symbols in ReST format
  
  =over 8
  
  $ scripts/get_abi.pl rest --dir Documentation/ABI/obsolete
  
  =back
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
686
687
  
  =head1 BUGS
7ce7b89bf   Mauro Carvalho Chehab   scripts/get_abi.p...
688
  Report bugs to Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
689
690
  
  =head1 COPYRIGHT
7ce7b89bf   Mauro Carvalho Chehab   scripts/get_abi.p...
691
  Copyright (c) 2016-2019 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
bbc249f2b   Mauro Carvalho Chehab   scripts: add an s...
692
693
694
695
696
697
698
  
  License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
  
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.
  
  =cut