kusano 7d535a
#!/usr/bin/perl
kusano 7d535a
kusano 7d535a
# Transform K&R C function definitions into ANSI equivalent.
kusano 7d535a
#
kusano 7d535a
# Author: Paul Marquess
kusano 7d535a
# Version: 1.0
kusano 7d535a
# Date: 3 October 2006
kusano 7d535a
kusano 7d535a
# TODO
kusano 7d535a
#
kusano 7d535a
# Asumes no function pointer parameters. unless they are typedefed.
kusano 7d535a
# Assumes no literal strings that look like function definitions
kusano 7d535a
# Assumes functions start at the beginning of a line
kusano 7d535a
kusano 7d535a
use strict;
kusano 7d535a
use warnings;
kusano 7d535a
kusano 7d535a
local $/;
kusano 7d535a
$_ = <>;
kusano 7d535a
kusano 7d535a
my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments
kusano 7d535a
kusano 7d535a
my $d1    = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ;
kusano 7d535a
my $decl  = qr{ $sp (?: \w+ $sp )+ $d1 }xo ;
kusano 7d535a
my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ;
kusano 7d535a
kusano 7d535a
kusano 7d535a
while (s/^
kusano 7d535a
            (                  # Start $1
kusano 7d535a
                (              #   Start $2
kusano 7d535a
                    .*?        #     Minimal eat content
kusano 7d535a
                    ( ^ \w [\w\s\*]+ )    #     $3 -- function name
kusano 7d535a
                    \s*        #     optional whitespace
kusano 7d535a
                )              # $2 - Matched up to before parameter list
kusano 7d535a
kusano 7d535a
                \( \s*         # Literal "(" + optional whitespace
kusano 7d535a
                ( [^\)]+ )     # $4 - one or more anythings except ")"
kusano 7d535a
                \s* \)         # optional whitespace surrounding a Literal ")"
kusano 7d535a
kusano 7d535a
                ( (?: $dList )+ ) # $5
kusano 7d535a
kusano 7d535a
                $sp ^ {        # literal "{" at start of line
kusano 7d535a
            )                  # Remember to $1
kusano 7d535a
        //xsom
kusano 7d535a
      )
kusano 7d535a
{
kusano 7d535a
    my $all = $1 ;
kusano 7d535a
    my $prefix = $2;
kusano 7d535a
    my $param_list = $4 ;
kusano 7d535a
    my $params = $5;
kusano 7d535a
kusano 7d535a
    StripComments($params);
kusano 7d535a
    StripComments($param_list);
kusano 7d535a
    $param_list =~ s/^\s+//;
kusano 7d535a
    $param_list =~ s/\s+$//;
kusano 7d535a
kusano 7d535a
    my $i = 0 ;
kusano 7d535a
    my %pList = map { $_ => $i++ }
kusano 7d535a
                split /\s*,\s*/, $param_list;
kusano 7d535a
    my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ;
kusano 7d535a
kusano 7d535a
    my @params = split /\s*;\s*/, $params;
kusano 7d535a
    my @outParams = ();
kusano 7d535a
    foreach my $p (@params)
kusano 7d535a
    {
kusano 7d535a
        if ($p =~ /,/)
kusano 7d535a
        {
kusano 7d535a
            my @bits = split /\s*,\s*/, $p;
kusano 7d535a
            my $first = shift @bits;
kusano 7d535a
            $first =~ s/^\s*//;
kusano 7d535a
            push @outParams, $first;
kusano 7d535a
            $first =~ /^(\w+\s*)/;
kusano 7d535a
            my $type = $1 ;
kusano 7d535a
            push @outParams, map { $type . $_ } @bits;
kusano 7d535a
        }
kusano 7d535a
        else
kusano 7d535a
        {
kusano 7d535a
            $p =~ s/^\s+//;
kusano 7d535a
            push @outParams, $p;
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
kusano 7d535a
    my %tmp = map { /$pMatch/;  $_ => $pList{$1}  }
kusano 7d535a
              @outParams ;
kusano 7d535a
kusano 7d535a
    @outParams = map  { "    $_" }
kusano 7d535a
                 sort { $tmp{$a} <=> $tmp{$b} }
kusano 7d535a
                 @outParams ;
kusano 7d535a
kusano 7d535a
    print $prefix ;
kusano 7d535a
    print "(\n" . join(",\n", @outParams) . ")\n";
kusano 7d535a
    print "{" ;
kusano 7d535a
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
# Output any trailing code.
kusano 7d535a
print ;
kusano 7d535a
exit 0;
kusano 7d535a
kusano 7d535a
kusano 7d535a
sub StripComments
kusano 7d535a
{
kusano 7d535a
kusano 7d535a
  no warnings;
kusano 7d535a
kusano 7d535a
  # Strip C & C++ coments
kusano 7d535a
  # From the perlfaq
kusano 7d535a
  $_[0] =~
kusano 7d535a
kusano 7d535a
    s{
kusano 7d535a
       /\*         ##  Start of /* ... */ comment
kusano 7d535a
       [^*]*\*+    ##  Non-* followed by 1-or-more *'s
kusano 7d535a
       (
kusano 7d535a
         [^/*][^*]*\*+
kusano 7d535a
       )*          ##  0-or-more things which don't start with /
kusano 7d535a
                   ##    but do end with '*'
kusano 7d535a
       /           ##  End of /* ... */ comment
kusano 7d535a
kusano 7d535a
     |         ##     OR  C++ Comment
kusano 7d535a
       //          ## Start of C++ comment //
kusano 7d535a
       [^\n]*      ## followed by 0-or-more non end of line characters
kusano 7d535a
kusano 7d535a
     |         ##     OR  various things which aren't comments:
kusano 7d535a
kusano 7d535a
       (
kusano 7d535a
         "           ##  Start of " ... " string
kusano 7d535a
         (
kusano 7d535a
           \\.           ##  Escaped char
kusano 7d535a
         |               ##    OR
kusano 7d535a
           [^"\\]        ##  Non "\
kusano 7d535a
         )*
kusano 7d535a
         "           ##  End of " ... " string
kusano 7d535a
kusano 7d535a
       |         ##     OR
kusano 7d535a
kusano 7d535a
         '           ##  Start of ' ... ' string
kusano 7d535a
         (
kusano 7d535a
           \\.           ##  Escaped char
kusano 7d535a
         |               ##    OR
kusano 7d535a
           [^'\\]        ##  Non '\
kusano 7d535a
         )*
kusano 7d535a
         '           ##  End of ' ... ' string
kusano 7d535a
kusano 7d535a
       |         ##     OR
kusano 7d535a
kusano 7d535a
         .           ##  Anything other char
kusano 7d535a
         [^/"'\\]*   ##  Chars which doesn't start a comment, string or escape
kusano 7d535a
       )
kusano 7d535a
     }{$2}gxs;
kusano 7d535a
kusano 7d535a
}