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