Merge branch 'upstream'
[jelmer/samba4-debian.git] / source / pidl / lib / Parse / Pidl / Samba4 / NDR / Parser.pm
index cfd16c7b409dfd18dbf4698c3b44f34922c5f00f..0d1806a0fae31201cfb847e8735b0d75f382cd1f 100644 (file)
@@ -9,14 +9,15 @@ package Parse::Pidl::Samba4::NDR::Parser;
 
 require Exporter;
 @ISA = qw(Exporter);
-@EXPORT_OK = qw(check_null_pointer GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint);
+@EXPORT_OK = qw(check_null_pointer NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint);
 
 use strict;
 use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody);
 use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid);
-use Parse::Pidl::CUtil qw(get_pointer_to get_value_of);
-use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
+use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array);
 use Parse::Pidl::Samba4 qw(is_intree choose_header);
+use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
 use Parse::Pidl qw(warning);
 
 use vars qw($VERSION);
@@ -41,19 +42,21 @@ sub append_prefix($$)
 {
        my ($e, $var_name) = @_;
        my $pointers = 0;
+       my $arrays = 0;
 
        foreach my $l (@{$e->{LEVELS}}) {
                if ($l->{TYPE} eq "POINTER") {
                        $pointers++;
                } elsif ($l->{TYPE} eq "ARRAY") {
+                       $arrays++;
                        if (($pointers == 0) and 
                            (not $l->{IS_FIXED}) and
                            (not $l->{IS_INLINE})) {
-                               return get_value_of($var_name); 
+                               return get_value_of($var_name);
                        }
                } elsif ($l->{TYPE} eq "DATA") {
                        if (Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
-                               return get_value_of($var_name) unless ($pointers);
+                               return get_value_of($var_name) unless ($pointers or $arrays);
                        }
                }
        }
@@ -77,19 +80,6 @@ sub has_fast_array($$)
        return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string");
 }
 
-sub is_charset_array($$)
-{
-       my ($e,$l) = @_;
-
-       return 0 if ($l->{TYPE} ne "ARRAY");
-
-       my $nl = GetNextLevel($e,$l);
-
-       return 0 unless ($nl->{TYPE} eq "DATA");
-
-       return has_property($e, "charset");
-}
-
 
 ####################################
 # pidl() is our basic output routine
@@ -193,68 +183,6 @@ sub end_flags($$)
        }
 }
 
-sub GenerateStructEnv($$)
-{
-       my ($x, $v) = @_;
-       my %env;
-
-       foreach my $e (@{$x->{ELEMENTS}}) {
-               $env{$e->{NAME}} = "$v->$e->{NAME}";
-       }
-
-       $env{"this"} = $v;
-
-       return \%env;
-}
-
-sub EnvSubstituteValue($$)
-{
-       my ($env,$s) = @_;
-
-       # Substitute the value() values in the env
-       foreach my $e (@{$s->{ELEMENTS}}) {
-               next unless (defined(my $v = has_property($e, "value")));
-               
-               $env->{$e->{NAME}} = ParseExpr($v, $env, $e);
-       }
-
-       return $env;
-}
-
-sub GenerateFunctionInEnv($;$)
-{
-       my ($fn, $base) = @_;
-       my %env;
-
-       $base = "r->" unless defined($base);
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (grep (/in/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."in.$e->{NAME}";
-               }
-       }
-
-       return \%env;
-}
-
-sub GenerateFunctionOutEnv($;$)
-{
-       my ($fn, $base) = @_;
-       my %env;
-
-       $base = "r->" unless defined($base);
-
-       foreach my $e (@{$fn->{ELEMENTS}}) {
-               if (grep (/out/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."out.$e->{NAME}";
-               } elsif (grep (/in/, @{$e->{DIRECTION}})) {
-                       $env{$e->{NAME}} = $base."in.$e->{NAME}";
-               }
-       }
-
-       return \%env;
-}
-
 #####################################################################
 # parse the data of an array - push side
 sub ParseArrayPushHeader($$$$$$)
@@ -449,7 +377,7 @@ sub ParseArrayPullHeader($$$$$$)
        }
 
        if (not $l->{IS_FIXED} and not is_charset_array($e, $l)) {
-               $self->AllocateArrayLevel($e,$l,$ndr,$env,$size);
+               $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size);
        }
 
        return $length;
