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