• 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 generating prototypes for C functions
3# Written by Jelmer Vernooij
4# based on the original mkproto.sh by Andrew Tridgell
5
6use strict;
7
8# don't use warnings module as it is not portable enough
9# use warnings;
10
11use Getopt::Long;
12use File::Basename;
13use File::Path;
14
15#####################################################################
16# read a file into a string
17
18my $public_file = undef;
19my $private_file = undef;
20my $all_file = undef;
21my $public_define = undef;
22my $private_define = undef;
23my $_public = "";
24my $_private = "";
25my $public_data = \$_public;
26my $private_data = \$_private;
27my $builddir = ".";
28my $srcdir = ".";
29
30sub public($)
31{
32	my ($d) = @_;
33	$$public_data .= $d;
34}
35
36sub private($)
37{
38	my ($d) = @_;
39	$$private_data .= $d;
40}
41
42sub usage()
43{
44	print "Usage: mkproto.pl [options] [c files]\n";
45	print "OPTIONS:\n";
46	print "  --public=FILE          Write prototypes for public functions to FILE\n";
47	print "  --private=FILE         Write prototypes for private functions to FILE\n";
48	print "  --define=DEF           Use DEF to check whether header was already included\n";
49	print "  --public-define=DEF    Same as --define, but just for public header\n";
50	print "  --private-define=DEF   Same as --define, but just for private header\n";
51	print "  --srcdir=path          Read files relative to this directory\n";
52	print "  --builddir=path        Write file relative to this directory\n";
53	print "  --help                 Print this help message\n\n";
54	exit 0;
55}
56
57GetOptions(
58	'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
59	'all=s' => sub { my ($f,$v) = @_; $public_file = $v; $private_file = $v; },
60	'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
61	'define=s' => sub {
62		my ($f,$v) = @_;
63		$public_define = $v;
64		$private_define = "$v\_PRIVATE";
65	},
66	'public-define=s' => \$public_define,
67	'private-define=s' => \$private_define,
68	'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; },
69	'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; },
70	'help' => \&usage
71) or exit(1);
72
73sub normalize_define($$)
74{
75	my ($define, $file) = @_;
76
77	if (not defined($define) and defined($file)) {
78		$define = "__" . uc($file) . "__";
79		$define =~ tr{./}{__};
80		$define =~ tr{\-}{_};
81	} elsif (not defined($define)) {
82		$define = '_PROTO_H_';
83	}
84
85	return $define;
86}
87
88$public_define = normalize_define($public_define, $public_file);
89$private_define = normalize_define($private_define, $private_file);
90
91if ((defined($private_file) and defined($public_file) and ($private_file eq $public_file)) or
92	(not defined($private_file) and not defined($public_file))) {
93	$private_data = $public_data;
94}
95
96sub file_load($)
97{
98    my($filename) = @_;
99    local(*INPUTFILE);
100    open(INPUTFILE, $filename) or return undef;
101    my($saved_delim) = $/;
102    undef $/;
103    my($data) = <INPUTFILE>;
104    close(INPUTFILE);
105    $/ = $saved_delim;
106    return $data;
107}
108
109sub print_header($$)
110{
111	my ($file, $header_name) = @_;
112	$file->("#ifndef $header_name\n");
113	$file->("#define $header_name\n\n");
114	$file->("#undef _PRINTF_ATTRIBUTE\n");
115	$file->("#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n");
116	$file->("/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n");
117}
118
119sub print_footer($$)
120{
121	my ($file, $header_name) = @_;
122	$file->("#undef _PRINTF_ATTRIBUTE\n");
123	$file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n");
124	$file->("\n#endif /* $header_name */\n\n");
125}
126
127sub handle_loadparm($$)
128{
129	my ($file,$line) = @_;
130
131	if ($line =~ /^_PUBLIC_ FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
132		my $scope = $1;
133		my $type = $2;
134		my $name = $3;
135
136		my %tmap = (
137			    "BOOL" => "bool ",
138			    "CONST_STRING" => "const char *",
139			    "STRING" => "const char *",
140			    "INTEGER" => "int ",
141			    "CHAR" => "char ",
142			    "LIST" => "const char **",
143			    );
144
145		my %smap = (
146			    "GLOBAL" => "struct loadparm_context *",
147			    "LOCAL" => "struct loadparm_service *, struct loadparm_service *"
148			    );
149
150		$file->("$tmap{$type}$name($smap{$scope});\n");
151	}
152}
153
154sub process_file($$$)
155{
156	my ($public_file, $private_file, $filename) = @_;
157
158	$filename =~ s/\.o$/\.c/g;
159
160	if ($filename =~ /^\//) {
161		open(FH, "<$filename") or die("Failed to open $filename");
162	} elsif (!open(FH, "< $builddir/$filename")) {
163	    open(FH, "< $srcdir/$filename") || die "Failed to open $filename";
164	}
165
166	$private_file->("\n/* The following definitions come from $filename  */\n\n");
167
168	my $comment = undef;
169	my $incomment = 0;
170	while (my $line = <FH>) {
171		my $target = \&private;
172		my $is_public = 0;
173
174		if ($line =~ /^\/\*\*/) {
175			$comment = "";
176			$incomment = 1;
177		}
178
179		if ($incomment) {
180			$comment .= $line;
181			if ($line =~ /\*\//) {
182				$incomment = 0;
183			}
184		}
185
186		# these are ordered for maximum speed
187		next if ($line =~ /^\s/);
188
189		next unless ($line =~ /\(/);
190
191		next if ($line =~ /^\/|[;]/);
192
193		if ($line =~ /^_PUBLIC_ FN_/) {
194			handle_loadparm($public_file, $line);
195			handle_loadparm($private_file, $line);
196			next;
197		}
198
199		if ($line =~ /^_PUBLIC_[\t ]/) {
200			$target = \&public;
201			$is_public = 1;
202		}
203
204		next unless ( $is_public || $line =~ /
205			      ^(_DEPRECATED_ |_NORETURN_ |_WARN_UNUSED_RESULT_ |_PURE_ )*(
206				  void|bool|int|struct|char|const|\w+_[tT]\s|uint|unsigned|long|NTSTATUS|
207				  ADS_STATUS|enum\s.*\(|DATA_BLOB|WERROR|XFILE|FILE|DIR|
208			      double|TDB_CONTEXT|TDB_DATA|TALLOC_CTX|NTTIME|FN_|init_module|
209			      GtkWidget|GType|smb_ucs2_t|krb5_error_code|NET_API_STATUS)
210			      /xo);
211
212		next if ($line =~ /^int\s*main/);
213
214		$target->("\n$comment") if (defined($comment)); $comment = undef;
215
216		if ( $line =~ /\(.*\)\s*$/o ) {
217			chomp $line;
218			$target->("$line;\n");
219			next;
220		}
221
222		$target->($line);
223
224		while ($line = <FH>) {
225			if ($line =~ /\)\s*$/o) {
226				chomp $line;
227				$target->("$line;\n");
228				last;
229			}
230			$target->($line);
231		}
232	}
233
234	close(FH);
235}
236
237
238print_header(\&public, $public_define);
239if (defined($private_file) and defined($public_file) and $public_file ne $private_file) {
240	print_header(\&private, $private_define);
241
242	private("/* this file contains prototypes for functions that " .
243			"are private \n * to this subsystem or library. These functions " .
244			"should not be \n * used outside this particular subsystem! */\n\n");
245
246	public("/* this file contains prototypes for functions that " .
247			"are part of \n * the public API of this subsystem or library. */\n\n");
248
249}
250
251public("#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n");
252public("#ifndef _PURE_\n#define _PURE_\n#endif\n\n");
253public("#ifndef _NORETURN_\n#define _NORETURN_\n#endif\n\n");
254public("#ifndef _DEPRECATED_\n#define _DEPRECATED_\n#endif\n\n");
255public("#ifndef _WARN_UNUSED_RESULT_\n#define _WARN_UNUSED_RESULT_\n#endif\n\n");
256
257process_file(\&public, \&private, $_) foreach (@ARGV);
258print_footer(\&public, $public_define);
259if (defined($private_file) and $public_file ne $private_file) {
260	print_footer(\&private, $private_define);
261}
262
263if (not defined($public_file)) {
264	print STDOUT $$public_data;
265}
266
267if (not defined($private_file) and defined($public_file)) {
268	print STDOUT $$private_data;
269}
270
271mkpath(dirname($public_file), 0, 0755);
272open(PUBLIC, ">$public_file") or die("Can't open `$public_file': $!");
273print PUBLIC "$$public_data";
274close(PUBLIC);
275
276if (defined($private_file) and $public_file ne $private_file) {
277	mkpath(dirname($private_file), 0, 0755);
278	open(PRIVATE, ">$private_file") or die("Can't open `$private_file': $!");
279	print PRIVATE "$$private_data";
280	close(PRIVATE);
281}
282