update documentation
[metze/heimdal/wip.git] / cf / make-proto.pl
1 # Make prototypes from .c files
2 # $Id$
3
4 ##use Getopt::Std;
5 require 'getopts.pl';
6
7 my $comment = 0;
8 my $if_0 = 0;
9 my $brace = 0;
10 my $line = "";
11 my $debug = 0;
12 my $oproto = 1;
13 my $private_func_re = "^_";
14
15 do Getopts('x:m:o:p:dqE:R:P:') || die "foo";
16
17 if($opt_d) {
18     $debug = 1;
19 }
20
21 if($opt_q) {
22     $oproto = 0;
23 }
24
25 if($opt_R) {
26     $private_func_re = $opt_R;
27 }
28 %flags = (
29           'multiline-proto' => 1,
30           'header' => 1,
31           'function-blocking' => 0,
32           'gnuc-attribute' => 1,
33           'cxx' => 1
34           );
35 if($opt_m) {
36     foreach $i (split(/,/, $opt_m)) {
37         if($i eq "roken") {
38             $flags{"multiline-proto"} = 0;
39             $flags{"header"} = 0;
40             $flags{"function-blocking"} = 0;
41             $flags{"gnuc-attribute"} = 0;
42             $flags{"cxx"} = 0;
43         } else {
44             if(substr($i, 0, 3) eq "no-") {
45                 $flags{substr($i, 3)} = 0;
46             } else {
47                 $flags{$i} = 1;
48             }
49         }
50     }
51 }
52
53 if($opt_x) {
54     open(EXP, $opt_x);
55     while(<EXP>) {
56         chomp;
57         s/\#.*//g;
58         s/\s+/ /g;
59         if(/^([a-zA-Z0-9_]+)\s?(.*)$/) {
60             $exported{$1} = $2;
61         } else {
62             print $_, "\n";
63         }
64     }
65     close EXP;
66 }
67
68 while(<>) {
69     print $brace, " ", $_ if($debug);
70     
71     # Handle C comments
72     s@/\*.*\*/@@;
73     s@//.*/@@;
74     if ( s@/\*.*@@) { $comment = 1;
75     } elsif ($comment && s@.*\*/@@) { $comment = 0;
76     } elsif ($comment) { next; }
77
78     if(/^\#if 0/) {
79         $if_0 = 1;
80     }
81     if($if_0 && /^\#endif/) {
82         $if_0 = 0;
83     }
84     if($if_0) { next }
85     if(/^\s*\#/) {
86         next;
87     }
88     if(/^\s*$/) {
89         $line = "";
90         next;
91     }
92     if(/\{/){
93         if (!/\}/) {
94             $brace++;
95         }
96         $_ = $line;
97         while(s/\*\//\ca/){
98             s/\/\*(.|\n)*\ca//;
99         }
100         s/^\s*//;
101         s/\s*$//;
102         s/\s+/ /g;
103         if($_ =~ /\)$/ or $_ =~ /DEPRECATED$/){
104             if(!/^static/ && !/^PRIVATE/){
105                 $attr = "";
106                 if(m/(.*)(__attribute__\s?\(.*\))/) {
107                     $attr .= " $2";
108                     $_ = $1;
109                 }
110                 if(m/(.*)\s(\w+DEPRECATED)/) {
111                     $attr .= " $2";
112                     $_ = $1;
113                 }
114                 # remove outer ()
115                 s/\s*\(/</;
116                 s/\)\s?$/>/;
117                 # remove , within ()
118                 while(s/\(([^()]*),(.*)\)/($1\$$2)/g){}
119                 s/\<\s*void\s*\>/<>/;
120                 # remove parameter names 
121                 if($opt_P eq "remove") {
122                     s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g;
123                     s/\s+\*/*/g;
124                     s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g;
125                 } elsif($opt_P eq "comment") {
126                     s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g;
127                     s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g;
128                 }
129                 s/\<\>/<void>/;
130                 # add newlines before parameters
131                 if($flags{"multiline-proto"}) {
132                     s/,\s*/,\n\t/g;
133                 } else {
134                     s/,\s*/, /g;
135                 }
136                 # fix removed ,
137                 s/\$/,/g;
138                 # match function name
139                 /([a-zA-Z0-9_]+)\s*\</;
140                 $f = $1;
141                 if($oproto) {
142                     $LP = "__P((";
143                     $RP = "))";
144                 } else {
145                     $LP = "(";
146                     $RP = ")";
147                 }
148                 # only add newline if more than one parameter
149                 if($flags{"multiline-proto"} && /,/){ 
150                     s/\</ $LP\n\t/;
151                 }else{
152                     s/\</ $LP/;
153                 }
154                 s/\>/$RP/;
155                 # insert newline before function name
156                 if($flags{"multiline-proto"}) {
157                     s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/;
158                 }
159                 if($attr ne "") {
160                     $_ .= "\n    $attr";
161                 }
162                 $_ = $_ . ";";
163                 $funcs{$f} = $_;
164             }
165         }
166         $line = "";
167     }
168     if(/\}/){
169         $brace--;
170     }
171     if(/^\}/){
172         $brace = 0;
173     }
174     if($brace == 0) {
175         $line = $line . " " . $_;
176     }
177 }
178
179 sub foo {
180     local ($arg) = @_;
181     $_ = $arg;
182     s/.*\/([^\/]*)/$1/;
183     s/[^a-zA-Z0-9]/_/g;
184     "__" . $_ . "__";
185 }
186
187 if($opt_o) {
188     open(OUT, ">$opt_o");
189     $block = &foo($opt_o);
190 } else {
191     $block = "__public_h__";
192 }
193
194 if($opt_p) {
195     open(PRIV, ">$opt_p");
196     $private = &foo($opt_p);
197 } else {
198     $private = "__private_h__";
199 }
200
201 $public_h = "";
202 $private_h = "";
203
204 $public_h_header .= "/* This is a generated file */
205 #ifndef $block
206 #define $block
207
208 ";
209 if ($oproto) {
210     $public_h_header .= "#ifdef __STDC__
211 #include <stdarg.h>
212 #ifndef __P
213 #define __P(x) x
214 #endif
215 #else
216 #ifndef __P
217 #define __P(x) ()
218 #endif
219 #endif
220
221 ";
222 } else {
223     $public_h_header .= "#include <stdarg.h>
224
225 ";
226 }
227 $public_h_trailer = "";
228
229 $private_h_header = "/* This is a generated file */
230 #ifndef $private
231 #define $private
232
233 ";
234 if($oproto) {
235     $private_h_header .= "#ifdef __STDC__
236 #include <stdarg.h>
237 #ifndef __P
238 #define __P(x) x
239 #endif
240 #else
241 #ifndef __P
242 #define __P(x) ()
243 #endif
244 #endif
245
246 ";
247 } else {
248     $private_h_header .= "#include <stdarg.h>
249
250 ";
251 }
252 $private_h_trailer = "";
253
254 foreach(sort keys %funcs){
255     if(/^(main)$/) { next }
256     if(!defined($exported{$_}) && /$private_func_re/) {
257         $private_h .= $funcs{$_} . "\n\n";
258         if($funcs{$_} =~ /__attribute__/) {
259             $private_attribute_seen = 1;
260         }
261     } else {
262         if($flags{"function-blocking"}) {
263             $fupper = uc $_;
264             if($exported{$_} =~ /proto/) {
265                 $public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n";
266             } else {
267                 $public_h .= "#ifndef HAVE_$fupper\n";
268             }
269         }
270         $public_h .= $funcs{$_} . "\n";
271         if($funcs{$_} =~ /__attribute__/) {
272             $public_attribute_seen = 1;
273         }
274         if($flags{"function-blocking"}) {
275             $public_h .= "#endif\n";
276         }
277         $public_h .= "\n";
278     }
279 }
280
281 if($flags{"gnuc-attribute"}) {
282     if ($public_attribute_seen) {
283         $public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
284 #define __attribute__(x)
285 #endif
286
287 ";
288     }
289
290     if ($private_attribute_seen) {
291         $private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
292 #define __attribute__(x)
293 #endif
294
295 ";
296     }
297 }
298 if($flags{"cxx"}) {
299     $public_h_header .= "#ifdef __cplusplus
300 extern \"C\" {
301 #endif
302
303 ";
304     $public_h_trailer .= "#ifdef __cplusplus
305 }
306 #endif
307
308 ";
309
310 }
311 if ($opt_E) {
312     $public_h_header .= "#ifndef $opt_E
313 #if defined(_WIN32)
314 #define ${opt_E}_FUNCTION _stdcall __declspec(dllimport)
315 #define ${opt_E}_VARIABLE __declspec(dllimport)
316 #else
317 #define ${opt_E}_FUNCTION
318 #define ${opt_E}_VARIABLE
319 #endif
320 #endif
321
322 ";
323     
324     $private_h_header .= "#ifndef $opt_E
325 #if defined(_WIN32)
326 #define ${opt_E}_FUNCTION _stdcall __declspec(dllimport)
327 #define ${opt_E}_VARIABLE __declspec(dllimport)
328 #else
329 #define ${opt_E}_FUNCTION
330 #define ${opt_E}_VARIABLE
331 #endif
332 #endif
333
334 ";
335 }
336     
337 if ($public_h ne "" && $flags{"header"}) {
338     $public_h = $public_h_header . $public_h . 
339         $public_h_trailer . "#endif /* $block */\n";
340 }
341 if ($private_h ne "" && $flags{"header"}) {
342     $private_h = $private_h_header . $private_h .
343         $private_h_trailer . "#endif /* $private */\n";
344 }
345
346 if($opt_o) {
347     print OUT $public_h;
348
349 if($opt_p) {
350     print PRIV $private_h;
351
352
353 close OUT;
354 close PRIV;