@@ -458,7 +386,7 @@ sub ParseArrayPullHeader($$$$$$)
 sub compression_alg($$)
 {
        my ($e, $l) = @_;
-       my ($alg, $clen, $dlen) = split(/ /, $l->{COMPRESSION});
+       my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION});
 
        return $alg;
 }
@@ -466,7 +394,7 @@ sub compression_alg($$)
 sub compression_clen($$$)
 {
        my ($e, $l, $env) = @_;
-       my ($alg, $clen, $dlen) = split(/ /, $l->{COMPRESSION});
+       my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION});
 
        return ParseExpr($clen, $env, $e->{ORIGINAL});
 }
@@ -474,7 +402,7 @@ sub compression_clen($$$)
 sub compression_dlen($$$)
 {
        my ($e,$l,$env) = @_;
-       my ($alg, $clen, $dlen) = split(/ /, $l->{COMPRESSION});
+       my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION});
 
        return ParseExpr($dlen, $env, $e->{ORIGINAL});
 }
@@ -656,7 +584,7 @@ sub ParseElementPushLevel
                my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
                my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
 
-               $var_name = $var_name . "[$counter]";
+               $var_name = get_array_element($var_name, $counter);
 
                if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
                        $self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
@@ -743,23 +671,48 @@ sub ParsePtrPush($$$$)
        }
 }
 
