doc-rst: fix parsing comments and '{' on a separate line
[linux-2.6-block.git] / Documentation / sphinx / parse-headers.pl
CommitLineData
dabf8be3
MCC
1#!/usr/bin/perl
2use strict;
3use Text::Tabs;
4
5# Uncomment if debug is needed
6#use Data::Dumper;
7
8# change to 1 to generate some debug prints
9my $debug = 0;
10
11if (scalar @ARGV < 2 || scalar @ARGV > 3) {
12 die "Usage:\n\t$0 <file in> <file out> [<exceptions file>]\n";
13}
14
15my ($file_in, $file_out, $file_exceptions) = @ARGV;
16
17my $data;
18my %ioctls;
19my %defines;
20my %typedefs;
21my %enums;
22my %enum_symbols;
23my %structs;
24
25#
26# read the file and get identifiers
27#
28
29my $is_enum = 0;
30open IN, $file_in or die "Can't open $file_in";
31while (<IN>) {
9afe5112
MCC
32 my $ln = $_;
33 $ln =~ s,/\*.*\*/,,;
34
dabf8be3
MCC
35 $data .= $_;
36
9afe5112 37 if ($is_enum && $ln =~ m/^\s*([_A-Z][^\s\}\,\=]+)\s*[\,=]?/) {
dabf8be3
MCC
38 my $s = $1;
39 my $n = $1;
40 $n =~ tr/A-Z/a-z/;
41 $n =~ tr/_/-/;
42
43 $enum_symbols{$s} = $n;
44
45 $is_enum = 0 if ($is_enum && m/\}/);
46 next;
47 }
48 $is_enum = 0 if ($is_enum && m/\}/);
49
9afe5112 50 if ($ln =~ m/^\s*#\s*define\s+([_A-Z]\S+)\s+_IO/) {
dabf8be3
MCC
51 my $s = $1;
52 my $n = $1;
53 $n =~ tr/A-Z/a-z/;
54
55 $ioctls{$s} = $n;
56 next;
57 }
58
9afe5112 59 if ($ln =~ m/^\s*#\s*define\s+([_A-Z]\S+)\s+/) {
dabf8be3
MCC
60 my $s = $1;
61 my $n = $1;
62 $n =~ tr/A-Z/a-z/;
63 $n =~ tr/_/-/;
64
65 $defines{$s} = $n;
66 next;
67 }
68
9afe5112 69 if ($ln =~ m/^\s*typedef\s+.*\s+([_\w]\S+);/) {
dabf8be3
MCC
70 my $s = $1;
71 my $n = $1;
72 $n =~ tr/A-Z/a-z/;
73 $n =~ tr/_/-/;
74
75 $typedefs{$s} = $n;
76 next;
77 }
9afe5112
MCC
78 if ($ln =~ m/^\s*enum\s+(\S+)\s+\{/
79 || $ln =~ m/^\s*enum\s+(\S+)$/) {
dabf8be3
MCC
80 my $s = $1;
81 my $n = $1;
82 $n =~ tr/A-Z/a-z/;
83 $n =~ tr/_/-/;
84
85 $enums{$s} = $n;
86
87 $is_enum = $1;
88 next;
89 }
9afe5112
MCC
90 if ($ln =~ m/^\s*struct\s+([_A-Za-z_]\S+)\s+\{/
91 || $ln =~ m/^\s*struct\s+([A-Za-z_]\S+)$/) {
dabf8be3
MCC
92 my $s = $1;
93 my $n = $1;
94 $n =~ tr/A-Z/a-z/;
95 $n =~ tr/_/-/;
96
97 $structs{$s} = $n;
98 next;
99 }
100}
101close IN;
102
103#
104# Handle multi-line typedefs
105#
106
107my @matches = $data =~ m/typedef\s+struct\s+\S+\s*\{[^\}]+\}\s*(\S+)\s*\;/g;
108foreach my $m (@matches) {
109 my $s = $1;
110 my $n = $1;
111 $n =~ tr/A-Z/a-z/;
112 $n =~ tr/_/-/;
113
114 $typedefs{$s} = $n;
115 next;
116}
117
118#
119# Handle exceptions, if any
120#
121
122if ($file_exceptions) {
123 open IN, $file_exceptions or die "Can't read $file_exceptions";
124 while (<IN>) {
125 next if (m/^\s*$/ || m/^\s*#/);
126
127 # Parsers to ignore a symbol
128
129 if (m/^ignore\s+ioctl\s+(\S+)/) {
130 delete $ioctls{$1} if (exists($ioctls{$1}));
131 next;
132 }
133 if (m/^ignore\s+define\s+(\S+)/) {
134 delete $defines{$1} if (exists($defines{$1}));
135 next;
136 }
137 if (m/^ignore\s+typedef\s+(\S+)/) {
138 delete $typedefs{$1} if (exists($typedefs{$1}));
139 next;
140 }
141 if (m/^ignore\s+enum\s+(\S+)/) {
142 delete $enums{$1} if (exists($enums{$1}));
143 next;
144 }
145 if (m/^ignore\s+struct\s+(\S+)/) {
146 delete $structs{$1} if (exists($structs{$1}));
147 next;
148 }
149
150 # Parsers to replace a symbol
151
152 if (m/^replace\s+ioctl\s+(\S+)\s+(\S+)/) {
153 $ioctls{$1} = $2 if (exists($ioctls{$1}));
154 next;
155 }
156 if (m/^replace\s+define\s+(\S+)\s+(\S+)/) {
157 $defines{$1} = $2 if (exists($defines{$1}));
158 next;
159 }
160 if (m/^replace\s+typedef\s+(\S+)\s+(\S+)/) {
161 $typedefs{$1} = $2 if (exists($typedefs{$1}));
162 next;
163 }
164 if (m/^replace\s+enum\s+(\S+)\s+(\S+)/) {
165 $enums{$1} = $2 if (exists($enums{$1}));
166 next;
167 }
168 if (m/^replace\s+symbol\s+(\S+)\s+(\S+)/) {
169 $enum_symbols{$1} = $2 if (exists($enum_symbols{$1}));
170 next;
171 }
172 if (m/^replace\s+struct\s+(\S+)\s+(\S+)/) {
173 $structs{$1} = $2 if (exists($structs{$1}));
174 next;
175 }
176
177 die "Can't parse $file_exceptions: $_";
178 }
179}
180
181if ($debug) {
182 print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls);
183 print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs);
184 print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums);
185 print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs);
186 print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines);
187 print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols);
188}
189
190#
191# Align block
192#
193$data = expand($data);
194$data = " " . $data;
195$data =~ s/\n/\n /g;
196$data =~ s/\n\s+$/\n/g;
197$data =~ s/\n\s+\n/\n\n/g;
198
199#
200# Add escape codes for special characters
201#
202$data =~ s,([\_\`\*\<\>\&\\\\:\/]),\\$1,g;
203
7d95fa8d
MCC
204$data =~ s,DEPRECATED,**DEPRECATED**,g;
205
dabf8be3
MCC
206#
207# Add references
208#
209
6fe79d1e
MCC
210my $start_delim = "[ \n\t\(\=\*\@]";
211my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
dabf8be3
MCC
212
213foreach my $r (keys %ioctls) {
214 my $n = $ioctls{$r};
215
6fe79d1e 216 my $s = "\\ :ref:`$r <$n>`\\ ";
dabf8be3
MCC
217
218 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
219
220 print "$r -> $s\n" if ($debug);
221
6fe79d1e 222 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
dabf8be3
MCC
223}
224
225foreach my $r (keys %defines) {
226 my $n = $defines{$r};
227
6fe79d1e 228 my $s = "\\ :ref:`$r <$n>`\\ ";
dabf8be3
MCC
229
230 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
231
232 print "$r -> $s\n" if ($debug);
233
6fe79d1e 234 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
dabf8be3
MCC
235}
236
237foreach my $r (keys %enum_symbols) {
238 my $n = $enum_symbols{$r};
239
6fe79d1e 240 my $s = "\\ :ref:`$r <$n>`\\ ";
dabf8be3
MCC
241
242 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
243
244 print "$r -> $s\n" if ($debug);
245
6fe79d1e 246 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
dabf8be3
MCC
247}
248
249foreach my $r (keys %enums) {
250 my $n = $enums{$r};
251
6fe79d1e 252 my $s = "\\ :ref:`enum $r <$n>`\\ ";
dabf8be3
MCC
253
254 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
255
256 print "$r -> $s\n" if ($debug);
257
6fe79d1e 258 $data =~ s/enum\s+($r)$end_delim/$s$2/g;
dabf8be3
MCC
259}
260
261foreach my $r (keys %structs) {
262 my $n = $structs{$r};
263
6fe79d1e 264 my $s = "\\ :ref:`struct $r <$n>`\\ ";
dabf8be3
MCC
265
266 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
267
268 print "$r -> $s\n" if ($debug);
269
6fe79d1e 270 $data =~ s/struct\s+($r)$end_delim/$s$2/g;
dabf8be3
MCC
271}
272
273foreach my $r (keys %typedefs) {
274 my $n = $typedefs{$r};
275
6fe79d1e 276 my $s = "\\ :ref:`$r <$n>`\\ ";
dabf8be3
MCC
277
278 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
279
280 print "$r -> $s\n" if ($debug);
281
6fe79d1e 282 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
dabf8be3
MCC
283}
284
285#
286# Generate output file
287#
288
289my $title = $file_in;
290$title =~ s,.*/,,;
291
292open OUT, "> $file_out" or die "Can't open $file_out";
293print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
294print OUT "$title\n";
295print OUT "=" x length($title);
296print OUT "\n\n.. parsed-literal::\n\n";
297print OUT $data;
298close OUT;