xref: /OK3568_Linux_fs/kernel/Documentation/sphinx/parse-headers.pl (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env perl
2*4882a593Smuzhiyunuse strict;
3*4882a593Smuzhiyunuse Text::Tabs;
4*4882a593Smuzhiyunuse Getopt::Long;
5*4882a593Smuzhiyunuse Pod::Usage;
6*4882a593Smuzhiyun
7*4882a593Smuzhiyunmy $debug;
8*4882a593Smuzhiyunmy $help;
9*4882a593Smuzhiyunmy $man;
10*4882a593Smuzhiyun
11*4882a593SmuzhiyunGetOptions(
12*4882a593Smuzhiyun	"debug" => \$debug,
13*4882a593Smuzhiyun	'usage|?' => \$help,
14*4882a593Smuzhiyun	'help' => \$man
15*4882a593Smuzhiyun) or pod2usage(2);
16*4882a593Smuzhiyun
17*4882a593Smuzhiyunpod2usage(1) if $help;
18*4882a593Smuzhiyunpod2usage(-exitstatus => 0, -verbose => 2) if $man;
19*4882a593Smuzhiyunpod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyunmy ($file_in, $file_out, $file_exceptions) = @ARGV;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunmy $data;
24*4882a593Smuzhiyunmy %ioctls;
25*4882a593Smuzhiyunmy %defines;
26*4882a593Smuzhiyunmy %typedefs;
27*4882a593Smuzhiyunmy %enums;
28*4882a593Smuzhiyunmy %enum_symbols;
29*4882a593Smuzhiyunmy %structs;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyunrequire Data::Dumper if ($debug);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun#
34*4882a593Smuzhiyun# read the file and get identifiers
35*4882a593Smuzhiyun#
36*4882a593Smuzhiyun
37*4882a593Smuzhiyunmy $is_enum = 0;
38*4882a593Smuzhiyunmy $is_comment = 0;
39*4882a593Smuzhiyunopen IN, $file_in or die "Can't open $file_in";
40*4882a593Smuzhiyunwhile (<IN>) {
41*4882a593Smuzhiyun	$data .= $_;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun	my $ln = $_;
44*4882a593Smuzhiyun	if (!$is_comment) {
45*4882a593Smuzhiyun		$ln =~ s,/\*.*(\*/),,g;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun		$is_comment = 1 if ($ln =~ s,/\*.*,,);
48*4882a593Smuzhiyun	} else {
49*4882a593Smuzhiyun		if ($ln =~ s,^(.*\*/),,) {
50*4882a593Smuzhiyun			$is_comment = 0;
51*4882a593Smuzhiyun		} else {
52*4882a593Smuzhiyun			next;
53*4882a593Smuzhiyun		}
54*4882a593Smuzhiyun	}
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun	if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) {
57*4882a593Smuzhiyun		my $s = $1;
58*4882a593Smuzhiyun		my $n = $1;
59*4882a593Smuzhiyun		$n =~ tr/A-Z/a-z/;
60*4882a593Smuzhiyun		$n =~ tr/_/-/;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun		$enum_symbols{$s} =  "\\ :ref:`$s <$n>`\\ ";
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun		$is_enum = 0 if ($is_enum && m/\}/);
65*4882a593Smuzhiyun		next;
66*4882a593Smuzhiyun	}
67*4882a593Smuzhiyun	$is_enum = 0 if ($is_enum && m/\}/);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun	if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) {
70*4882a593Smuzhiyun		my $s = $1;
71*4882a593Smuzhiyun		my $n = $1;
72*4882a593Smuzhiyun		$n =~ tr/A-Z/a-z/;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun		$ioctls{$s} = "\\ :ref:`$s <$n>`\\ ";
75*4882a593Smuzhiyun		next;
76*4882a593Smuzhiyun	}
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun	if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) {
79*4882a593Smuzhiyun		my $s = $1;
80*4882a593Smuzhiyun		my $n = $1;
81*4882a593Smuzhiyun		$n =~ tr/A-Z/a-z/;
82*4882a593Smuzhiyun		$n =~ tr/_/-/;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun		$defines{$s} = "\\ :ref:`$s <$n>`\\ ";
85*4882a593Smuzhiyun		next;
86*4882a593Smuzhiyun	}
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun	if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) {
89*4882a593Smuzhiyun		my $s = $2;
90*4882a593Smuzhiyun		my $n = $3;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun		$typedefs{$n} = "\\ :c:type:`$n <$s>`\\ ";
93*4882a593Smuzhiyun		next;
94*4882a593Smuzhiyun	}
95*4882a593Smuzhiyun	if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/
96*4882a593Smuzhiyun	    || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/
97*4882a593Smuzhiyun	    || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/
98*4882a593Smuzhiyun	    || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) {
99*4882a593Smuzhiyun		my $s = $1;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun		$enums{$s} =  "enum :c:type:`$s`\\ ";
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun		$is_enum = $1;
104*4882a593Smuzhiyun		next;
105*4882a593Smuzhiyun	}
106*4882a593Smuzhiyun	if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/
107*4882a593Smuzhiyun	    || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/
108*4882a593Smuzhiyun	    || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/
109*4882a593Smuzhiyun	    || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/
110*4882a593Smuzhiyun	    ) {
111*4882a593Smuzhiyun		my $s = $1;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun		$structs{$s} = "struct $s\\ ";
114*4882a593Smuzhiyun		next;
115*4882a593Smuzhiyun	}
116*4882a593Smuzhiyun}
117*4882a593Smuzhiyunclose IN;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun#
120*4882a593Smuzhiyun# Handle multi-line typedefs
121*4882a593Smuzhiyun#
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunmy @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,
124*4882a593Smuzhiyun	       $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,);
125*4882a593Smuzhiyunforeach my $m (@matches) {
126*4882a593Smuzhiyun	my $s = $m;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	$typedefs{$s} = "\\ :c:type:`$s`\\ ";
129*4882a593Smuzhiyun	next;
130*4882a593Smuzhiyun}
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun#
133*4882a593Smuzhiyun# Handle exceptions, if any
134*4882a593Smuzhiyun#
135*4882a593Smuzhiyun
136*4882a593Smuzhiyunmy %def_reftype = (
137*4882a593Smuzhiyun	"ioctl"   => ":ref",
138*4882a593Smuzhiyun	"define"  => ":ref",
139*4882a593Smuzhiyun	"symbol"  => ":ref",
140*4882a593Smuzhiyun	"typedef" => ":c:type",
141*4882a593Smuzhiyun	"enum"    => ":c:type",
142*4882a593Smuzhiyun	"struct"  => ":c:type",
143*4882a593Smuzhiyun);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyunif ($file_exceptions) {
146*4882a593Smuzhiyun	open IN, $file_exceptions or die "Can't read $file_exceptions";
147*4882a593Smuzhiyun	while (<IN>) {
148*4882a593Smuzhiyun		next if (m/^\s*$/ || m/^\s*#/);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun		# Parsers to ignore a symbol
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun		if (m/^ignore\s+ioctl\s+(\S+)/) {
153*4882a593Smuzhiyun			delete $ioctls{$1} if (exists($ioctls{$1}));
154*4882a593Smuzhiyun			next;
155*4882a593Smuzhiyun		}
156*4882a593Smuzhiyun		if (m/^ignore\s+define\s+(\S+)/) {
157*4882a593Smuzhiyun			delete $defines{$1} if (exists($defines{$1}));
158*4882a593Smuzhiyun			next;
159*4882a593Smuzhiyun		}
160*4882a593Smuzhiyun		if (m/^ignore\s+typedef\s+(\S+)/) {
161*4882a593Smuzhiyun			delete $typedefs{$1} if (exists($typedefs{$1}));
162*4882a593Smuzhiyun			next;
163*4882a593Smuzhiyun		}
164*4882a593Smuzhiyun		if (m/^ignore\s+enum\s+(\S+)/) {
165*4882a593Smuzhiyun			delete $enums{$1} if (exists($enums{$1}));
166*4882a593Smuzhiyun			next;
167*4882a593Smuzhiyun		}
168*4882a593Smuzhiyun		if (m/^ignore\s+struct\s+(\S+)/) {
169*4882a593Smuzhiyun			delete $structs{$1} if (exists($structs{$1}));
170*4882a593Smuzhiyun			next;
171*4882a593Smuzhiyun		}
172*4882a593Smuzhiyun		if (m/^ignore\s+symbol\s+(\S+)/) {
173*4882a593Smuzhiyun			delete $enum_symbols{$1} if (exists($enum_symbols{$1}));
174*4882a593Smuzhiyun			next;
175*4882a593Smuzhiyun		}
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun		# Parsers to replace a symbol
178*4882a593Smuzhiyun		my ($type, $old, $new, $reftype);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun		if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) {
181*4882a593Smuzhiyun			$type = $1;
182*4882a593Smuzhiyun			$old = $2;
183*4882a593Smuzhiyun			$new = $3;
184*4882a593Smuzhiyun		} else {
185*4882a593Smuzhiyun			die "Can't parse $file_exceptions: $_";
186*4882a593Smuzhiyun		}
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun		if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) {
189*4882a593Smuzhiyun			$reftype = ":c:$1";
190*4882a593Smuzhiyun			$new = $2;
191*4882a593Smuzhiyun		} elsif ($new =~ m/\:ref\:\`(.+)\`/) {
192*4882a593Smuzhiyun			$reftype = ":ref";
193*4882a593Smuzhiyun			$new = $1;
194*4882a593Smuzhiyun		} else {
195*4882a593Smuzhiyun			$reftype = $def_reftype{$type};
196*4882a593Smuzhiyun		}
197*4882a593Smuzhiyun		$new = "$reftype:`$old <$new>`";
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun		if ($type eq "ioctl") {
200*4882a593Smuzhiyun			$ioctls{$old} = $new if (exists($ioctls{$old}));
201*4882a593Smuzhiyun			next;
202*4882a593Smuzhiyun		}
203*4882a593Smuzhiyun		if ($type eq "define") {
204*4882a593Smuzhiyun			$defines{$old} = $new if (exists($defines{$old}));
205*4882a593Smuzhiyun			next;
206*4882a593Smuzhiyun		}
207*4882a593Smuzhiyun		if ($type eq "symbol") {
208*4882a593Smuzhiyun			$enum_symbols{$old} = $new if (exists($enum_symbols{$old}));
209*4882a593Smuzhiyun			next;
210*4882a593Smuzhiyun		}
211*4882a593Smuzhiyun		if ($type eq "typedef") {
212*4882a593Smuzhiyun			$typedefs{$old} = $new if (exists($typedefs{$old}));
213*4882a593Smuzhiyun			next;
214*4882a593Smuzhiyun		}
215*4882a593Smuzhiyun		if ($type eq "enum") {
216*4882a593Smuzhiyun			$enums{$old} = $new if (exists($enums{$old}));
217*4882a593Smuzhiyun			next;
218*4882a593Smuzhiyun		}
219*4882a593Smuzhiyun		if ($type eq "struct") {
220*4882a593Smuzhiyun			$structs{$old} = $new if (exists($structs{$old}));
221*4882a593Smuzhiyun			next;
222*4882a593Smuzhiyun		}
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun		die "Can't parse $file_exceptions: $_";
225*4882a593Smuzhiyun	}
226*4882a593Smuzhiyun}
227*4882a593Smuzhiyun
228*4882a593Smuzhiyunif ($debug) {
229*4882a593Smuzhiyun	print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
230*4882a593Smuzhiyun	print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
231*4882a593Smuzhiyun	print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
232*4882a593Smuzhiyun	print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
233*4882a593Smuzhiyun	print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
234*4882a593Smuzhiyun	print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
235*4882a593Smuzhiyun}
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun#
238*4882a593Smuzhiyun# Align block
239*4882a593Smuzhiyun#
240*4882a593Smuzhiyun$data = expand($data);
241*4882a593Smuzhiyun$data = "    " . $data;
242*4882a593Smuzhiyun$data =~ s/\n/\n    /g;
243*4882a593Smuzhiyun$data =~ s/\n\s+$/\n/g;
244*4882a593Smuzhiyun$data =~ s/\n\s+\n/\n\n/g;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun#
247*4882a593Smuzhiyun# Add escape codes for special characters
248*4882a593Smuzhiyun#
249*4882a593Smuzhiyun$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun$data =~ s,DEPRECATED,**DEPRECATED**,g;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun#
254*4882a593Smuzhiyun# Add references
255*4882a593Smuzhiyun#
256*4882a593Smuzhiyun
257*4882a593Smuzhiyunmy $start_delim = "[ \n\t\(\=\*\@]";
258*4882a593Smuzhiyunmy $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
259*4882a593Smuzhiyun
260*4882a593Smuzhiyunforeach my $r (keys %ioctls) {
261*4882a593Smuzhiyun	my $s = $ioctls{$r};
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
268*4882a593Smuzhiyun}
269*4882a593Smuzhiyun
270*4882a593Smuzhiyunforeach my $r (keys %defines) {
271*4882a593Smuzhiyun	my $s = $defines{$r};
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
278*4882a593Smuzhiyun}
279*4882a593Smuzhiyun
280*4882a593Smuzhiyunforeach my $r (keys %enum_symbols) {
281*4882a593Smuzhiyun	my $s = $enum_symbols{$r};
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
288*4882a593Smuzhiyun}
289*4882a593Smuzhiyun
290*4882a593Smuzhiyunforeach my $r (keys %enums) {
291*4882a593Smuzhiyun	my $s = $enums{$r};
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun	$data =~ s/enum\s+($r)$end_delim/$s$2/g;
298*4882a593Smuzhiyun}
299*4882a593Smuzhiyun
300*4882a593Smuzhiyunforeach my $r (keys %structs) {
301*4882a593Smuzhiyun	my $s = $structs{$r};
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun	$data =~ s/struct\s+($r)$end_delim/$s$2/g;
308*4882a593Smuzhiyun}
309*4882a593Smuzhiyun
310*4882a593Smuzhiyunforeach my $r (keys %typedefs) {
311*4882a593Smuzhiyun	my $s = $typedefs{$r};
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun	$r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun	print "$r -> $s\n" if ($debug);
316*4882a593Smuzhiyun	$data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
317*4882a593Smuzhiyun}
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun$data =~ s/\\ ([\n\s])/\1/g;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun#
322*4882a593Smuzhiyun# Generate output file
323*4882a593Smuzhiyun#
324*4882a593Smuzhiyun
325*4882a593Smuzhiyunmy $title = $file_in;
326*4882a593Smuzhiyun$title =~ s,.*/,,;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyunopen OUT, "> $file_out" or die "Can't open $file_out";
329*4882a593Smuzhiyunprint OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
330*4882a593Smuzhiyunprint OUT "$title\n";
331*4882a593Smuzhiyunprint OUT "=" x length($title);
332*4882a593Smuzhiyunprint OUT "\n\n.. parsed-literal::\n\n";
333*4882a593Smuzhiyunprint OUT $data;
334*4882a593Smuzhiyunclose OUT;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun__END__
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun=head1 NAME
339*4882a593Smuzhiyun
340*4882a593Smuzhiyunparse_headers.pl - parse a C file, in order to identify functions, structs,
341*4882a593Smuzhiyunenums and defines and create cross-references to a Sphinx book.
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun=head1 SYNOPSIS
344*4882a593Smuzhiyun
345*4882a593SmuzhiyunB<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
346*4882a593Smuzhiyun
347*4882a593SmuzhiyunWhere <options> can be: --debug, --help or --usage.
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun=head1 OPTIONS
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun=over 8
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun=item B<--debug>
354*4882a593Smuzhiyun
355*4882a593SmuzhiyunPut the script in verbose mode, useful for debugging.
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun=item B<--usage>
358*4882a593Smuzhiyun
359*4882a593SmuzhiyunPrints a brief help message and exits.
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun=item B<--help>
362*4882a593Smuzhiyun
363*4882a593SmuzhiyunPrints a more detailed help message and exits.
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun=back
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun=head1 DESCRIPTION
368*4882a593Smuzhiyun
369*4882a593SmuzhiyunConvert a C header or source file (C_FILE), into a ReStructured Text
370*4882a593Smuzhiyunincluded via ..parsed-literal block with cross-references for the
371*4882a593Smuzhiyundocumentation files that describe the API. It accepts an optional
372*4882a593SmuzhiyunEXCEPTIONS_FILE with describes what elements will be either ignored or
373*4882a593Smuzhiyunbe pointed to a non-default reference.
374*4882a593Smuzhiyun
375*4882a593SmuzhiyunThe output is written at the (OUT_FILE).
376*4882a593Smuzhiyun
377*4882a593SmuzhiyunIt is capable of identifying defines, functions, structs, typedefs,
378*4882a593Smuzhiyunenums and enum symbols and create cross-references for all of them.
379*4882a593SmuzhiyunIt is also capable of distinguish #define used for specifying a Linux
380*4882a593Smuzhiyunioctl.
381*4882a593Smuzhiyun
382*4882a593SmuzhiyunThe EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
383*4882a593Smuzhiyunto replace the default references by a custom one.
384*4882a593Smuzhiyun
385*4882a593SmuzhiyunPlease read Documentation/doc-guide/parse-headers.rst at the Kernel's
386*4882a593Smuzhiyuntree for more details.
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun=head1 BUGS
389*4882a593Smuzhiyun
390*4882a593SmuzhiyunReport bugs to Mauro Carvalho Chehab <mchehab@kernel.org>
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun=head1 COPYRIGHT
393*4882a593Smuzhiyun
394*4882a593SmuzhiyunCopyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>.
395*4882a593Smuzhiyun
396*4882a593SmuzhiyunLicense GPLv2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>.
397*4882a593Smuzhiyun
398*4882a593SmuzhiyunThis is free software: you are free to change and redistribute it.
399*4882a593SmuzhiyunThere is NO WARRANTY, to the extent permitted by law.
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun=cut
402