2003-11-23 04:29:42 +03:00
#!/usr/bin/perl
2006-03-21 12:25:36 +03:00
# Simple script for generating prototypes for C functions
# Written by Jelmer Vernooij
# based on the original mkproto.sh by Andrew Tridgell
2003-11-23 04:29:42 +03:00
use strict ;
2003-12-16 06:34:23 +03:00
# don't use warnings module as it is not portable enough
# use warnings;
2003-11-23 04:29:42 +03:00
2005-12-23 15:29:13 +03:00
use Getopt::Long ;
2006-04-11 15:37:52 +04:00
use File::Basename ;
use File::Path ;
2005-12-23 15:29:13 +03:00
2006-03-21 12:25:36 +03:00
#####################################################################
# read a file into a string
2005-12-23 15:29:13 +03:00
my $ public_file = undef ;
my $ private_file = undef ;
my $ public_define = undef ;
my $ private_define = undef ;
2006-03-21 12:25:36 +03:00
my $ _public = "" ;
my $ _private = "" ;
my $ public_data = \ $ _public ;
my $ private_data = \ $ _private ;
2006-04-11 15:37:52 +04:00
my $ builddir = undef ;
my $ srcdir = undef ;
2006-03-21 12:25:36 +03:00
sub public ($)
{
my ( $ d ) = @ _ ;
$$ public_data . = $ d ;
}
sub private ($)
{
my ( $ d ) = @ _ ;
$$ private_data . = $ d ;
}
2005-12-23 15:29:13 +03:00
2005-12-27 23:29:19 +03:00
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" ;
2006-05-16 20:57:56 +04:00
print " --srcdir=path Read files relative to this directory\n" ;
print " --builddir=path Write file relative to this directory\n" ;
2005-12-27 23:29:19 +03:00
print " --help Print this help message\n\n" ;
exit 0 ;
}
2005-12-23 15:29:13 +03:00
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 ,
2005-12-27 23:29:19 +03:00
'private-define=s' = > \ $ private_define ,
2006-05-16 20:57:56 +04:00
'srcdir=s' = > sub { my ( $ f , $ v ) = @ _ ; $ srcdir = $ v ; } ,
2006-04-11 15:37:52 +04:00
'builddir=s' = > sub { my ( $ f , $ v ) = @ _ ; $ builddir = $ v ; } ,
2006-05-16 20:57:56 +04:00
'help' = > \ & usage
2005-12-27 23:29:19 +03:00
) or exit ( 1 ) ;
2005-12-23 15:29:13 +03:00
2005-12-23 16:01:26 +03:00
if ( not defined ( $ public_define ) and defined ( $ public_file ) ) {
2005-12-27 23:29:19 +03:00
$ public_define = ".." . uc ( $ public_file ) . "__" ;
2005-12-23 15:29:13 +03:00
$ public_define =~ tr { . / } { __ } ;
2005-12-23 16:01:26 +03:00
} elsif ( not defined ( $ public_define ) ) {
2005-12-23 15:29:13 +03:00
$ public_define = '_PROTO_H_' ;
2003-11-23 04:29:42 +03:00
}
2005-12-23 16:01:26 +03:00
if ( not defined ( $ private_define ) and defined ( $ private_file ) ) {
2005-12-27 23:29:19 +03:00
$ private_define = "__" . uc ( $ private_file ) . "__" ;
2005-12-23 15:29:13 +03:00
$ private_define =~ tr { . / } { __ } ;
2005-12-23 16:01:26 +03:00
} elsif ( not defined ( $ public_define ) ) {
2005-12-23 15:29:13 +03:00
$ public_define = '_PROTO_H_' ;
2003-11-23 04:29:42 +03:00
}
2006-03-21 12:25:36 +03:00
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 ;
2003-11-23 04:29:42 +03:00
}
2006-03-21 12:25:36 +03:00
sub file_load ($)
{
my ( $ filename ) = shift ;
local ( * INPUTFILE ) ;
open ( INPUTFILE , $ filename ) || return undef ;
my ( $ saved_delim ) = $/ ;
undef $/ ;
my ( $ data ) = <INPUTFILE> ;
close ( INPUTFILE ) ;
$/ = $ saved_delim ;
return $ data ;
2005-12-23 15:29:13 +03:00
}
sub print_header ($$)
{
my ( $ file , $ header_name ) = @ _ ;
2006-03-21 12:25:36 +03:00
$ 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" ) ;
2005-12-23 15:29:13 +03:00
}
2003-11-23 04:53:54 +03:00
2005-12-23 15:29:13 +03:00
sub print_footer ($$)
{
my ( $ file , $ header_name ) = @ _ ;
2006-03-21 12:25:36 +03:00
$ file - > ( "#undef _PRINTF_ATTRIBUTE\n" ) ;
$ file - > ( "#define _PRINTF_ATTRIBUTE(a1, a2)\n" ) ;
$ file - > ( "\n#endif /* $header_name */\n\n" ) ;
2005-12-23 15:29:13 +03:00
}
sub handle_loadparm ($$)
{
my ( $ file , $ line ) = @ _ ;
2003-11-23 05:00:40 +03:00
2006-03-07 19:51:56 +03:00
if ( $ line =~ /^_PUBLIC_ FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|CHAR|INTEGER|LIST)\((\w+),.*\)/o ) {
2003-11-23 05:11:55 +03:00
my $ scope = $ 1 ;
my $ type = $ 2 ;
my $ name = $ 3 ;
my % tmap = (
"BOOL" = > "BOOL " ,
"CONST_STRING" = > "const char *" ,
2004-06-14 03:50:55 +04:00
"STRING" = > "const char *" ,
2003-11-23 05:11:55 +03:00
"INTEGER" = > "int " ,
"CHAR" = > "char " ,
"LIST" = > "const char **" ,
) ;
my % smap = (
"GLOBAL" = > "void" ,
"LOCAL" = > "int "
) ;
2006-03-21 12:25:36 +03:00
$ file - > ( "$tmap{$type}$name($smap{$scope});\n" ) ;
2003-11-23 04:53:54 +03:00
}
}
2005-12-23 15:29:13 +03:00
sub process_file ($$$)
2003-11-23 05:33:46 +03:00
{
2005-12-23 15:29:13 +03:00
my ( $ public_file , $ private_file , $ filename ) = @ _ ;
$ filename =~ s/\.o$/\.c/g ;
2003-11-23 04:29:42 +03:00
2006-04-11 15:37:52 +04:00
if ( ! open ( FH , "< $builddir/$filename" ) ) {
open ( FH , "< $srcdir/$filename" ) || die "Failed to open $filename" ;
}
2003-11-23 04:29:42 +03:00
2006-03-21 12:25:36 +03:00
$ private_file - > ( "\n/* The following definitions come from $filename */\n\n" ) ;
2003-11-23 04:29:42 +03:00
2003-11-23 05:44:23 +03:00
while ( my $ line = <FH> ) {
2006-03-21 12:25:36 +03:00
my $ target = \ & private ;
2006-01-10 19:54:21 +03:00
my $ is_public = 0 ;
2005-12-23 15:29:13 +03:00
2003-11-23 05:44:23 +03:00
# these are ordered for maximum speed
2003-11-23 05:33:46 +03:00
next if ( $ line =~ /^\s/ ) ;
2003-11-23 05:44:23 +03:00
next unless ( $ line =~ /\(/ ) ;
next if ( $ line =~ /^\/|[;]/ ) ;
2006-03-07 19:51:56 +03:00
if ( $ line =~ /^_PUBLIC_ FN_/ ) {
handle_loadparm ( $ public_file , $ line ) ;
next ;
}
2006-03-07 00:14:41 +03:00
if ( $ line =~ /^_PUBLIC_[\t ]/ ) {
2006-03-21 12:25:36 +03:00
$ target = \ & public ;
2006-01-10 19:54:21 +03:00
$ is_public = 1 ;
2005-12-28 01:51:30 +03:00
}
2006-01-10 19:54:21 +03:00
next unless ( $ is_public || $ line =~ /
2003-11-23 05:44:23 +03:00
^ void | ^ BOOL | ^ int | ^ struct | ^ char | ^ const | ^ \ w + _ [ tT ] \ s | ^ uint | ^ unsigned | ^ long |
^ NTSTATUS | ^ ADS_STATUS | ^ enum \ s . * \ ( | ^ DATA_BLOB | ^ WERROR | ^ XFILE | ^ FILE | ^ DIR |
2005-12-26 19:46:55 +03:00
^ double | ^ TDB_CONTEXT | ^ TDB_DATA | ^ TALLOC_CTX | ^ NTTIME | ^ FN_ | ^ init_module |
2004-09-18 12:18:44 +04:00
^ GtkWidget | ^ GType | ^ smb_ucs2_t
2003-11-23 05:44:23 +03:00
/ xo ) ;
2003-11-23 05:33:46 +03:00
2004-09-24 09:51:29 +04:00
next if ( $ line =~ /^int\s*main/ ) ;
2003-11-23 05:33:46 +03:00
if ( $ line =~ /\(.*\)\s*$/o ) {
chomp $ line ;
2006-03-21 12:25:36 +03:00
$ target - > ( "$line;\n" ) ;
2003-11-23 05:33:46 +03:00
next ;
}
2003-11-23 04:29:42 +03:00
2006-03-21 12:25:36 +03:00
$ target - > ( $ line ) ;
2003-11-23 04:29:42 +03:00
2003-11-23 05:33:46 +03:00
while ( $ line = <FH> ) {
if ( $ line =~ /\)\s*$/o ) {
2003-11-23 06:03:27 +03:00
chomp $ line ;
2006-03-21 12:25:36 +03:00
$ target - > ( "$line;\n" ) ;
2003-11-23 05:33:46 +03:00
last ;
2003-11-23 04:29:42 +03:00
}
2006-03-21 12:25:36 +03:00
$ target - > ( $ line ) ;
2003-11-23 04:29:42 +03:00
}
}
2003-11-23 05:44:23 +03:00
close ( FH ) ;
2003-11-23 04:29:42 +03:00
}
2006-04-11 15:37:52 +04:00
2006-03-21 12:25:36 +03:00
print_header ( \ & public , $ public_define ) ;
2005-12-23 16:01:26 +03:00
if ( $ public_file ne $ private_file ) {
2006-03-21 12:25:36 +03:00
print_header ( \ & private , $ private_define ) ;
2005-12-27 23:29:19 +03:00
2006-03-21 12:25:36 +03:00
private ( "/* this file contains prototypes for functions that " .
2005-12-27 23:29:19 +03:00
"are private \n * to this subsystem or library. These functions " .
2006-03-21 12:25:36 +03:00
"should not be \n * used outside this particular subsystem! */\n\n" ) ;
2005-12-27 23:29:19 +03:00
2006-03-21 12:25:36 +03:00
public ( "/* this file contains prototypes for functions that " .
"are part of \n * the public API of this subsystem or library. */\n\n" ) ;
2006-03-16 17:34:55 +03:00
2005-12-23 15:29:13 +03:00
}
2006-03-16 17:34:55 +03:00
2006-03-21 12:25:36 +03:00
public ( "#ifndef _PUBLIC_\n#define _PUBLIC_\n#endif\n\n" ) ;
2006-03-16 17:34:55 +03:00
2006-03-21 12:25:36 +03:00
process_file ( \ & public , \ & private , $ _ ) foreach ( @ ARGV ) ;
print_footer ( \ & public , $ public_define ) ;
2005-12-23 16:01:26 +03:00
if ( $ public_file ne $ private_file ) {
2006-03-21 12:25:36 +03:00
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 ;
}
2006-08-23 17:20:16 +04:00
mkpath ( dirname ( $ public_file ) , 0 , 0755 ) ;
open ( PUBLIC , ">$public_file" ) or die ( "Can't open `$public_file': $!" ) ;
print PUBLIC "$$public_data" ;
close ( PUBLIC ) ;
2006-03-21 12:25:36 +03:00
2006-08-23 17:20:16 +04:00
if ( $ public_file ne $ private_file ) {
2006-04-11 15:37:52 +04:00
mkpath ( dirname ( $ private_file ) , 0 , 0755 ) ;
2006-03-21 12:25:36 +03:00
open ( PRIVATE , ">$private_file" ) or die ( "Can't open `$private_file': $!" ) ;
print PRIVATE "$$private_data" ;
close ( PRIVATE ) ;
2003-11-23 05:33:46 +03:00
}