r13964: make lp_* functions public
[samba.git] / source4 / script / mkproto.pl
1 #!/usr/bin/perl
2
3 use strict;
4
5 # don't use warnings module as it is not portable enough
6 # use warnings;
7
8
9 use Getopt::Long;
10
11 my $public_file = undef;
12 my $private_file = undef;
13 my $public_define = undef;
14 my $private_define = undef;
15 my $public_fd = \*STDOUT;
16 my $private_fd = \*STDOUT;
17
18 sub usage()
19 {
20         print "Usage: mkproto.pl [options] [c files]\n";
21         print "OPTIONS:\n";
22         print "  --public=FILE          Write prototypes for public functions to FILE\n";
23         print "  --private=FILE         Write prototypes for private functions to FILE\n";
24         print "  --define=DEF           Use DEF to check whether header was already included\n";
25         print "  --public-define=DEF    Same as --define, but just for public header\n";
26         print "  --private-define=DEF   Same as --define, but just for private header\n";
27         print "  --help                 Print this help message\n\n";
28         exit 0;
29 }
30
31 GetOptions(
32         'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
33         'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
34         'define=s' => sub { 
35                 my ($f,$v) = @_; 
36                 $public_define = $v; 
37                 $private_define = "$v\_PRIVATE"; 
38         },
39         'public-define=s' => \$public_define,
40         'private-define=s' => \$private_define,
41         'help' => \&usage
42 ) or exit(1);
43
44 if (not defined($public_define) and defined($public_file)) {
45         $public_define = ".." . uc($public_file) . "__";
46         $public_define =~ tr{./}{__};
47 } elsif (not defined($public_define)) {
48         $public_define = '_PROTO_H_';
49 }
50
51 if (not defined($private_define) and defined($private_file)) {
52         $private_define = "__" . uc($private_file) . "__";
53         $private_define =~ tr{./}{__};
54 } elsif (not defined($public_define)) {
55         $public_define = '_PROTO_H_';
56 }
57
58 if (defined($public_file)) {
59         open PUBLIC, ">$public_file" or die("Can't open `$public_file': $!"); 
60         $public_fd = \*PUBLIC;
61 }
62
63 if ($private_file eq $public_file) {
64         $private_fd = $public_fd;
65 } elsif (defined($private_file)) {
66         open PRIVATE, ">$private_file" or die("Can't open `$private_file': $!"); ; 
67         $private_fd = \*PRIVATE;
68 }
69
70 sub print_header($$)
71 {
72         my ($file, $header_name) = @_;
73         print $file "#ifndef $header_name\n";
74         print $file "#define $header_name\n\n";
75         print $file "#undef _PRINTF_ATTRIBUTE\n";
76         print $file "#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n";
77         print $file "/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n";
78 }
79
80 sub print_footer($$) 
81 {
82         my ($file, $header_name) = @_;
83         print $file "#undef _PRINTF_ATTRIBUTE\n";
84         print $file "#define _PRINTF_ATTRIBUTE(a1, a2)\n";
85         print $file "\n#endif /* $header_name */\n\n";
86 }
87
88 sub handle_loadparm($$) 
89 {
90         my ($file,$line) = @_;
91
92         if ($line =~ /^_PUBLIC_ FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
93                 my $scope = $1;
94                 my $type = $2;
95                 my $name = $3;
96
97                 my %tmap = (
98                             "BOOL" => "BOOL ",
99                             "CONST_STRING" => "const char *",
100                             "STRING" => "const char *",
101                             "INTEGER" => "int ",
102                             "CHAR" => "char ",
103                             "LIST" => "const char **",
104                             );
105
106                 my %smap = (
107                             "GLOBAL" => "void",
108                             "LOCAL" => "int "
109                             );
110
111                 print $file "$tmap{$type}$name($smap{$scope});\n";
112         }
113 }
114
115 sub process_file($$$) 
116 {
117         my ($public_file, $private_file, $filename) = @_;
118
119         $filename =~ s/\.o$/\.c/g;
120
121         open(FH, "< $filename") || die "Failed to open $filename";
122
123         print $private_file "\n/* The following definitions come from $filename  */\n\n";
124
125         while (my $line = <FH>) {             
126                 my $target = $private_file;
127                 my $is_public = 0;
128
129                 # these are ordered for maximum speed
130                 next if ($line =~ /^\s/);
131               
132                 next unless ($line =~ /\(/);
133
134                 next if ($line =~ /^\/|[;]/);
135
136                 if ($line =~ /^_PUBLIC_ FN_/) {
137                         handle_loadparm($public_file, $line);
138                         next;
139                 }
140
141                 if ($line =~ /^_PUBLIC_[\t ]/) {
142                         $target = $public_file;
143                         $is_public = 1;
144                 }
145
146                 next unless ( $is_public || $line =~ /
147                               ^void|^BOOL|^int|^struct|^char|^const|^\w+_[tT]\s|^uint|^unsigned|^long|
148                               ^NTSTATUS|^ADS_STATUS|^enum\s.*\(|^DATA_BLOB|^WERROR|^XFILE|^FILE|^DIR|
149                               ^double|^TDB_CONTEXT|^TDB_DATA|^TALLOC_CTX|^NTTIME|^FN_|^init_module|
150                               ^GtkWidget|^GType|^smb_ucs2_t
151                               /xo);
152
153                 next if ($line =~ /^int\s*main/);
154
155                 if ( $line =~ /\(.*\)\s*$/o ) {
156                         chomp $line;
157                         print $target "$line;\n";
158                         next;
159                 }
160
161                 print $target $line;
162
163                 while ($line = <FH>) {
164                         if ($line =~ /\)\s*$/o) {
165                                 chomp $line;
166                                 print $target "$line;\n";
167                                 last;
168                         }
169                         print $target $line;
170                 }
171         }
172
173         close(FH);
174 }
175
176 print_header($public_fd, $public_define);
177 if ($public_file ne $private_file) {
178         print_header($private_fd, $private_define);
179
180         print $private_fd "/* this file contains prototypes for functions that " .
181                         "are private \n * to this subsystem or library. These functions " .
182                         "should not be \n * used outside this particular subsystem! */\n\n";
183
184         print $public_fd "/* this file contains prototypes for functions that " . 
185                         "are part of \n * the public API of this subsystem or library. */\n\n";
186 }
187 process_file($public_fd, $private_fd, $_) foreach (@ARGV);
188 print_footer($public_fd, $public_define);
189 if ($public_file ne $private_file) {
190         print_footer($private_fd, $private_define);
191 }