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