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 |
} |