1f59d82ffSelric# Make prototypes from .c files
2fcfd9267Selric# Id
3f59d82ffSelric
4603f2576Spettaiuse Getopt::Std;
5603f2576Spettaiuse File::Compare;
6f59d82ffSelric
7*e0895134Schristosuse JSON;
8*e0895134Schristos
9f59d82ffSelricmy $comment = 0;
10*e0895134Schristosmy $doxygen = 0;
11*e0895134Schristosmy $funcdoc = 0;
12f59d82ffSelricmy $if_0 = 0;
13f59d82ffSelricmy $brace = 0;
14f59d82ffSelricmy $line = "";
15f59d82ffSelricmy $debug = 0;
16f59d82ffSelricmy $oproto = 1;
17f59d82ffSelricmy $private_func_re = "^_";
18*e0895134Schristosmy %depfunction;
19*e0895134Schristosmy %exported;
20*e0895134Schristosmy %deprecated;
21*e0895134Schristosmy $apple = 0;
22*e0895134Schristosmy %documentation;
23f59d82ffSelric
24603f2576Spettaigetopts('x:m:o:p:dqE:R:P:') || die "foo";
25*e0895134Schristosif($opt_a) {
26*e0895134Schristos    $apple = 1;
27*e0895134Schristos}
28*e0895134Schristos
29*e0895134Schristosif($opt_a) {
30*e0895134Schristos    $apple = 1;
31*e0895134Schristos}
32f59d82ffSelric
33f59d82ffSelricif($opt_d) {
34f59d82ffSelric    $debug = 1;
35f59d82ffSelric}
36f59d82ffSelric
37f59d82ffSelricif($opt_q) {
38f59d82ffSelric    $oproto = 0;
39f59d82ffSelric}
40f59d82ffSelric
41f59d82ffSelricif($opt_R) {
42f59d82ffSelric    $private_func_re = $opt_R;
43f59d82ffSelric}
44603f2576Spettaimy %flags = (
45f59d82ffSelric	  'multiline-proto' => 1,
46f59d82ffSelric	  'header' => 1,
47f59d82ffSelric	  'function-blocking' => 0,
48f59d82ffSelric	  'gnuc-attribute' => 1,
49f59d82ffSelric	  'cxx' => 1
50f59d82ffSelric	  );
51f59d82ffSelricif($opt_m) {
52f59d82ffSelric    foreach $i (split(/,/, $opt_m)) {
53f59d82ffSelric	if($i eq "roken") {
54f59d82ffSelric	    $flags{"multiline-proto"} = 0;
55f59d82ffSelric	    $flags{"header"} = 0;
56f59d82ffSelric	    $flags{"function-blocking"} = 0;
57f59d82ffSelric	    $flags{"gnuc-attribute"} = 0;
58f59d82ffSelric	    $flags{"cxx"} = 0;
59f59d82ffSelric	} else {
60f59d82ffSelric	    if(substr($i, 0, 3) eq "no-") {
61f59d82ffSelric		$flags{substr($i, 3)} = 0;
62f59d82ffSelric	    } else {
63f59d82ffSelric		$flags{$i} = 1;
64f59d82ffSelric	    }
65f59d82ffSelric	}
66f59d82ffSelric    }
67f59d82ffSelric}
68f59d82ffSelric
69f59d82ffSelricif($opt_x) {
70*e0895134Schristos    my $EXP;
71*e0895134Schristos    local $/;
72*e0895134Schristos    open(EXP, '<', $opt_x) || die "open ${opt_x}";
73*e0895134Schristos    my $obj = JSON->new->utf8->decode(<EXP>);
74*e0895134Schristos    close $EXP;
75*e0895134Schristos
76*e0895134Schristos    foreach my $x (keys %$obj) {
77*e0895134Schristos	if (defined $obj->{$x}->{"export"}) {
78*e0895134Schristos	    $exported{$x} = $obj->{$x};
79*e0895134Schristos	}
80*e0895134Schristos	if (defined $obj->{$x}->{"deprecated"}) {
81*e0895134Schristos	    $deprecated{$x} = $obj->{$x}->{"deprecated"};
82f59d82ffSelric	}
83f59d82ffSelric    }
84f59d82ffSelric}
85f59d82ffSelric
86f59d82ffSelricwhile(<>) {
87f59d82ffSelric    print $brace, " ", $_ if($debug);
88f59d82ffSelric
89f59d82ffSelric    # Handle C comments
90f59d82ffSelric    s@/\*.*\*/@@;
91f59d82ffSelric    s@//.*/@@;
92*e0895134Schristos    if ( s@/\*\*(.*)@@) { $comment = 1; $doxygen = 1; $funcdoc = $1;
93*e0895134Schristos    } elsif ( s@/\*.*@@) { $comment = 1;
94*e0895134Schristos    } elsif ($comment && s@.*\*/@@) { $comment = 0; $doxygen = 0;
95*e0895134Schristos    } elsif ($doxygen) { $funcdoc .= $_; next;
96f59d82ffSelric    } elsif ($comment) { next; }
97f59d82ffSelric
98f59d82ffSelric    if(/^\#if 0/) {
99f59d82ffSelric	$if_0 = 1;
100f59d82ffSelric    }
101f59d82ffSelric    if($if_0 && /^\#endif/) {
102f59d82ffSelric	$if_0 = 0;
103f59d82ffSelric    }
104f59d82ffSelric    if($if_0) { next }
105f59d82ffSelric    if(/^\s*\#/) {
106f59d82ffSelric	next;
107f59d82ffSelric    }
108f59d82ffSelric    if(/^\s*$/) {
109f59d82ffSelric	$line = "";
110f59d82ffSelric	next;
111f59d82ffSelric    }
112f59d82ffSelric    if(/\{/){
113f59d82ffSelric	if (!/\}/) {
114f59d82ffSelric	    $brace++;
115f59d82ffSelric	}
116f59d82ffSelric	$_ = $line;
117f59d82ffSelric	while(s/\*\//\ca/){
118f59d82ffSelric	    s/\/\*(.|\n)*\ca//;
119f59d82ffSelric	}
120f59d82ffSelric	s/^\s*//;
121f59d82ffSelric	s/\s*$//;
122f59d82ffSelric	s/\s+/ /g;
123603f2576Spettai	if($_ =~ /\)$/){
124f59d82ffSelric	    if(!/^static/ && !/^PRIVATE/){
125f59d82ffSelric		$attr = "";
126f59d82ffSelric		if(m/(.*)(__attribute__\s?\(.*\))/) {
127f59d82ffSelric		    $attr .= " $2";
128f59d82ffSelric		    $_ = $1;
129f59d82ffSelric		}
130603f2576Spettai		if(m/(.*)\s(\w+DEPRECATED_FUNCTION)\s?(\(.*\))(.*)/) {
131603f2576Spettai		    $depfunction{$2} = 1;
132603f2576Spettai		    $attr .= " $2$3";
133603f2576Spettai		    $_ = "$1 $4";
134603f2576Spettai		}
135603f2576Spettai		if(m/(.*)\s(\w+DEPRECATED)(.*)/) {
136f59d82ffSelric		    $attr .= " $2";
137603f2576Spettai		    $_ = "$1 $3";
138f59d82ffSelric		}
139*e0895134Schristos		if(m/(.*)\s(HEIMDAL_\w+_ATTRIBUTE)\s?(\(.*\))?(.*)/) {
140*e0895134Schristos		    $attr .= " $2$3";
141*e0895134Schristos		    $_ = "$1 $4";
142*e0895134Schristos		}
143f59d82ffSelric		# remove outer ()
144f59d82ffSelric		s/\s*\(/</;
145f59d82ffSelric		s/\)\s?$/>/;
146f59d82ffSelric		# remove , within ()
147f59d82ffSelric		while(s/\(([^()]*),(.*)\)/($1\$$2)/g){}
148f59d82ffSelric		s/\<\s*void\s*\>/<>/;
149f59d82ffSelric		# remove parameter names
150f59d82ffSelric		if($opt_P eq "remove") {
151f59d82ffSelric		    s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g;
152f59d82ffSelric		    s/\s+\*/*/g;
153f59d82ffSelric		    s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g;
154f59d82ffSelric		} elsif($opt_P eq "comment") {
155f59d82ffSelric		    s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g;
156f59d82ffSelric		    s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g;
157f59d82ffSelric		}
158f59d82ffSelric		s/\<\>/<void>/;
159f59d82ffSelric		# add newlines before parameters
160f59d82ffSelric		if($flags{"multiline-proto"}) {
161f59d82ffSelric		    s/,\s*/,\n\t/g;
162f59d82ffSelric		} else {
163f59d82ffSelric		    s/,\s*/, /g;
164f59d82ffSelric		}
165f59d82ffSelric		# fix removed ,
166f59d82ffSelric		s/\$/,/g;
167f59d82ffSelric		# match function name
168f59d82ffSelric		/([a-zA-Z0-9_]+)\s*\</;
169f59d82ffSelric		$f = $1;
170f59d82ffSelric		if($oproto) {
171f59d82ffSelric		    $LP = "__P((";
172f59d82ffSelric		    $RP = "))";
173f59d82ffSelric		} else {
174f59d82ffSelric		    $LP = "(";
175f59d82ffSelric		    $RP = ")";
176f59d82ffSelric		}
177f59d82ffSelric		# only add newline if more than one parameter
178f59d82ffSelric                if($flags{"multiline-proto"} && /,/){
179f59d82ffSelric		    s/\</ $LP\n\t/;
180f59d82ffSelric		}else{
181f59d82ffSelric		    s/\</ $LP/;
182f59d82ffSelric		}
183f59d82ffSelric		s/\>/$RP/;
184f59d82ffSelric		# insert newline before function name
185f59d82ffSelric		if($flags{"multiline-proto"}) {
186f59d82ffSelric		    s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/;
187f59d82ffSelric		}
188f59d82ffSelric		if($attr ne "") {
189f59d82ffSelric		    $_ .= "\n    $attr";
190f59d82ffSelric		}
191*e0895134Schristos		if ($funcdoc) {
192*e0895134Schristos		    $documentation{$f} = $funcdoc;
193*e0895134Schristos		}
194*e0895134Schristos		$funcdoc = undef;
195*e0895134Schristos		if ($apple && exists $exported{$f}) {
196*e0895134Schristos		    $ios = $exported{$f}{ios};
197*e0895134Schristos		    $ios = "NA" if (!defined $ios);
198*e0895134Schristos		    $mac = $exported{$f}{macos};
199*e0895134Schristos		    $mac = "NA" if (!defined $mac);
200*e0895134Schristos		    die "$f neither" if ($mac eq "NA" and $ios eq "NA");
201*e0895134Schristos		    $_ = $_ . "  __OSX_AVAILABLE_STARTING(__MAC_${mac}, __IPHONE_${ios})";
202*e0895134Schristos		}
203*e0895134Schristos		if (exists $deprecated{$f}) {
204*e0895134Schristos		    $_ = $_ . "  GSSAPI_DEPRECATED_FUNCTION(\"$deprecated{$f}\")";
205*e0895134Schristos		    $depfunction{GSSAPI_DEPRECATED_FUNCTION} = 1;
206*e0895134Schristos		}
207f59d82ffSelric		$_ = $_ . ";";
208f59d82ffSelric		$funcs{$f} = $_;
209f59d82ffSelric	    }
210f59d82ffSelric	}
211f59d82ffSelric	$line = "";
212f59d82ffSelric    }
213f59d82ffSelric    if(/\}/){
214f59d82ffSelric	$brace--;
215f59d82ffSelric    }
216f59d82ffSelric    if(/^\}/){
217f59d82ffSelric	$brace = 0;
218f59d82ffSelric    }
219f59d82ffSelric    if($brace == 0) {
220f59d82ffSelric	$line = $line . " " . $_;
221f59d82ffSelric    }
222f59d82ffSelric}
223f59d82ffSelric
224*e0895134Schristosdie "reached end of code and still in doxygen comment" if ($doxygen);
225*e0895134Schristosdie "reached end of code and still in comment" if ($comment);
226*e0895134Schristos
227f59d82ffSelricsub foo {
228f59d82ffSelric    local ($arg) = @_;
229f59d82ffSelric    $_ = $arg;
230f59d82ffSelric    s/.*\/([^\/]*)/$1/;
231f59d82ffSelric    s/.*\\([^\\]*)/$1/;
232f59d82ffSelric    s/[^a-zA-Z0-9]/_/g;
233f59d82ffSelric    "__" . $_ . "__";
234f59d82ffSelric}
235f59d82ffSelric
236f59d82ffSelricif($opt_o) {
237603f2576Spettai    open(OUT, ">${opt_o}.new");
238f59d82ffSelric    $block = &foo($opt_o);
239f59d82ffSelric} else {
240f59d82ffSelric    $block = "__public_h__";
241f59d82ffSelric}
242f59d82ffSelric
243f59d82ffSelricif($opt_p) {
244603f2576Spettai    open(PRIV, ">${opt_p}.new");
245f59d82ffSelric    $private = &foo($opt_p);
246f59d82ffSelric} else {
247f59d82ffSelric    $private = "__private_h__";
248f59d82ffSelric}
249f59d82ffSelric
250f59d82ffSelric$public_h = "";
251f59d82ffSelric$private_h = "";
252f59d82ffSelric
253f59d82ffSelric$public_h_header .= "/* This is a generated file */
254f59d82ffSelric#ifndef $block
255f59d82ffSelric#define $block
256*e0895134Schristos#ifndef DOXY
257f59d82ffSelric
258f59d82ffSelric";
259f59d82ffSelricif ($oproto) {
260f59d82ffSelric    $public_h_header .= "#ifdef __STDC__
261f59d82ffSelric#include <stdarg.h>
262f59d82ffSelric#ifndef __P
263f59d82ffSelric#define __P(x) x
264f59d82ffSelric#endif
265f59d82ffSelric#else
266f59d82ffSelric#ifndef __P
267f59d82ffSelric#define __P(x) ()
268f59d82ffSelric#endif
269f59d82ffSelric#endif
270f59d82ffSelric
271f59d82ffSelric";
272f59d82ffSelric} else {
273f59d82ffSelric    $public_h_header .= "#include <stdarg.h>
274f59d82ffSelric
275f59d82ffSelric";
276f59d82ffSelric}
277f59d82ffSelric$public_h_trailer = "";
278f59d82ffSelric
279f59d82ffSelric$private_h_header = "/* This is a generated file */
280f59d82ffSelric#ifndef $private
281f59d82ffSelric#define $private
282f59d82ffSelric
283f59d82ffSelric";
284f59d82ffSelricif($oproto) {
285f59d82ffSelric    $private_h_header .= "#ifdef __STDC__
286f59d82ffSelric#include <stdarg.h>
287f59d82ffSelric#ifndef __P
288f59d82ffSelric#define __P(x) x
289f59d82ffSelric#endif
290f59d82ffSelric#else
291f59d82ffSelric#ifndef __P
292f59d82ffSelric#define __P(x) ()
293f59d82ffSelric#endif
294f59d82ffSelric#endif
295f59d82ffSelric
296f59d82ffSelric";
297f59d82ffSelric} else {
298f59d82ffSelric    $private_h_header .= "#include <stdarg.h>
299f59d82ffSelric
300f59d82ffSelric";
301f59d82ffSelric}
302f59d82ffSelric$private_h_trailer = "";
303f59d82ffSelric
304*e0895134Schristos
305f59d82ffSelricforeach(sort keys %funcs){
306*e0895134Schristos    if(/^(DllMain|main)$/) { next }
307f59d82ffSelric    if ($funcs{$_} =~ /\^/) {
308f59d82ffSelric	$beginblock = "#ifdef __BLOCKS__\n";
309f59d82ffSelric	$endblock = "#endif /* __BLOCKS__ */\n";
310f59d82ffSelric    } else {
311f59d82ffSelric	$beginblock = $endblock = "";
312f59d82ffSelric    }
313*e0895134Schristos    # if we have an export table and doesn't have content, or matches private RE
314*e0895134Schristos    if((scalar(keys(%exported)) ne 0 && !exists $exported{$_} ) || /$private_func_re/) {
315*e0895134Schristos	$private_h .= $beginblock;
316*e0895134Schristos#	if ($apple and not /$private_func_re/) {
317*e0895134Schristos#	    $private_h .= "#define $_ __ApplePrivate_${_}\n";
318*e0895134Schristos#	}
319*e0895134Schristos	$private_h .= $funcs{$_} . "\n" ;
320*e0895134Schristos	$private_h .= $endblock . "\n";
321f59d82ffSelric	if($funcs{$_} =~ /__attribute__/) {
322f59d82ffSelric	    $private_attribute_seen = 1;
323f59d82ffSelric	}
324f59d82ffSelric    } else {
325*e0895134Schristos	if($documentation{$_}) {
326*e0895134Schristos	    $public_h .= "/**\n";
327*e0895134Schristos	    $public_h .= "$documentation{$_}";
328*e0895134Schristos	    $public_h .= " */\n\n";
329*e0895134Schristos	}
330f59d82ffSelric	if($flags{"function-blocking"}) {
331f59d82ffSelric	    $fupper = uc $_;
332f59d82ffSelric	    if($exported{$_} =~ /proto/) {
333f59d82ffSelric		$public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n";
334f59d82ffSelric	    } else {
335f59d82ffSelric		$public_h .= "#ifndef HAVE_$fupper\n";
336f59d82ffSelric	    }
337f59d82ffSelric	}
338f59d82ffSelric	$public_h .= $beginblock . $funcs{$_} . "\n" . $endblock;
339f59d82ffSelric	if($funcs{$_} =~ /__attribute__/) {
340f59d82ffSelric	    $public_attribute_seen = 1;
341f59d82ffSelric	}
342f59d82ffSelric	if($flags{"function-blocking"}) {
343f59d82ffSelric	    $public_h .= "#endif\n";
344f59d82ffSelric	}
345f59d82ffSelric	$public_h .= "\n";
346f59d82ffSelric    }
347f59d82ffSelric}
348f59d82ffSelric
349f59d82ffSelricif($flags{"gnuc-attribute"}) {
350f59d82ffSelric    if ($public_attribute_seen) {
351f59d82ffSelric	$public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
352f59d82ffSelric#define __attribute__(x)
353f59d82ffSelric#endif
354f59d82ffSelric
355f59d82ffSelric";
356f59d82ffSelric    }
357f59d82ffSelric
358f59d82ffSelric    if ($private_attribute_seen) {
359f59d82ffSelric	$private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
360f59d82ffSelric#define __attribute__(x)
361f59d82ffSelric#endif
362f59d82ffSelric
363f59d82ffSelric";
364f59d82ffSelric    }
365f59d82ffSelric}
366603f2576Spettai
367603f2576Spettaimy $depstr = "";
368603f2576Spettaimy $undepstr = "";
369603f2576Spettaiforeach (keys %depfunction) {
370603f2576Spettai    $depstr .= "#ifndef $_
371603f2576Spettai#ifndef __has_extension
372603f2576Spettai#define __has_extension(x) 0
373603f2576Spettai#define ${_}has_extension 1
374603f2576Spettai#endif
375603f2576Spettai#if __has_extension(attribute_deprecated_with_message)
376603f2576Spettai#define $_(x) __attribute__((__deprecated__(x)))
377603f2576Spettai#elif defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))
378603f2576Spettai#define $_(X) __attribute__((__deprecated__))
379603f2576Spettai#else
380603f2576Spettai#define $_(X)
381603f2576Spettai#endif
382603f2576Spettai#ifdef ${_}has_extension
383603f2576Spettai#undef __has_extension
384603f2576Spettai#undef ${_}has_extension
385603f2576Spettai#endif
386603f2576Spettai#endif /* $_ */
387603f2576Spettai
388603f2576Spettai
389603f2576Spettai";
390603f2576Spettai    $public_h_trailer .= "#undef $_
391603f2576Spettai
392603f2576Spettai";
393603f2576Spettai    $private_h_trailer .= "#undef $_
394603f2576Spettai#define $_(X)
395603f2576Spettai
396603f2576Spettai";
397603f2576Spettai}
398603f2576Spettai
399603f2576Spettai$public_h_header .= $depstr;
400603f2576Spettai$private_h_header .= $depstr;
401603f2576Spettai
402603f2576Spettai
403f59d82ffSelricif($flags{"cxx"}) {
404f59d82ffSelric    $public_h_header .= "#ifdef __cplusplus
405f59d82ffSelricextern \"C\" {
406f59d82ffSelric#endif
407f59d82ffSelric
408f59d82ffSelric";
409603f2576Spettai    $public_h_trailer = "#ifdef __cplusplus
410f59d82ffSelric}
411f59d82ffSelric#endif
412f59d82ffSelric
413603f2576Spettai" . $public_h_trailer;
414f59d82ffSelric
415f59d82ffSelric}
416f59d82ffSelricif ($opt_E) {
417f59d82ffSelric    $public_h_header .= "#ifndef $opt_E
418f59d82ffSelric#ifndef ${opt_E}_FUNCTION
419f59d82ffSelric#if defined(_WIN32)
420f59d82ffSelric#define ${opt_E}_FUNCTION __declspec(dllimport)
421f59d82ffSelric#define ${opt_E}_CALL __stdcall
422f59d82ffSelric#define ${opt_E}_VARIABLE __declspec(dllimport)
423f59d82ffSelric#else
424f59d82ffSelric#define ${opt_E}_FUNCTION
425f59d82ffSelric#define ${opt_E}_CALL
426f59d82ffSelric#define ${opt_E}_VARIABLE
427f59d82ffSelric#endif
428f59d82ffSelric#endif
429f59d82ffSelric#endif
430f59d82ffSelric";
431f59d82ffSelric
432f59d82ffSelric    $private_h_header .= "#ifndef $opt_E
433f59d82ffSelric#ifndef ${opt_E}_FUNCTION
434f59d82ffSelric#if defined(_WIN32)
435f59d82ffSelric#define ${opt_E}_FUNCTION __declspec(dllimport)
436f59d82ffSelric#define ${opt_E}_CALL __stdcall
437f59d82ffSelric#define ${opt_E}_VARIABLE __declspec(dllimport)
438f59d82ffSelric#else
439f59d82ffSelric#define ${opt_E}_FUNCTION
440f59d82ffSelric#define ${opt_E}_CALL
441f59d82ffSelric#define ${opt_E}_VARIABLE
442f59d82ffSelric#endif
443f59d82ffSelric#endif
444f59d82ffSelric#endif
445f59d82ffSelric
446f59d82ffSelric";
447f59d82ffSelric}
448f59d82ffSelric
449603f2576Spettai$public_h_trailer .= $undepstr;
450603f2576Spettai$private_h_trailer .= $undepstr;
451603f2576Spettai
452f59d82ffSelricif ($public_h ne "" && $flags{"header"}) {
453f59d82ffSelric    $public_h = $public_h_header . $public_h .
454*e0895134Schristos	$public_h_trailer . "#endif /* DOXY */\n#endif /* $block */\n";
455f59d82ffSelric}
456f59d82ffSelricif ($private_h ne "" && $flags{"header"}) {
457f59d82ffSelric    $private_h = $private_h_header . $private_h .
458f59d82ffSelric	$private_h_trailer . "#endif /* $private */\n";
459f59d82ffSelric}
460f59d82ffSelric
461f59d82ffSelricif($opt_o) {
462f59d82ffSelric    print OUT $public_h;
463f59d82ffSelric}
464f59d82ffSelricif($opt_p) {
465f59d82ffSelric    print PRIV $private_h;
466f59d82ffSelric}
467f59d82ffSelric
468f59d82ffSelricclose OUT;
469f59d82ffSelricclose PRIV;
470603f2576Spettai
471603f2576Spettaiif ($opt_o) {
472603f2576Spettai
473603f2576Spettai    if (compare("${opt_o}.new", ${opt_o}) != 0) {
474603f2576Spettai	printf("updating ${opt_o}\n");
475603f2576Spettai	rename("${opt_o}.new", ${opt_o});
476603f2576Spettai    } else {
477603f2576Spettai	unlink("${opt_o}.new");
478603f2576Spettai    }
479603f2576Spettai}
480603f2576Spettai
481603f2576Spettaiif ($opt_p) {
482603f2576Spettai    if (compare("${opt_p}.new", ${opt_p}) != 0) {
483603f2576Spettai	printf("updating ${opt_p}\n");
484603f2576Spettai	rename("${opt_p}.new", ${opt_p});
485603f2576Spettai    } else {
486603f2576Spettai	unlink("${opt_p}.new");
487603f2576Spettai    }
488603f2576Spettai}
489