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