2005-08-02 10:10:31 +04:00
#!/usr/bin/perl
2005-08-02 21:02:25 +04:00
#
# Create ejs interfaces for structures in a C header file
#
2005-08-02 10:10:31 +04:00
2005-08-02 21:02:25 +04:00
use File::Basename ;
2005-08-05 08:50:32 +04:00
use Data::Dumper ;
2005-08-07 22:04:34 +04:00
#
# Generate parse tree for header file
#
2005-08-02 10:10:31 +04:00
2005-08-07 22:04:34 +04:00
my $ file = shift ;
2005-08-02 10:10:31 +04:00
require smb_interfaces ;
2005-08-02 21:02:25 +04:00
my $ parser = new smb_interfaces ;
$ header = $ parser - > parse ( $ file ) ;
2005-08-02 10:10:31 +04:00
2005-08-07 22:04:34 +04:00
#
2005-08-08 01:10:32 +04:00
# Make second pass over tree to make it easier to process.
2005-08-07 22:04:34 +04:00
#
2005-08-08 01:10:32 +04:00
sub flatten_structs ($) {
2005-08-07 22:04:34 +04:00
my $ obj = shift ;
2005-08-08 01:10:32 +04:00
my $ s = { %$ obj } ;
2005-08-07 22:04:34 +04:00
# Map NAME, STRUCT_NAME and UNION_NAME elements into a more likeable
# property.
2005-08-08 01:10:32 +04:00
if ( defined ( $ obj - > { STRUCT_NAME } ) or defined ( $ obj - > { UNION_NAME } ) ) {
2005-08-07 22:04:34 +04:00
2005-08-08 01:10:32 +04:00
$ s - > { TYPE_DEFINED } = defined ( $ obj - > { STRUCT_NAME } ) ? $ obj - > { STRUCT_NAME }
2005-08-07 22:04:34 +04:00
: $ obj - > { UNION_NAME } ;
2005-08-08 01:10:32 +04:00
delete $ s - > { STRUCT_NAME } ;
delete $ s - > { UNION_NAME } ;
2005-08-07 22:04:34 +04:00
}
2005-08-08 02:14:30 +04:00
# Create a new list of structure fields with flattened names
2005-08-07 22:04:34 +04:00
foreach my $ elt ( @ { $ obj - > { DATA } } ) {
foreach my $ name ( @ { $ elt - > { NAME } } ) {
2005-08-08 01:10:32 +04:00
my $ new_elt = { %$ elt } ;
$ new_elt - > { NAME } = $ name ;
2005-08-08 06:19:35 +04:00
# $new_elt->{PARENT} = $s;
2005-08-08 01:10:32 +04:00
push ( @ { $ s - > { FIELDS } } , flatten_structs ( $ new_elt ) ) ;
2005-08-07 22:04:34 +04:00
}
}
2005-08-08 01:10:32 +04:00
delete $ s - > { DATA } ;
2005-08-07 22:04:34 +04:00
2005-08-08 01:10:32 +04:00
return $ s ;
2005-08-07 22:04:34 +04:00
}
2005-08-08 02:14:30 +04:00
@ newheader = map { flatten_structs ( $ _ ) } @ { $ header } ;
2005-08-02 21:02:25 +04:00
2005-08-07 23:22:20 +04:00
#
# Generate implementation
#
2005-08-02 21:02:25 +04:00
2005-08-08 04:24:05 +04:00
my $ basename = basename ( $ file , ".h" ) ;
stat "libcli/gen_raw" || mkdir ( "libcli/gen_raw" ) || die ( "mkdir" ) ;
2005-08-05 09:32:39 +04:00
open ( FILE , ">libcli/gen_raw/ejs_${basename}.c" ) ;
2005-08-02 21:02:25 +04:00
print FILE "/* EJS wrapper functions auto-generated by build_smb_interfaces.pl */\n\n" ;
2005-08-05 09:32:39 +04:00
print FILE "#include \"includes.h\"\n" ;
2005-08-13 05:42:14 +04:00
print FILE "#include \"scripting/ejs/smbcalls.h\"\n" ;
2005-08-05 09:32:39 +04:00
print FILE "#include \"lib/appweb/ejs/ejs.h\"\n" ;
print FILE "#include \"scripting/ejs/ejsrpc.h\"\n" ; # TODO: remove this
print FILE "\n" ;
2005-08-08 06:19:35 +04:00
sub transfer_element ($$$) {
my $ dir = shift ;
my $ prefix = shift ;
my $ elt = shift ;
2005-08-09 04:34:24 +04:00
$ type = $ elt - > { TYPE } ;
$ type =~ s/_t$// ;
2005-08-13 06:59:56 +04:00
print FILE "\tNDR_CHECK(ejs_${dir}_$type(ejs, v, \"$prefix.$elt->{NAME}\"));\n" ;
2005-08-08 06:19:35 +04:00
}
sub transfer_struct ($$) {
my $ dir = shift ;
my $ struct = shift ;
foreach my $ field ( @ { $ struct - > { FIELDS } } ) {
next if $ dir eq "pull" and $ field - > { NAME } eq "out" ;
next if $ dir eq "push" and $ field - > { NAME } eq "in" ;
if ( $ field - > { TYPE } eq "struct" ) {
foreach $ subfield ( @ { $ field - > { FIELDS } } ) {
transfer_element ( $ dir , $ field - > { NAME } , $ subfield ) ;
}
} else {
transfer_element ( $ dir , $ struct - > { NAME } , $ field ) ;
}
}
}
2005-08-08 02:14:30 +04:00
# Top level call functions
2005-08-05 08:50:32 +04:00
2005-08-08 02:14:30 +04:00
foreach my $ s ( @ newheader ) {
2005-08-05 19:54:11 +04:00
2005-08-08 02:14:30 +04:00
if ( $ s - > { TYPE } eq "struct" ) {
2005-08-05 22:06:15 +04:00
2005-08-09 04:34:24 +04:00
# Push/pull top level struct
print FILE "NTSTATUS ejs_pull_$s->{TYPE_DEFINED}(struct ejs_rpc *ejs, struct MprVar *v, struct $s->{TYPE_DEFINED} *r)\n" ;
print FILE "{\n" ;
2005-08-13 06:47:14 +04:00
transfer_struct ( "pull" , $ s ) ;
print FILE "\n\treturn NT_STATUS_OK;\n" ;
2005-08-09 04:34:24 +04:00
print FILE "}\n\n" ;
print FILE "NTSTATUS ejs_push_$s->{TYPE_DEFINED}(struct ejs_rpc *ejs, struct MprVar *v, const struct $s->{TYPE_DEFINED} *r)\n" ;
print FILE "{\n" ;
2005-08-13 06:47:14 +04:00
transfer_struct ( "push" , $ s ) ;
print FILE "\n\treturn NT_STATUS_OK;\n" ;
2005-08-09 04:34:24 +04:00
print FILE "}\n\n" ;
2005-08-13 06:59:56 +04:00
# Function call
print FILE "static int ejs_$s->{TYPE_DEFINED}(int eid, int argc, struct MprVar **argv)\n" ;
print FILE "{\n" ;
print FILE "\treturn ejs_raw_call(eid, argc, argv, (ejs_pull_function_t)ejs_pull_$s->{TYPE_DEFINED}, (ejs_push_function_t)ejs_push_$s->{TYPE_DEFINED});\n" ;
print FILE "}\n\n" ;
2005-08-08 02:14:30 +04:00
} else {
2005-08-05 05:23:35 +04:00
2005-08-08 02:14:30 +04:00
# Top level union
2005-08-05 08:50:32 +04:00
2005-08-08 02:14:30 +04:00
foreach my $ arm ( @ { $ s - > { FIELDS } } ) {
2005-08-05 08:50:32 +04:00
2005-08-09 04:34:24 +04:00
# Push/pull union arm
2005-08-13 05:42:14 +04:00
print FILE "NTSTATUS ejs_pull_$s->{TYPE_DEFINED}_$arm->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, union $s->{TYPE_DEFINED} *r)\n" ;
2005-08-09 04:34:24 +04:00
print FILE "{\n" ;
2005-08-13 06:47:14 +04:00
transfer_struct ( "pull" , $ arm ) ;
print FILE "\n\treturn NT_STATUS_OK;\n" ;
2005-08-09 04:34:24 +04:00
print FILE "}\n\n" ;
2005-08-13 05:42:14 +04:00
print FILE "NTSTATUS ejs_push_$s->{TYPE_DEFINED}_$arm->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, const union $s->{TYPE_DEFINED} *r)\n" ;
2005-08-09 04:34:24 +04:00
print FILE "{\n" ;
2005-08-13 06:47:14 +04:00
transfer_struct ( "push" , $ arm ) ;
print FILE "\n\treturn NT_STATUS_OK;\n" ;
2005-08-09 04:34:24 +04:00
print FILE "}\n\n" ;
2005-08-05 08:50:32 +04:00
}
}
2005-08-05 05:23:35 +04:00
}
2005-08-08 02:14:30 +04:00
close ( FILE ) ;