OLD | NEW |
| (Empty) |
1 #!/usr/bin/perl | |
2 | |
3 # mksigs.pl - extract signatures from C headers | |
4 # | |
5 # Copyright (C) Michael Adam 2009 | |
6 # | |
7 # This program is free software; you can redistribute it and/or modify it | |
8 # under the terms of the GNU General Public License as published by the Free | |
9 # Software Foundation; either version 3 of the License, or (at your option) | |
10 # any later version. | |
11 # | |
12 # This program is distributed in the hope that it will be useful, but WITHOUT | |
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
15 # more details. | |
16 # | |
17 # You should have received a copy of the GNU General Public License along with | |
18 # this program; if not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 # USAGE: cat $header_files | mksigs.pl > $signature_file | |
21 # | |
22 # The header files to parse are read from stdin. | |
23 # The output is in a form as produced by gcc with the -aux-info switch | |
24 # and printed to stdout. | |
25 | |
26 use strict; | |
27 use warnings; | |
28 | |
29 my $in_comment = 0; | |
30 my $extern_C_block = 0; | |
31 | |
32 while (my $LINE = <>) { | |
33 # find end of started multi-line-comment | |
34 if ($in_comment) { | |
35 if ($LINE =~ /^.*?\*\/(.*)$/) { | |
36 $LINE = $1; | |
37 $in_comment = 0; | |
38 } else { | |
39 # whole line within comment | |
40 next; | |
41 } | |
42 } | |
43 | |
44 # strip C++-style comments | |
45 $LINE =~ s/^(.*?)\/\/.*$/$1/; | |
46 | |
47 # strip in-line-comments: | |
48 while ($LINE =~ /\/\*.*?\*\//) { | |
49 $LINE =~ s/\/\*.*?\*\///; | |
50 } | |
51 | |
52 # find starts of multi-line-comments | |
53 if ($LINE =~ /^(.*)\/\*/) { | |
54 $in_comment = 1; | |
55 $LINE = $1; | |
56 } | |
57 | |
58 # skip empty lines | |
59 next if $LINE =~ /^\s*$/; | |
60 | |
61 # remove leading spaces | |
62 $LINE =~ s/^\s*(.*)$/$1/; | |
63 | |
64 # concatenate lines split with "\" (usually macro defines) | |
65 while ($LINE =~ /^(.*?)\s+\\$/) { | |
66 my $LINE2 = <>; | |
67 $LINE = $1; | |
68 $LINE2 =~ s/^\s*(.*)$/$1/; | |
69 $LINE .= " " . $LINE2; | |
70 } | |
71 | |
72 # remove all preprocessor directives | |
73 next if ($LINE =~ /^#/); | |
74 | |
75 if ($LINE =~ /^extern\s+"C"\s+\{/) { | |
76 $extern_C_block = 1; | |
77 next; | |
78 } | |
79 | |
80 if (($LINE =~ /^[^\{]*\}/) and $extern_C_block) { | |
81 $extern_C_block = 0; | |
82 next; | |
83 } | |
84 | |
85 $LINE =~ s/^extern\s//; | |
86 | |
87 # concatenate braces stretched over multiple lines | |
88 # (from structs or enums) | |
89 my $REST = $LINE; | |
90 my $braces = 0; | |
91 while (($REST =~ /[\{\}]/) or ($braces)) { | |
92 while ($REST =~ /[\{\}]/) { | |
93 # collect opening | |
94 while ($REST =~ /^[^\{\}]*\{(.*)$/) { | |
95 $braces++; | |
96 $REST = $1; | |
97 } | |
98 | |
99 # collect closing | |
100 while ($REST =~ /^[^\{\}]*\}(.*)$/) { | |
101 $braces--; | |
102 $REST = $1; | |
103 } | |
104 } | |
105 | |
106 # concatenate if not balanced | |
107 if ($braces) { | |
108 if (my $LINE2 = <>) { | |
109 $LINE2 =~ s/^\s*(.*)$/$1/; | |
110 chomp($LINE); | |
111 $LINE .= " " . $LINE2; | |
112 chomp $REST; | |
113 $REST .= " " . $LINE2; | |
114 } else { | |
115 print "ERROR: unbalanced braces ($braces)\n"; | |
116 last; | |
117 } | |
118 } | |
119 } | |
120 | |
121 # concetenate function prototypes that stretch over multiple lines | |
122 $REST = $LINE; | |
123 my $parenthesis = 0; | |
124 while (($REST =~ /[\(\)]/) or ($parenthesis)) { | |
125 while ($REST =~ /[\(\)]/) { | |
126 # collect opening | |
127 while ($REST =~ /^[^\(\)]*\((.*)$/) { | |
128 $parenthesis++; | |
129 $REST = $1; | |
130 } | |
131 | |
132 # collect closing | |
133 while ($REST =~ /^[^\(\)]*\)(.*)$/) { | |
134 $parenthesis--; | |
135 $REST = $1; | |
136 } | |
137 } | |
138 | |
139 # concatenate if not balanced | |
140 if ($parenthesis) { | |
141 if (my $LINE2 = <>) { | |
142 $LINE2 =~ s/^\s*(.*)$/$1/; | |
143 chomp($LINE); | |
144 $LINE .= " " . $LINE2; | |
145 chomp($REST); | |
146 $REST .= " " . $LINE2; | |
147 } else { | |
148 print "ERROR: unbalanced parantheses ($parenthes
is)\n"; | |
149 last; | |
150 } | |
151 } | |
152 } | |
153 | |
154 next if ($LINE =~ /^typedef\s/); | |
155 next if ($LINE =~ /^enum\s+[^\{\(]+\s+\{/); | |
156 next if ($LINE =~ /^struct\s+[^\{\(]+\s+\{.*\}\s*;/); | |
157 next if ($LINE =~ /^struct\s+[a-zA-Z0-9_]+\s*;/); | |
158 | |
159 # remove trailing spaces | |
160 $LINE =~ s/(.*?)\s*$/$1/; | |
161 | |
162 $LINE =~ s/^(.*\))\s+PRINTF_ATTRIBUTE\([^\)]*\)(\s*[;,])/$1$2/; | |
163 $LINE =~ s/^(.*\))\s*[a-zA-Z0-9_]+\s*;$/$1;/; | |
164 | |
165 # remove parameter names - slightly too coarse probably | |
166 $LINE =~ s/([\s\(]\*?)[_0-9a-zA-Z]+\s*([,\)])/$1$2/g; | |
167 | |
168 # remedy (void) from last line | |
169 $LINE =~ s/\(\)/(void)/g; | |
170 | |
171 # normalize spaces | |
172 $LINE =~ s/\s*\)\s*/)/g; | |
173 $LINE =~ s/\s*\(\s*/ (/g; | |
174 $LINE =~ s/\s*,\s*/, /g; | |
175 | |
176 # normalize unsigned | |
177 $LINE =~ s/([\s,\(])unsigned([,\)])/$1unsigned int$2/g; | |
178 | |
179 # normalize bool | |
180 $LINE =~ s/(\b)bool(\b)/_Bool/g; | |
181 | |
182 print $LINE . "\n"; | |
183 } | |
OLD | NEW |