diff options
Diffstat (limited to 'source4/script')
-rwxr-xr-x | source4/script/buildtree.pl | 40 | ||||
-rwxr-xr-x | source4/script/depfilter.py | 53 | ||||
-rwxr-xr-x | source4/script/extract_allparms.sh | 2 | ||||
-rwxr-xr-x | source4/script/find_unused_options.sh | 37 | ||||
-rwxr-xr-x | source4/script/minimal_includes.pl | 171 | ||||
-rwxr-xr-x | source4/script/mkproto.pl | 252 | ||||
-rwxr-xr-x | source4/script/update-proto.pl | 242 |
7 files changed, 797 insertions, 0 deletions
diff --git a/source4/script/buildtree.pl b/source4/script/buildtree.pl new file mode 100755 index 0000000..a40036a --- /dev/null +++ b/source4/script/buildtree.pl @@ -0,0 +1,40 @@ +#! /usr/bin/env perl -w + eval 'exec /usr/bin/env perl -S $0 ${1+"$@"}' + if 0; #$running_under_some_shell + +use strict; +use File::Find (); +use File::Path qw(mkpath); +use Cwd 'abs_path'; + +# Set the variable $File::Find::dont_use_nlink if you're using AFS, +# since AFS cheats. + +# for the convenience of &wanted calls, including -eval statements: +use vars qw/*name *dir *prune/; +*name = *File::Find::name; +*dir = *File::Find::dir; +*prune = *File::Find::prune; +my $builddir = abs_path($ENV{builddir}); +my $srcdir = abs_path($ENV{srcdir}); +sub wanted; + + + +# Traverse desired filesystems +File::Find::find({wanted => \&wanted, no_chdir => 1}, $srcdir); +exit; + + +sub wanted { + my ($dev,$ino,$mode,$nlink,$uid,$gid,$newdir); + + if ((($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && + (-d _) && (($newdir = abs_path($_)) !~ /$builddir/)) + { + $newdir =~ s!$srcdir!$builddir!; + mkpath($newdir); + print("Creating $newdir\n"); + } +} + diff --git a/source4/script/depfilter.py b/source4/script/depfilter.py new file mode 100755 index 0000000..ee2ce9d --- /dev/null +++ b/source4/script/depfilter.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# +# Filter out arcs in a dotty graph that are at or below a certain +# node. This is useful for visualising parts of the dependency graph. +# + +# Command line stuff + +import sys +import re + +if len(sys.argv) != 2: + print('Usage: depfilter.py NODE') + sys.exit(1) + +top = sys.argv[1] + +# Read in dot file + +lines = sys.stdin.readlines() + +graph = {} + +for arc in lines[1:-1]: + match = re.search('"(.*)" -> "(.*)"', arc) + n1, n2 = match.group(1), match.group(2) + if n1 not in graph: + graph[n1] = [] + graph[n1].append(n2) + +# Create subset of 'graph' rooted at 'top' + +subgraph = {} + + +def add_deps(node): + if node in graph and node not in subgraph: + subgraph[node] = graph[node] + for n in graph[node]: + add_deps(n) + + +add_deps(top) + +# Generate output + +print(lines[0], end=' ') + +for key, value in subgraph.items(): + for n in value: + print('\t"%s" -> "%s"' % (key, n)) + +print(lines[-1], end=' ') diff --git a/source4/script/extract_allparms.sh b/source4/script/extract_allparms.sh new file mode 100755 index 0000000..f16068b --- /dev/null +++ b/source4/script/extract_allparms.sh @@ -0,0 +1,2 @@ +#!/bin/sh +grep '{".*P_[GL]' param/loadparm.c | sed -e 's/&.*$//g' -e 's/",.*P_LOCAL.*$/ S/' -e 's/",.*P_GLOBAL.*$/ G/' -e 's/^ .*{"//g' | sort -f diff --git a/source4/script/find_unused_options.sh b/source4/script/find_unused_options.sh new file mode 100755 index 0000000..36e9771 --- /dev/null +++ b/source4/script/find_unused_options.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# this script finds unused lp_*() functions +# +# use it like this: +# +# user@host:~/samba/source>./script/find_unused_options.sh +# + +LIST_GLOBAL=$(grep '^FN_GLOBAL' param/loadparm.c | sed -e's/^FN_GLOBAL.*(\(.*\).*,.*\(&Globals\..*\)).*/\1:\2/') + +LIST_LOCAL=$(grep '^FN_LOCAL' param/loadparm.c | sed -e's/^FN_LOCAL.*(\(.*\).*,[ ]*\(.*\)).*/\1:\2/') + +CFILES=$(find . -name "*.c") + +for i in $LIST_GLOBAL; do + key=$(echo $i | cut -d ':' -f1) + val=$(echo $i | cut -d ':' -f2) + + found=$(grep "$key[ ]*()" $CFILES) + if test -z "$found"; then + echo "Not Used Global: $key() -> $val" + fi +done + +for i in $LIST_LOCAL; do + key=$(echo $i | cut -d ':' -f1) + val=$(echo $i | cut -d ':' -f2) + + found=$(grep "$key[ ]*(" $CFILES) + + if test -z "$found"; then + echo "Not Used LOCAL: $key() -> $val" + fi +done + +echo "# do a 'make clean;make everything' before removing anything!" diff --git a/source4/script/minimal_includes.pl b/source4/script/minimal_includes.pl new file mode 100755 index 0000000..4203d00 --- /dev/null +++ b/source4/script/minimal_includes.pl @@ -0,0 +1,171 @@ +#!/usr/bin/perl -w +# find a list of #include lines in C code that might not be needed +# usually called with something like this: +# minimal_includes.pl `find . -name "*.c"` +# Andrew Tridgell <tridge@samba.org> + +use strict; +use Data::Dumper; +use Getopt::Long; + +my $opt_help = 0; +my $opt_remove = 0; +my $opt_skip_system = 0; +my $opt_waf = 0; + +##################################################################### +# write a string into a file +sub FileSave($$) +{ + my($filename) = shift; + my($v) = shift; + local(*FILE); + open(FILE, ">$filename") || die "can't open $filename"; + print FILE $v; + close(FILE); +} + +sub load_lines($) +{ + my $fname = shift; + my @lines = split(/^/m, `cat $fname`); + return @lines; +} + +sub save_lines($$) +{ + my $fname = shift; + my $lines = shift; + my $data = join('', @{$lines}); + FileSave($fname, $data); +} + +sub test_compile($) +{ + my $fname = shift; + my $obj; + if ($opt_waf) { + my $ret = `../buildtools/bin/waf $fname 2>&1`; + return $ret + } + if ($fname =~ s/(.*)\..*$/$1.o/) { + $obj = "$1.o"; + } else { + return "NOT A C FILE"; + } + unlink($obj); + my $ret = `make $obj 2>&1`; + if (!unlink("$obj")) { + return "COMPILE FAILED"; + } + return $ret; +} + +sub test_include($$$$) +{ + my $fname = shift; + my $lines = shift; + my $i = shift; + my $original = shift; + my $line = $lines->[$i]; + my $testfname; + + $lines->[$i] = ""; + + my $mname = $fname . ".misaved"; + + unlink($mname); + rename($fname, $mname) || die "failed to rename $fname"; + save_lines($fname, $lines); + + my $out = test_compile($fname); + + if ($out eq $original) { + if ($opt_remove) { + if ($opt_skip_system && + $line =~ /system\//) { + print "$fname: not removing system include $line\n"; + } else { + print "$fname: removing $line\n"; + unlink($mname); + return; + } + } else { + print "$fname: might be able to remove $line\n"; + } + } + + $lines->[$i] = $line; + rename($mname, $fname) || die "failed to restore $fname"; +} + +sub process_file($) +{ + my $fname = shift; + my @lines = load_lines($fname); + my $num_lines = $#lines; + + my $original = test_compile($fname); + + if ($original eq "COMPILE FAILED") { + print "Failed to compile $fname\n"; + return; + } + + print "Processing $fname (with $num_lines lines)\n"; + + my $if_level = 0; + + for (my $i=0;$i<=$num_lines;$i++) { + my $line = $lines[$i]; + if ($line =~ /^\#\s*if/) { + $if_level++; + } + if ($line =~ /^\#\s*endif/) { + $if_level--; + } + if ($if_level == 0 && + $line =~ /^\#\s*include/ && + !($line =~ /needed/)) { + test_include($fname, \@lines, $i, $original); + } + } +} + + +######################################### +# display help text +sub ShowHelp() +{ + print " + minimise includes + Copyright (C) tridge\@samba.org + + Usage: minimal_includes.pl [options] <C files....> + + Options: + --help show help + --remove remove includes, don't just list them + --skip-system don't remove system/ includes + --waf use waf target conventions +"; +} + + +# main program +GetOptions ( + 'h|help|?' => \$opt_help, + 'remove' => \$opt_remove, + 'skip-system' => \$opt_skip_system, + 'waf' => \$opt_waf, + ); + +if ($opt_help) { + ShowHelp(); + exit(0); +} + +for (my $i=0;$i<=$#ARGV;$i++) { + my $fname = $ARGV[$i]; + process_file($fname); +} diff --git a/source4/script/mkproto.pl b/source4/script/mkproto.pl new file mode 100755 index 0000000..2c3ebac --- /dev/null +++ b/source4/script/mkproto.pl @@ -0,0 +1,252 @@ +#!/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 = ""; +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() +{ + print "Usage: mkproto.pl [options] [c files]\n"; + print "OPTIONS:\n"; + print " --public=FILE Write prototypes for public functions to FILE\n"; + print " --private=FILE Write prototypes for private functions to FILE\n"; + 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) = @_; + $public_define = $v; + $private_define = "$v\_PRIVATE"; + }, + '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); + +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_'; + } + + return $define; +} + +$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; +} + +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) = @_; + $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) = @_; + $file->("#undef _PRINTF_ATTRIBUTE\n"); + $file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n"); + $file->("\n#endif /* $header_name */\n\n"); +} + +sub process_file($$$) +{ + my ($public_file, $private_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"; + } + + $private_file->("\n/* The following definitions come from $filename */\n\n"); + + my $comment = undef; + my $incomment = 0; + while (my $line = <FH>) { + 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/); + + next unless ($line =~ /\(/); + + next if ($line =~ /^\/|[;]/); + + if ($line =~ /^FN_/) { + next; + } + + 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/); + + $target->("\n$comment") if (defined($comment)); $comment = undef; + + if ( $line =~ /\(.*\)\s*$/o ) { + chomp $line; + $target->("$line;\n"); + next; + } + + $target->($line); + + while ($line = <FH>) { + if ($line =~ /\)\s*$/o) { + chomp $line; + $target->("$line;\n"); + last; + } + $target->($line); + } + } + + close(FH); +} + + +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"); + + public("/* this file contains prototypes for functions that " . + "are part of \n * the public API of this subsystem or library. */\n\n"); + +} + +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); +} diff --git a/source4/script/update-proto.pl b/source4/script/update-proto.pl new file mode 100755 index 0000000..c130650 --- /dev/null +++ b/source4/script/update-proto.pl @@ -0,0 +1,242 @@ +#!/usr/bin/perl +# Simple script for updating the prototypes in a C header file +# +# Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL + +use strict; +use warnings; +use Getopt::Long; + +=head1 NAME + +update-proto - automatically update prototypes in header files + +=head1 SYNOPSIS + +update-proto [OPTIONS] <HEADER> <C-FILE>... + +update-proto [OPTIONS] <HEADER> + +=head1 DESCRIPTION + +Update-proto makes sure the prototypes in a C header file are current +by comparing the existing prototypes in a header with the function definition +in the source file. It aims to keep the diff between the original header +and generated one as small as possible. + +New prototypes are inserted before any line that contains the following comment: + +/* New prototypes are inserted above this line */ + +It will automatically parse C files after it encounters a line that contains: + +/* The following definitions come from FILE */ + +When two or more prototypes exist for a function, only the first one +will be kept. + +=head1 OPTIONS + +=over 4 + +=item I<--verbose|-v> + +Increase verbosity. Currently only two levels of verbosity are used. + +=item I<--help> + +Show list of options + +=back + +=head1 BUGS + +Strange complex functions are not recognized. In particular those +created by macros or returning (without typedef) function pointers. + +=head1 LICENSE + +update-proto is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>. + +=head1 AUTHOR + +update-proto was written by Jelmer Vernooij L<jelmer@samba.org>. + +=cut + +sub Usage() +{ + print "Usage: update-proto.pl [OPTIONS] <HEADER> <C-FILE>...\n"; + exit 1; +} + +sub Help() +{ + print "Usage: update-proto.pl [OPTIONS] <HEADER> <C-FILE>...\n"; + print "Options:\n"; + print " --help Show this help message\n"; + print " --verbose Write changes made to standard error\n\n"; + exit 0; +} + +my %new_protos = (); + +my $verbose = 0; + +GetOptions( + 'help|h' => \&Help, + 'v|verbose' => sub { $verbose += 1; } +) or Usage(); + +sub count($$) +{ + my ($t, $s) = @_; + my $count = 0; + while($s =~ s/^(.)//) { $count++ if $1 eq $t; } + return $count; +} + +my $header = shift @ARGV; + +sub process_file($) +{ + my $file = shift; + open (IN, "<$file"); + while (my $line = <IN>) { + $_ = $line; + next if /^\s/; + next unless /\(/; + next if /^\/|[;]|^#|}|^\s*static/; + s/\/\*(.*?)\*\///g; + my $public = s/_PUBLIC_//g; + s/_PRINTF_ATTRIBUTE\([^)]+\)//g; + next unless /^(struct\s+\w+|union\s+\w+|\w+)\s+\**\s*(\w+)\s*\((.*)$/; + + my $name = $2; + + next if ($name eq "main"); + + # Read continuation lines if any + my $prn = 1 + count("(", $3) - count(")", $3); + + while ($prn) { + my $l = <IN>; + $l or die("EOF while parsing function prototype"); + $line .= $l; + $prn += count("(", $l) - count(")", $l); + } + + $line =~ s/\n$//; + + # Strip off possible start of function + $line =~ s/{\s*$//g; + + $new_protos{$name} = "$line;"; + } + close(IN); +} + +process_file($_) foreach (@ARGV); + +my $added = 0; +my $modified = 0; +my $deleted = 0; +my $kept = 0; + +sub insert_new_protos() +{ + foreach (keys %new_protos) { + print "$new_protos{$_}\n"; + print STDERR "Inserted prototype for `$_'\n" if ($verbose); + $added+=1; + } + %new_protos = (); +} + +my $blankline_due = 0; + +open (HDR, "<$header"); +while (my $line = <HDR>) { + if ($line eq "\n") { + $blankline_due = 1; + $line = <HDR>; + } + + # Recognize C files that prototypes came from + if ($line =~ /\/\* The following definitions come from (.*) \*\//) { + insert_new_protos(); + if ($blankline_due) { + print "\n"; + $blankline_due = 0; + } + process_file($1); + print "$line"; + next; + } + + if ($blankline_due) { + print "\n"; + $blankline_due = 0; + } + + # Insert prototypes that weren't in the header before + if ($line =~ /\/\* New prototypes are inserted above this line.*\*\/\s*/) { + insert_new_protos(); + print "$line\n"; + next; + } + + if ($line =~ /^\s*typedef |^\#|^\s*static/) { + print "$line"; + next; + } + + $_ = $line; + s/\/\*(.*?)\*\///g; + my $public = s/_PUBLIC_//g; + s/_PRINTF_ATTRIBUTE\([^)]+\)//g; + unless (/^(struct\s+\w+|union\s+\w+|\w+)\s+\**\s*(\w+)\s*\((.*)$/) { + print "$line"; + next; + } + + # Read continuation lines if any + my $prn = 1 + count("(", $3) - count(")", $3); + + while ($prn) { + my $l = <HDR>; + $l or die("EOF while parsing function prototype"); + $line .= $l; + $prn += count("(", $l) - count(")", $l); + } + + my $name = $2; + + # This prototype is for a function that was removed + unless (defined($new_protos{$name})) { + $deleted+=1; + print STDERR "Removed prototype for `$name'\n" if ($verbose); + next; + } + + my $nline = $line; + chop($nline); + + if ($new_protos{$name} ne $nline) { + $modified+=1; + print STDERR "Updated prototype for `$name'\n" if ($verbose); + print "$new_protos{$name}\n"; + } else { + $kept+=1; + print STDERR "Prototype for `$name' didn't change\n" if ($verbose > 1); + print "$line"; + } + + delete $new_protos{$name}; +} +close(HDR); + +print STDERR "$added added, $modified modified, $deleted deleted, $kept unchanged.\n"; + +1; |