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