1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-23 20:23:50 +03:00
Files
samba-mirror/source/build/pidl/ndr_header.pm

472 lines
11 KiB
Perl

###################################################
# create C header files for an IDL structure
# Copyright tridge@samba.org 2000
# Copyright jelmer@samba.org 2005
# released under the GNU GPL
package NdrHeader;
use strict;
use pidl::typelist;
my($res);
my($tab_depth);
sub pidl ($)
{
$res .= shift;
}
sub tabs()
{
for (my($i)=0; $i < $tab_depth; $i++) {
pidl "\t";
}
}
#####################################################################
# parse a properties list
sub HeaderProperties($$)
{
my($props,$ignores) = @_;
my $ret = "";
foreach my $d (keys %{$props}) {
next if (grep(/^$d$/, @$ignores));
if($props->{$d} ne "1") {
$ret.= "$d($props->{$d}),";
} else {
$ret.="$d,";
}
}
if ($ret) {
pidl "/* [" . substr($ret, 0, -1) . "] */";
}
}
#####################################################################
# parse a structure element
sub HeaderElement($)
{
my($element) = shift;
pidl tabs();
HeaderType($element, $element->{TYPE}, "");
pidl " ";
my $prefix = "";
my $postfix = "";
foreach my $l (@{$element->{LEVELS}})
{
if (($l->{TYPE} eq "POINTER")) {
my $nl = Ndr::GetNextLevel($element, $l);
$nl = Ndr::GetNextLevel($element, $nl) if ($nl->{TYPE} eq "SUBCONTEXT");
next if ($nl->{TYPE} eq "DATA" and typelist::scalar_is_reference($nl->{DATA_TYPE}));
$prefix .= "*";
} elsif ($l->{TYPE} eq "ARRAY") {
my $pl = Ndr::GetPrevLevel($element, $l);
next if ($pl and $pl->{TYPE} eq "POINTER");
if ($l->{IS_FIXED}) {
$postfix .= "[$l->{SIZE_IS}]";
} else {
$prefix .= "*";
}
} elsif ($l->{TYPE} eq "DATA") {
pidl "$prefix$element->{NAME}$postfix";
}
}
if (defined $element->{ARRAY_LEN}[0] && util::is_constant($element->{ARRAY_LEN}[0])) {
pidl "[$element->{ARRAY_LEN}[0]]";
}
pidl ";";
if (defined $element->{PROPERTIES}) {
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
}
pidl "\n";
}
#####################################################################
# parse a struct
sub HeaderStruct($$)
{
my($struct,$name) = @_;
pidl "\nstruct $name {\n";
$tab_depth++;
my $el_count=0;
if (defined $struct->{ELEMENTS}) {
foreach my $e (@{$struct->{ELEMENTS}}) {
HeaderElement($e);
$el_count++;
}
}
if ($el_count == 0) {
# some compilers can't handle empty structures
pidl "\tchar _empty_;\n";
}
$tab_depth--;
pidl "}";
if (defined $struct->{PROPERTIES}) {
HeaderProperties($struct->{PROPERTIES}, []);
}
}
#####################################################################
# parse a enum
sub HeaderEnum($$)
{
my($enum,$name) = @_;
my $first = 1;
if (not util::useUintEnums()) {
pidl "\nenum $name {\n";
$tab_depth++;
foreach my $e (@{$enum->{ELEMENTS}}) {
unless ($first) { pidl ",\n"; }
$first = 0;
tabs();
pidl $e;
}
pidl "\n";
$tab_depth--;
pidl "}";
} else {
my $count = 0;
pidl "\nenum $name { __donnot_use_enum_$name=0x7FFFFFFF};\n";
my $with_val = 0;
my $without_val = 0;
foreach my $e (@{$enum->{ELEMENTS}}) {
my $t = "$e";
my $name;
my $value;
if ($t =~ /(.*)=(.*)/) {
$name = $1;
$value = $2;
$with_val = 1;
die ("you can't mix enum member with values and without values when using --uint-enums!")
unless ($without_val == 0);
} else {
$name = $t;
$value = $count++;
$without_val = 1;
die ("you can't mix enum member with values and without values when using --uint-enums!")
unless ($with_val == 0);
}
pidl "#define $name ( $value )\n";
}
pidl "\n";
}
}
#####################################################################
# parse a bitmap
sub HeaderBitmap($$)
{
my($bitmap,$name) = @_;
pidl "\n/* bitmap $name */\n";
foreach my $e (@{$bitmap->{ELEMENTS}})
{
pidl "#define $e\n";
}
pidl "\n";
}
#####################################################################
# parse a union
sub HeaderUnion($$)
{
my($union,$name) = @_;
my %done = ();
pidl "\nunion $name {\n";
$tab_depth++;
foreach my $e (@{$union->{ELEMENTS}}) {
if ($e->{TYPE} ne "EMPTY") {
if (! defined $done{$e->{NAME}}) {
HeaderElement($e);
}
$done{$e->{NAME}} = 1;
}
}
$tab_depth--;
pidl "}";
if (defined $union->{PROPERTIES}) {
HeaderProperties($union->{PROPERTIES}, []);
}
}
#####################################################################
# parse a type
sub HeaderType($$$)
{
my($e,$data,$name) = @_;
if (ref($data) eq "HASH") {
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
return;
}
if (util::has_property($e, "charset")) {
pidl "const char";
} else {
pidl typelist::mapType($e->{TYPE});
}
}
#####################################################################
# parse a typedef
sub HeaderTypedef($)
{
my($typedef) = shift;
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
}
#####################################################################
# prototype a typedef
sub HeaderTypedefProto($)
{
my($d) = shift;
my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE});
if (util::has_property($d, "gensize")) {
my $size_args = $tf->{SIZE_FN_ARGS}->($d);
pidl "size_t ndr_size_$d->{NAME}($size_args);\n";
}
return unless util::has_property($d, "public");
my $pull_args = $tf->{PULL_FN_ARGS}->($d);
my $push_args = $tf->{PUSH_FN_ARGS}->($d);
my $print_args = $tf->{PRINT_FN_ARGS}->($d);
unless (util::has_property($d, "nopush")) {
pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n";
}
unless (util::has_property($d, "nopull")) {
pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n";
}
unless (util::has_property($d, "noprint")) {
pidl "void ndr_print_$d->{NAME}($print_args);\n";
}
}
#####################################################################
# parse a const
sub HeaderConst($)
{
my($const) = shift;
if (!defined($const->{ARRAY_LEN}[0])) {
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
} else {
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
}
}
#####################################################################
# parse a function
sub HeaderFunctionInOut($$)
{
my($fn,$prop) = @_;
foreach my $e (@{$fn->{ELEMENTS}}) {
if (util::has_property($e, $prop)) {
HeaderElement($e);
}
}
}
#####################################################################
# determine if we need an "in" or "out" section
sub HeaderFunctionInOut_needed($$)
{
my($fn,$prop) = @_;
if ($prop eq "out" && $fn->{RETURN_TYPE}) {
return 1;
}
foreach my $e (@{$fn->{ELEMENTS}}) {
if (util::has_property($e, $prop)) {
return 1;
}
}
return undef;
}
my %headerstructs = ();
#####################################################################
# parse a function
sub HeaderFunction($)
{
my($fn) = shift;
return if ($headerstructs{$fn->{NAME}});
$headerstructs{$fn->{NAME}} = 1;
pidl "\nstruct $fn->{NAME} {\n";
$tab_depth++;
my $needed = 0;
if (HeaderFunctionInOut_needed($fn, "in")) {
tabs();
pidl "struct {\n";
$tab_depth++;
HeaderFunctionInOut($fn, "in");
$tab_depth--;
tabs();
pidl "} in;\n\n";
$needed++;
}
if (HeaderFunctionInOut_needed($fn, "out")) {
tabs();
pidl "struct {\n";
$tab_depth++;
HeaderFunctionInOut($fn, "out");
if ($fn->{RETURN_TYPE}) {
tabs();
pidl typelist::mapType($fn->{RETURN_TYPE}) . " result;\n";
}
$tab_depth--;
tabs();
pidl "} out;\n\n";
$needed++;
}
if (! $needed) {
# sigh - some compilers don't like empty structures
tabs();
pidl "int _dummy_element;\n";
}
$tab_depth--;
pidl "};\n\n";
}
#####################################################################
# output prototypes for a IDL function
sub HeaderFnProto($$)
{
my ($interface,$fn) = @_;
my $name = $fn->{NAME};
pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, const struct $name *r);\n";
if (defined($fn->{OPNUM})) {
pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
}
return unless util::has_property($fn, "public");
pidl "NTSTATUS ndr_push_$name(struct ndr_push *ndr, int flags, const struct $name *r);\n";
pidl "NTSTATUS ndr_pull_$name(struct ndr_pull *ndr, int flags, struct $name *r);\n";
pidl "\n";
}
#####################################################################
# parse the interface definitions
sub HeaderInterface($)
{
my($interface) = shift;
my $count = 0;
pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n";
pidl "#define _HEADER_NDR_$interface->{NAME}\n\n";
if (defined $interface->{PROPERTIES}->{depends}) {
my @d = split / /, $interface->{PROPERTIES}->{depends};
foreach my $i (@d) {
pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
}
}
if (defined $interface->{PROPERTIES}->{uuid}) {
my $name = uc $interface->{NAME};
pidl "#define DCERPC_$name\_UUID " .
util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
}
foreach my $d (@{$interface->{FUNCTIONS}}) {
next if not defined($d->{OPNUM});
my $u_name = uc $d->{NAME};
pidl "#define DCERPC_$u_name (";
if (defined($interface->{BASE})) {
pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
}
if ($d->{OPNUM} != $count) {
die ("Function ".$d->{NAME}." has: wrong opnum [".$d->{OPNUM}."] should be [".$count."]");
}
pidl sprintf("0x%02x", $count) . ")\n";
$count++;
}
pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
if (defined($interface->{BASE})) {
pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
}
pidl "$count)\n\n";
foreach my $d (@{$interface->{CONSTS}}) {
HeaderConst($d);
}
foreach my $d (@{$interface->{TYPEDEFS}}) {
HeaderTypedef($d);
HeaderTypedefProto($d);
}
foreach my $d (@{$interface->{FUNCTIONS}}) {
HeaderFunction($d);
HeaderFnProto($interface, $d);
}
pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
}
#####################################################################
# parse a parsed IDL into a C header
sub Parse($)
{
my($idl) = shift;
$tab_depth = 0;
$res = "";
pidl "/* header auto-generated by pidl */\n\n";
foreach my $x (@{$idl}) {
($x->{TYPE} eq "INTERFACE") && HeaderInterface($x);
}
return $res;
}
1;