2 # Simple script for generating prototypes for C functions
3 # Written by Jelmer Vernooij
4 # based on the original mkproto.sh by Andrew Tridgell
8 # don't use warnings module as it is not portable enough
15 #####################################################################
16 # read a file into a string
18 my $public_file = undef;
19 my $private_file = undef;
20 my $public_define = undef;
21 my $private_define = undef;
24 my $public_data = \
$_public;
25 my $private_data = \
$_private;
43 print "Usage: mkproto.pl [options] [c files]\n";
45 print " --public=FILE Write prototypes for public functions to FILE\n";
46 print " --private=FILE Write prototypes for private functions to FILE\n";
47 print " --define=DEF Use DEF to check whether header was already included\n";
48 print " --public-define=DEF Same as --define, but just for public header\n";
49 print " --private-define=DEF Same as --define, but just for private header\n";
50 print " --help Print this help message\n\n";
55 'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
56 'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
60 $private_define = "$v\_PRIVATE";
62 'public-define=s' => \
$public_define,
63 'private-define=s' => \
$private_define,
65 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; },
66 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }
69 if (not defined($public_define) and defined($public_file)) {
70 $public_define = ".." . uc($public_file) . "__";
71 $public_define =~ tr{./}{__};
72 } elsif (not defined($public_define)) {
73 $public_define = '_PROTO_H_';
76 if (not defined($private_define) and defined($private_file)) {
77 $private_define = "__" . uc($private_file) . "__";
78 $private_define =~ tr{./}{__};
79 } elsif (not defined($public_define)) {
80 $public_define = '_PROTO_H_';
83 if ((defined($private_file) and defined($public_file) and ($private_file eq $public_file)) or
84 (not defined($private_file) and not defined($public_file))) {
85 $private_data = $public_data;
90 my($filename) = shift;
92 open(INPUTFILE
, $filename) || return undef;
93 my($saved_delim) = $/;
95 my($data) = <INPUTFILE
>;
103 my ($file, $header_name) = @_;
104 $file->("#ifndef $header_name\n");
105 $file->("#define $header_name\n\n");
106 $file->("#undef _PRINTF_ATTRIBUTE\n");
107 $file->("#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n");
108 $file->("/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n");
113 my ($file, $header_name) = @_;
114 $file->("#undef _PRINTF_ATTRIBUTE\n");
115 $file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n");
116 $file->("\n#endif /* $header_name */\n\n");
119 sub handle_loadparm
($$)
121 my ($file,$line) = @_;
123 if ($line =~ /^_PUBLIC_ FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
130 "CONST_STRING" => "const char *",
131 "STRING" => "const char *",
134 "LIST" => "const char **",
142 $file->("$tmap{$type}$name($smap{$scope});\n");
146 sub process_file
($$$)
148 my ($public_file, $private_file, $filename) = @_;
150 $filename =~ s/\.o$/\.c/g;
152 if (!open(FH
, "< $builddir/$filename")) {
153 open(FH
, "< $srcdir/$filename") || die "Failed to open $filename";
156 $private_file->("\n/* The following definitions come from $filename */\n\n");
158 while (my $line = <FH
>) {
159 my $target = \
&private
;
162 # these are ordered for maximum speed
163 next if ($line =~ /^\s/);
165 next unless ($line =~ /\(/);
167 next if ($line =~ /^\/|[;]/);
169 if ($line =~ /^_PUBLIC_ FN_/) {
170 handle_loadparm
($public_file, $line);
174 if ($line =~ /^_PUBLIC_[\t ]/) {
179 next unless ( $is_public || $line =~ /
180 ^void
|^BOOL
|^int|^struct
|^char
|^const
|^\w
+_
[tT
]\s
|^uint
|^unsigned
|^long
|
181 ^NTSTATUS
|^ADS_STATUS
|^enum\s
.*\
(|^DATA_BLOB
|^WERROR
|^XFILE
|^FILE
|^DIR
|
182 ^double
|^TDB_CONTEXT
|^TDB_DATA
|^TALLOC_CTX
|^NTTIME
|^FN_
|^init_module
|
183 ^GtkWidget
|^GType
|^smb_ucs2_t
186 next if ($line =~ /^int\s*main/);
188 if ( $line =~ /\(.*\)\s*$/o ) {
190 $target->("$line;\n");
196 while ($line = <FH
>) {
197 if ($line =~ /\)\s*$/o) {
199 $target->("$line;\n");
210 print_header
(\
&public
, $public_define);
211 if ($public_file ne $private_file) {
212 print_header
(\
&private
, $private_define);
214 private
("/* this file contains prototypes for functions that " .
215 "are private \n * to this subsystem or library. These functions " .
216 "should not be \n * used outside this particular subsystem! */\n\n");
218 public
("/* this file contains prototypes for functions that " .
219 "are part of \n * the public API of this subsystem or library. */\n\n");
223 public
("#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n");
225 process_file
(\
&public
, \
&private
, $_) foreach (@ARGV);
226 print_footer
(\
&public
, $public_define);
227 if ($public_file ne $private_file) {
228 print_footer
(\
&private
, $private_define);
231 if (not defined($public_file)) {
232 print STDOUT
$$public_data;
235 if (not defined($private_file) and defined($public_file)) {
236 print STDOUT
$$private_data;
239 my $old_public_data = file_load
($public_file);
240 my $old_private_data = file_load
($private_file);
242 if (not defined($old_public_data) or ($old_public_data ne $$public_data))
244 mkpath
(dirname
($public_file), 0, 0755);
245 open(PUBLIC
, ">$public_file") or die("Can't open `$public_file': $!");
246 print PUBLIC
"$$public_data";
250 if (($public_file ne $private_file) and (
251 not defined($old_private_data) or ($old_private_data ne $$private_data))) {
253 mkpath
(dirname
($private_file), 0, 0755);
254 open(PRIVATE
, ">$private_file") or die("Can't open `$private_file': $!");
255 print PRIVATE
"$$private_data";