5 # Uncomment if debug is needed
8 # change to 1 to generate some debug prints
11 if (scalar @ARGV < 2 || scalar @ARGV > 3) {
12 die "Usage:\n\t$0 <file in> <file out> [<exceptions file>]\n";
15 my ($file_in, $file_out, $file_exceptions) = @ARGV;
26 # read the file and get identifiers
30 open IN, $file_in or die "Can't open $file_in";
37 if ($is_enum && $ln =~ m/^\s*([_A-Z][^\s\}\,\=]+)\s*[\,=]?/) {
43 $enum_symbols{$s} = $n;
45 $is_enum = 0 if ($is_enum && m/\}/);
48 $is_enum = 0 if ($is_enum && m/\}/);
50 if ($ln =~ m/^\s*#\s*define\s+([_A-Z]\S+)\s+_IO/) {
59 if ($ln =~ m/^\s*#\s*define\s+([_A-Z]\S+)\s+/) {
69 if ($ln =~ m/^\s*typedef\s+.*\s+([_\w]\S+);/) {
78 if ($ln =~ m/^\s*enum\s+(\S+)\s+\{/
79 || $ln =~ m/^\s*enum\s+(\S+)$/) {
90 if ($ln =~ m/^\s*struct\s+([_A-Za-z_]\S+)\s+\{/
91 || $ln =~ m/^\s*struct\s+([A-Za-z_]\S+)$/) {
104 # Handle multi-line typedefs
107 my @matches = $data =~ m/typedef\s+struct\s+\S+\s*\{[^\}]+\}\s*(\S+)\s*\;/g;
108 foreach my $m (@matches) {
119 # Handle exceptions, if any
122 if ($file_exceptions) {
123 open IN, $file_exceptions or die "Can't read $file_exceptions";
125 next if (m/^\s*$/ || m/^\s*#/);
127 # Parsers to ignore a symbol
129 if (m/^ignore\s+ioctl\s+(\S+)/) {
130 delete $ioctls{$1} if (exists($ioctls{$1}));
133 if (m/^ignore\s+define\s+(\S+)/) {
134 delete $defines{$1} if (exists($defines{$1}));
137 if (m/^ignore\s+typedef\s+(\S+)/) {
138 delete $typedefs{$1} if (exists($typedefs{$1}));
141 if (m/^ignore\s+enum\s+(\S+)/) {
142 delete $enums{$1} if (exists($enums{$1}));
145 if (m/^ignore\s+struct\s+(\S+)/) {
146 delete $structs{$1} if (exists($structs{$1}));
150 # Parsers to replace a symbol
152 if (m/^replace\s+ioctl\s+(\S+)\s+(\S+)/) {
153 $ioctls{$1} = $2 if (exists($ioctls{$1}));
156 if (m/^replace\s+define\s+(\S+)\s+(\S+)/) {
157 $defines{$1} = $2 if (exists($defines{$1}));
160 if (m/^replace\s+typedef\s+(\S+)\s+(\S+)/) {
161 $typedefs{$1} = $2 if (exists($typedefs{$1}));
164 if (m/^replace\s+enum\s+(\S+)\s+(\S+)/) {
165 $enums{$1} = $2 if (exists($enums{$1}));
168 if (m/^replace\s+symbol\s+(\S+)\s+(\S+)/) {
169 $enum_symbols{$1} = $2 if (exists($enum_symbols{$1}));
172 if (m/^replace\s+struct\s+(\S+)\s+(\S+)/) {
173 $structs{$1} = $2 if (exists($structs{$1}));
177 die "Can't parse $file_exceptions: $_";
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);
193 $data = expand($data);
196 $data =~ s/\n\s+$/\n/g;
197 $data =~ s/\n\s+\n/\n\n/g;
200 # Add escape codes for special characters
202 $data =~ s,([\_\`\*\<\>\&\\\\:\/]),\\$1,g;
204 $data =~ s,DEPRECATED,**DEPRECATED**,g;
210 my $start_delim = "[ \n\t\(\=\*\@]";
211 my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)";
213 foreach my $r (keys %ioctls) {
216 my $s = "\\ :ref:`$r <$n>`\\ ";
218 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
220 print "$r -> $s\n" if ($debug);
222 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
225 foreach my $r (keys %defines) {
226 my $n = $defines{$r};
228 my $s = "\\ :ref:`$r <$n>`\\ ";
230 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
232 print "$r -> $s\n" if ($debug);
234 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
237 foreach my $r (keys %enum_symbols) {
238 my $n = $enum_symbols{$r};
240 my $s = "\\ :ref:`$r <$n>`\\ ";
242 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
244 print "$r -> $s\n" if ($debug);
246 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
249 foreach my $r (keys %enums) {
252 my $s = "\\ :ref:`enum $r <$n>`\\ ";
254 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
256 print "$r -> $s\n" if ($debug);
258 $data =~ s/enum\s+($r)$end_delim/$s$2/g;
261 foreach my $r (keys %structs) {
262 my $n = $structs{$r};
264 my $s = "\\ :ref:`struct $r <$n>`\\ ";
266 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
268 print "$r -> $s\n" if ($debug);
270 $data =~ s/struct\s+($r)$end_delim/$s$2/g;
273 foreach my $r (keys %typedefs) {
274 my $n = $typedefs{$r};
276 my $s = "\\ :ref:`$r <$n>`\\ ";
278 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g;
280 print "$r -> $s\n" if ($debug);
282 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g;
286 # Generate output file
289 my $title = $file_in;
292 open OUT, "> $file_out" or die "Can't open $file_out";
293 print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n";
294 print OUT "$title\n";
295 print OUT "=" x length($title);
296 print OUT "\n\n.. parsed-literal::\n\n";