lib/param: Merge struct loadparm_service into common
[samba.git] / source4 / script / mkproto.pl
index 1b2a9d355abbf56e068087ed903721160cfd724c..348f150e6dadfb80ea6fb3de2a1492a058614c59 100755 (executable)
@@ -1,19 +1,43 @@
 #!/usr/bin/perl
+# Simple script for generating prototypes for C functions
+# Written by Jelmer Vernooij
+# based on the original mkproto.sh by Andrew Tridgell
 
 use strict;
 
 # don't use warnings module as it is not portable enough
 # use warnings;
 
-
 use Getopt::Long;
+use File::Basename;
+use File::Path;
+
+#####################################################################
+# read a file into a string
 
 my $public_file = undef;
 my $private_file = undef;
+my $all_file = undef;
 my $public_define = undef;
 my $private_define = undef;
-my $public_fd = \*STDOUT;
-my $private_fd = \*STDOUT;
+my $_public = "";
+my $_private = "";
+my $public_data = \$_public;
+my $private_data = \$_private;
+my $builddir = ".";
+my $srcdir = ".";
+
+sub public($)
+{
+       my ($d) = @_;
+       $$public_data .= $d;
+}
+
+sub private($)
+{
+       my ($d) = @_;
+       $$private_data .= $d;
+}
 
 sub usage()
 {
@@ -24,12 +48,15 @@ sub usage()
        print "  --define=DEF           Use DEF to check whether header was already included\n";
        print "  --public-define=DEF    Same as --define, but just for public header\n";
        print "  --private-define=DEF   Same as --define, but just for private header\n";
+       print "  --srcdir=path          Read files relative to this directory\n";
+       print "  --builddir=path        Write file relative to this directory\n";
        print "  --help                 Print this help message\n\n";
        exit 0;
 }
 
 GetOptions(
        'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
+       'all=s' => sub { my ($f,$v) = @_; $public_file = $v; $private_file = $v; },
        'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
        'define=s' => sub { 
                my ($f,$v) = @_; 
@@ -38,74 +65,102 @@ GetOptions(
        },
        'public-define=s' => \$public_define,
        'private-define=s' => \$private_define,
+       'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; },
+       'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; },
        'help' => \&usage
 ) or exit(1);
 
-if (not defined($public_define) and defined($public_file)) {
-       $public_define = ".." . uc($public_file) . "__";
-       $public_define =~ tr{./}{__};
-} elsif (not defined($public_define)) {
-       $public_define = '_PROTO_H_';
-}
+sub normalize_define($$)
+{
+       my ($define, $file) = @_;
+
+       if (not defined($define) and defined($file)) {
+               $define = "__" . uc($file) . "__";
+               $define =~ tr{./}{__};
+               $define =~ tr{\-}{_};
+       } elsif (not defined($define)) {
+               $define = '_PROTO_H_';
+       }
 
-if (not defined($private_define) and defined($private_file)) {
-       $private_define = "__" . uc($private_file) . "__";
-       $private_define =~ tr{./}{__};
-} elsif (not defined($public_define)) {
-       $public_define = '_PROTO_H_';
+       return $define;
 }
 
-if (defined($public_file)) {
-       open PUBLIC, ">$public_file" or die("Can't open `$public_file': $!"); 
-       $public_fd = \*PUBLIC;
+$public_define = normalize_define($public_define, $public_file);
+$private_define = normalize_define($private_define, $private_file);
+
+if ((defined($private_file) and defined($public_file) and ($private_file eq $public_file)) or 
+       (not defined($private_file) and not defined($public_file))) {
+       $private_data = $public_data;
 }
 
-if ($private_file eq $public_file) {
-       $private_fd = $public_fd;
-} elsif (defined($private_file)) {
-       open PRIVATE, ">$private_file" or die("Can't open `$private_file': $!"); ; 
-       $private_fd = \*PRIVATE;
+sub file_load($)
+{
+    my($filename) = @_;
+    local(*INPUTFILE);
+    open(INPUTFILE, $filename) or return undef;
+    my($saved_delim) = $/;
+    undef $/;
+    my($data) = <INPUTFILE>;
+    close(INPUTFILE);
+    $/ = $saved_delim;
+    return $data;
 }
 
 sub print_header($$)
 {
        my ($file, $header_name) = @_;
-       print $file "#ifndef $header_name\n";
-       print $file "#define $header_name\n\n";
-       print $file "/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n";
+       $file->("#ifndef $header_name\n");
+       $file->("#define $header_name\n\n");
+       $file->("#undef _PRINTF_ATTRIBUTE\n");
+       $file->("#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n");
+       $file->("/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n");
 }
 
 sub print_footer($$) 
 {
        my ($file, $header_name) = @_;
-       printf $file "\n#endif /*  %s  */\n", $header_name;
+       $file->("#undef _PRINTF_ATTRIBUTE\n");
+       $file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n");
+       $file->("\n#endif /* $header_name */\n\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";
+       my $scope;
+       my $type;
+       my $name;
+       my $var;
+
+       if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) {
+               $scope = $1;
+               $type = $2;
+               $name = $3;
+               $var = $4;
+       } elsif ($line =~ /^FN_(GLOBAL|LOCAL)_PARM_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) {
+               $scope = $1;
+               $type = $2;
+               $name = $3;
+               $var = $4;
+       } else {
+               return;
        }
+
+       my %tmap = (
+               "BOOL" => "bool ",
+               "CONST_STRING" => "const char *",
+               "STRING" => "const char *",
+               "INTEGER" => "int ",
+               "CHAR" => "char ",
+               "LIST" => "const char **",
+       );
+
+       my %smap = (
+               "GLOBAL" => "struct loadparm_context *",
+               "LOCAL" => "struct loadparm_service *, struct loadparm_service *"
+               );
+
+       $file->("$tmap{$type}lpcfg_$name($smap{$scope});\n");
 }
 
 sub process_file($$$) 
@@ -114,12 +169,31 @@ sub process_file($$$)
 
        $filename =~ s/\.o$/\.c/g;
 
-       open(FH, "< $filename") || die "Failed to open $filename";
+       if ($filename =~ /^\//) {
+               open(FH, "<$filename") or die("Failed to open $filename");
+       } elsif (!open(FH, "< $builddir/$filename")) {
+           open(FH, "< $srcdir/$filename") || die "Failed to open $filename";
+       }
 
-       print $private_file "\n/* The following definitions come from $filename  */\n\n";
+       $private_file->("\n/* The following definitions come from $filename  */\n\n");
 
+       my $comment = undef;
+       my $incomment = 0;
        while (my $line = <FH>) {             
-               my $target = $private_file;
+               my $target = \&private;
+               my $is_public = 0;
+
+               if ($line =~ /^\/\*\*/) { 
+                       $comment = "";
+                       $incomment = 1;
+               }
+
+               if ($incomment) {
+                       $comment .= $line;
+                       if ($line =~ /\*\//) {
+                               $incomment = 0;
+                       }
+               } 
 
                # these are ordered for maximum speed
                next if ($line =~ /^\s/);
@@ -128,58 +202,92 @@ sub process_file($$$)
 
                next if ($line =~ /^\/|[;]/);
 
-               if ($line =~ s/^_PUBLIC_[\t ]//) {
-                       $target = $public_file;
+               if ($line =~ /^FN_/) {
+                       handle_loadparm($public_file, $line);
+                       handle_loadparm($private_file, $line);
+                       next;
                }
 
-               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
+               if ($line =~ /^_PUBLIC_[\t ]/) {
+                       $target = \&public;
+                       $is_public = 1;
+               }
+
+               next unless ( $is_public || $line =~ /
+                             ^(_DEPRECATED_ |_NORETURN_ |_WARN_UNUSED_RESULT_ |_PURE_ )*(
+                                 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|krb5_error_code|NET_API_STATUS)
                              /xo);
 
                next if ($line =~ /^int\s*main/);
 
-               if ($line =~ /^FN_/) {
-                       handle_loadparm($public_file, $line);
-                       next;
-               }
+               $target->("\n$comment") if (defined($comment)); $comment = undef;
 
                if ( $line =~ /\(.*\)\s*$/o ) {
                        chomp $line;
-                       print $target "$line;\n";
+                       $target->("$line;\n");
                        next;
                }
 
-               print $target $line;
+               $target->($line);
 
                while ($line = <FH>) {
                        if ($line =~ /\)\s*$/o) {
                                chomp $line;
-                               print $target "$line;\n";
+                               $target->("$line;\n");
                                last;
                        }
-                       print $target $line;
+                       $target->($line);
                }
        }
 
        close(FH);
 }
 
-print_header($public_fd, $public_define);
-if ($public_file ne $private_file) {
-       print_header($private_fd, $private_define);
 
-       print $private_fd "/* this file contains prototypes for functions that " .
+print_header(\&public, $public_define);
+if (defined($private_file) and defined($public_file) and $public_file ne $private_file) {
+       print_header(\&private, $private_define);
+
+       private("/* this file contains prototypes for functions that " .
                        "are private \n * to this subsystem or library. These functions " .
-                       "should not be \n * used outside this particular subsystem! */\n\n";
+                       "should not be \n * used outside this particular subsystem! */\n\n");
+
+       public("/* this file contains prototypes for functions that " . 
+                       "are part of \n * the public API of this subsystem or library. */\n\n");
 
-       print $public_fd "/* this file contains prototypes for functions that " . 
-                       "are part of \n * the public API of this subsystem or library. */\n\n";
 }
-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);
+
+public("#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n");
+public("#ifndef _PURE_\n#define _PURE_\n#endif\n\n");
+public("#ifndef _NORETURN_\n#define _NORETURN_\n#endif\n\n");
+public("#ifndef _DEPRECATED_\n#define _DEPRECATED_\n#endif\n\n");
+public("#ifndef _WARN_UNUSED_RESULT_\n#define _WARN_UNUSED_RESULT_\n#endif\n\n");
+
+process_file(\&public, \&private, $_) foreach (@ARGV);
+print_footer(\&public, $public_define);
+if (defined($private_file) and $public_file ne $private_file) {
+       print_footer(\&private, $private_define);
+}
+
+if (not defined($public_file)) {
+       print STDOUT $$public_data;
+}
+
+if (not defined($private_file) and defined($public_file)) {
+       print STDOUT $$private_data;
+}
+
+mkpath(dirname($public_file), 0, 0755);
+open(PUBLIC, ">$public_file") or die("Can't open `$public_file': $!"); 
+print PUBLIC "$$public_data";
+close(PUBLIC);
+
+if (defined($private_file) and $public_file ne $private_file) {
+       mkpath(dirname($private_file), 0, 0755);
+       open(PRIVATE, ">$private_file") or die("Can't open `$private_file': $!"); 
+       print PRIVATE "$$private_data";
+       close(PRIVATE);
 }