+sub need_pointer_to($$$)
+{
+       my ($e, $l, $scalar_only) = @_;
+
+       my $t;
+       if (ref($l->{DATA_TYPE})) {
+               $t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}";
+       } else {
+               $t = $l->{DATA_TYPE};
+       }
+
+       if (not Parse::Pidl::Typelist::is_scalar($t)) {
+               return 1 if $scalar_only;
+       }
+
+       my $arrays = 0;
+
+       foreach my $tl (@{$e->{LEVELS}}) {
+               last if $l == $tl;
+               if ($tl->{TYPE} eq "ARRAY") {
+                       $arrays++;
+               }
+       }
+
+       if (Parse::Pidl::Typelist::scalar_is_reference($t)) {
+               return 1 unless $arrays;
+       }
+
+       return 0;
+}
+
 sub ParseDataPrint($$$$)
 {
        my ($self, $e, $l, $var_name) = @_;
        
-       if (not ref($l->{DATA_TYPE}) or 
-               defined($l->{DATA_TYPE}->{NAME})) {
-               my $t;
-               if (ref($l->{DATA_TYPE})) {
-                       $t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}";
-               } else {
-                       $t = $l->{DATA_TYPE};
-               }
-               if (not Parse::Pidl::Typelist::is_scalar($t) or 
-                       Parse::Pidl::Typelist::scalar_is_reference($t)) {
+       if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {
+
+               if (need_pointer_to($e, $l, 1)) {
                        $var_name = get_pointer_to($var_name);
                }
-               $self->pidl("ndr_print_$t(ndr, \"$e->{NAME}\", $var_name);");
+
+               $self->pidl(TypeFunctionName("ndr_print", $l->{DATA_TYPE})."(ndr, \"$e->{NAME}\", $var_name);");
        } else {
                $self->ParseTypePrint($l->{DATA_TYPE}, $var_name);
        }
@@ -822,11 +775,10 @@ sub ParseElementPrint($$$$)
                                $self->pidl("for ($counter=0;$counter<$length;$counter++) {");
                                $self->indent;
                                $self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;");
-                               $self->pidl("asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);");
-                               $self->pidl("if (idx_$l->{LEVEL_INDEX}) {");
+                               $self->pidl("if (asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter) != -1) {");
                                $self->indent;
 
-                               $var_name = $var_name . "[$counter]";
+                               $var_name = get_array_element($var_name, $counter);
                        }
                } elsif ($l->{TYPE} eq "DATA") {
                        $self->ParseDataPrint($e, $l, $var_name);
@@ -889,12 +841,11 @@ sub ParseDataPull($$$$$$$)
 {
        my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_;
 
-       if (not ref($l->{DATA_TYPE}) or 
-               defined($l->{DATA_TYPE}->{NAME})) {
+       if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {
 
                my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
 
-               if (Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
+               if (need_pointer_to($e, $l, 0)) {
                        $var_name = get_pointer_to($var_name);
                }
 
@@ -904,7 +855,7 @@ sub ParseDataPull($$$$$$$)
 
                if (my $range = has_property($e, "range")) {
                        $var_name = get_value_of($var_name);
-                       my ($low, $high) = split(/ /, $range, 2);
+                       my ($low, $high) = split(/,/, $range, 2);
                        $self->pidl("if ($var_name < $low || $var_name > $high) {");
                        $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
                        $self->pidl("}");
@@ -919,21 +870,15 @@ sub ParseDataPush($$$$$$$)
        my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_;
 
        if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {
-               my $t;
-               if (ref($l->{DATA_TYPE}) eq "HASH") {
-                       $t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}";
-               } else {
-                       $t = $l->{DATA_TYPE};
-               }
-                               
+
+               my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
+
                # strings are passed by value rather than reference
-               if (not Parse::Pidl::Typelist::is_scalar($t) or 
-                       Parse::Pidl::Typelist::scalar_is_reference($t)) {
+               if (need_pointer_to($e, $l, 1)) {
                        $var_name = get_pointer_to($var_name);
                }
 
-               my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
-               $self->pidl("NDR_CHECK(ndr_push_$t($ndr, $ndr_flags, $var_name));");
+               $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
        } else {
                $self->ParseTypePush($l->{DATA_TYPE}, $var_name, $primitives, $deferred);
        }
@@ -964,15 +909,17 @@ sub CalcNdrFlags($$$)
        return undef;
 }
 
-sub ParseMemCtxPullStart($$$$)
+sub ParseMemCtxPullFlags($$$$)
 {
-       my ($self, $e, $l, $ptr_name) = @_;
+       my ($self, $e, $l) = @_;
 
-       my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
-       my $mem_c_ctx = $ptr_name;
-       my $mem_c_flags = "0";
+       return undef unless ($l->{TYPE} eq "POINTER" or $l->{TYPE} eq "ARRAY");
+
+       return undef if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
+       return undef if has_fast_array($e, $l);
+       return undef if is_charset_array($e, $l);
 
-       return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
+       my $mem_flags = "0";
 
        if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
                my $nl = GetNextLevel($e, $l);
@@ -980,12 +927,25 @@ sub ParseMemCtxPullStart($$$$)
                my $next_is_string = (($nl->{TYPE} eq "DATA") and 
                                        ($nl->{DATA_TYPE} eq "string"));
                if ($next_is_array or $next_is_string) {
-                       return;
-               } else {
-                       $mem_c_flags = "LIBNDR_FLAG_REF_ALLOC";
+                       return undef;
+               } elsif ($l->{LEVEL} eq "TOP") {
+                       $mem_flags = "LIBNDR_FLAG_REF_ALLOC";
                }
        }
 
+       return $mem_flags;
+}
+
+sub ParseMemCtxPullStart($$$$)
+{
+       my ($self, $e, $l, $ptr_name) = @_;
+
+       my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
+       my $mem_c_ctx = $ptr_name;
+       my $mem_c_flags = $self->ParseMemCtxPullFlags($e, $l);
+
+       return unless defined($mem_c_flags);
+
        $self->pidl("$mem_r_ctx = NDR_PULL_GET_MEM_CTX(ndr);");
        $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_c_ctx, $mem_c_flags);");
 }
@@ -995,21 +955,9 @@ sub ParseMemCtxPullEnd($$$)
        my ($self, $e, $l) = @_;
 
        my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
-       my $mem_r_flags = "0";
+       my $mem_r_flags = $self->ParseMemCtxPullFlags($e, $l);
 
-       return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
-
-       if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
-               my $nl = GetNextLevel($e, $l);
-               my $next_is_array = ($nl->{TYPE} eq "ARRAY");
-               my $next_is_string = (($nl->{TYPE} eq "DATA") and 
-                                       ($nl->{DATA_TYPE} eq "string"));
-               if ($next_is_array or $next_is_string) {
-                       return;
-               } else {
-                       $mem_r_flags = "LIBNDR_FLAG_REF_ALLOC";
-               }
-       }
+       return unless defined($mem_r_flags);
 
        $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_r_ctx, $mem_r_flags);");
 }
