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