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>) { 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} 96close IN; 97 98# 99# Handle multi-line typedefs 100# 101 102my @matches = $data =~ m/typedef\s+struct\s+\S+\s*\{[^\}]+\}\s*(\S+)\s*\;/g; 103foreach 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 117if ($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 176if ($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$data =~ s,DEPRECATED,**DEPRECATED**,g; 200 201# 202# Add references 203# 204 205my $start_delim = "[ \n\t\(\=\*\@]"; 206my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)"; 207 208foreach my $r (keys %ioctls) { 209 my $n = $ioctls{$r}; 210 211 my $s = "\\ :ref:`$r <$n>`\\ "; 212 213 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 214 215 print "$r -> $s\n" if ($debug); 216 217 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 218} 219 220foreach my $r (keys %defines) { 221 my $n = $defines{$r}; 222 223 my $s = "\\ :ref:`$r <$n>`\\ "; 224 225 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 226 227 print "$r -> $s\n" if ($debug); 228 229 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 230} 231 232foreach my $r (keys %enum_symbols) { 233 my $n = $enum_symbols{$r}; 234 235 my $s = "\\ :ref:`$r <$n>`\\ "; 236 237 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 238 239 print "$r -> $s\n" if ($debug); 240 241 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 242} 243 244foreach my $r (keys %enums) { 245 my $n = $enums{$r}; 246 247 my $s = "\\ :ref:`enum $r <$n>`\\ "; 248 249 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 250 251 print "$r -> $s\n" if ($debug); 252 253 $data =~ s/enum\s+($r)$end_delim/$s$2/g; 254} 255 256foreach my $r (keys %structs) { 257 my $n = $structs{$r}; 258 259 my $s = "\\ :ref:`struct $r <$n>`\\ "; 260 261 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 262 263 print "$r -> $s\n" if ($debug); 264 265 $data =~ s/struct\s+($r)$end_delim/$s$2/g; 266} 267 268foreach my $r (keys %typedefs) { 269 my $n = $typedefs{$r}; 270 271 my $s = "\\ :ref:`$r <$n>`\\ "; 272 273 $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 274 275 print "$r -> $s\n" if ($debug); 276 277 $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 278} 279 280# 281# Generate output file 282# 283 284my $title = $file_in; 285$title =~ s,.*/,,; 286 287open OUT, "> $file_out" or die "Can't open $file_out"; 288print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n"; 289print OUT "$title\n"; 290print OUT "=" x length($title); 291print OUT "\n\n.. parsed-literal::\n\n"; 292print OUT $data; 293close OUT; 294