1 ###################################################
2 # Samba4 NDR parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # Copyright jelmer@samba.org 2004-2006
6 # released under the GNU GPL
8 package Parse::Pidl::Samba4::NDR::Parser;
11 use Parse::Pidl::Typelist qw(hasType getType mapType);
12 use Parse::Pidl::Util qw(has_property ParseExpr print_uuid);
13 use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
14 use Parse::Pidl::Samba4 qw(is_intree choose_header);
16 use vars qw($VERSION);
25 return $typefamily{$n};
30 my ($e, $var_name) = @_;
33 foreach my $l (@{$e->{LEVELS}}) {
34 if ($l->{TYPE} eq "POINTER") {
36 } elsif ($l->{TYPE} eq "ARRAY") {
37 if (($pointers == 0) and
38 (not $l->{IS_FIXED}) and
39 (not $l->{IS_INLINE})) {
40 return get_value_of($var_name);
42 } elsif ($l->{TYPE} eq "DATA") {
43 if (Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
44 return get_value_of($var_name) unless ($pointers);
52 sub has_fast_array($$)
56 return 0 if ($l->{TYPE} ne "ARRAY");
58 my $nl = GetNextLevel($e,$l);
59 return 0 unless ($nl->{TYPE} eq "DATA");
60 return 0 unless (hasType($nl->{DATA_TYPE}));
62 my $t = getType($nl->{DATA_TYPE});
64 # Only uint8 and string have fast array functions at the moment
65 return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string");
68 sub is_charset_array($$)
72 return 0 if ($l->{TYPE} ne "ARRAY");
74 my $nl = GetNextLevel($e,$l);
76 return 0 unless ($nl->{TYPE} eq "DATA");
78 return has_property($e, "charset");
85 if ($var_name =~ /^\*(.*)$/) {
87 } elsif ($var_name =~ /^\&(.*)$/) {
88 return "&($var_name)";
98 if ($var_name =~ /^\&(.*)$/) {
109 ####################################
110 # pidl() is our basic output routine
123 sub pidl_hdr ($) { my $d = shift; $res_hdr .= "$d\n"; }
125 ####################################
126 # defer() is like pidl(), but adds to
127 # a deferred buffer which is then added to the
128 # output buffer at the end of the structure/union/function
129 # This is needed to cope with code that must be pushed back
130 # to the end of a block of elements
141 ########################################
142 # add the deferred content to the current
157 $tabs = substr($tabs, 0, -1);
160 #####################################################################
161 # check that a variable we get from ParseExpr isn't a null pointer
162 sub check_null_pointer($)
165 if ($size =~ /^\*/) {
166 my $size2 = substr($size, 1);
167 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
171 #####################################################################
172 # check that a variable we get from ParseExpr isn't a null pointer,
173 # putting the check at the end of the structure/function
174 sub check_null_pointer_deferred($)
177 if ($size =~ /^\*/) {
178 my $size2 = substr($size, 1);
179 defer "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
183 #####################################################################
184 # check that a variable we get from ParseExpr isn't a null pointer
185 # void return varient
186 sub check_null_pointer_void($)
189 if ($size =~ /^\*/) {
190 my $size2 = substr($size, 1);
191 pidl "if ($size2 == NULL) return;";
195 #####################################################################
196 # declare a function public or static, depending on its attributes
201 if (has_property($fn, "public")) {
203 pidl "_PUBLIC_ $decl";
209 ###################################################################
210 # setup any special flags for an element or structure
214 my $flags = has_property($e, "flag");
215 if (defined $flags) {
218 pidl "uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
219 pidl "ndr_set_flags(&ndr->flags, $flags);";
223 ###################################################################
224 # end any special flags for an element or structure
228 my $flags = has_property($e, "flag");
229 if (defined $flags) {
230 pidl "ndr->flags = _flags_save_$e->{TYPE};";
236 sub GenerateStructEnv($)
241 foreach my $e (@{$x->{ELEMENTS}}) {
242 $env{$e->{NAME}} = "r->$e->{NAME}";
250 sub EnvSubstituteValue($$)
254 # Substitute the value() values in the env
255 foreach my $e (@{$s->{ELEMENTS}}) {
256 next unless (my $v = has_property($e, "value"));
258 $env->{$e->{NAME}} = ParseExpr($v, $env);
264 sub GenerateFunctionInEnv($)
269 foreach my $e (@{$fn->{ELEMENTS}}) {
270 if (grep (/in/, @{$e->{DIRECTION}})) {
271 $env{$e->{NAME}} = "r->in.$e->{NAME}";
278 sub GenerateFunctionOutEnv($)
283 foreach my $e (@{$fn->{ELEMENTS}}) {
284 if (grep (/out/, @{$e->{DIRECTION}})) {
285 $env{$e->{NAME}} = "r->out.$e->{NAME}";
286 } elsif (grep (/in/, @{$e->{DIRECTION}})) {
287 $env{$e->{NAME}} = "r->in.$e->{NAME}";
294 #####################################################################
295 # parse the data of an array - push side
296 sub ParseArrayPushHeader($$$$$)
298 my ($e,$l,$ndr,$var_name,$env) = @_;
303 if ($l->{IS_ZERO_TERMINATED}) {
304 if (has_property($e, "charset")) {
305 $size = $length = "ndr_charset_length($var_name, CH_$e->{PROPERTIES}->{charset})";
307 $size = $length = "ndr_string_length($var_name, sizeof(*$var_name))";
310 $size = ParseExpr($l->{SIZE_IS}, $env);
311 $length = ParseExpr($l->{LENGTH_IS}, $env);
314 if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
315 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $size));";
318 if ($l->{IS_VARYING}) {
319 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));"; # array offset
320 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
326 #####################################################################
327 # parse an array - pull side
328 sub ParseArrayPullHeader($$$$$)
330 my ($e,$l,$ndr,$var_name,$env) = @_;
335 if ($l->{IS_CONFORMANT}) {
336 $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
337 } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
338 $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
340 $length = $size = ParseExpr($l->{SIZE_IS}, $env);
343 if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
344 pidl "NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));";
348 if ($l->{IS_VARYING}) {
349 pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));";
350 $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
353 check_null_pointer($length);
355 if ($length ne $size) {
356 pidl "if ($length > $size) {";
358 pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);";
363 if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) {
364 my $size = ParseExpr($l->{SIZE_IS}, $env);
365 defer "if ($var_name) {";
366 check_null_pointer_deferred($size);
367 defer "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
371 if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
372 my $length = ParseExpr($l->{LENGTH_IS}, $env);
373 defer "if ($var_name) {";
374 check_null_pointer_deferred($length);
375 defer "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
379 if (not $l->{IS_FIXED} and not is_charset_array($e, $l)) {
380 AllocateArrayLevel($e,$l,$ndr,$env,$size);
386 sub compression_alg($$)
389 my $compression = $l->{COMPRESSION};
390 my ($alg, $clen, $dlen) = split(/ /, $compression);
395 sub compression_clen($$$)
397 my ($e,$l,$env) = @_;
398 my $compression = $l->{COMPRESSION};
399 my ($alg, $clen, $dlen) = split(/ /, $compression);
401 return ParseExpr($clen, $env);
404 sub compression_dlen($$$)
406 my ($e,$l,$env) = @_;
407 my $compression = $l->{COMPRESSION};
408 my ($alg, $clen, $dlen) = split(/ /, $compression);
410 return ParseExpr($dlen, $env);
413 sub ParseCompressionPushStart($$$$)
415 my ($e,$l,$ndr,$env) = @_;
416 my $comndr = "$ndr\_compressed";
417 my $alg = compression_alg($e, $l);
418 my $dlen = compression_dlen($e, $l, $env);
422 pidl "struct ndr_push *$comndr;";
423 pidl "NDR_CHECK(ndr_push_compression_start($ndr, &$comndr, $alg, $dlen));";
428 sub ParseCompressionPushEnd($$$$)
430 my ($e,$l,$ndr,$env) = @_;
431 my $comndr = "$ndr\_compressed";
432 my $alg = compression_alg($e, $l);
433 my $dlen = compression_dlen($e, $l, $env);
435 pidl "NDR_CHECK(ndr_push_compression_end($ndr, $comndr, $alg, $dlen));";
440 sub ParseCompressionPullStart($$$$)
442 my ($e,$l,$ndr,$env) = @_;
443 my $comndr = "$ndr\_compressed";
444 my $alg = compression_alg($e, $l);
445 my $dlen = compression_dlen($e, $l, $env);
449 pidl "struct ndr_pull *$comndr;";
450 pidl "NDR_CHECK(ndr_pull_compression_start($ndr, &$comndr, $alg, $dlen));";
455 sub ParseCompressionPullEnd($$$$)
457 my ($e,$l,$ndr,$env) = @_;
458 my $comndr = "$ndr\_compressed";
459 my $alg = compression_alg($e, $l);
460 my $dlen = compression_dlen($e, $l, $env);
462 pidl "NDR_CHECK(ndr_pull_compression_end($ndr, $comndr, $alg, $dlen));";
467 sub ParseObfuscationPushStart($$)
470 my $obfuscation = has_property($e, "obfuscation");
472 pidl "NDR_CHECK(ndr_push_obfuscation_start($ndr, $obfuscation));";
477 sub ParseObfuscationPushEnd($$)
480 my $obfuscation = has_property($e, "obfuscation");
482 pidl "NDR_CHECK(ndr_push_obfuscation_end($ndr, $obfuscation));";
485 sub ParseObfuscationPullStart($$)
488 my $obfuscation = has_property($e, "obfuscation");
490 pidl "NDR_CHECK(ndr_pull_obfuscation_start($ndr, $obfuscation));";
495 sub ParseObfuscationPullEnd($$)
498 my $obfuscation = has_property($e, "obfuscation");
500 pidl "NDR_CHECK(ndr_pull_obfuscation_end($ndr, $obfuscation));";
503 sub ParseSubcontextPushStart($$$$)
505 my ($e,$l,$ndr,$env) = @_;
506 my $subndr = "_ndr_$e->{NAME}";
507 my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
511 pidl "struct ndr_push *$subndr;";
512 pidl "NDR_CHECK(ndr_push_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));";
514 if (defined $l->{COMPRESSION}) {
515 $subndr = ParseCompressionPushStart($e, $l, $subndr, $env);
518 if (defined $l->{OBFUSCATION}) {
519 $subndr = ParseObfuscationPushStart($e, $subndr);
525 sub ParseSubcontextPushEnd($$$$)
527 my ($e,$l,$ndr,$env) = @_;
528 my $subndr = "_ndr_$e->{NAME}";
529 my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
531 if (defined $l->{COMPRESSION}) {
532 ParseCompressionPushEnd($e, $l, $subndr, $env);
535 if (defined $l->{OBFUSCATION}) {
536 ParseObfuscationPushEnd($e, $subndr);
539 pidl "NDR_CHECK(ndr_push_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));";
544 sub ParseSubcontextPullStart($$$$)
546 my ($e,$l,$ndr,$env) = @_;
547 my $subndr = "_ndr_$e->{NAME}";
548 my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
552 pidl "struct ndr_pull *$subndr;";
553 pidl "NDR_CHECK(ndr_pull_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));";
555 if (defined $l->{COMPRESSION}) {
556 $subndr = ParseCompressionPullStart($e, $l, $subndr, $env);
559 if (defined $l->{OBFUSCATION}) {
560 $subndr = ParseObfuscationPullStart($e, $subndr);
566 sub ParseSubcontextPullEnd($$$$)
568 my ($e,$l,$ndr,$env) = @_;
569 my $subndr = "_ndr_$e->{NAME}";
570 my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE},$env);
572 if (defined $l->{COMPRESSION}) {
573 ParseCompressionPullEnd($e, $l, $subndr, $env);
576 if (defined $l->{OBFUSCATION}) {
577 ParseObfuscationPullEnd($e, $subndr);
580 pidl "NDR_CHECK(ndr_pull_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));";
585 sub ParseElementPushLevel
587 my ($e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_;
589 my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
591 if ($l->{TYPE} eq "ARRAY" and ($l->{IS_CONFORMANT} or $l->{IS_VARYING})) {
592 $var_name = get_pointer_to($var_name);
595 if (defined($ndr_flags)) {
596 if ($l->{TYPE} eq "SUBCONTEXT") {
597 my $subndr = ParseSubcontextPushStart($e, $l, $ndr, $env);
598 ParseElementPushLevel($e, GetNextLevel($e, $l), $subndr, $var_name, $env, 1, 1);
599 ParseSubcontextPushEnd($e, $l, $ndr, $env);
600 } elsif ($l->{TYPE} eq "POINTER") {
601 ParsePtrPush($e, $l, $var_name);
602 } elsif ($l->{TYPE} eq "ARRAY") {
603 my $length = ParseArrayPushHeader($e, $l, $ndr, $var_name, $env);
605 my $nl = GetNextLevel($e, $l);
607 # Allow speedups for arrays of scalar types
608 if (is_charset_array($e,$l)) {
609 pidl "NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
611 } elsif (has_fast_array($e,$l)) {
612 pidl "NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
615 } elsif ($l->{TYPE} eq "SWITCH") {
616 ParseSwitchPush($e, $l, $ndr, $var_name, $ndr_flags, $env);
617 } elsif ($l->{TYPE} eq "DATA") {
618 ParseDataPush($e, $l, $ndr, $var_name, $ndr_flags);
622 if ($l->{TYPE} eq "POINTER" and $deferred) {
623 if ($l->{POINTER_TYPE} ne "ref") {
624 pidl "if ($var_name) {";
626 if ($l->{POINTER_TYPE} eq "relative") {
627 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));";
630 $var_name = get_value_of($var_name);
631 ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
633 if ($l->{POINTER_TYPE} ne "ref") {
637 } elsif ($l->{TYPE} eq "ARRAY" and not has_fast_array($e,$l) and
638 not is_charset_array($e, $l)) {
639 my $length = ParseExpr($l->{LENGTH_IS}, $env);
640 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
642 $var_name = $var_name . "[$counter]";
644 if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
645 pidl "for ($counter = 0; $counter < $length; $counter++) {";
647 ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
652 if ($deferred and ContainsDeferred($e, $l)) {
653 pidl "for ($counter = 0; $counter < $length; $counter++) {";
655 ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
659 } elsif ($l->{TYPE} eq "SWITCH") {
660 ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
664 #####################################################################
665 # parse scalars in a structure element
666 sub ParseElementPush($$$$$$)
668 my ($e,$ndr,$var_prefix,$env,$primitives,$deferred) = @_;
671 my $var_name = $var_prefix.$e->{NAME};
673 return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
675 # Representation type is different from transmit_as
676 if ($e->{REPRESENTATION_TYPE}) {
679 my $transmit_name = "_transmit_$e->{NAME}";
680 pidl mapType($e->{TYPE}) ." $transmit_name;";
681 pidl "NDR_CHECK(ndr_$e->{REPRESENTATION_TYPE}_to_$e->{TYPE}($var_name, " . get_pointer_to($transmit_name) . "));";
682 $var_name = $transmit_name;
685 $var_name = append_prefix($e, $var_name);
689 if (my $value = has_property($e, "value")) {
690 $var_name = ParseExpr($value, $env);
693 ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred);
697 if ($e->{REPRESENTATION_TYPE}) {
703 #####################################################################
704 # parse a pointer in a struct element or function
705 sub ParsePtrPush($$$)
707 my ($e,$l,$var_name) = @_;
709 if ($l->{POINTER_TYPE} eq "ref") {
710 if ($l->{LEVEL} eq "EMBEDDED") {
711 pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_name));";
713 check_null_pointer(get_value_of($var_name));
715 } elsif ($l->{POINTER_TYPE} eq "relative") {
716 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));";
717 } elsif ($l->{POINTER_TYPE} eq "unique") {
718 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));";
719 } elsif ($l->{POINTER_TYPE} eq "sptr") {
720 pidl "NDR_CHECK(ndr_push_sptr_ptr(ndr, $var_name));";
722 die("Unhandled pointer type $l->{POINTER_TYPE}");
726 #####################################################################
727 # print scalars in a structure element
728 sub ParseElementPrint($$$)
730 my($e,$var_name,$env) = @_;
732 $var_name = append_prefix($e, $var_name);
733 return if (has_property($e, "noprint"));
735 if (my $value = has_property($e, "value")) {
736 $var_name = "(ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env) . ":$var_name";
739 foreach my $l (@{$e->{LEVELS}}) {
740 if ($l->{TYPE} eq "POINTER") {
741 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);";
742 pidl "ndr->depth++;";
743 if ($l->{POINTER_TYPE} ne "ref") {
744 pidl "if ($var_name) {";
747 $var_name = get_value_of($var_name);
748 } elsif ($l->{TYPE} eq "ARRAY") {
751 if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {
752 $var_name = get_pointer_to($var_name);
755 if ($l->{IS_ZERO_TERMINATED}) {
756 $length = "ndr_string_length($var_name, sizeof(*$var_name))";
758 $length = ParseExpr($l->{LENGTH_IS}, $env);
761 if (is_charset_array($e,$l)) {
762 pidl "ndr_print_string(ndr, \"$e->{NAME}\", $var_name);";
764 } elsif (has_fast_array($e, $l)) {
765 my $nl = GetNextLevel($e, $l);
766 pidl "ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
769 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
771 pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);";
772 pidl 'ndr->depth++;';
773 pidl "for ($counter=0;$counter<$length;$counter++) {";
775 pidl "char *idx_$l->{LEVEL_INDEX}=NULL;";
776 pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);";
777 pidl "if (idx_$l->{LEVEL_INDEX}) {";
780 $var_name = $var_name . "[$counter]";
782 } elsif ($l->{TYPE} eq "DATA") {
783 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE}) or Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
784 $var_name = get_pointer_to($var_name);
786 pidl "ndr_print_$l->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name);";
787 } elsif ($l->{TYPE} eq "SWITCH") {
788 my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
789 check_null_pointer_void($switch_var);
790 pidl "ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);";
794 foreach my $l (reverse @{$e->{LEVELS}}) {
795 if ($l->{TYPE} eq "POINTER") {
796 if ($l->{POINTER_TYPE} ne "ref") {
800 pidl "ndr->depth--;";
801 } elsif (($l->{TYPE} eq "ARRAY")
802 and not is_charset_array($e,$l)
803 and not has_fast_array($e,$l)) {
804 pidl "free(idx_$l->{LEVEL_INDEX});";
809 pidl "ndr->depth--;";
814 #####################################################################
815 # parse scalars in a structure element - pull size
816 sub ParseSwitchPull($$$$$$)
818 my($e,$l,$ndr,$var_name,$ndr_flags,$env) = @_;
819 my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
821 check_null_pointer($switch_var);
823 $var_name = get_pointer_to($var_name);
824 pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));";
827 #####################################################################
828 # push switch element
829 sub ParseSwitchPush($$$$$$)
831 my($e,$l,$ndr,$var_name,$ndr_flags,$env) = @_;
832 my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
834 check_null_pointer($switch_var);
835 $var_name = get_pointer_to($var_name);
836 pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));";
839 sub ParseDataPull($$$$$)
841 my ($e,$l,$ndr,$var_name,$ndr_flags) = @_;
843 if (Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
844 $var_name = get_pointer_to($var_name);
847 $var_name = get_pointer_to($var_name);
849 pidl "NDR_CHECK(ndr_pull_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
851 if (my $range = has_property($e, "range")) {
852 $var_name = get_value_of($var_name);
853 my ($low, $high) = split(/ /, $range, 2);
854 pidl "if ($var_name < $low || $var_name > $high) {";
855 pidl "\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
860 sub ParseDataPush($$$$$)
862 my ($e,$l,$ndr,$var_name,$ndr_flags) = @_;
864 # strings are passed by value rather then reference
865 if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE}) or Parse::Pidl::Typelist::scalar_is_reference($l->{DATA_TYPE})) {
866 $var_name = get_pointer_to($var_name);
869 pidl "NDR_CHECK(ndr_push_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
872 sub CalcNdrFlags($$$)
874 my ($l,$primitives,$deferred) = @_;
879 # Add NDR_SCALARS if this one is deferred
880 # and deferreds may be pushed
881 $scalars = 1 if ($l->{IS_DEFERRED} and $deferred);
883 # Add NDR_SCALARS if this one is not deferred and
884 # primitives may be pushed
885 $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives);
887 # Add NDR_BUFFERS if this one contains deferred stuff
888 # and deferreds may be pushed
889 $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred);
891 return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers);
892 return "NDR_SCALARS" if ($scalars);
893 return "NDR_BUFFERS" if ($buffers);
897 sub ParseMemCtxPullStart($$$)
901 my $ptr_name = shift;
903 my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
904 my $mem_c_ctx = $ptr_name;
905 my $mem_c_flags = "0";
907 return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
909 if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
910 my $nl = GetNextLevel($e, $l);
911 my $next_is_array = ($nl->{TYPE} eq "ARRAY");
912 my $next_is_string = (($nl->{TYPE} eq "DATA") and
913 ($nl->{DATA_TYPE} eq "string"));
914 if ($next_is_array or $next_is_string) {
917 $mem_c_flags = "LIBNDR_FLAG_REF_ALLOC";
921 pidl "$mem_r_ctx = NDR_PULL_GET_MEM_CTX(ndr);";
922 pidl "NDR_PULL_SET_MEM_CTX(ndr, $mem_c_ctx, $mem_c_flags);";
925 sub ParseMemCtxPullEnd($$)
930 my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
931 my $mem_r_flags = "0";
933 return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
935 if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
936 my $nl = GetNextLevel($e, $l);
937 my $next_is_array = ($nl->{TYPE} eq "ARRAY");
938 my $next_is_string = (($nl->{TYPE} eq "DATA") and
939 ($nl->{DATA_TYPE} eq "string"));
940 if ($next_is_array or $next_is_string) {
943 $mem_r_flags = "LIBNDR_FLAG_REF_ALLOC";
947 pidl "NDR_PULL_SET_MEM_CTX(ndr, $mem_r_ctx, $mem_r_flags);";
950 sub CheckStringTerminator($$$$)
952 my ($ndr,$e,$l,$length) = @_;
953 my $nl = GetNextLevel($e, $l);
955 # Make sure last element is zero!
956 pidl "NDR_CHECK(ndr_check_string_terminator($ndr, $length, sizeof($nl->{DATA_TYPE}_t)));";
959 sub ParseElementPullLevel
961 my($e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_;
963 my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
965 if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
966 $var_name = get_pointer_to($var_name);
969 # Only pull something if there's actually something to be pulled
970 if (defined($ndr_flags)) {
971 if ($l->{TYPE} eq "SUBCONTEXT") {
972 my $subndr = ParseSubcontextPullStart($e, $l, $ndr, $env);
973 ParseElementPullLevel($e, GetNextLevel($e,$l), $subndr, $var_name, $env, 1, 1);
974 ParseSubcontextPullEnd($e, $l, $ndr, $env);
975 } elsif ($l->{TYPE} eq "ARRAY") {
976 my $length = ParseArrayPullHeader($e, $l, $ndr, $var_name, $env);
978 my $nl = GetNextLevel($e, $l);
980 if (is_charset_array($e,$l)) {
981 if ($l->{IS_ZERO_TERMINATED}) {
982 CheckStringTerminator($ndr, $e, $l, $length);
984 pidl "NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapType($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));";
986 } elsif (has_fast_array($e, $l)) {
987 if ($l->{IS_ZERO_TERMINATED}) {
988 CheckStringTerminator($ndr,$e,$l,$length);
990 pidl "NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));";
993 } elsif ($l->{TYPE} eq "POINTER") {
994 ParsePtrPull($e, $l, $ndr, $var_name);
995 } elsif ($l->{TYPE} eq "SWITCH") {
996 ParseSwitchPull($e, $l, $ndr, $var_name, $ndr_flags, $env);
997 } elsif ($l->{TYPE} eq "DATA") {
998 ParseDataPull($e, $l, $ndr, $var_name, $ndr_flags);
1002 # add additional constructions
1003 if ($l->{TYPE} eq "POINTER" and $deferred) {
1004 if ($l->{POINTER_TYPE} ne "ref") {
1005 pidl "if ($var_name) {";
1008 if ($l->{POINTER_TYPE} eq "relative") {
1009 pidl "struct ndr_pull_save _relative_save;";
1010 pidl "ndr_pull_save(ndr, &_relative_save);";
1011 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));";
1015 ParseMemCtxPullStart($e,$l, $var_name);
1017 $var_name = get_value_of($var_name);
1018 ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
1020 ParseMemCtxPullEnd($e,$l);
1022 if ($l->{POINTER_TYPE} ne "ref") {
1023 if ($l->{POINTER_TYPE} eq "relative") {
1024 pidl "ndr_pull_restore(ndr, &_relative_save);";
1029 } elsif ($l->{TYPE} eq "ARRAY" and
1030 not has_fast_array($e,$l) and not is_charset_array($e, $l)) {
1031 my $length = ParseExpr($l->{LENGTH_IS}, $env);
1032 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
1033 my $array_name = $var_name;
1035 $var_name = $var_name . "[$counter]";
1037 ParseMemCtxPullStart($e,$l, $array_name);
1039 if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
1040 my $nl = GetNextLevel($e,$l);
1042 if ($l->{IS_ZERO_TERMINATED}) {
1043 CheckStringTerminator($ndr,$e,$l,$length);
1046 pidl "for ($counter = 0; $counter < $length; $counter++) {";
1048 ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, 1, 0);
1053 if ($deferred and ContainsDeferred($e, $l)) {
1054 pidl "for ($counter = 0; $counter < $length; $counter++) {";
1056 ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
1061 ParseMemCtxPullEnd($e,$l);
1063 } elsif ($l->{TYPE} eq "SWITCH") {
1064 ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
1068 #####################################################################
1069 # parse scalars in a structure element - pull size
1070 sub ParseElementPull($$$$$$)
1072 my($e,$ndr,$var_prefix,$env,$primitives,$deferred) = @_;
1074 my $var_name = $var_prefix.$e->{NAME};
1078 return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
1080 if ($e->{REPRESENTATION_TYPE}) {
1083 $represent_name = $var_name;
1084 $transmit_name = "_transmit_$e->{NAME}";
1085 $var_name = $transmit_name;
1086 pidl mapType($e->{TYPE})." $var_name;";
1089 $var_name = append_prefix($e, $var_name);
1093 ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred);
1097 # Representation type is different from transmit_as
1098 if ($e->{REPRESENTATION_TYPE}) {
1099 pidl "NDR_CHECK(ndr_$e->{TYPE}_to_$e->{REPRESENTATION_TYPE}($transmit_name, ".get_pointer_to($represent_name)."));";
1105 #####################################################################
1106 # parse a pointer in a struct element or function
1107 sub ParsePtrPull($$$$)
1109 my($e,$l,$ndr,$var_name) = @_;
1111 my $nl = GetNextLevel($e, $l);
1112 my $next_is_array = ($nl->{TYPE} eq "ARRAY");
1113 my $next_is_string = (($nl->{TYPE} eq "DATA") and
1114 ($nl->{DATA_TYPE} eq "string"));
1116 if ($l->{POINTER_TYPE} eq "ref") {
1117 unless ($l->{LEVEL} eq "TOP") {
1118 pidl "NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));";
1121 unless ($next_is_array or $next_is_string) {
1122 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1123 pidl "\tNDR_PULL_ALLOC($ndr, $var_name);";
1128 } elsif (($l->{POINTER_TYPE} eq "unique") or
1129 ($l->{POINTER_TYPE} eq "relative") or
1130 ($l->{POINTER_TYPE} eq "sptr")) {
1131 pidl "NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));";
1132 pidl "if (_ptr_$e->{NAME}) {";
1135 die("Unhandled pointer type $l->{POINTER_TYPE}");
1138 # Don't do this for arrays, they're allocated at the actual level
1140 unless ($next_is_array or $next_is_string) {
1141 pidl "NDR_PULL_ALLOC($ndr, $var_name);";
1143 # FIXME: Yes, this is nasty.
1144 # We allocate an array twice
1145 # - once just to indicate that it's there,
1146 # - then the real allocation...
1147 pidl "NDR_PULL_ALLOC_SIZE($ndr, $var_name, 1);";
1150 #pidl "memset($var_name, 0, sizeof($var_name));";
1151 if ($l->{POINTER_TYPE} eq "relative") {
1152 pidl "NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));";
1156 pidl "\t$var_name = NULL;";
1160 #####################################################################
1162 sub ParseStructPush($$)
1164 my($struct,$name) = @_;
1166 return unless defined($struct->{ELEMENTS});
1168 my $env = GenerateStructEnv($struct);
1170 EnvSubstituteValue($env, $struct);
1172 # save the old relative_base_offset
1173 pidl "uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);" if defined($struct->{PROPERTIES}{relative_base});
1175 foreach my $e (@{$struct->{ELEMENTS}}) {
1176 DeclareArrayVariables($e);
1179 start_flags($struct);
1181 # see if the structure contains a conformant array. If it
1182 # does, then it must be the last element of the structure, and
1183 # we need to push the conformant length early, as it fits on
1184 # the wire before the structure (and even before the structure
1186 if (defined($struct->{SURROUNDING_ELEMENT})) {
1187 my $e = $struct->{SURROUNDING_ELEMENT};
1189 if (defined($e->{LEVELS}[0]) and
1190 $e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
1193 if ($e->{LEVELS}[0]->{IS_ZERO_TERMINATED}) {
1194 if (has_property($e, "charset")) {
1195 $size = "ndr_charset_length(r->$e->{NAME}, CH_$e->{PROPERTIES}->{charset})";
1197 $size = "ndr_string_length(r->$e->{NAME}, sizeof(*r->$e->{NAME}))";
1200 $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env);
1203 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
1205 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
1209 pidl "if (ndr_flags & NDR_SCALARS) {";
1212 pidl "NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));";
1214 if (defined($struct->{PROPERTIES}{relative_base})) {
1215 # set the current offset as base for relative pointers
1216 # and store it based on the toplevel struct/union
1217 pidl "NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));";
1220 foreach my $e (@{$struct->{ELEMENTS}}) {
1221 ParseElementPush($e, "ndr", "r->", $env, 1, 0);
1227 pidl "if (ndr_flags & NDR_BUFFERS) {";
1229 if (defined($struct->{PROPERTIES}{relative_base})) {
1230 # retrieve the current offset as base for relative pointers
1231 # based on the toplevel struct/union
1232 pidl "NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, r));";
1234 foreach my $e (@{$struct->{ELEMENTS}}) {
1235 ParseElementPush($e, "ndr", "r->", $env, 0, 1);
1242 # restore the old relative_base_offset
1243 pidl "ndr_push_restore_relative_base_offset(ndr, _save_relative_base_offset);" if defined($struct->{PROPERTIES}{relative_base});
1246 #####################################################################
1247 # generate a push function for an enum
1248 sub ParseEnumPush($$)
1250 my($enum,$name) = @_;
1251 my($type_fn) = $enum->{BASE_TYPE};
1254 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1258 #####################################################################
1259 # generate a pull function for an enum
1260 sub ParseEnumPull($$)
1262 my($enum,$name) = @_;
1263 my($type_fn) = $enum->{BASE_TYPE};
1264 my($type_v_decl) = mapType($type_fn);
1266 pidl "$type_v_decl v;";
1268 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1274 #####################################################################
1275 # generate a print function for an enum
1276 sub ParseEnumPrint($$)
1278 my($enum,$name) = @_;
1280 pidl "const char *val = NULL;";
1285 pidl "switch (r) {";
1287 my $els = \@{$enum->{ELEMENTS}};
1288 foreach my $i (0 .. $#{$els}) {
1289 my $e = ${$els}[$i];
1291 if ($e =~ /^(.*)=/) {
1294 pidl "case $e: val = \"$e\"; break;";
1300 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1308 return "enum $e->{NAME} " .
1309 ($t eq "pull"?"*":"") . "r";
1312 $typefamily{ENUM} = {
1314 PUSH_FN_BODY => \&ParseEnumPush,
1315 PULL_FN_BODY => \&ParseEnumPull,
1316 PRINT_FN_BODY => \&ParseEnumPrint,
1319 #####################################################################
1320 # generate a push function for a bitmap
1321 sub ParseBitmapPush($$)
1323 my($bitmap,$name) = @_;
1324 my($type_fn) = $bitmap->{BASE_TYPE};
1326 start_flags($bitmap);
1328 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1333 #####################################################################
1334 # generate a pull function for an bitmap
1335 sub ParseBitmapPull($$)
1337 my($bitmap,$name) = @_;
1338 my $type_fn = $bitmap->{BASE_TYPE};
1339 my($type_decl) = mapType($bitmap->{BASE_TYPE});
1341 pidl "$type_decl v;";
1342 start_flags($bitmap);
1343 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1349 #####################################################################
1350 # generate a print function for an bitmap
1351 sub ParseBitmapPrintElement($$$)
1353 my($e,$bitmap,$name) = @_;
1354 my($type_decl) = mapType($bitmap->{BASE_TYPE});
1355 my($type_fn) = $bitmap->{BASE_TYPE};
1358 if ($e =~ /^(\w+) .*$/) {
1361 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1364 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1367 #####################################################################
1368 # generate a print function for an bitmap
1369 sub ParseBitmapPrint($$)
1371 my($bitmap,$name) = @_;
1372 my($type_decl) = mapType($bitmap->{TYPE});
1373 my($type_fn) = $bitmap->{BASE_TYPE};
1375 start_flags($bitmap);
1377 pidl "ndr_print_$type_fn(ndr, name, r);";
1379 pidl "ndr->depth++;";
1380 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1381 ParseBitmapPrintElement($e, $bitmap, $name);
1383 pidl "ndr->depth--;";
1391 return mapType(Parse::Pidl::Typelist::bitmap_type_fn($e->{DATA})) .
1392 ($t eq "pull"?" *":" ") . "r";
1395 $typefamily{BITMAP} = {
1396 DECL => \&DeclBitmap,
1397 PUSH_FN_BODY => \&ParseBitmapPush,
1398 PULL_FN_BODY => \&ParseBitmapPull,
1399 PRINT_FN_BODY => \&ParseBitmapPrint,
1402 #####################################################################
1403 # generate a struct print function
1404 sub ParseStructPrint($$)
1406 my($struct,$name) = @_;
1408 return unless defined $struct->{ELEMENTS};
1410 my $env = GenerateStructEnv($struct);
1412 EnvSubstituteValue($env, $struct);
1414 foreach my $e (@{$struct->{ELEMENTS}}) {
1415 DeclareArrayVariables($e);
1418 pidl "ndr_print_struct(ndr, name, \"$name\");";
1420 start_flags($struct);
1422 pidl "ndr->depth++;";
1423 foreach my $e (@{$struct->{ELEMENTS}}) {
1424 ParseElementPrint($e, "r->$e->{NAME}", $env);
1426 pidl "ndr->depth--;";
1431 sub DeclarePtrVariables($)
1434 foreach my $l (@{$e->{LEVELS}}) {
1435 if ($l->{TYPE} eq "POINTER" and
1436 not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
1437 pidl "uint32_t _ptr_$e->{NAME};";
1443 sub DeclareArrayVariables($)
1447 foreach my $l (@{$e->{LEVELS}}) {
1448 next if has_fast_array($e,$l);
1449 next if is_charset_array($e,$l);
1450 if ($l->{TYPE} eq "ARRAY") {
1451 pidl "uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};";
1456 sub need_decl_mem_ctx($$)
1461 return 0 if has_fast_array($e,$l);
1462 return 0 if is_charset_array($e,$l);
1463 return 1 if (($l->{TYPE} eq "ARRAY") and not $l->{IS_FIXED});
1465 if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
1466 my $nl = GetNextLevel($e, $l);
1467 my $next_is_array = ($nl->{TYPE} eq "ARRAY");
1468 my $next_is_string = (($nl->{TYPE} eq "DATA") and
1469 ($nl->{DATA_TYPE} eq "string"));
1470 return 0 if ($next_is_array or $next_is_string);
1472 return 1 if ($l->{TYPE} eq "POINTER");
1477 sub DeclareMemCtxVariables($)
1480 foreach my $l (@{$e->{LEVELS}}) {
1481 if (need_decl_mem_ctx($e, $l)) {
1482 pidl "TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};";
1487 #####################################################################
1488 # parse a struct - pull side
1489 sub ParseStructPull($$)
1491 my($struct,$name) = @_;
1493 return unless defined $struct->{ELEMENTS};
1495 my $env = GenerateStructEnv($struct);
1497 # declare any internal pointers we need
1498 foreach my $e (@{$struct->{ELEMENTS}}) {
1499 DeclarePtrVariables($e);
1500 DeclareArrayVariables($e);
1501 DeclareMemCtxVariables($e);
1504 # save the old relative_base_offset
1505 pidl "uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);" if defined($struct->{PROPERTIES}{relative_base});
1507 start_flags($struct);
1509 pidl "if (ndr_flags & NDR_SCALARS) {";
1512 if (defined $struct->{SURROUNDING_ELEMENT}) {
1513 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &r->$struct->{SURROUNDING_ELEMENT}->{NAME}));";
1516 pidl "NDR_CHECK(ndr_pull_align(ndr, $struct->{ALIGN}));";
1518 if (defined($struct->{PROPERTIES}{relative_base})) {
1519 # set the current offset as base for relative pointers
1520 # and store it based on the toplevel struct/union
1521 pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));";
1524 foreach my $e (@{$struct->{ELEMENTS}}) {
1525 ParseElementPull($e, "ndr", "r->", $env, 1, 0);
1532 pidl "if (ndr_flags & NDR_BUFFERS) {";
1534 if (defined($struct->{PROPERTIES}{relative_base})) {
1535 # retrieve the current offset as base for relative pointers
1536 # based on the toplevel struct/union
1537 pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));";
1539 foreach my $e (@{$struct->{ELEMENTS}}) {
1540 ParseElementPull($e, "ndr", "r->", $env, 0, 1);
1549 # restore the old relative_base_offset
1550 pidl "ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);" if defined($struct->{PROPERTIES}{relative_base});
1553 #####################################################################
1554 # calculate size of ndr struct
1555 sub ParseStructNdrSize($)
1560 if (my $flags = has_property($t, "flag")) {
1561 pidl "flags |= $flags;";
1563 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1569 return ($t ne "pull"?"const ":"") . "struct $e->{NAME} *r";
1572 sub ArgsStructNdrSize($)
1575 return "const struct $d->{NAME} *r, int flags";
1578 $typefamily{STRUCT} = {
1579 PUSH_FN_BODY => \&ParseStructPush,
1580 DECL => \&DeclStruct,
1581 PULL_FN_BODY => \&ParseStructPull,
1582 PRINT_FN_BODY => \&ParseStructPrint,
1583 SIZE_FN_BODY => \&ParseStructNdrSize,
1584 SIZE_FN_ARGS => \&ArgsStructNdrSize,
1587 #####################################################################
1588 # calculate size of ndr struct
1589 sub ParseUnionNdrSize($)
1594 if (my $flags = has_property($t, "flag")) {
1595 pidl "flags |= $flags;";
1598 pidl "return ndr_size_union(r, flags, level, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1601 #####################################################################
1602 # parse a union - push side
1603 sub ParseUnionPush($$)
1606 my $have_default = 0;
1608 # save the old relative_base_offset
1609 pidl "uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);" if defined($e->{PROPERTIES}{relative_base});
1614 pidl "level = ndr_push_get_switch_value(ndr, r);";
1616 pidl "if (ndr_flags & NDR_SCALARS) {";
1619 if (defined($e->{SWITCH_TYPE})) {
1620 pidl "NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}(ndr, NDR_SCALARS, level));";
1623 pidl "switch (level) {";
1625 foreach my $el (@{$e->{ELEMENTS}}) {
1626 if ($el->{CASE} eq "default") {
1629 pidl "$el->{CASE}:";
1631 if ($el->{TYPE} ne "EMPTY") {
1633 if (defined($e->{PROPERTIES}{relative_base})) {
1634 pidl "NDR_CHECK(ndr_push_align(ndr, $el->{ALIGN}));";
1635 # set the current offset as base for relative pointers
1636 # and store it based on the toplevel struct/union
1637 pidl "NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));";
1639 DeclareArrayVariables($el);
1640 ParseElementPush($el, "ndr", "r->", {}, 1, 0);
1646 if (! $have_default) {
1648 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1654 pidl "if (ndr_flags & NDR_BUFFERS) {";
1656 if (defined($e->{PROPERTIES}{relative_base})) {
1657 # retrieve the current offset as base for relative pointers
1658 # based on the toplevel struct/union
1659 pidl "NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, r));";
1661 pidl "switch (level) {";
1663 foreach my $el (@{$e->{ELEMENTS}}) {
1664 pidl "$el->{CASE}:";
1665 if ($el->{TYPE} ne "EMPTY") {
1667 ParseElementPush($el, "ndr", "r->", {}, 0, 1);
1673 if (! $have_default) {
1675 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1683 # restore the old relative_base_offset
1684 pidl "ndr_push_restore_relative_base_offset(ndr, _save_relative_base_offset);" if defined($e->{PROPERTIES}{relative_base});
1687 #####################################################################
1689 sub ParseUnionPrint($$)
1692 my $have_default = 0;
1695 foreach my $el (@{$e->{ELEMENTS}}) {
1696 DeclareArrayVariables($el);
1701 pidl "level = ndr_print_get_switch_value(ndr, r);";
1703 pidl "ndr_print_union(ndr, name, level, \"$name\");";
1705 pidl "switch (level) {";
1707 foreach my $el (@{$e->{ELEMENTS}}) {
1708 if ($el->{CASE} eq "default") {
1711 pidl "$el->{CASE}:";
1712 if ($el->{TYPE} ne "EMPTY") {
1714 ParseElementPrint($el, "r->$el->{NAME}", {});
1720 if (! $have_default) {
1722 pidl "\tndr_print_bad_level(ndr, name, level);";
1730 #####################################################################
1731 # parse a union - pull side
1732 sub ParseUnionPull($$)
1735 my $have_default = 0;
1736 my $switch_type = $e->{SWITCH_TYPE};
1738 # save the old relative_base_offset
1739 pidl "uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);" if defined($e->{PROPERTIES}{relative_base});
1741 if (defined($switch_type)) {
1742 if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) {
1743 $switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type));
1745 pidl mapType($switch_type) . " _level;";
1748 my %double_cases = ();
1749 foreach my $el (@{$e->{ELEMENTS}}) {
1750 next if ($el->{TYPE} eq "EMPTY");
1751 next if ($double_cases{"$el->{NAME}"});
1752 DeclareMemCtxVariables($el);
1753 $double_cases{"$el->{NAME}"} = 1;
1758 pidl "level = ndr_pull_get_switch_value(ndr, r);";
1760 pidl "if (ndr_flags & NDR_SCALARS) {";
1763 if (defined($switch_type)) {
1764 pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
1765 pidl "if (_level != level) {";
1766 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $name\", _level);";
1770 pidl "switch (level) {";
1772 foreach my $el (@{$e->{ELEMENTS}}) {
1773 if ($el->{CASE} eq "default") {
1776 pidl "$el->{CASE}: {";
1778 if ($el->{TYPE} ne "EMPTY") {
1780 DeclarePtrVariables($el);
1781 DeclareArrayVariables($el);
1782 if (defined($e->{PROPERTIES}{relative_base})) {
1783 pidl "NDR_CHECK(ndr_pull_align(ndr, $el->{ALIGN}));";
1784 # set the current offset as base for relative pointers
1785 # and store it based on the toplevel struct/union
1786 pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));";
1788 ParseElementPull($el, "ndr", "r->", {}, 1, 0);
1794 if (! $have_default) {
1796 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1802 pidl "if (ndr_flags & NDR_BUFFERS) {";
1804 if (defined($e->{PROPERTIES}{relative_base})) {
1805 # retrieve the current offset as base for relative pointers
1806 # based on the toplevel struct/union
1807 pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));";
1809 pidl "switch (level) {";
1811 foreach my $el (@{$e->{ELEMENTS}}) {
1812 pidl "$el->{CASE}:";
1813 if ($el->{TYPE} ne "EMPTY") {
1815 ParseElementPull($el, "ndr", "r->", {}, 0, 1);
1821 if (! $have_default) {
1823 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1834 # restore the old relative_base_offset
1835 pidl "ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);" if defined($e->{PROPERTIES}{relative_base});
1841 return ($t ne "pull"?"const ":"") . "union $e->{NAME} *r";
1844 sub ArgsUnionNdrSize($)
1847 return "const union $d->{NAME} *r, uint32_t level, int flags";
1850 $typefamily{UNION} = {
1851 PUSH_FN_BODY => \&ParseUnionPush,
1852 DECL => \&DeclUnion,
1853 PULL_FN_BODY => \&ParseUnionPull,
1854 PRINT_FN_BODY => \&ParseUnionPrint,
1855 SIZE_FN_ARGS => \&ArgsUnionNdrSize,
1856 SIZE_FN_BODY => \&ParseUnionNdrSize,
1859 #####################################################################
1860 # parse a typedef - push side
1861 sub ParseTypedefPush($)
1865 my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"push");
1866 fn_declare($e, "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, $args)");
1870 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA}, $e->{NAME});
1871 pidl "return NT_STATUS_OK;";
1877 #####################################################################
1878 # parse a typedef - pull side
1879 sub ParseTypedefPull($)
1883 my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"pull");
1885 fn_declare($e, "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, $args)");
1889 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA}, $e->{NAME});
1890 pidl "return NT_STATUS_OK;";
1896 #####################################################################
1897 # parse a typedef - print side
1898 sub ParseTypedefPrint($)
1902 my $args = $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e,"print");
1904 pidl "_PUBLIC_ void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $args)";
1905 pidl_hdr "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $args);";
1908 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}, $e->{NAME});
1914 #####################################################################
1915 ## calculate the size of a structure
1916 sub ParseTypedefNdrSize($)
1920 my $tf = $typefamily{$t->{DATA}->{TYPE}};
1921 my $args = $tf->{SIZE_FN_ARGS}->($t);
1923 fn_declare($t, "size_t ndr_size_$t->{NAME}($args)");
1927 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($t);
1933 #####################################################################
1934 # parse a function - print side
1935 sub ParseFunctionPrint($)
1939 return if has_property($fn, "noprint");
1941 pidl "_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r)";
1942 pidl_hdr "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r);";
1946 foreach my $e (@{$fn->{ELEMENTS}}) {
1947 DeclareArrayVariables($e);
1950 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1951 pidl "ndr->depth++;";
1953 pidl "if (flags & NDR_SET_VALUES) {";
1954 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1957 pidl "if (flags & NDR_IN) {";
1959 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1960 pidl "ndr->depth++;";
1962 my $env = GenerateFunctionInEnv($fn);
1963 EnvSubstituteValue($env, $fn);
1965 foreach my $e (@{$fn->{ELEMENTS}}) {
1966 if (grep(/in/,@{$e->{DIRECTION}})) {
1967 ParseElementPrint($e, "r->in.$e->{NAME}", $env);
1970 pidl "ndr->depth--;";
1974 pidl "if (flags & NDR_OUT) {";
1976 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1977 pidl "ndr->depth++;";
1979 $env = GenerateFunctionOutEnv($fn);
1980 foreach my $e (@{$fn->{ELEMENTS}}) {
1981 if (grep(/out/,@{$e->{DIRECTION}})) {
1982 ParseElementPrint($e, "r->out.$e->{NAME}", $env);
1985 if ($fn->{RETURN_TYPE}) {
1986 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);";
1988 pidl "ndr->depth--;";
1992 pidl "ndr->depth--;";
1998 #####################################################################
2000 sub ParseFunctionPush($)
2004 return if has_property($fn, "nopush");
2006 fn_declare($fn, "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, const struct $fn->{NAME} *r)");
2011 foreach my $e (@{$fn->{ELEMENTS}}) {
2012 DeclareArrayVariables($e);
2015 pidl "if (flags & NDR_IN) {";
2018 my $env = GenerateFunctionInEnv($fn);
2020 EnvSubstituteValue($env, $fn);
2022 foreach my $e (@{$fn->{ELEMENTS}}) {
2023 if (grep(/in/,@{$e->{DIRECTION}})) {
2024 ParseElementPush($e, "ndr", "r->in.", $env, 1, 1);
2031 pidl "if (flags & NDR_OUT) {";
2034 $env = GenerateFunctionOutEnv($fn);
2035 foreach my $e (@{$fn->{ELEMENTS}}) {
2036 if (grep(/out/,@{$e->{DIRECTION}})) {
2037 ParseElementPush($e, "ndr", "r->out.", $env, 1, 1);
2041 if ($fn->{RETURN_TYPE}) {
2042 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
2047 pidl "return NT_STATUS_OK;";
2053 sub AllocateArrayLevel($$$$$)
2055 my ($e,$l,$ndr,$env,$size) = @_;
2057 my $var = ParseExpr($e->{NAME}, $env);
2059 check_null_pointer($size);
2060 my $pl = GetPrevLevel($e, $l);
2061 if (defined($pl) and
2062 $pl->{TYPE} eq "POINTER" and
2063 $pl->{POINTER_TYPE} eq "ref"
2064 and not $l->{IS_ZERO_TERMINATED}) {
2065 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
2066 pidl "\tNDR_PULL_ALLOC_N($ndr, $var, $size);";
2068 if (grep(/in/,@{$e->{DIRECTION}}) and
2069 grep(/out/,@{$e->{DIRECTION}})) {
2070 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
2075 pidl "NDR_PULL_ALLOC_N($ndr, $var, $size);";
2078 #####################################################################
2080 sub ParseFunctionPull($)
2084 return if has_property($fn, "nopull");
2086 # pull function args
2087 fn_declare($fn, "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)");
2091 # declare any internal pointers we need
2092 foreach my $e (@{$fn->{ELEMENTS}}) {
2093 DeclarePtrVariables($e);
2094 DeclareArrayVariables($e);
2097 my %double_cases = ();
2098 foreach my $e (@{$fn->{ELEMENTS}}) {
2099 next if ($e->{TYPE} eq "EMPTY");
2100 next if ($double_cases{"$e->{NAME}"});
2101 DeclareMemCtxVariables($e);
2102 $double_cases{"$e->{NAME}"} = 1;
2105 pidl "if (flags & NDR_IN) {";
2108 # auto-init the out section of a structure. I originally argued that
2109 # this was a bad idea as it hides bugs, but coping correctly
2110 # with initialisation and not wiping ref vars is turning
2111 # out to be too tricky (tridge)
2112 foreach my $e (@{$fn->{ELEMENTS}}) {
2113 next unless grep(/out/, @{$e->{DIRECTION}});
2114 pidl "ZERO_STRUCT(r->out);";
2119 my $env = GenerateFunctionInEnv($fn);
2121 foreach my $e (@{$fn->{ELEMENTS}}) {
2122 next unless (grep(/in/, @{$e->{DIRECTION}}));
2123 ParseElementPull($e, "ndr", "r->in.", $env, 1, 1);
2126 # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's
2127 # own flag rather then be in NDR_IN ?
2129 foreach my $e (@{$fn->{ELEMENTS}}) {
2130 next unless (grep(/out/, @{$e->{DIRECTION}}));
2131 next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and
2132 $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
2133 next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and
2134 ($e->{LEVELS}[1]->{DATA_TYPE} eq "string"));
2135 next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY")
2136 and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED});
2138 if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
2139 my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
2140 check_null_pointer($size);
2142 pidl "NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
2144 if (grep(/in/, @{$e->{DIRECTION}})) {
2145 pidl "memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));";
2147 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
2150 pidl "NDR_PULL_ALLOC(ndr, r->out.$e->{NAME});";
2152 if (grep(/in/, @{$e->{DIRECTION}})) {
2153 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
2155 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
2164 pidl "if (flags & NDR_OUT) {";
2167 $env = GenerateFunctionOutEnv($fn);
2168 foreach my $e (@{$fn->{ELEMENTS}}) {
2169 next unless grep(/out/, @{$e->{DIRECTION}});
2170 ParseElementPull($e, "ndr", "r->out.", $env, 1, 1);
2173 if ($fn->{RETURN_TYPE}) {
2174 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
2181 pidl "return NT_STATUS_OK;";
2187 #####################################################################
2188 # produce a function call table
2189 sub FunctionTable($)
2191 my($interface) = shift;
2193 my $uname = uc $interface->{NAME};
2195 return if ($#{$interface->{FUNCTIONS}}+1 == 0);
2196 return unless defined ($interface->{PROPERTIES}->{uuid});
2198 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
2199 foreach my $d (@{$interface->{FUNCTIONS}}) {
2200 next if not defined($d->{OPNUM});
2202 pidl "\t\t\"$d->{NAME}\",";
2203 pidl "\t\tsizeof(struct $d->{NAME}),";
2204 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
2205 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
2206 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME},";
2207 pidl "\t\t".($d->{ASYNC}?"True":"False").",";
2211 pidl "\t{ NULL, 0, NULL, NULL, NULL, False }";
2215 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
2216 foreach my $ep (@{$interface->{ENDPOINTS}}) {
2219 my $endpoint_count = $#{$interface->{ENDPOINTS}}+1;
2224 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
2225 pidl "\t.count\t= $endpoint_count,";
2226 pidl "\t.names\t= $interface->{NAME}\_endpoint_strings";
2230 if (! defined $interface->{PROPERTIES}->{authservice}) {
2231 $interface->{PROPERTIES}->{authservice} = "\"host\"";
2234 my @a = split / /, $interface->{PROPERTIES}->{authservice};
2235 my $authservice_count = $#a + 1;
2237 pidl "static const char * const $interface->{NAME}\_authservice_strings[] = {";
2238 foreach my $ap (@a) {
2244 pidl "static const struct dcerpc_authservice_list $interface->{NAME}\_authservices = {";
2245 pidl "\t.count\t= $endpoint_count,";
2246 pidl "\t.names\t= $interface->{NAME}\_authservice_strings";
2250 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
2251 pidl "\t.name\t\t= \"$interface->{NAME}\",";
2252 pidl "\t.uuid\t\t= ". print_uuid($interface->{UUID}) .",";
2253 pidl "\t.if_version\t= DCERPC_$uname\_VERSION,";
2254 pidl "\t.helpstring\t= DCERPC_$uname\_HELPSTRING,";
2255 pidl "\t.num_calls\t= $count,";
2256 pidl "\t.calls\t\t= $interface->{NAME}\_calls,";
2257 pidl "\t.endpoints\t= &$interface->{NAME}\_endpoints,";
2258 pidl "\t.authservices\t= &$interface->{NAME}\_authservices";
2264 #####################################################################
2265 # generate prototypes and defines for the interface definitions
2266 # FIXME: these prototypes are for the DCE/RPC client functions, not the
2267 # NDR parser and so do not belong here, technically speaking
2268 sub HeaderInterface($)
2270 my($interface) = shift;
2274 pidl_hdr choose_header("librpc/ndr/libndr.h", "ndr.h");
2276 if (has_property($interface, "object")) {
2277 pidl choose_header("librpc/gen_ndr/ndr_orpc.h", "ndr/orpc.h");
2280 if (defined $interface->{PROPERTIES}->{depends}) {
2281 my @d = split / /, $interface->{PROPERTIES}->{depends};
2282 foreach my $i (@d) {
2283 pidl choose_header("librpc/gen_ndr/ndr_$i\.h", "gen_ndr/ndr_$i.h");
2287 if (defined $interface->{PROPERTIES}->{helper}) {
2288 foreach (split / /, $interface->{PROPERTIES}->{helper}) {
2289 pidl_hdr "#include $_";
2293 if (defined $interface->{PROPERTIES}->{uuid}) {
2294 my $name = uc $interface->{NAME};
2295 pidl_hdr "#define DCERPC_$name\_UUID " .
2296 Parse::Pidl::Util::make_str(lc($interface->{PROPERTIES}->{uuid}));
2298 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
2299 pidl_hdr "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}";
2301 pidl_hdr "#define DCERPC_$name\_NAME \"$interface->{NAME}\"";
2303 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
2304 pidl_hdr "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}";
2306 pidl_hdr "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};";
2307 pidl_hdr "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);";
2310 foreach (@{$interface->{FUNCTIONS}}) {
2311 next if has_property($_, "noopnum");
2312 next if grep(/$_->{NAME}/,@{$interface->{INHERITED_FUNCTIONS}});
2313 my $u_name = uc $_->{NAME};
2315 my $val = sprintf("0x%02x", $count);
2316 if (defined($interface->{BASE})) {
2317 $val .= " + DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT";
2320 pidl_hdr "#define DCERPC_$u_name ($val)";
2328 if (defined($interface->{BASE})) {
2329 $val .= " + DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT";
2332 pidl_hdr "#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT ($val)";
2336 #####################################################################
2337 # parse the interface definitions
2338 sub ParseInterface($$)
2340 my($interface,$needed) = @_;
2342 pidl_hdr "#ifndef _HEADER_NDR_$interface->{NAME}";
2343 pidl_hdr "#define _HEADER_NDR_$interface->{NAME}";
2347 if ($needed->{"compression"}) {
2348 pidl choose_header("librpc/ndr/ndr_compression.h", "ndr/compression.h");
2351 if ($needed->{"obfuscate"}) {
2352 pidl "#include \"ndr_obfuscate.h\"";
2355 HeaderInterface($interface);
2358 foreach my $d (@{$interface->{TYPES}}) {
2359 ($needed->{"push_$d->{NAME}"}) && ParseTypedefPush($d);
2360 ($needed->{"pull_$d->{NAME}"}) && ParseTypedefPull($d);
2361 ($needed->{"print_$d->{NAME}"}) && ParseTypedefPrint($d);
2363 # Make sure we don't generate a function twice...
2364 $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} =
2365 $needed->{"print_$d->{NAME}"} = 0;
2367 ($needed->{"ndr_size_$d->{NAME}"}) && ParseTypedefNdrSize($d);
2371 foreach my $d (@{$interface->{FUNCTIONS}}) {
2372 ($needed->{"push_$d->{NAME}"}) && ParseFunctionPush($d);
2373 ($needed->{"pull_$d->{NAME}"}) && ParseFunctionPull($d);
2374 ($needed->{"print_$d->{NAME}"}) && ParseFunctionPrint($d);
2376 # Make sure we don't generate a function twice...
2377 $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} =
2378 $needed->{"print_$d->{NAME}"} = 0;
2381 FunctionTable($interface);
2383 pidl_hdr "#endif /* _HEADER_NDR_$interface->{NAME} */";
2386 #####################################################################
2387 # parse a parsed IDL structure back into an IDL file
2390 my($ndr,$gen_header,$ndr_header) = @_;
2396 pidl_hdr "/* header auto-generated by pidl */";
2398 pidl_hdr "#include \"$gen_header\"" if ($gen_header);
2401 pidl "/* parser auto-generated by pidl */";
2404 pidl "#include \"includes.h\"";
2406 pidl "#define _GNU_SOURCE";
2407 pidl "#include <stdint.h>";
2408 pidl "#include <stdlib.h>";
2409 pidl "#include <stdio.h>";
2410 pidl "#include <stdarg.h>";
2411 pidl "#include <string.h>";
2413 pidl choose_header("libcli/util/nterr.h", "core/nterr.h");
2414 pidl choose_header("librpc/gen_ndr/ndr_misc.h", "gen_ndr/ndr_misc.h");
2415 pidl choose_header("librpc/gen_ndr/ndr_dcerpc.h", "gen_ndr/ndr_dcerpc.h");
2416 pidl "#include \"$ndr_header\"" if ($ndr_header);
2417 pidl choose_header("librpc/rpc/dcerpc.h", "dcerpc.h"); #FIXME: This shouldn't be here!
2423 ($_->{TYPE} eq "INTERFACE") && NeededInterface($_, \%needed);
2427 ($_->{TYPE} eq "INTERFACE") && ParseInterface($_, \%needed);
2430 return ($res_hdr, $res);
2433 sub NeededFunction($$)
2435 my ($fn,$needed) = @_;
2436 $needed->{"pull_$fn->{NAME}"} = 1;
2437 $needed->{"push_$fn->{NAME}"} = 1;
2438 $needed->{"print_$fn->{NAME}"} = 1;
2439 foreach my $e (@{$fn->{ELEMENTS}}) {
2441 unless(defined($needed->{"pull_$e->{TYPE}"})) {
2442 $needed->{"pull_$e->{TYPE}"} = 1;
2444 unless(defined($needed->{"push_$e->{TYPE}"})) {
2445 $needed->{"push_$e->{TYPE}"} = 1;
2447 unless(defined($needed->{"print_$e->{TYPE}"})) {
2448 $needed->{"print_$e->{TYPE}"} = 1;
2453 sub NeededTypedef($$)
2455 my ($t,$needed) = @_;
2456 if (has_property($t, "public")) {
2457 $needed->{"pull_$t->{NAME}"} = not has_property($t, "nopull");
2458 $needed->{"push_$t->{NAME}"} = not has_property($t, "nopush");
2459 $needed->{"print_$t->{NAME}"} = not has_property($t, "noprint");
2462 if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
2463 if (has_property($t, "gensize")) {
2464 $needed->{"ndr_size_$t->{NAME}"} = 1;
2467 for my $e (@{$t->{DATA}->{ELEMENTS}}) {
2468 $e->{PARENT} = $t->{DATA};
2469 if (has_property($e, "compression")) {
2470 $needed->{"compression"} = 1;
2472 if (has_property($e, "obfuscation")) {
2473 $needed->{"obfuscate"} = 1;
2475 if ($needed->{"pull_$t->{NAME}"} and
2476 not defined($needed->{"pull_$e->{TYPE}"})) {
2477 $needed->{"pull_$e->{TYPE}"} = 1;
2479 if ($needed->{"push_$t->{NAME}"} and
2480 not defined($needed->{"push_$e->{TYPE}"})) {
2481 $needed->{"push_$e->{TYPE}"} = 1;
2483 if ($needed->{"print_$t->{NAME}"} and
2484 not defined($needed->{"print_$e->{TYPE}"})) {
2485 $needed->{"print_$e->{TYPE}"} = 1;
2491 #####################################################################
2492 # work out what parse functions are needed
2493 sub NeededInterface($$)
2495 my ($interface,$needed) = @_;
2496 NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
2497 NeededTypedef($_, $needed) foreach (reverse @{$interface->{TYPES}});