• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/script/
1#!/usr/bin/perl
2# Simple script for updating the prototypes in a C header file
3#
4# Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
5# Published under the GNU GPL
6
7use strict;
8use warnings;
9use Getopt::Long;
10
11=head1 NAME
12
13update-proto - automatically update prototypes in header files
14
15=head1 SYNOPSIS
16
17update-proto [OPTIONS] <HEADER> <C-FILE>...
18
19update-proto [OPTIONS] <HEADER>
20
21=head1 DESCRIPTION
22
23Update-proto makes sure the prototypes in a C header file are current
24by comparing the existing prototypes in a header with the function definition
25in the source file. It aims to keep the diff between the original header
26and generated one as small as possible.
27
28New prototypes are inserted before any line that contains the following comment:
29
30/* New prototypes are inserted above this line */
31
32It will automatically parse C files after it encounters a line that contains:
33
34/* The following definitions come from FILE */
35
36When two or more prototypes exist for a function, only the first one
37will be kept.
38
39=head1 OPTIONS
40
41=over 4
42
43=item I<--verbose|-v>
44
45Increase verbosity. Currently only two levels of verbosity are used.
46
47=item I<--help>
48
49Show list of options
50
51=back
52
53=head1 BUGS
54
55Strange complex functions are not recognized. In particular those
56created by macros or returning (without typedef) function pointers.
57
58=head1 LICENSE
59
60update-proto is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
61
62=head1 AUTHOR
63
64update-proto was written by Jelmer Vernooij L<jelmer@samba.org>.
65
66=cut
67
68sub Usage()
69{
70	print "Usage: update-proto.pl [OPTIONS] <HEADER> <C-FILE>...\n";
71	exit 1;
72}
73
74sub Help()
75{
76	print "Usage: update-proto.pl [OPTIONS] <HEADER> <C-FILE>...\n";
77	print "Options:\n";
78	print "	--help			Show this help message\n";
79	print "	--verbose		Write changes made to standard error\n\n";
80	exit 0;
81}
82
83my %new_protos = ();
84
85my $verbose = 0;
86
87GetOptions(
88	'help|h' => \&Help,
89	'v|verbose' => sub { $verbose += 1; }
90) or Usage();
91
92sub count($$)
93{
94	my ($t, $s) = @_;
95	my $count = 0;
96	while($s =~ s/^(.)//) { $count++ if $1 eq $t; }
97	return $count;
98}
99
100my $header = shift @ARGV;
101
102sub process_file($)
103{
104	my $file = shift;
105	open (IN, "<$file");
106	while (my $line = <IN>) {
107		$_ = $line;
108		next if /^\s/;
109		next unless /\(/;
110		next if /^\/|[;]|^#|}|^\s*static/;
111		s/\/\*(.*?)\*\///g;
112		my $public = s/_PUBLIC_//g;
113		s/_PRINTF_ATTRIBUTE\([^)]+\)//g;
114		next unless /^(struct\s+\w+|union\s+\w+|\w+)\s+\**\s*(\w+)\s*\((.*)$/;
115
116		my $name = $2;
117
118		next if ($name eq "main");
119
120		# Read continuation lines if any
121		my $prn = 1 + count("(", $3) - count(")", $3);
122
123		while ($prn) {
124			my $l = <IN>;
125			$l or die("EOF while parsing function prototype");
126			$line .= $l;
127			$prn += count("(", $l) - count(")", $l);
128		}
129
130		$line =~ s/\n$//;
131
132		# Strip off possible start of function
133		$line =~ s/{\s*$//g;
134
135		$new_protos{$name} = "$line;";
136	}
137	close(IN);
138}
139
140process_file($_) foreach (@ARGV);
141
142my $added = 0;
143my $modified = 0;
144my $deleted = 0;
145my $kept = 0;
146
147sub insert_new_protos()
148{
149	foreach (keys %new_protos) {
150		print "$new_protos{$_}\n";
151		print STDERR "Inserted prototype for `$_'\n" if ($verbose);
152		$added+=1;
153	}
154	%new_protos = ();
155}
156
157my $blankline_due = 0;
158
159open (HDR, "<$header");
160while (my $line = <HDR>) {
161	if ($line eq "\n") {
162		$blankline_due = 1;
163		$line = <HDR>;
164	}
165
166	# Recognize C files that prototypes came from
167	if ($line =~ /\/\* The following definitions come from (.*) \*\//) {
168		insert_new_protos();
169		if ($blankline_due) {
170			print "\n";
171			$blankline_due = 0;
172		}
173		process_file($1);
174		print "$line";
175		next;
176	}
177
178	if ($blankline_due) {
179		print "\n";
180		$blankline_due = 0;
181	}
182
183	# Insert prototypes that weren't in the header before
184	if ($line =~ /\/\* New prototypes are inserted above this line.*\*\/\s*/) {
185		insert_new_protos();
186		print "$line\n";
187		next;
188	}
189
190	if ($line =~ /^\s*typedef |^\#|^\s*static/) {
191		print "$line";
192		next;
193	}
194
195	$_ = $line;
196	s/\/\*(.*?)\*\///g;
197	my $public = s/_PUBLIC_//g;
198	s/_PRINTF_ATTRIBUTE\([^)]+\)//g;
199	unless (/^(struct\s+\w+|union\s+\w+|\w+)\s+\**\s*(\w+)\s*\((.*)$/) {
200		print "$line";
201		next;
202	}
203
204	# Read continuation lines if any
205	my $prn = 1 + count("(", $3) - count(")", $3);
206
207	while ($prn) {
208		my $l = <HDR>;
209		$l or die("EOF while parsing function prototype");
210		$line .= $l;
211		$prn += count("(", $l) - count(")", $l);
212	}
213
214	my $name = $2;
215
216	# This prototype is for a function that was removed
217	unless (defined($new_protos{$name})) {
218		$deleted+=1;
219		print STDERR "Removed prototype for `$name'\n" if ($verbose);
220		next;
221	}
222
223	my $nline = $line;
224	chop($nline);
225
226	if ($new_protos{$name} ne $nline) {
227		$modified+=1;
228		print STDERR "Updated prototype for `$name'\n" if ($verbose);
229		print "$new_protos{$name}\n";
230	} else {
231		$kept+=1;
232		print STDERR "Prototype for `$name' didn't change\n" if ($verbose > 1);
233		print "$line";
234	}
235
236	delete $new_protos{$name};
237}
238close(HDR);
239
240print STDERR "$added added, $modified modified, $deleted deleted, $kept unchanged.\n";
241
2421;
243