r12494: Support loading modules from .so files for most subsystems.
[samba.git] / source4 / script / mkproto.pl
old mode 100644 (file)
new mode 100755 (executable)
index b13c4b1..7d80c63
 #!/usr/bin/perl
 
 use strict;
-use warnings;
 
-my $header_name = '_PROTO_H_';
+# don't use warnings module as it is not portable enough
+# use warnings;
+
+
+use Getopt::Long;
+
+my $public_file = undef;
+my $private_file = undef;
+my $public_define = undef;
+my $private_define = undef;
+my $public_fd = \*STDOUT;
+my $private_fd = \*STDOUT;
+
+GetOptions(
+       'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
+       'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
+       'define=s' => sub { 
+               my ($f,$v) = @_; 
+               $public_define = $v; 
+               $private_define = "$v\_PRIVATE"; 
+       },
+       'public-define=s' => \$public_define,
+       'private-define=s' => \$private_define
+);
+
+if (not defined($public_define) and defined($public_file)) {
+       $public_define = $public_file;
+       $public_define =~ tr{./}{__};
+} elsif (not defined($public_define)) {
+       $public_define = '_PROTO_H_';
+}
 
-if ($ARGV[0] eq '-h') {
-       shift @ARGV;
-       $header_name = shift @ARGV;
+if (not defined($private_define) and defined($private_file)) {
+       $private_define = $private_file;
+       $private_define =~ tr{./}{__};
+} elsif (not defined($public_define)) {
+       $public_define = '_PROTO_H_';
 }
 
+if (defined($public_file)) {
+       open PUBLIC, ">$public_file"; 
+       $public_fd = \*PUBLIC;
+}
 
-sub print_header {
-       print "#ifndef $header_name\n";
-       print "#define $header_name\n\n";
-       print "/* This file is automatically generated with \"make proto\". DO NOT EDIT */\n\n";
+if ($private_file eq $public_file) {
+       $private_fd = $public_fd;
+} elsif (not defined($private_file)) {
+       open PRIVATE, ">$private_file"; 
+       $private_fd = \*PRIVATE;
 }
 
-sub print_footer {
-       printf "\n#endif /*  %s  */\n", $header_name;
+sub print_header($$)
+{
+       my ($file, $header_name) = @_;
+       print $file "#ifndef $header_name\n";
+       print $file "#define $header_name\n\n";
+       print $file "/* This file is automatically generated with \"make proto\". DO NOT EDIT */\n\n";
 }
 
+sub print_footer($$) 
+{
+       my ($file, $header_name) = @_;
+       printf $file "\n#endif /*  %s  */\n", $header_name;
+}
 
-sub handle_loadparm {
-       my $line = shift;
-       
-       if ($line =~ /^FN_GLOBAL_STRING/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "char *$fnName(void);\n";
-       } elsif ($line =~ /^FN_LOCAL_STRING/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "char *$fnName(int );\n";
-       } elsif ($line =~ /^FN_GLOBAL_BOOL/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "BOOL $fnName(void);\n";
-       }
-       elsif ($line =~ /^FN_LOCAL_BOOL/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "BOOL $fnName(int );\n";
-       }
-       elsif ($line =~ /^FN_GLOBAL_INTEGER/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "int $fnName(void);\n";
-       }
-       elsif ($line =~ /^FN_LOCAL_INTEGER/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "int $fnName(int );\n";
-       }
-       elsif ($line =~ /^FN_GLOBAL_LIST/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "const char **$fnName(void);\n";
-       }
-       elsif ($line =~ /^FN_LOCAL_LIST/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "const char **$fnName(int );\n";
-       }
-       elsif ($line =~ /^FN_GLOBAL_CONST_STRING/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "const char *$fnName(void);\n";
-       }
-       elsif ($line =~ /^FN_LOCAL_CONST_STRING/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "const char *$fnName(int );\n";
-       }
-       elsif ($line =~ /^FN_LOCAL_CHAR/o) {
-               my $fnName = (split(/[\(,]/, $line))[1];
-               print "char $fnName(int );\n";
+sub handle_loadparm($$) 
+{
+       my ($file,$line) = @_;
+
+       if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
+               my $scope = $1;
+               my $type = $2;
+               my $name = $3;
+
+               my %tmap = (
+                           "BOOL" => "BOOL ",
+                           "CONST_STRING" => "const char *",
+                           "STRING" => "const char *",
+                           "INTEGER" => "int ",
+                           "CHAR" => "char ",
+                           "LIST" => "const char **",
+                           );
+
+               my %smap = (
+                           "GLOBAL" => "void",
+                           "LOCAL" => "int "
+                           );
+
+               print $file "$tmap{$type}$name($smap{$scope});\n";
        }
 }
 
+sub process_file($$$) 
+{
+       my ($public_file, $private_file, $filename) = @_;
 
-sub process_files {
-       my $line;
-       my $inheader;
-       my $gotstart;
+       $filename =~ s/\.o$/\.c/g;
 
-      FILE: foreach my $filename (@ARGV) {
-               next FILE unless (open(FH, "< $filename")); # skip over file unless it can be opened
-               print "\n/* The following definitions come from $filename  */\n\n";
+       open(FH, "< $filename") || die "Failed to open $filename";
 
-               $inheader = 0;
-               $gotstart = 0;
-             LINE: while (defined($line = <FH>)) {
+       print $private_file "\n/* The following definitions come from $filename  */\n\n";
 
-                       if ($inheader) {
-                               # this chomp is somewhat expensive, so don't do it unless we know
-                               # that we probably want to use it
-                               chomp $line;
-                               if ($line =~ /\)\s*$/o) {
-                                       $inheader = 0;
-                                       print "$line;\n";
-                               } else {
-                                       print "$line\n";
-                               }
-                               next LINE;
-                       }
+       while (my $line = <FH>) {             
+               my $target = $private_file;
 
-                       $gotstart = 0;
-
-                       # ignore static and extern declarations
-                       if ($line =~ /^static|^extern/o ||
-                           $line !~ /^[a-zA-Z]/o ||
-                           $line =~ /[;]/o) {
-                               next LINE;
-                       }
+               # these are ordered for maximum speed
+               next if ($line =~ /^\s/);
+             
+               next unless ($line =~ /\(/);
 
+               next if ($line =~ /^\/|[;]/);
 
-                       if ($line =~ /^FN_/) {
-                               handle_loadparm($line);
-                       }
+               next unless ( $line =~ /
+                             ^void|^BOOL|^int|^struct|^char|^const|^\w+_[tT]\s|^uint|^unsigned|^long|
+                             ^NTSTATUS|^ADS_STATUS|^enum\s.*\(|^DATA_BLOB|^WERROR|^XFILE|^FILE|^DIR|
+                             ^double|^TDB_CONTEXT|^TDB_DATA|^TALLOC_CTX|^NTTIME|^FN_|^init_module|
+                             ^GtkWidget|^GType|^smb_ucs2_t
+                             /xo);
 
+               next if ($line =~ /^int\s*main/);
 
-                       # I'm going to leave these as is for now - perl can probably handle larger regex, though -- vance
-                       # I've also sort of put these in approximate order of most commonly called
+               if ($line =~ /^FN_/) {
+                       handle_loadparm($public_file, $line);
+                       next;
+               }
 
-                       elsif ( $line =~ /^NTSTATUS|^void|^BOOL|^int|^struct|^char|^const|^\w+_[tT]\s|^uint|^ADS_STATUS|^enum\s.*\(|^DATA_BLOB|^WERROR/o ) {
-                               $gotstart = 1;
-                       } elsif ( $line =~ /^long|^XFILE|^FILE|^unsigned|^DIR/o) {
-                               $gotstart = 1;
-                       } elsif ( $line =~ /^double|^TDB_CONTEXT|^TDB_DATA|^TALLOC_CTX|^NTTIME/o ) {
-                               $gotstart = 1;
-                       }
+               if ($line =~ s/_PUBLIC_//xo) {
+                       $target = $public_file;
+               }
 
+               if ( $line =~ /\(.*\)\s*$/o ) {
+                       chomp $line;
+                       print $target "$line;\n";
+                       next;
+               }
 
-                       # goto next line if we don't have a start
-                       next LINE unless $gotstart;
+               print $target $line;
 
-                       if ( $line =~ /\(.*\)\s*$/o ) {
-                       # now that we're here, we know we
+               while ($line = <FH>) {
+                       if ($line =~ /\)\s*$/o) {
                                chomp $line;
-                               print "$line;\n";
-                               next LINE;
-                       }
-                       elsif ( $line =~ /\(/o ) {
-
-                               $inheader = 1;
-                               # line hasn't been chomped, so we can assume it already has the \n
-                               print $line;
-                               next LINE;
+                               print $target "$line;\n";
+                               last;
                        }
+                       print $target $line;
                }
        }
+
+       close(FH);
 }
 
-print_header();
-process_files();
-print_footer();
+if ($public_file ne $private_file) {
+       print_header($private_fd, $private_define);
+}
+print_header($public_fd, $public_define);
+process_file($public_fd, $private_fd, $_) foreach (@ARGV);
+print_footer($public_fd, $public_define);
+if ($public_file ne $private_file) {
+       print_footer($private_fd, $private_define);
+}