1*78a88f79SMario Six#!/usr/bin/perl 2*78a88f79SMario Sixuse strict; 3*78a88f79SMario Sixuse Text::Tabs; 4*78a88f79SMario Sixuse Getopt::Long; 5*78a88f79SMario Sixuse Pod::Usage; 6*78a88f79SMario Six 7*78a88f79SMario Sixmy $debug; 8*78a88f79SMario Sixmy $help; 9*78a88f79SMario Sixmy $man; 10*78a88f79SMario Six 11*78a88f79SMario SixGetOptions( 12*78a88f79SMario Six "debug" => \$debug, 13*78a88f79SMario Six 'usage|?' => \$help, 14*78a88f79SMario Six 'help' => \$man 15*78a88f79SMario Six) or pod2usage(2); 16*78a88f79SMario Six 17*78a88f79SMario Sixpod2usage(1) if $help; 18*78a88f79SMario Sixpod2usage(-exitstatus => 0, -verbose => 2) if $man; 19*78a88f79SMario Sixpod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3); 20*78a88f79SMario Six 21*78a88f79SMario Sixmy ($file_in, $file_out, $file_exceptions) = @ARGV; 22*78a88f79SMario Six 23*78a88f79SMario Sixmy $data; 24*78a88f79SMario Sixmy %ioctls; 25*78a88f79SMario Sixmy %defines; 26*78a88f79SMario Sixmy %typedefs; 27*78a88f79SMario Sixmy %enums; 28*78a88f79SMario Sixmy %enum_symbols; 29*78a88f79SMario Sixmy %structs; 30*78a88f79SMario Six 31*78a88f79SMario Sixrequire Data::Dumper if ($debug); 32*78a88f79SMario Six 33*78a88f79SMario Six# 34*78a88f79SMario Six# read the file and get identifiers 35*78a88f79SMario Six# 36*78a88f79SMario Six 37*78a88f79SMario Sixmy $is_enum = 0; 38*78a88f79SMario Sixmy $is_comment = 0; 39*78a88f79SMario Sixopen IN, $file_in or die "Can't open $file_in"; 40*78a88f79SMario Sixwhile (<IN>) { 41*78a88f79SMario Six $data .= $_; 42*78a88f79SMario Six 43*78a88f79SMario Six my $ln = $_; 44*78a88f79SMario Six if (!$is_comment) { 45*78a88f79SMario Six $ln =~ s,/\*.*(\*/),,g; 46*78a88f79SMario Six 47*78a88f79SMario Six $is_comment = 1 if ($ln =~ s,/\*.*,,); 48*78a88f79SMario Six } else { 49*78a88f79SMario Six if ($ln =~ s,^(.*\*/),,) { 50*78a88f79SMario Six $is_comment = 0; 51*78a88f79SMario Six } else { 52*78a88f79SMario Six next; 53*78a88f79SMario Six } 54*78a88f79SMario Six } 55*78a88f79SMario Six 56*78a88f79SMario Six if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) { 57*78a88f79SMario Six my $s = $1; 58*78a88f79SMario Six my $n = $1; 59*78a88f79SMario Six $n =~ tr/A-Z/a-z/; 60*78a88f79SMario Six $n =~ tr/_/-/; 61*78a88f79SMario Six 62*78a88f79SMario Six $enum_symbols{$s} = "\\ :ref:`$s <$n>`\\ "; 63*78a88f79SMario Six 64*78a88f79SMario Six $is_enum = 0 if ($is_enum && m/\}/); 65*78a88f79SMario Six next; 66*78a88f79SMario Six } 67*78a88f79SMario Six $is_enum = 0 if ($is_enum && m/\}/); 68*78a88f79SMario Six 69*78a88f79SMario Six if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) { 70*78a88f79SMario Six my $s = $1; 71*78a88f79SMario Six my $n = $1; 72*78a88f79SMario Six $n =~ tr/A-Z/a-z/; 73*78a88f79SMario Six 74*78a88f79SMario Six $ioctls{$s} = "\\ :ref:`$s <$n>`\\ "; 75*78a88f79SMario Six next; 76*78a88f79SMario Six } 77*78a88f79SMario Six 78*78a88f79SMario Six if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) { 79*78a88f79SMario Six my $s = $1; 80*78a88f79SMario Six my $n = $1; 81*78a88f79SMario Six $n =~ tr/A-Z/a-z/; 82*78a88f79SMario Six $n =~ tr/_/-/; 83*78a88f79SMario Six 84*78a88f79SMario Six $defines{$s} = "\\ :ref:`$s <$n>`\\ "; 85*78a88f79SMario Six next; 86*78a88f79SMario Six } 87*78a88f79SMario Six 88*78a88f79SMario Six if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) { 89*78a88f79SMario Six my $s = $2; 90*78a88f79SMario Six my $n = $3; 91*78a88f79SMario Six 92*78a88f79SMario Six $typedefs{$n} = "\\ :c:type:`$n <$s>`\\ "; 93*78a88f79SMario Six next; 94*78a88f79SMario Six } 95*78a88f79SMario Six if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/ 96*78a88f79SMario Six || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/ 97*78a88f79SMario Six || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/ 98*78a88f79SMario Six || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) { 99*78a88f79SMario Six my $s = $1; 100*78a88f79SMario Six 101*78a88f79SMario Six $enums{$s} = "enum :c:type:`$s`\\ "; 102*78a88f79SMario Six 103*78a88f79SMario Six $is_enum = $1; 104*78a88f79SMario Six next; 105*78a88f79SMario Six } 106*78a88f79SMario Six if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/ 107*78a88f79SMario Six || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/ 108*78a88f79SMario Six || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/ 109*78a88f79SMario Six || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/ 110*78a88f79SMario Six ) { 111*78a88f79SMario Six my $s = $1; 112*78a88f79SMario Six 113*78a88f79SMario Six $structs{$s} = "struct :c:type:`$s`\\ "; 114*78a88f79SMario Six next; 115*78a88f79SMario Six } 116*78a88f79SMario Six} 117*78a88f79SMario Sixclose IN; 118*78a88f79SMario Six 119*78a88f79SMario Six# 120*78a88f79SMario Six# Handle multi-line typedefs 121*78a88f79SMario Six# 122*78a88f79SMario Six 123*78a88f79SMario Sixmy @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g, 124*78a88f79SMario Six $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,); 125*78a88f79SMario Sixforeach my $m (@matches) { 126*78a88f79SMario Six my $s = $m; 127*78a88f79SMario Six 128*78a88f79SMario Six $typedefs{$s} = "\\ :c:type:`$s`\\ "; 129*78a88f79SMario Six next; 130*78a88f79SMario Six} 131*78a88f79SMario Six 132*78a88f79SMario Six# 133*78a88f79SMario Six# Handle exceptions, if any 134*78a88f79SMario Six# 135*78a88f79SMario Six 136*78a88f79SMario Sixmy %def_reftype = ( 137*78a88f79SMario Six "ioctl" => ":ref", 138*78a88f79SMario Six "define" => ":ref", 139*78a88f79SMario Six "symbol" => ":ref", 140*78a88f79SMario Six "typedef" => ":c:type", 141*78a88f79SMario Six "enum" => ":c:type", 142*78a88f79SMario Six "struct" => ":c:type", 143*78a88f79SMario Six); 144*78a88f79SMario Six 145*78a88f79SMario Sixif ($file_exceptions) { 146*78a88f79SMario Six open IN, $file_exceptions or die "Can't read $file_exceptions"; 147*78a88f79SMario Six while (<IN>) { 148*78a88f79SMario Six next if (m/^\s*$/ || m/^\s*#/); 149*78a88f79SMario Six 150*78a88f79SMario Six # Parsers to ignore a symbol 151*78a88f79SMario Six 152*78a88f79SMario Six if (m/^ignore\s+ioctl\s+(\S+)/) { 153*78a88f79SMario Six delete $ioctls{$1} if (exists($ioctls{$1})); 154*78a88f79SMario Six next; 155*78a88f79SMario Six } 156*78a88f79SMario Six if (m/^ignore\s+define\s+(\S+)/) { 157*78a88f79SMario Six delete $defines{$1} if (exists($defines{$1})); 158*78a88f79SMario Six next; 159*78a88f79SMario Six } 160*78a88f79SMario Six if (m/^ignore\s+typedef\s+(\S+)/) { 161*78a88f79SMario Six delete $typedefs{$1} if (exists($typedefs{$1})); 162*78a88f79SMario Six next; 163*78a88f79SMario Six } 164*78a88f79SMario Six if (m/^ignore\s+enum\s+(\S+)/) { 165*78a88f79SMario Six delete $enums{$1} if (exists($enums{$1})); 166*78a88f79SMario Six next; 167*78a88f79SMario Six } 168*78a88f79SMario Six if (m/^ignore\s+struct\s+(\S+)/) { 169*78a88f79SMario Six delete $structs{$1} if (exists($structs{$1})); 170*78a88f79SMario Six next; 171*78a88f79SMario Six } 172*78a88f79SMario Six if (m/^ignore\s+symbol\s+(\S+)/) { 173*78a88f79SMario Six delete $enum_symbols{$1} if (exists($enum_symbols{$1})); 174*78a88f79SMario Six next; 175*78a88f79SMario Six } 176*78a88f79SMario Six 177*78a88f79SMario Six # Parsers to replace a symbol 178*78a88f79SMario Six my ($type, $old, $new, $reftype); 179*78a88f79SMario Six 180*78a88f79SMario Six if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) { 181*78a88f79SMario Six $type = $1; 182*78a88f79SMario Six $old = $2; 183*78a88f79SMario Six $new = $3; 184*78a88f79SMario Six } else { 185*78a88f79SMario Six die "Can't parse $file_exceptions: $_"; 186*78a88f79SMario Six } 187*78a88f79SMario Six 188*78a88f79SMario Six if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) { 189*78a88f79SMario Six $reftype = ":c:$1"; 190*78a88f79SMario Six $new = $2; 191*78a88f79SMario Six } elsif ($new =~ m/\:ref\:\`(.+)\`/) { 192*78a88f79SMario Six $reftype = ":ref"; 193*78a88f79SMario Six $new = $1; 194*78a88f79SMario Six } else { 195*78a88f79SMario Six $reftype = $def_reftype{$type}; 196*78a88f79SMario Six } 197*78a88f79SMario Six $new = "$reftype:`$old <$new>`"; 198*78a88f79SMario Six 199*78a88f79SMario Six if ($type eq "ioctl") { 200*78a88f79SMario Six $ioctls{$old} = $new if (exists($ioctls{$old})); 201*78a88f79SMario Six next; 202*78a88f79SMario Six } 203*78a88f79SMario Six if ($type eq "define") { 204*78a88f79SMario Six $defines{$old} = $new if (exists($defines{$old})); 205*78a88f79SMario Six next; 206*78a88f79SMario Six } 207*78a88f79SMario Six if ($type eq "symbol") { 208*78a88f79SMario Six $enum_symbols{$old} = $new if (exists($enum_symbols{$old})); 209*78a88f79SMario Six next; 210*78a88f79SMario Six } 211*78a88f79SMario Six if ($type eq "typedef") { 212*78a88f79SMario Six $typedefs{$old} = $new if (exists($typedefs{$old})); 213*78a88f79SMario Six next; 214*78a88f79SMario Six } 215*78a88f79SMario Six if ($type eq "enum") { 216*78a88f79SMario Six $enums{$old} = $new if (exists($enums{$old})); 217*78a88f79SMario Six next; 218*78a88f79SMario Six } 219*78a88f79SMario Six if ($type eq "struct") { 220*78a88f79SMario Six $structs{$old} = $new if (exists($structs{$old})); 221*78a88f79SMario Six next; 222*78a88f79SMario Six } 223*78a88f79SMario Six 224*78a88f79SMario Six die "Can't parse $file_exceptions: $_"; 225*78a88f79SMario Six } 226*78a88f79SMario Six} 227*78a88f79SMario Six 228*78a88f79SMario Sixif ($debug) { 229*78a88f79SMario Six print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls); 230*78a88f79SMario Six print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs); 231*78a88f79SMario Six print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums); 232*78a88f79SMario Six print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs); 233*78a88f79SMario Six print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines); 234*78a88f79SMario Six print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols); 235*78a88f79SMario Six} 236*78a88f79SMario Six 237*78a88f79SMario Six# 238*78a88f79SMario Six# Align block 239*78a88f79SMario Six# 240*78a88f79SMario Six$data = expand($data); 241*78a88f79SMario Six$data = " " . $data; 242*78a88f79SMario Six$data =~ s/\n/\n /g; 243*78a88f79SMario Six$data =~ s/\n\s+$/\n/g; 244*78a88f79SMario Six$data =~ s/\n\s+\n/\n\n/g; 245*78a88f79SMario Six 246*78a88f79SMario Six# 247*78a88f79SMario Six# Add escape codes for special characters 248*78a88f79SMario Six# 249*78a88f79SMario Six$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g; 250*78a88f79SMario Six 251*78a88f79SMario Six$data =~ s,DEPRECATED,**DEPRECATED**,g; 252*78a88f79SMario Six 253*78a88f79SMario Six# 254*78a88f79SMario Six# Add references 255*78a88f79SMario Six# 256*78a88f79SMario Six 257*78a88f79SMario Sixmy $start_delim = "[ \n\t\(\=\*\@]"; 258*78a88f79SMario Sixmy $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)"; 259*78a88f79SMario Six 260*78a88f79SMario Sixforeach my $r (keys %ioctls) { 261*78a88f79SMario Six my $s = $ioctls{$r}; 262*78a88f79SMario Six 263*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 264*78a88f79SMario Six 265*78a88f79SMario Six print "$r -> $s\n" if ($debug); 266*78a88f79SMario Six 267*78a88f79SMario Six $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 268*78a88f79SMario Six} 269*78a88f79SMario Six 270*78a88f79SMario Sixforeach my $r (keys %defines) { 271*78a88f79SMario Six my $s = $defines{$r}; 272*78a88f79SMario Six 273*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 274*78a88f79SMario Six 275*78a88f79SMario Six print "$r -> $s\n" if ($debug); 276*78a88f79SMario Six 277*78a88f79SMario Six $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 278*78a88f79SMario Six} 279*78a88f79SMario Six 280*78a88f79SMario Sixforeach my $r (keys %enum_symbols) { 281*78a88f79SMario Six my $s = $enum_symbols{$r}; 282*78a88f79SMario Six 283*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 284*78a88f79SMario Six 285*78a88f79SMario Six print "$r -> $s\n" if ($debug); 286*78a88f79SMario Six 287*78a88f79SMario Six $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 288*78a88f79SMario Six} 289*78a88f79SMario Six 290*78a88f79SMario Sixforeach my $r (keys %enums) { 291*78a88f79SMario Six my $s = $enums{$r}; 292*78a88f79SMario Six 293*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 294*78a88f79SMario Six 295*78a88f79SMario Six print "$r -> $s\n" if ($debug); 296*78a88f79SMario Six 297*78a88f79SMario Six $data =~ s/enum\s+($r)$end_delim/$s$2/g; 298*78a88f79SMario Six} 299*78a88f79SMario Six 300*78a88f79SMario Sixforeach my $r (keys %structs) { 301*78a88f79SMario Six my $s = $structs{$r}; 302*78a88f79SMario Six 303*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 304*78a88f79SMario Six 305*78a88f79SMario Six print "$r -> $s\n" if ($debug); 306*78a88f79SMario Six 307*78a88f79SMario Six $data =~ s/struct\s+($r)$end_delim/$s$2/g; 308*78a88f79SMario Six} 309*78a88f79SMario Six 310*78a88f79SMario Sixforeach my $r (keys %typedefs) { 311*78a88f79SMario Six my $s = $typedefs{$r}; 312*78a88f79SMario Six 313*78a88f79SMario Six $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; 314*78a88f79SMario Six 315*78a88f79SMario Six print "$r -> $s\n" if ($debug); 316*78a88f79SMario Six $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; 317*78a88f79SMario Six} 318*78a88f79SMario Six 319*78a88f79SMario Six$data =~ s/\\ ([\n\s])/\1/g; 320*78a88f79SMario Six 321*78a88f79SMario Six# 322*78a88f79SMario Six# Generate output file 323*78a88f79SMario Six# 324*78a88f79SMario Six 325*78a88f79SMario Sixmy $title = $file_in; 326*78a88f79SMario Six$title =~ s,.*/,,; 327*78a88f79SMario Six 328*78a88f79SMario Sixopen OUT, "> $file_out" or die "Can't open $file_out"; 329*78a88f79SMario Sixprint OUT ".. -*- coding: utf-8; mode: rst -*-\n\n"; 330*78a88f79SMario Sixprint OUT "$title\n"; 331*78a88f79SMario Sixprint OUT "=" x length($title); 332*78a88f79SMario Sixprint OUT "\n\n.. parsed-literal::\n\n"; 333*78a88f79SMario Sixprint OUT $data; 334*78a88f79SMario Sixclose OUT; 335*78a88f79SMario Six 336*78a88f79SMario Six__END__ 337*78a88f79SMario Six 338*78a88f79SMario Six=head1 NAME 339*78a88f79SMario Six 340*78a88f79SMario Sixparse_headers.pl - parse a C file, in order to identify functions, structs, 341*78a88f79SMario Sixenums and defines and create cross-references to a Sphinx book. 342*78a88f79SMario Six 343*78a88f79SMario Six=head1 SYNOPSIS 344*78a88f79SMario Six 345*78a88f79SMario SixB<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>] 346*78a88f79SMario Six 347*78a88f79SMario SixWhere <options> can be: --debug, --help or --man. 348*78a88f79SMario Six 349*78a88f79SMario Six=head1 OPTIONS 350*78a88f79SMario Six 351*78a88f79SMario Six=over 8 352*78a88f79SMario Six 353*78a88f79SMario Six=item B<--debug> 354*78a88f79SMario Six 355*78a88f79SMario SixPut the script in verbose mode, useful for debugging. 356*78a88f79SMario Six 357*78a88f79SMario Six=item B<--usage> 358*78a88f79SMario Six 359*78a88f79SMario SixPrints a brief help message and exits. 360*78a88f79SMario Six 361*78a88f79SMario Six=item B<--help> 362*78a88f79SMario Six 363*78a88f79SMario SixPrints a more detailed help message and exits. 364*78a88f79SMario Six 365*78a88f79SMario Six=back 366*78a88f79SMario Six 367*78a88f79SMario Six=head1 DESCRIPTION 368*78a88f79SMario Six 369*78a88f79SMario SixConvert a C header or source file (C_FILE), into a ReStructured Text 370*78a88f79SMario Sixincluded via ..parsed-literal block with cross-references for the 371*78a88f79SMario Sixdocumentation files that describe the API. It accepts an optional 372*78a88f79SMario SixEXCEPTIONS_FILE with describes what elements will be either ignored or 373*78a88f79SMario Sixbe pointed to a non-default reference. 374*78a88f79SMario Six 375*78a88f79SMario SixThe output is written at the (OUT_FILE). 376*78a88f79SMario Six 377*78a88f79SMario SixIt is capable of identifying defines, functions, structs, typedefs, 378*78a88f79SMario Sixenums and enum symbols and create cross-references for all of them. 379*78a88f79SMario SixIt is also capable of distinguish #define used for specifying a Linux 380*78a88f79SMario Sixioctl. 381*78a88f79SMario Six 382*78a88f79SMario SixThe EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or 383*78a88f79SMario Sixto replace the default references by a custom one. 384*78a88f79SMario Six 385*78a88f79SMario SixPlease read Documentation/doc-guide/parse-headers.rst at the Kernel's 386*78a88f79SMario Sixtree for more details. 387*78a88f79SMario Six 388*78a88f79SMario Six=head1 BUGS 389*78a88f79SMario Six 390*78a88f79SMario SixReport bugs to Mauro Carvalho Chehab <mchehab@kernel.org> 391*78a88f79SMario Six 392*78a88f79SMario Six=head1 COPYRIGHT 393*78a88f79SMario Six 394*78a88f79SMario SixCopyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>. 395*78a88f79SMario Six 396*78a88f79SMario SixLicense GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. 397*78a88f79SMario Six 398*78a88f79SMario SixThis is free software: you are free to change and redistribute it. 399*78a88f79SMario SixThere is NO WARRANTY, to the extent permitted by law. 400*78a88f79SMario Six 401*78a88f79SMario Six=cut 402