#!/usr/bin/perl # Generate loadparm tables for loadparm.c # by Andrew Bartlett # based on mkproto.pl 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 $file = undef; my $public_define = undef; my $_public = ""; my $_private = ""; my $public_data = \$_public; my $builddir = "."; my $srcdir = "."; my $generate_scope = undef; sub public($) { my ($d) = @_; $$public_data .= $d; } sub usage() { print "Usage: mkparamdefs.pl [options] [c files]\n"; print "OPTIONS:\n"; print " --srcdir=path Read files relative to this directory\n"; print " --builddir=path Write file relative to this directory\n"; print " --generate-scope=[GLOBAL|LOCAL] Filter which definitions to generate\n"; print " --help Print this help message\n\n"; exit 0; } GetOptions( 'file=s' => sub { my ($f,$v) = @_; $file = $v; }, 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }, 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; }, 'generate-scope=s' => sub { my ($f,$v) = @_; $generate_scope = $v; }, 'help' => \&usage ) or exit(1); 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 = '_S3_PARAM_H_'; } return $define; } $public_define = normalize_define($public_define, $file); sub file_load($) { my($filename) = @_; local(*INPUTFILE); open(INPUTFILE, $filename) or return undef; my($saved_delim) = $/; undef $/; my($data) = ; close(INPUTFILE); $/ = $saved_delim; return $data; } sub print_header($$$) { my ($file, $header_name,$generate_scope) = @_; $file->("#ifndef $header_name\n"); $file->("#define $header_name\n\n"); $file->("/* This file was automatically generated by mkparamdefs.pl. DO NOT EDIT */\n\n"); $file->("/**\n"); if ($generate_scope eq "GLOBAL") { $file->(" * This structure describes global (ie., server-wide) parameters.\n"); $file->(" */\n"); $file->("struct loadparm_global \n"); $file->("{\n"); $file->("\tTALLOC_CTX *ctx; /* Context for talloced members */\n"); } elsif ($generate_scope eq "LOCAL") { $file->(" * This structure describes a single service.\n"); $file->(" */\n"); $file->("struct loadparm_service \n"); $file->("{\n"); } } sub print_footer($$$) { my ($file, $header_name, $generate_scope) = @_; $file->("LOADPARM_EXTRA_" . $generate_scope . "S\n"); $file->("};\n"); $file->("\n#endif /* $header_name */\n\n"); } sub handle_loadparm($$$) { my ($file,$line,$generate_scope) = @_; 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" => "char *", "STRING" => "char *", "INTEGER" => "int ", "CHAR" => "char ", "LIST" => "const char **", ); if ($scope eq $generate_scope) { $file->("\t$tmap{$type} $var;\n"); } } sub process_file($$) { my ($file, $filename) = @_; $filename =~ s/\.o$/\.c/g; 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"; } my $comment = undef; my $incomment = 0; while (my $line = ) { if ($line =~ /^\/\*\*/) { $comment = ""; $incomment = 1; } if ($incomment) { $comment .= $line; if ($line =~ /\*\//) { $incomment = 0; } } # these are ordered for maximum speed next if ($line =~ /^\s/); next unless ($line =~ /\(/); next if ($line =~ /^\/|[;]/); if ($line =~ /^static (FN_.*)/) { handle_loadparm($file, $1, $generate_scope); } elsif ($line =~ /^FN_/) { handle_loadparm($file, $line, $generate_scope); } next; } close(FH); } print_header(\&public, $public_define, $generate_scope); process_file(\&public, $_) foreach (@ARGV); print_footer(\&public, $public_define, $generate_scope); if (not defined($file)) { print STDOUT $$public_data; } mkpath(dirname($file), 0, 0755); open(PUBLIC, ">$file") or die("Can't open `$file': $!"); print PUBLIC "$$public_data"; close(PUBLIC);