[745] | 1 | #!/usr/bin/perl
|
---|
| 2 | # Simple script for generating prototypes for C functions
|
---|
| 3 | # Written by Jelmer Vernooij
|
---|
| 4 | # based on the original mkproto.sh by Andrew Tridgell
|
---|
| 5 |
|
---|
| 6 | use strict;
|
---|
| 7 |
|
---|
| 8 | # don't use warnings module as it is not portable enough
|
---|
| 9 | # use warnings;
|
---|
| 10 |
|
---|
| 11 | use Getopt::Long;
|
---|
| 12 | use File::Basename;
|
---|
| 13 | use File::Path;
|
---|
| 14 |
|
---|
| 15 | #####################################################################
|
---|
| 16 | # read a file into a string
|
---|
| 17 |
|
---|
| 18 | my $public_file = undef;
|
---|
| 19 | my $private_file = undef;
|
---|
| 20 | my $all_file = undef;
|
---|
| 21 | my $public_define = undef;
|
---|
| 22 | my $private_define = undef;
|
---|
| 23 | my $_public = "";
|
---|
| 24 | my $_private = "";
|
---|
| 25 | my $public_data = \$_public;
|
---|
| 26 | my $private_data = \$_private;
|
---|
| 27 | my $builddir = ".";
|
---|
| 28 | my $srcdir = ".";
|
---|
| 29 |
|
---|
| 30 | sub public($)
|
---|
| 31 | {
|
---|
| 32 | my ($d) = @_;
|
---|
| 33 | $$public_data .= $d;
|
---|
| 34 | }
|
---|
| 35 |
|
---|
| 36 | sub private($)
|
---|
| 37 | {
|
---|
| 38 | my ($d) = @_;
|
---|
| 39 | $$private_data .= $d;
|
---|
| 40 | }
|
---|
| 41 |
|
---|
| 42 | sub usage()
|
---|
| 43 | {
|
---|
| 44 | print "Usage: mkproto.pl [options] [c files]\n";
|
---|
| 45 | print "OPTIONS:\n";
|
---|
| 46 | print " --public=FILE Write prototypes for public functions to FILE\n";
|
---|
| 47 | print " --private=FILE Write prototypes for private functions to FILE\n";
|
---|
| 48 | print " --define=DEF Use DEF to check whether header was already included\n";
|
---|
| 49 | print " --public-define=DEF Same as --define, but just for public header\n";
|
---|
| 50 | print " --private-define=DEF Same as --define, but just for private header\n";
|
---|
| 51 | print " --srcdir=path Read files relative to this directory\n";
|
---|
| 52 | print " --builddir=path Write file relative to this directory\n";
|
---|
| 53 | print " --help Print this help message\n\n";
|
---|
| 54 | exit 0;
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | GetOptions(
|
---|
| 58 | 'public=s' => sub { my ($f,$v) = @_; $public_file = $v; },
|
---|
| 59 | 'all=s' => sub { my ($f,$v) = @_; $public_file = $v; $private_file = $v; },
|
---|
| 60 | 'private=s' => sub { my ($f,$v) = @_; $private_file = $v; },
|
---|
| 61 | 'define=s' => sub {
|
---|
| 62 | my ($f,$v) = @_;
|
---|
| 63 | $public_define = $v;
|
---|
| 64 | $private_define = "$v\_PRIVATE";
|
---|
| 65 | },
|
---|
| 66 | 'public-define=s' => \$public_define,
|
---|
| 67 | 'private-define=s' => \$private_define,
|
---|
| 68 | 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; },
|
---|
| 69 | 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; },
|
---|
| 70 | 'help' => \&usage
|
---|
| 71 | ) or exit(1);
|
---|
| 72 |
|
---|
| 73 | sub normalize_define($$)
|
---|
| 74 | {
|
---|
| 75 | my ($define, $file) = @_;
|
---|
| 76 |
|
---|
| 77 | if (not defined($define) and defined($file)) {
|
---|
| 78 | $define = "__" . uc($file) . "__";
|
---|
| 79 | $define =~ tr{./}{__};
|
---|
| 80 | $define =~ tr{\-}{_};
|
---|
| 81 | } elsif (not defined($define)) {
|
---|
| 82 | $define = '_PROTO_H_';
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | return $define;
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | $public_define = normalize_define($public_define, $public_file);
|
---|
| 89 | $private_define = normalize_define($private_define, $private_file);
|
---|
| 90 |
|
---|
| 91 | if ((defined($private_file) and defined($public_file) and ($private_file eq $public_file)) or
|
---|
| 92 | (not defined($private_file) and not defined($public_file))) {
|
---|
| 93 | $private_data = $public_data;
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | sub file_load($)
|
---|
| 97 | {
|
---|
| 98 | my($filename) = @_;
|
---|
| 99 | local(*INPUTFILE);
|
---|
| 100 | open(INPUTFILE, $filename) or return undef;
|
---|
| 101 | my($saved_delim) = $/;
|
---|
| 102 | undef $/;
|
---|
| 103 | my($data) = <INPUTFILE>;
|
---|
| 104 | close(INPUTFILE);
|
---|
| 105 | $/ = $saved_delim;
|
---|
| 106 | return $data;
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | sub print_header($$)
|
---|
| 110 | {
|
---|
| 111 | my ($file, $header_name) = @_;
|
---|
| 112 | $file->("#ifndef $header_name\n");
|
---|
| 113 | $file->("#define $header_name\n\n");
|
---|
| 114 | $file->("#undef _PRINTF_ATTRIBUTE\n");
|
---|
| 115 | $file->("#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)\n");
|
---|
| 116 | $file->("/* This file was automatically generated by mkproto.pl. DO NOT EDIT */\n\n");
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | sub print_footer($$)
|
---|
| 120 | {
|
---|
| 121 | my ($file, $header_name) = @_;
|
---|
| 122 | $file->("#undef _PRINTF_ATTRIBUTE\n");
|
---|
| 123 | $file->("#define _PRINTF_ATTRIBUTE(a1, a2)\n");
|
---|
| 124 | $file->("\n#endif /* $header_name */\n\n");
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | sub handle_loadparm($$)
|
---|
| 128 | {
|
---|
| 129 | my ($file,$line) = @_;
|
---|
| 130 |
|
---|
| 131 | if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) {
|
---|
| 132 | my $scope = $1;
|
---|
| 133 | my $type = $2;
|
---|
| 134 | my $name = $3;
|
---|
| 135 |
|
---|
| 136 | my %tmap = (
|
---|
| 137 | "BOOL" => "bool ",
|
---|
| 138 | "CONST_STRING" => "const char *",
|
---|
| 139 | "STRING" => "const char *",
|
---|
| 140 | "INTEGER" => "int ",
|
---|
| 141 | "CHAR" => "char ",
|
---|
| 142 | "LIST" => "const char **",
|
---|
| 143 | );
|
---|
| 144 |
|
---|
| 145 | my %smap = (
|
---|
| 146 | "GLOBAL" => "struct loadparm_context *",
|
---|
| 147 | "LOCAL" => "struct loadparm_service *, struct loadparm_service *"
|
---|
| 148 | );
|
---|
| 149 |
|
---|
| 150 | $file->("$tmap{$type}lpcfg_$name($smap{$scope});\n");
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | sub process_file($$$)
|
---|
| 155 | {
|
---|
| 156 | my ($public_file, $private_file, $filename) = @_;
|
---|
| 157 |
|
---|
| 158 | $filename =~ s/\.o$/\.c/g;
|
---|
| 159 |
|
---|
| 160 | if ($filename =~ /^\//) {
|
---|
| 161 | open(FH, "<$filename") or die("Failed to open $filename");
|
---|
| 162 | } elsif (!open(FH, "< $builddir/$filename")) {
|
---|
| 163 | open(FH, "< $srcdir/$filename") || die "Failed to open $filename";
|
---|
| 164 | }
|
---|
| 165 |
|
---|
| 166 | $private_file->("\n/* The following definitions come from $filename */\n\n");
|
---|
| 167 |
|
---|
| 168 | my $comment = undef;
|
---|
| 169 | my $incomment = 0;
|
---|
| 170 | while (my $line = <FH>) {
|
---|
| 171 | my $target = \&private;
|
---|
| 172 | my $is_public = 0;
|
---|
| 173 |
|
---|
| 174 | if ($line =~ /^\/\*\*/) {
|
---|
| 175 | $comment = "";
|
---|
| 176 | $incomment = 1;
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | if ($incomment) {
|
---|
| 180 | $comment .= $line;
|
---|
| 181 | if ($line =~ /\*\//) {
|
---|
| 182 | $incomment = 0;
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | # these are ordered for maximum speed
|
---|
| 187 | next if ($line =~ /^\s/);
|
---|
| 188 |
|
---|
| 189 | next unless ($line =~ /\(/);
|
---|
| 190 |
|
---|
| 191 | next if ($line =~ /^\/|[;]/);
|
---|
| 192 |
|
---|
| 193 | if ($line =~ /^FN_/) {
|
---|
| 194 | handle_loadparm($public_file, $line);
|
---|
| 195 | handle_loadparm($private_file, $line);
|
---|
| 196 | next;
|
---|
| 197 | }
|
---|
| 198 |
|
---|
| 199 | if ($line =~ /^_PUBLIC_[\t ]/) {
|
---|
| 200 | $target = \&public;
|
---|
| 201 | $is_public = 1;
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | next unless ( $is_public || $line =~ /
|
---|
| 205 | ^(_DEPRECATED_ |_NORETURN_ |_WARN_UNUSED_RESULT_ |_PURE_ )*(
|
---|
| 206 | void|bool|int|struct|char|const|\w+_[tT]\s|uint|unsigned|long|NTSTATUS|
|
---|
| 207 | ADS_STATUS|enum\s.*\(|DATA_BLOB|WERROR|XFILE|FILE|DIR|
|
---|
| 208 | double|TDB_CONTEXT|TDB_DATA|TALLOC_CTX|NTTIME|FN_|init_module|
|
---|
| 209 | GtkWidget|GType|smb_ucs2_t|krb5_error_code|NET_API_STATUS)
|
---|
| 210 | /xo);
|
---|
| 211 |
|
---|
| 212 | next if ($line =~ /^int\s*main/);
|
---|
| 213 |
|
---|
| 214 | $target->("\n$comment") if (defined($comment)); $comment = undef;
|
---|
| 215 |
|
---|
| 216 | if ( $line =~ /\(.*\)\s*$/o ) {
|
---|
| 217 | chomp $line;
|
---|
| 218 | $target->("$line;\n");
|
---|
| 219 | next;
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | $target->($line);
|
---|
| 223 |
|
---|
| 224 | while ($line = <FH>) {
|
---|
| 225 | if ($line =~ /\)\s*$/o) {
|
---|
| 226 | chomp $line;
|
---|
| 227 | $target->("$line;\n");
|
---|
| 228 | last;
|
---|
| 229 | }
|
---|
| 230 | $target->($line);
|
---|
| 231 | }
|
---|
| 232 | }
|
---|
| 233 |
|
---|
| 234 | close(FH);
|
---|
| 235 | }
|
---|
| 236 |
|
---|
| 237 |
|
---|
| 238 | print_header(\&public, $public_define);
|
---|
| 239 | if (defined($private_file) and defined($public_file) and $public_file ne $private_file) {
|
---|
| 240 | print_header(\&private, $private_define);
|
---|
| 241 |
|
---|
| 242 | private("/* this file contains prototypes for functions that " .
|
---|
| 243 | "are private \n * to this subsystem or library. These functions " .
|
---|
| 244 | "should not be \n * used outside this particular subsystem! */\n\n");
|
---|
| 245 |
|
---|
| 246 | public("/* this file contains prototypes for functions that " .
|
---|
| 247 | "are part of \n * the public API of this subsystem or library. */\n\n");
|
---|
| 248 |
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | public("#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n");
|
---|
| 252 | public("#ifndef _PURE_\n#define _PURE_\n#endif\n\n");
|
---|
| 253 | public("#ifndef _NORETURN_\n#define _NORETURN_\n#endif\n\n");
|
---|
| 254 | public("#ifndef _DEPRECATED_\n#define _DEPRECATED_\n#endif\n\n");
|
---|
| 255 | public("#ifndef _WARN_UNUSED_RESULT_\n#define _WARN_UNUSED_RESULT_\n#endif\n\n");
|
---|
| 256 |
|
---|
| 257 | process_file(\&public, \&private, $_) foreach (@ARGV);
|
---|
| 258 | print_footer(\&public, $public_define);
|
---|
| 259 | if (defined($private_file) and $public_file ne $private_file) {
|
---|
| 260 | print_footer(\&private, $private_define);
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 | if (not defined($public_file)) {
|
---|
| 264 | print STDOUT $$public_data;
|
---|
| 265 | }
|
---|
| 266 |
|
---|
| 267 | if (not defined($private_file) and defined($public_file)) {
|
---|
| 268 | print STDOUT $$private_data;
|
---|
| 269 | }
|
---|
| 270 |
|
---|
| 271 | mkpath(dirname($public_file), 0, 0755);
|
---|
| 272 | open(PUBLIC, ">$public_file") or die("Can't open `$public_file': $!");
|
---|
| 273 | print PUBLIC "$$public_data";
|
---|
| 274 | close(PUBLIC);
|
---|
| 275 |
|
---|
| 276 | if (defined($private_file) and $public_file ne $private_file) {
|
---|
| 277 | mkpath(dirname($private_file), 0, 0755);
|
---|
| 278 | open(PRIVATE, ">$private_file") or die("Can't open `$private_file': $!");
|
---|
| 279 | print PRIVATE "$$private_data";
|
---|
| 280 | close(PRIVATE);
|
---|
| 281 | }
|
---|