@@ -1099,7 +1047,7 @@ sub ParseElementPullLevel
                my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
                my $array_name = $var_name;
 
-               $var_name = $var_name . "[$counter]";
+               $var_name = get_array_element($var_name, $counter);
 
                $self->ParseMemCtxPullStart($e, $l, $array_name);
 
@@ -1180,10 +1128,7 @@ sub ParsePtrPull($$$$$)
        my $next_is_string = (($nl->{TYPE} eq "DATA") and 
                                                 ($nl->{DATA_TYPE} eq "string"));
 
-       if ($l->{POINTER_TYPE} eq "ref") {
-               if ($l->{LEVEL} eq "EMBEDDED") {
-                       $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));");
-               }
+       if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") {
 
                if (!$next_is_array and !$next_is_string) {
                        $self->pidl("if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {");
@@ -1192,16 +1137,19 @@ sub ParsePtrPull($$$$$)
                }
                
                return;
+       } elsif ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "EMBEDDED") {
+               $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));");
        } elsif (($l->{POINTER_TYPE} eq "unique") or 
                 ($l->{POINTER_TYPE} eq "relative") or
                 ($l->{POINTER_TYPE} eq "full")) {
                $self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));");
-               $self->pidl("if (_ptr_$e->{NAME}) {");
-               $self->indent;
        } else {
                die("Unhandled pointer type $l->{POINTER_TYPE}");
        }
 
+       $self->pidl("if (_ptr_$e->{NAME}) {");
+       $self->indent;
+
        # Don't do this for arrays, they're allocated at the actual level 
        # of the array
        unless ($next_is_array or $next_is_string) { 
@@ -1515,31 +1463,12 @@ sub DeclareArrayVariables($$)
        }
 }
 
-sub need_decl_mem_ctx($$)
-{
-       my ($e,$l) = @_;
-
-       return 0 if has_fast_array($e,$l);
-       return 0 if is_charset_array($e,$l);
-       return 1 if (($l->{TYPE} eq "ARRAY") and not $l->{IS_FIXED});
-
-       if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
-               my $nl = GetNextLevel($e, $l);
-               my $next_is_array = ($nl->{TYPE} eq "ARRAY");
-               my $next_is_string = (($nl->{TYPE} eq "DATA") and 
-                                       ($nl->{DATA_TYPE} eq "string"));
-               return 0 if ($next_is_array or $next_is_string);
-       }
-       return 1 if ($l->{TYPE} eq "POINTER");
-
-       return 0;
-}
-
 sub DeclareMemCtxVariables($$)
 {
        my ($self,$e) = @_;
        foreach my $l (@{$e->{LEVELS}}) {
-               if (need_decl_mem_ctx($e, $l)) {
+               my $mem_flags = $self->ParseMemCtxPullFlags($e, $l);
+               if (defined($mem_flags)) {
                        $self->pidl("TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};");
                }
        }
@@ -1681,7 +1610,7 @@ sub ParseUnionPushPrimitives($$$)
                if ($el->{CASE} eq "default") {
                        $have_default = 1;
                }
-               $self->pidl("$el->{CASE}:");
+               $self->pidl("$el->{CASE}: {");
 
                if ($el->{TYPE} ne "EMPTY") {
                        $self->indent;
@@ -1695,7 +1624,7 @@ sub ParseUnionPushPrimitives($$$)
                        $self->ParseElementPush($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0);
                        $self->deindent;
                }
-               $self->pidl("break;");
+               $self->pidl("break; }");
                $self->pidl("");
        }
        if (! $have_default) {
@@ -2132,9 +2061,7 @@ sub ParseFunctionPush($$)
 
 sub AllocateArrayLevel($$$$$$)
 {
-       my ($self,$e,$l,$ndr,$env,$size) = @_;
-
-       my $var = ParseExpr($e->{NAME}, $env, $e->{ORIGINAL});
+       my ($self,$e,$l,$ndr,$var,$size) = @_;
 
        my $pl = GetPrevLevel($e, $l);
        if (defined($pl) and 
@@ -2221,9 +2148,9 @@ sub ParseFunctionPull($$)
                        $self->pidl("NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);");
 
                        if (grep(/in/, @{$e->{DIRECTION}})) {
-                               $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));");
+                               $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));");
                        } else {
-                               $self->pidl("memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));");
+                               $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));");
                        }
                } else {
                        $self->pidl("NDR_PULL_ALLOC(ndr, r->out.$e->{NAME});");
@@ -2263,6 +2190,26 @@ sub ParseFunctionPull($$)
        $self->pidl("");
 }
 
