source: branches/samba-3.5.x/source4/script/update-proto.pl

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 4.8 KB
Line 
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;
Note: See TracBrowser for help on using the repository browser.