Home | History | Annotate | Download | only in src
      1 #!/usr/bin/perl
      2 
      3 # Transform K&R C function definitions into ANSI equivalent.
      4 #
      5 # Author: Paul Marquess
      6 # Version: 1.0
      7 # Date: 3 October 2006
      8 
      9 # TODO
     10 #
     11 # Asumes no function pointer parameters. unless they are typedefed.
     12 # Assumes no literal strings that look like function definitions
     13 # Assumes functions start at the beginning of a line
     14 
     15 use strict;
     16 use warnings;
     17 
     18 local $/;
     19 $_ = <>;
     20 
     21 my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments
     22 
     23 my $d1    = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ;
     24 my $decl  = qr{ $sp (?: \w+ $sp )+ $d1 }xo ;
     25 my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ;
     26 
     27 
     28 while (s/^
     29             (                  # Start $1
     30                 (              #   Start $2
     31                     .*?        #     Minimal eat content
     32                     ( ^ \w [\w\s\*]+ )    #     $3 -- function name
     33                     \s*        #     optional whitespace
     34                 )              # $2 - Matched up to before parameter list
     35 
     36                 \( \s*         # Literal "(" + optional whitespace
     37                 ( [^\)]+ )     # $4 - one or more anythings except ")"
     38                 \s* \)         # optional whitespace surrounding a Literal ")"
     39 
     40                 ( (?: $dList )+ ) # $5
     41 
     42                 $sp ^ {        # literal "{" at start of line
     43             )                  # Remember to $1
     44         //xsom
     45       )
     46 {
     47     my $all = $1 ;
     48     my $prefix = $2;
     49     my $param_list = $4 ;
     50     my $params = $5;
     51 
     52     StripComments($params);
     53     StripComments($param_list);
     54     $param_list =~ s/^\s+//;
     55     $param_list =~ s/\s+$//;
     56 
     57     my $i = 0 ;
     58     my %pList = map { $_ => $i++ }
     59                 split /\s*,\s*/, $param_list;
     60     my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ;
     61 
     62     my @params = split /\s*;\s*/, $params;
     63     my @outParams = ();
     64     foreach my $p (@params)
     65     {
     66         if ($p =~ /,/)
     67         {
     68             my @bits = split /\s*,\s*/, $p;
     69             my $first = shift @bits;
     70             $first =~ s/^\s*//;
     71             push @outParams, $first;
     72             $first =~ /^(\w+\s*)/;
     73             my $type = $1 ;
     74             push @outParams, map { $type . $_ } @bits;
     75         }
     76         else
     77         {
     78             $p =~ s/^\s+//;
     79             push @outParams, $p;
     80         }
     81     }
     82 
     83 
     84     my %tmp = map { /$pMatch/;  $_ => $pList{$1}  }
     85               @outParams ;
     86 
     87     @outParams = map  { "    $_" }
     88                  sort { $tmp{$a} <=> $tmp{$b} }
     89                  @outParams ;
     90 
     91     print $prefix ;
     92     print "(\n" . join(",\n", @outParams) . ")\n";
     93     print "{" ;
     94 
     95 }
     96 
     97 # Output any trailing code.
     98 print ;
     99 exit 0;
    100 
    101 
    102 sub StripComments
    103 {
    104 
    105   no warnings;
    106 
    107   # Strip C & C++ coments
    108   # From the perlfaq
    109   $_[0] =~
    110 
    111     s{
    112        /\*         ##  Start of /* ... */ comment
    113        [^*]*\*+    ##  Non-* followed by 1-or-more *'s
    114        (
    115          [^/*][^*]*\*+
    116        )*          ##  0-or-more things which don't start with /
    117                    ##    but do end with '*'
    118        /           ##  End of /* ... */ comment
    119 
    120      |         ##     OR  C++ Comment
    121        //          ## Start of C++ comment //
    122        [^\n]*      ## followed by 0-or-more non end of line characters
    123 
    124      |         ##     OR  various things which aren't comments:
    125 
    126        (
    127          "           ##  Start of " ... " string
    128          (
    129            \\.           ##  Escaped char
    130          |               ##    OR
    131            [^"\\]        ##  Non "\
    132          )*
    133          "           ##  End of " ... " string
    134 
    135        |         ##     OR
    136 
    137          '           ##  Start of ' ... ' string
    138          (
    139            \\.           ##  Escaped char
    140          |               ##    OR
    141            [^'\\]        ##  Non '\
    142          )*
    143          '           ##  End of ' ... ' string
    144 
    145        |         ##     OR
    146 
    147          .           ##  Anything other char
    148          [^/"'\\]*   ##  Chars which doesn't start a comment, string or escape
    149        )
    150      }{$2}gxs;
    151 
    152 }
    153