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