+sub AuthServiceStruct($$$)
+{
+       my ($self, $ifacename, $authservice) = @_;
+       my @a = split /,/, $authservice;
+       my $authservice_count = $#a + 1;
+
+       $self->pidl("static const char * const $ifacename\_authservice_strings[] = {");
+       foreach my $ap (@a) {
+               $self->pidl("\t$ap, ");
+       }
+       $self->pidl("};");
+       $self->pidl("");
+
+       $self->pidl("static const struct ndr_interface_string_array $ifacename\_authservices = {");
+       $self->pidl("\t.count\t= $authservice_count,");
+       $self->pidl("\t.names\t= $ifacename\_authservice_strings");
+       $self->pidl("};");
+       $self->pidl("");
+}
+
 #####################################################################
 # produce a function call table
 sub FunctionTable($$)
@@ -2310,21 +2257,8 @@ sub FunctionTable($$)
                $interface->{PROPERTIES}->{authservice} = "\"host\"";
        }
 
-       my @a = split / /, $interface->{PROPERTIES}->{authservice};
-       my $authservice_count = $#a + 1;
-
-       $self->pidl("static const char * const $interface->{NAME}\_authservice_strings[] = {");
-       foreach my $ap (@a) {
-               $self->pidl("\t$ap, ");
-       }
-       $self->pidl("};");
-       $self->pidl("");
-
-       $self->pidl("static const struct ndr_interface_string_array $interface->{NAME}\_authservices = {");
-       $self->pidl("\t.count\t= $endpoint_count,");
-       $self->pidl("\t.names\t= $interface->{NAME}\_authservice_strings");
-       $self->pidl("};");
-       $self->pidl("");
+       $self->AuthServiceStruct($interface->{NAME}, 
+                                    $interface->{PROPERTIES}->{authservice});
 
        $self->pidl("\nconst struct ndr_interface_table ndr_table_$interface->{NAME} = {");
        $self->pidl("\t.name\t\t= \"$interface->{NAME}\",");
@@ -2385,7 +2319,7 @@ sub HeaderInterface($$$)
        }
 
        if (defined $interface->{PROPERTIES}->{helper}) {
-               $self->HeaderInclude(split / /, $interface->{PROPERTIES}->{helper});
+               $self->HeaderInclude(split /,/, $interface->{PROPERTIES}->{helper});
        }
 
        if (defined $interface->{PROPERTIES}->{uuid}) {
@@ -2543,7 +2477,8 @@ sub ParseInterface($$$)
 
        # Typedefs
        foreach my $d (@{$interface->{TYPES}}) {
-               next unless typeHasBody($d);
+               next unless(typeHasBody($d));
+
                ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r");
                ($needed->{TypeFunctionName("ndr_pull", $d)}) && $self->ParseTypePullFunction($d, "r");
                ($needed->{TypeFunctionName("ndr_print", $d)}) && $self->ParseTypePrintFunction($d, "r");
@@ -2687,6 +2622,7 @@ sub NeededType($$$)
        NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF");
 
        if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") {
+               return unless defined($t->{ELEMENTS});
                for my $e (@{$t->{ELEMENTS}}) {
                        $e->{PARENT} = $t;
                        if (has_property($e, "compression")) {