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-2005
6 # released under the GNU GPL
20 return $typefamily{$n};
29 foreach my $l (@{$e->{LEVELS}}) {
30 if ($l->{TYPE} eq "POINTER") {
32 } elsif ($l->{TYPE} eq "ARRAY") {
33 if (($pointers == 0) and
34 (not $l->{IS_FIXED}) and
35 (not $l->{IS_INLINE})) {
36 return get_value_of($var_name);
38 } elsif ($l->{TYPE} eq "DATA") {
39 if (typelist::scalar_is_reference($l->{DATA_TYPE})) {
40 return get_value_of($var_name) unless ($pointers);
48 # see if a variable needs to be allocated by the NDR subsystem on pull
56 sub is_scalar_array($$)
61 return 0 if ($l->{TYPE} ne "ARRAY");
63 my $nl = Ndr::GetNextLevel($e,$l);
64 return (($nl->{TYPE} eq "DATA") and
65 (typelist::is_scalar($nl->{DATA_TYPE})));
72 if ($var_name =~ /^\*(.*)$/) {
74 } elsif ($var_name =~ /^\&(.*)$/) {
75 return "&($var_name)";
85 if ($var_name =~ /^\&(.*)$/) {
111 $tabs = substr($tabs, 0, -1);
114 ####################################################################
115 # work out the name of a size_is() variable
121 die("Undefined value in ParseExpr") if not defined($expr);
123 my @tokens = split /((?:[A-Za-z_])(?:(?:(?:[A-Za-z0-9_.])|(?:->))+))/, $expr;
126 foreach my $t (@tokens) {
127 if (defined($varlist->{$t})) {
128 $ret .= $varlist->{$t};
137 #####################################################################
138 # check that a variable we get from ParseExpr isn't a null pointer
139 sub check_null_pointer($)
142 if ($size =~ /^\*/) {
143 my $size2 = substr($size, 1);
144 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
148 #####################################################################
149 # check that a variable we get from ParseExpr isn't a null pointer
150 # void return varient
151 sub check_null_pointer_void($)
154 if ($size =~ /^\*/) {
155 my $size2 = substr($size, 1);
156 pidl "if ($size2 == NULL) return;";
160 #####################################################################
161 # work out is a parse function should be declared static or not
166 return "" if (util::has_property($fn, "public"));
170 ###################################################################
171 # setup any special flags for an element or structure
175 my $flags = util::has_property($e, "flag");
176 if (defined $flags) {
179 pidl "uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
180 pidl "ndr_set_flags(&ndr->flags, $flags);";
184 ###################################################################
185 # end any special flags for an element or structure
189 my $flags = util::has_property($e, "flag");
190 if (defined $flags) {
191 pidl "ndr->flags = _flags_save_$e->{TYPE};";
197 sub GenerateStructEnv($)
202 foreach my $e (@{$x->{ELEMENTS}}) {
203 $env{$e->{NAME}} = "r->$e->{NAME}";
211 sub GenerateFunctionEnv($)
216 foreach my $e (@{$fn->{ELEMENTS}}) {
217 if (grep (/out/, @{$e->{DIRECTION}})) {
218 $env{$e->{NAME}} = "r->out.$e->{NAME}";
220 if (grep (/in/, @{$e->{DIRECTION}})) {
221 $env{$e->{NAME}} = "r->in.$e->{NAME}";
228 #####################################################################
229 # parse array preceding data - push side
230 sub ParseArrayPushPreceding($$$$)
234 my $var_name = shift;
237 return if ($l->{NO_METADATA});
239 my $size = ParseExpr($l->{SIZE_IS}, $env);
241 # we need to emit the array size
242 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
245 #####################################################################
246 # parse the data of an array - push side
247 sub ParseArrayPushHeader($$$$$)
252 my $var_name = shift;
255 if (!$l->{NO_METADATA}) {
256 $var_name = get_pointer_to($var_name);
259 my $size = ParseExpr($l->{SIZE_IS}, $env);
260 my $length = ParseExpr($l->{LENGTH_IS}, $env);
262 # See whether the array size has been pushed yet
263 if (!$l->{IS_SURROUNDING}) {
264 ParseArrayPushPreceding($e, $l, $var_name, $env);
267 if ($l->{IS_VARYING}) {
268 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
269 pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
275 sub ParseArrayPullPreceding($$$)
279 my $var_name = shift;
281 return if ($l->{NO_METADATA});
283 # non fixed arrays encode the size just before the array
284 pidl "NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));";
287 #####################################################################
288 # parse an array - pull side
289 sub ParseArrayPullHeader($$$$$)
294 my $var_name = shift;
297 unless ($l->{NO_METADATA}) {
298 $var_name = get_pointer_to($var_name);
301 # $var_name contains the name of the first argument here
303 my $length = ParseExpr($l->{SIZE_IS}, $env);
306 if ($l->{IS_CONFORMANT}) {
307 $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
310 # if this is a conformant array then we use that size to allocate, and make sure
311 # we allocate enough to pull the elements
312 if (!$l->{IS_SURROUNDING}) {
313 ParseArrayPullPreceding($e, $l, $var_name);
317 if ($l->{IS_VARYING}) {
318 pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));";
319 $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
322 check_null_pointer($length);
324 if ($length ne $size) {
325 pidl "if ($length > $size) {";
327 pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);";
332 if ($l->{IS_CONFORMANT}) {
333 my $size = ParseExpr($l->{SIZE_IS}, $env);
334 check_null_pointer($size);
335 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));";
338 if ($l->{IS_VARYING}) {
339 my $length = ParseExpr($l->{LENGTH_IS}, $env);
340 check_null_pointer($length);
341 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
344 if (!$l->{IS_FIXED}) {
345 AllocateArrayLevel($e,$l,$ndr,$env,$size);
351 sub compression_alg($$)
355 my $compression = $l->{COMPRESSION};
356 my ($alg, $clen, $dlen) = split(/ /, $compression);
361 sub compression_clen($$$)
366 my $compression = $l->{COMPRESSION};
367 my ($alg, $clen, $dlen) = split(/ /, $compression);
369 return ParseExpr($clen, $env);
372 sub compression_dlen($$$)
377 my $compression = $l->{COMPRESSION};
378 my ($alg, $clen, $dlen) = split(/ /, $compression);
380 return ParseExpr($dlen, $env);
383 sub ParseCompressionPushStart($$$)
388 my $comndr = $subndr."_compressed";
392 pidl "struct ndr_push *$comndr;";
394 pidl "$comndr = ndr_push_init_ctx($subndr);";
395 pidl "if (!$comndr) return NT_STATUS_NO_MEMORY;";
396 pidl "$comndr->flags = $subndr->flags;";
402 sub ParseCompressionPushEnd($$$)
407 my $comndr = $subndr."_compressed";
408 my $alg = compression_alg($e, $l);
410 pidl "NDR_CHECK(ndr_push_compression($subndr, $comndr, $alg));";
415 sub ParseCompressionPullStart($$$$)
421 my $comndr = $subndr."_compressed";
422 my $alg = compression_alg($e, $l);
423 my $dlen = compression_dlen($e, $l, $env);
427 pidl "struct ndr_pull *$comndr;";
428 pidl "NDR_ALLOC($subndr, $comndr);";
429 pidl "NDR_CHECK(ndr_pull_compression($subndr, $comndr, $alg, $dlen));";
434 sub ParseCompressionPullEnd($$$)
439 my $comndr = $subndr."_compressed";
445 sub ParseObfuscationPushStart($$)
455 sub ParseObfuscationPushEnd($$)
459 my $obfuscation = util::has_property($e, "obfuscation");
461 pidl "NDR_CHECK(ndr_push_obfuscation($ndr, $obfuscation));";
464 sub ParseObfuscationPullStart($$)
468 my $obfuscation = util::has_property($e, "obfuscation");
470 pidl "NDR_CHECK(ndr_pull_obfuscation($ndr, $obfuscation));";
475 sub ParseObfuscationPullEnd($$)
483 sub ParseSubcontextPushStart($$$$$)
488 my $var_name = shift;
489 my $ndr_flags = shift;
490 my $retndr = "_ndr_$e->{NAME}";
494 pidl "struct ndr_push *$retndr;";
496 pidl "$retndr = ndr_push_init_ctx($ndr);";
497 pidl "if (!$retndr) return NT_STATUS_NO_MEMORY;";
498 pidl "$retndr->flags = $ndr->flags;";
501 if (defined $l->{COMPRESSION}) {
502 $retndr = ParseCompressionPushStart($e, $l, $retndr);
505 if (defined $l->{OBFUSCATION}) {
506 $retndr = ParseObfuscationPushStart($e, $retndr);
512 sub ParseSubcontextPushEnd($$$)
516 my $ndr_flags = shift;
517 my $ndr = "_ndr_$e->{NAME}";
519 if (defined $l->{COMPRESSION}) {
520 ParseCompressionPushEnd($e, $l, $ndr);
523 if (defined $l->{OBFUSCATION}) {
524 ParseObfuscationPushEnd($e, $ndr);
527 pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $ndr));";
528 pidl "NDR_CHECK(ndr_push_bytes(ndr, $ndr->data, $ndr->offset));";
533 sub ParseSubcontextPullStart($$$$$$)
538 my $var_name = shift;
539 my $ndr_flags = shift;
541 my $retndr = "_ndr_$e->{NAME}";
545 pidl "struct ndr_pull *$retndr;";
546 pidl "NDR_ALLOC(ndr, $retndr);";
547 pidl "NDR_CHECK(ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr));";
549 if (defined $l->{COMPRESSION}) {
550 $retndr = ParseCompressionPullStart($e, $l, $retndr, $env);
553 if (defined $l->{OBFUSCATION}) {
554 $retndr = ParseObfuscationPullStart($e, $retndr);
557 return ($retndr,$var_name);
560 sub ParseSubcontextPullEnd($$)
564 my $ndr = "_ndr_$e->{NAME}";
566 if (defined $l->{COMPRESSION}) {
567 ParseCompressionPullEnd($e, $l, $ndr);
570 if (defined $l->{OBFUSCATION}) {
571 ParseObfuscationPullEnd($e, $ndr);
575 if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) {
576 $advance = $l->{SUBCONTEXT_SIZE};
577 } elsif ($l->{HEADER_SIZE}) {
578 $advance = "$ndr->data_size";
580 $advance = "$ndr->offset";
582 pidl "NDR_CHECK(ndr_pull_advance(ndr, $advance));";
587 sub ParseElementPushLevel
592 my $var_name = shift;
594 my $primitives = shift;
595 my $deferred = shift;
597 my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
599 if (defined($ndr_flags)) {
600 if ($l->{TYPE} eq "SUBCONTEXT") {
601 $ndr = ParseSubcontextPushStart($e, $l, $ndr, $var_name, $ndr_flags);
602 ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
603 ParseSubcontextPushEnd($e, $l, $ndr_flags);
604 } elsif ($l->{TYPE} eq "POINTER") {
605 ParsePtrPush($e, $l, $var_name);
606 } elsif ($l->{TYPE} eq "ARRAY") {
607 my $length = ParseArrayPushHeader($e, $l, $ndr, $var_name, $env);
608 # Allow speedups for arrays of scalar types
609 if (is_scalar_array($e,$l)) {
610 unless ($l->{NO_METADATA}) {
611 $var_name = get_pointer_to($var_name);
614 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
617 } elsif ($l->{TYPE} eq "SWITCH") {
618 ParseSwitchPush($e, $l, $ndr, $var_name, $ndr_flags, $env);
619 } elsif ($l->{TYPE} eq "DATA") {
620 ParseDataPush($e, $l, $ndr, $var_name, $ndr_flags);
624 if ($l->{TYPE} eq "POINTER" and $deferred) {
625 if ($l->{POINTER_TYPE} ne "ref") {
626 pidl "if ($var_name) {";
628 if ($l->{POINTER_TYPE} eq "relative") {
629 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));";
632 $var_name = get_value_of($var_name);
633 ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
635 if ($l->{POINTER_TYPE} ne "ref") {
639 } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
640 my $length = ParseExpr($l->{LENGTH_IS}, $env);
641 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
643 $var_name = $var_name . "[$counter]";
645 unless ($l->{NO_METADATA}) {
646 $var_name = get_pointer_to($var_name);
649 if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
650 pidl "for ($counter = 0; $counter < $length; $counter++) {";
652 ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
657 if ($deferred and Ndr::ContainsDeferred($e, $l)) {
658 pidl "for ($counter = 0; $counter < $length; $counter++) {";
660 ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
664 } elsif ($l->{TYPE} eq "SWITCH") {
665 ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);
669 #####################################################################
670 # parse scalars in a structure element
671 sub ParseElementPush($$$$$$)
675 my $var_prefix = shift;
677 my $primitives = shift;
678 my $deferred = shift;
681 my $var_name = $var_prefix.$e->{NAME};
683 $var_name = append_prefix($e, $var_name);
685 return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0]));
689 if (my $value = util::has_property($e, "value")) {
690 pidl "$var_name = $value;";
693 ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred);
698 #####################################################################
699 # parse a pointer in a struct element or function
700 sub ParsePtrPush($$$)
704 my $var_name = shift;
706 if ($l->{POINTER_TYPE} eq "ref") {
707 if ($l->{LEVEL} eq "EMBEDDED") {
708 pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_name));";
710 check_null_pointer(get_value_of($var_name));
712 } elsif ($l->{POINTER_TYPE} eq "relative") {
713 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));";
714 } elsif ($l->{POINTER_TYPE} eq "unique") {
715 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));";
717 die("Unhandled pointer type $l->{POINTER_TYPE}");
721 #####################################################################
722 # print scalars in a structure element
723 sub ParseElementPrint($$$)
726 my($var_name) = shift;
729 $var_name = append_prefix($e, $var_name);
730 return if (util::has_property($e, "noprint"));
732 if (my $value = util::has_property($e, "value")) {
733 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
734 pidl "\t$var_name = $value;";
738 foreach my $l (@{$e->{LEVELS}}) {
739 if ($l->{TYPE} eq "POINTER") {
740 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);";
741 pidl "ndr->depth++;";
742 if ($l->{POINTER_TYPE} ne "ref") {
743 pidl "if ($var_name) {";
746 $var_name = get_value_of($var_name);
747 } elsif ($l->{TYPE} eq "ARRAY") {
748 my $length = ParseExpr($l->{LENGTH_IS}, $env);
750 if (is_scalar_array($e, $l)) {
751 unless ($l->{NO_METADATA}){
752 $var_name = get_pointer_to($var_name);
754 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);";
758 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
760 pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);";
761 pidl 'ndr->depth++;';
762 pidl "for ($counter=0;$counter<$length;$counter++) {";
764 pidl "char *idx_$l->{LEVEL_INDEX}=NULL;";
765 pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);";
766 pidl "if (idx_$l->{LEVEL_INDEX}) {";
769 $var_name = $var_name . "[$counter]";
771 unless ($l->{NO_METADATA}){ $var_name = get_pointer_to($var_name); }
773 } elsif ($l->{TYPE} eq "DATA") {
774 if (not typelist::is_scalar($l->{DATA_TYPE}) or typelist::scalar_is_reference($l->{DATA_TYPE})) {
775 $var_name = get_pointer_to($var_name);
777 pidl "ndr_print_$l->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name);";
778 } elsif ($l->{TYPE} eq "SWITCH") {
779 my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
780 check_null_pointer_void($switch_var);
781 pidl "ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);";
785 foreach my $l (reverse @{$e->{LEVELS}}) {
786 if ($l->{TYPE} eq "POINTER") {
787 if ($l->{POINTER_TYPE} ne "ref") {
791 pidl "ndr->depth--;";
792 } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e, $l)) {
793 pidl "free(idx_$l->{LEVEL_INDEX});";
798 pidl "ndr->depth--;";
803 #####################################################################
804 # parse scalars in a structure element - pull size
805 sub ParseSwitchPull($$$$$$)
810 my($var_name) = shift;
811 my($ndr_flags) = shift;
813 my $switch_var = ParseExpr($l->{SWITCH_IS}, $env);
815 check_null_pointer($switch_var);
817 $var_name = get_pointer_to($var_name);
818 pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));";
822 #####################################################################
823 # push switch element
824 sub ParseSwitchPush($$$$$$)
829 my($var_name) = shift;
830 my($ndr_flags) = shift;
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($$$$$)
844 my $var_name = shift;
845 my $ndr_flags = shift;
847 if (typelist::scalar_is_reference($l->{DATA_TYPE})) {
848 $var_name = get_pointer_to($var_name);
851 $var_name = get_pointer_to($var_name);
853 pidl "NDR_CHECK(ndr_pull_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
855 if (my $range = util::has_property($e, "range")) {
856 $var_name = get_value_of($var_name);
857 my ($low, $high) = split(/ /, $range, 2);
858 pidl "if ($var_name < $low || $var_name > $high) {";
859 pidl "\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
864 sub ParseDataPush($$$$$)
869 my $var_name = shift;
870 my $ndr_flags = shift;
872 # strings are passed by value rather then reference
873 if (not typelist::is_scalar($l->{DATA_TYPE}) or typelist::scalar_is_reference($l->{DATA_TYPE})) {
874 $var_name = get_pointer_to($var_name);
877 pidl "NDR_CHECK(ndr_push_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));";
880 sub CalcNdrFlags($$$)
883 my $primitives = shift;
884 my $deferred = shift;
889 # Add NDR_SCALARS if this one is deferred
890 # and deferreds may be pushed
891 $scalars = 1 if ($l->{IS_DEFERRED} and $deferred);
893 # Add NDR_SCALARS if this one is not deferred and
894 # primitives may be pushed
895 $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives);
897 # Add NDR_BUFFERS if this one contains deferred stuff
898 # and deferreds may be pushed
899 $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred);
901 return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers);
902 return "NDR_SCALARS" if ($scalars);
903 return "NDR_BUFFERS" if ($buffers);
907 sub ParseElementPullLevel
912 my($var_name) = shift;
914 my $primitives = shift;
915 my $deferred = shift;
917 my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
919 # Only pull something if there's actually something to be pulled
920 if (defined($ndr_flags)) {
921 if ($l->{TYPE} eq "SUBCONTEXT") {
922 ($ndr,$var_name) = ParseSubcontextPullStart($e, $l, $ndr, $var_name, $ndr_flags, $env);
923 ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
924 ParseSubcontextPullEnd($e, $l);
925 } elsif ($l->{TYPE} eq "ARRAY") {
926 my $length = ParseArrayPullHeader($e, $l, $ndr, $var_name, $env);
928 # Speed things up a little - special array pull functions
930 if (is_scalar_array($e, $l)) {
931 unless ($l->{NO_METADATA}) {
932 $var_name = get_pointer_to($var_name);
935 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));";
938 } elsif ($l->{TYPE} eq "POINTER") {
939 ParsePtrPull($e, $l, $ndr, $var_name);
940 } elsif ($l->{TYPE} eq "SWITCH") {
941 ParseSwitchPull($e, $l, $ndr, $var_name, $ndr_flags, $env);
942 } elsif ($l->{TYPE} eq "DATA") {
943 ParseDataPull($e, $l, $ndr, $var_name, $ndr_flags);
947 # add additional constructions
948 if ($l->{TYPE} eq "POINTER" and $deferred) {
949 if ($l->{POINTER_TYPE} ne "ref") {
950 pidl "if ($var_name) {";
953 if ($l->{POINTER_TYPE} eq "relative") {
954 pidl "struct ndr_pull_save _relative_save;";
955 pidl "ndr_pull_save(ndr, &_relative_save);";
956 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));";
960 $var_name = get_value_of($var_name);
961 ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
963 if ($l->{POINTER_TYPE} ne "ref") {
964 if ($l->{POINTER_TYPE} eq "relative") {
965 pidl "ndr_pull_restore(ndr, &_relative_save);";
970 } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) {
971 my $length = ParseExpr($l->{LENGTH_IS}, $env);
972 my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
974 $var_name = $var_name . "[$counter]";
975 unless ($l->{NO_METADATA}) {
976 $var_name = get_pointer_to($var_name);
979 if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
980 pidl "for ($counter = 0; $counter < $length; $counter++) {";
982 ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0);
987 if ($deferred and Ndr::ContainsDeferred($e, $l)) {
988 pidl "for ($counter = 0; $counter < $length; $counter++) {";
990 ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1);
994 } elsif ($l->{TYPE} eq "SWITCH") {
995 ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
999 #####################################################################
1000 # parse scalars in a structure element - pull size
1001 sub ParseElementPull($$$$$$)
1005 my($var_prefix) = shift;
1007 my $primitives = shift;
1008 my $deferred = shift;
1010 my $var_name = $var_prefix.$e->{NAME};
1012 $var_name = append_prefix($e, $var_name);
1014 return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0]));
1018 ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred);
1023 #####################################################################
1024 # parse a pointer in a struct element or function
1025 sub ParsePtrPull($$$$)
1030 my($var_name) = shift;
1032 my $nl = Ndr::GetNextLevel($e, $l);
1033 my $next_is_array = ($nl->{TYPE} eq "ARRAY");
1035 if ($l->{POINTER_TYPE} eq "ref") {
1036 unless ($l->{LEVEL} eq "TOP") {
1037 pidl "NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));";
1040 unless ($next_is_array) {
1041 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1042 pidl "\tNDR_ALLOC($ndr, $var_name);";
1048 pidl "NDR_CHECK(ndr_pull_unique_ptr($ndr, &_ptr_$e->{NAME}));";
1049 pidl "if (_ptr_$e->{NAME}) {";
1053 # Don't do this for arrays, they're allocated at the actual level
1055 unless ($next_is_array) {
1056 pidl "NDR_ALLOC($ndr, $var_name);";
1058 pidl "NDR_ALLOC_SIZE($ndr, $var_name, 1);"; # FIXME: Yes, this is nasty. We allocate an array twice - once just to indicate that it's there, then the real allocation...
1061 #pidl "memset($var_name, 0, sizeof($var_name));";
1062 if ($l->{POINTER_TYPE} eq "relative") {
1063 pidl "NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));";
1067 pidl "\t$var_name = NULL;";
1071 #####################################################################
1073 sub ParseStructPush($$)
1075 my($struct) = shift;
1078 return unless defined($struct->{ELEMENTS});
1080 my $env = GenerateStructEnv($struct);
1082 foreach my $e (@{$struct->{ELEMENTS}}) {
1083 DeclareArrayVariables($e);
1086 start_flags($struct);
1088 # see if the structure contains a conformant array. If it
1089 # does, then it must be the last element of the structure, and
1090 # we need to push the conformant length early, as it fits on
1091 # the wire before the structure (and even before the structure
1093 my $e = $struct->{ELEMENTS}[-1];
1094 if (defined($struct->{SURROUNDING_ELEMENT})) {
1095 my $e = $struct->{SURROUNDING_ELEMENT};
1097 if (defined($e->{LEVELS}[0]) and
1098 $e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
1099 ParseArrayPushPreceding($e, $e->{LEVELS}[0], "r->$e->{NAME}", $env);
1101 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
1105 pidl "if (ndr_flags & NDR_SCALARS) {";
1108 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1110 pidl "NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));";
1112 foreach my $e (@{$struct->{ELEMENTS}}) {
1113 ParseElementPush($e, "ndr", "r->", $env, 1, 0);
1119 pidl "if (ndr_flags & NDR_BUFFERS) {";
1121 foreach my $e (@{$struct->{ELEMENTS}}) {
1122 ParseElementPush($e, "ndr", "r->", $env, 0, 1);
1125 pidl "ndr_push_struct_end(ndr);";
1133 #####################################################################
1134 # generate a push function for an enum
1135 sub ParseEnumPush($$)
1139 my($type_fn) = $enum->{BASE_TYPE};
1142 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1146 #####################################################################
1147 # generate a pull function for an enum
1148 sub ParseEnumPull($$)
1152 my($type_fn) = $enum->{BASE_TYPE};
1153 my($type_v_decl) = typelist::mapType($type_fn);
1155 pidl "$type_v_decl v;";
1157 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1163 #####################################################################
1164 # generate a print function for an enum
1165 sub ParseEnumPrint($$)
1170 pidl "const char *val = NULL;";
1175 pidl "switch (r) {";
1177 my $els = \@{$enum->{ELEMENTS}};
1178 foreach my $i (0 .. $#{$els}) {
1179 my $e = ${$els}[$i];
1181 if ($e =~ /^(.*)=/) {
1184 pidl "case $e: val = \"$e\"; break;";
1190 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1198 return "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1201 sub ArgsEnumPrint($)
1204 return "struct ndr_print *ndr, const char *name, enum $e->{NAME} r";
1210 return "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1213 $typefamily{ENUM} = {
1214 PUSH_FN_BODY => \&ParseEnumPush,
1215 PUSH_FN_ARGS => \&ArgsEnumPush,
1216 PULL_FN_BODY => \&ParseEnumPull,
1217 PULL_FN_ARGS => \&ArgsEnumPull,
1218 PRINT_FN_BODY => \&ParseEnumPrint,
1219 PRINT_FN_ARGS => \&ArgsEnumPrint,
1222 #####################################################################
1223 # generate a push function for a bitmap
1224 sub ParseBitmapPush($$)
1226 my($bitmap) = shift;
1228 my($type_fn) = $bitmap->{BASE_TYPE};
1230 start_flags($bitmap);
1232 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1237 #####################################################################
1238 # generate a pull function for an bitmap
1239 sub ParseBitmapPull($$)
1241 my($bitmap) = shift;
1243 my $type_fn = $bitmap->{BASE_TYPE};
1244 my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE});
1246 pidl "$type_decl v;";
1247 start_flags($bitmap);
1248 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1254 #####################################################################
1255 # generate a print function for an bitmap
1256 sub ParseBitmapPrintElement($$$)
1259 my($bitmap) = shift;
1261 my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE});
1262 my($type_fn) = $bitmap->{BASE_TYPE};
1265 if ($e =~ /^(\w+) .*$/) {
1268 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1271 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1274 #####################################################################
1275 # generate a print function for an bitmap
1276 sub ParseBitmapPrint($$)
1278 my($bitmap) = shift;
1280 my($type_decl) = typelist::mapType($bitmap->{TYPE});
1281 my($type_fn) = $bitmap->{BASE_TYPE};
1283 start_flags($bitmap);
1285 pidl "ndr_print_$type_fn(ndr, name, r);";
1287 pidl "ndr->depth++;";
1288 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1289 ParseBitmapPrintElement($e, $bitmap, $name);
1291 pidl "ndr->depth--;";
1296 sub ArgsBitmapPush($)
1299 my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
1300 return "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1303 sub ArgsBitmapPrint($)
1306 my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
1307 return "struct ndr_print *ndr, const char *name, $type_decl r";
1310 sub ArgsBitmapPull($)
1313 my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE});
1314 return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1317 $typefamily{BITMAP} = {
1318 PUSH_FN_BODY => \&ParseBitmapPush,
1319 PUSH_FN_ARGS => \&ArgsBitmapPush,
1320 PULL_FN_BODY => \&ParseBitmapPull,
1321 PULL_FN_ARGS => \&ArgsBitmapPull,
1322 PRINT_FN_BODY => \&ParseBitmapPrint,
1323 PRINT_FN_ARGS => \&ArgsBitmapPrint,
1326 #####################################################################
1327 # generate a struct print function
1328 sub ParseStructPrint($$)
1330 my($struct) = shift;
1333 return unless defined $struct->{ELEMENTS};
1335 my $env = GenerateStructEnv($struct);
1337 foreach my $e (@{$struct->{ELEMENTS}}) {
1338 DeclareArrayVariables($e);
1341 pidl "ndr_print_struct(ndr, name, \"$name\");";
1343 start_flags($struct);
1345 pidl "ndr->depth++;";
1346 foreach my $e (@{$struct->{ELEMENTS}}) {
1347 ParseElementPrint($e, "r->$e->{NAME}", $env);
1349 pidl "ndr->depth--;";
1354 sub DeclarePtrVariables($)
1357 foreach my $l (@{$e->{LEVELS}}) {
1358 if ($l->{TYPE} eq "POINTER" and
1359 not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) {
1360 pidl "uint32_t _ptr_$e->{NAME};";
1366 sub DeclareArrayVariables($)
1370 foreach my $l (@{$e->{LEVELS}}) {
1371 next if (is_scalar_array($e,$l));
1372 if ($l->{TYPE} eq "ARRAY") {
1373 pidl "uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};";
1378 #####################################################################
1379 # parse a struct - pull side
1380 sub ParseStructPull($$)
1382 my($struct) = shift;
1386 return unless defined $struct->{ELEMENTS};
1388 my $env = GenerateStructEnv($struct);
1390 # see if the structure contains a conformant array. If it
1391 # does, then it must be the last element of the structure, and
1392 # we need to pull the conformant length early, as it fits on
1393 # the wire before the structure (and even before the structure
1395 $conform_e = $struct->{SURROUNDING_ELEMENT};
1397 # declare any internal pointers we need
1398 foreach my $e (@{$struct->{ELEMENTS}}) {
1399 DeclarePtrVariables($e);
1400 DeclareArrayVariables($e);
1403 start_flags($struct);
1405 pidl "if (ndr_flags & NDR_SCALARS) {";
1408 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1410 if (defined $conform_e) {
1411 ParseArrayPullPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}");
1414 pidl "NDR_CHECK(ndr_pull_align(ndr, $struct->{ALIGN}));";
1416 foreach my $e (@{$struct->{ELEMENTS}}) {
1417 ParseElementPull($e, "ndr", "r->", $env, 1, 0);
1422 pidl "if (ndr_flags & NDR_BUFFERS) {";
1424 foreach my $e (@{$struct->{ELEMENTS}}) {
1425 ParseElementPull($e, "ndr", "r->", $env, 0, 1);
1428 pidl "ndr_pull_struct_end(ndr);";
1436 #####################################################################
1437 # calculate size of ndr struct
1438 sub ParseStructNdrSize($)
1443 if (my $flags = util::has_property($t, "flag")) {
1444 pidl "flags |= $flags;";
1446 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1449 sub ArgsStructPush($)
1452 return "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1455 sub ArgsStructPrint($)
1458 return "struct ndr_print *ndr, const char *name, struct $e->{NAME} *r";
1461 sub ArgsStructPull($)
1464 return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1467 sub ArgsStructNdrSize($)
1470 return "const struct $d->{NAME} *r, int flags";
1473 $typefamily{STRUCT} = {
1474 PUSH_FN_BODY => \&ParseStructPush,
1475 PUSH_FN_ARGS => \&ArgsStructPush,
1476 PULL_FN_BODY => \&ParseStructPull,
1477 PULL_FN_ARGS => \&ArgsStructPull,
1478 PRINT_FN_BODY => \&ParseStructPrint,
1479 PRINT_FN_ARGS => \&ArgsStructPrint,
1480 SIZE_FN_BODY => \&ParseStructNdrSize,
1481 SIZE_FN_ARGS => \&ArgsStructNdrSize,
1484 #####################################################################
1485 # calculate size of ndr struct
1486 sub ParseUnionNdrSize($)
1491 if (my $flags = util::has_property($t, "flag")) {
1492 pidl "flags |= $flags;";
1495 pidl "return ndr_size_union(r, flags, level, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1498 #####################################################################
1499 # parse a union - push side
1500 sub ParseUnionPush($$)
1504 my $have_default = 0;
1511 pidl "level = ndr_push_get_switch_value(ndr, r);";
1513 pidl "if (ndr_flags & NDR_SCALARS) {";
1516 if (defined($e->{SWITCH_TYPE})) {
1517 pidl "NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}(ndr, NDR_SCALARS, level));";
1520 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1522 # my $align = union_alignment($e);
1523 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1525 pidl "switch (level) {";
1527 foreach my $el (@{$e->{ELEMENTS}}) {
1528 if ($el->{CASE} eq "default") {
1531 pidl "$el->{CASE}:";
1533 if ($el->{TYPE} ne "EMPTY") {
1535 DeclareArrayVariables($el);
1536 ParseElementPush($el, "ndr", "r->", {}, 1, 0);
1542 if (! $have_default) {
1544 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1550 pidl "if (ndr_flags & NDR_BUFFERS) {";
1552 pidl "switch (level) {";
1554 foreach my $el (@{$e->{ELEMENTS}}) {
1555 pidl "$el->{CASE}:";
1556 if ($el->{TYPE} ne "EMPTY") {
1558 ParseElementPush($el, "ndr", "r->", {}, 0, 1);
1564 if (! $have_default) {
1566 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1570 pidl "ndr_push_struct_end(ndr);";
1576 #####################################################################
1578 sub ParseUnionPrint($$)
1581 my $have_default = 0;
1584 pidl "int level = ndr_print_get_switch_value(ndr, r);";
1586 foreach my $el (@{$e->{ELEMENTS}}) {
1587 DeclareArrayVariables($el);
1590 pidl "ndr_print_union(ndr, name, level, \"$name\");";
1593 pidl "switch (level) {";
1595 foreach my $el (@{$e->{ELEMENTS}}) {
1596 if ($el->{CASE} eq "default") {
1599 pidl "$el->{CASE}:";
1600 if ($el->{TYPE} ne "EMPTY") {
1602 ParseElementPrint($el, "r->$el->{NAME}", {});
1608 if (! $have_default) {
1610 pidl "\tndr_print_bad_level(ndr, name, level);";
1618 #####################################################################
1619 # parse a union - pull side
1620 sub ParseUnionPull($$)
1624 my $have_default = 0;
1625 my $switch_type = $e->{SWITCH_TYPE};
1628 if (defined($switch_type)) {
1629 if (typelist::typeIs($switch_type, "ENUM")) {
1630 $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
1632 pidl typelist::mapType($switch_type) . " _level;";
1637 pidl "level = ndr_pull_get_switch_value(ndr, r);";
1639 pidl "if (ndr_flags & NDR_SCALARS) {";
1642 if (defined($switch_type)) {
1643 pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
1644 pidl "if (_level != level) {";
1645 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $name\", _level);";
1649 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1651 # my $align = union_alignment($e);
1652 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1654 pidl "switch (level) {";
1656 foreach my $el (@{$e->{ELEMENTS}}) {
1657 if ($el->{CASE} eq "default") {
1660 pidl "$el->{CASE}: {";
1662 if ($el->{TYPE} ne "EMPTY") {
1664 DeclarePtrVariables($el);
1665 DeclareArrayVariables($el);
1666 ParseElementPull($el, "ndr", "r->", {}, 1, 0);
1672 if (! $have_default) {
1674 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1680 pidl "if (ndr_flags & NDR_BUFFERS) {";
1682 pidl "switch (level) {";
1684 foreach my $el (@{$e->{ELEMENTS}}) {
1685 pidl "$el->{CASE}:";
1686 if ($el->{TYPE} ne "EMPTY") {
1688 ParseElementPull($el, "ndr", "r->", {}, 0, 1);
1694 if (! $have_default) {
1696 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1700 pidl "ndr_pull_struct_end(ndr);";
1706 sub ArgsUnionPush($)
1709 return "struct ndr_push *ndr, int ndr_flags, union $e->{NAME} *r";
1712 sub ArgsUnionPrint($)
1715 return "struct ndr_print *ndr, const char *name, union $e->{NAME} *r";
1718 sub ArgsUnionPull($)
1721 return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
1724 sub ArgsUnionNdrSize($)
1727 return "const union $d->{NAME} *r, uint32_t level, int flags";
1730 $typefamily{UNION} = {
1731 PUSH_FN_BODY => \&ParseUnionPush,
1732 PUSH_FN_ARGS => \&ArgsUnionPush,
1733 PULL_FN_BODY => \&ParseUnionPull,
1734 PULL_FN_ARGS => \&ArgsUnionPull,
1735 PRINT_FN_BODY => \&ParseUnionPrint,
1736 PRINT_FN_ARGS => \&ArgsUnionPrint,
1737 SIZE_FN_ARGS => \&ArgsUnionNdrSize,
1738 SIZE_FN_BODY => \&ParseUnionNdrSize,
1741 #####################################################################
1742 # parse a typedef - push side
1743 sub ParseTypedefPush($)
1747 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e);
1748 pidl fn_prefix($e) . "NTSTATUS ndr_push_$e->{NAME}($args)";
1752 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA}, $e->{NAME});
1753 pidl "return NT_STATUS_OK;";
1759 #####################################################################
1760 # parse a typedef - pull side
1761 sub ParseTypedefPull($)
1765 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e);
1767 pidl fn_prefix($e) . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1771 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA}, $e->{NAME});
1772 pidl "return NT_STATUS_OK;";
1778 #####################################################################
1779 # parse a typedef - print side
1780 sub ParseTypedefPrint($)
1784 my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
1786 pidl "void ndr_print_$e->{NAME}($args)";
1789 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}, $e->{NAME});
1795 #####################################################################
1796 ## calculate the size of a structure
1797 sub ParseTypedefNdrSize($)
1801 my $tf = $typefamily{$t->{DATA}->{TYPE}};
1802 my $args = $tf->{SIZE_FN_ARGS}->($t);
1804 pidl "size_t ndr_size_$t->{NAME}($args)";
1807 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($t);
1813 #####################################################################
1814 # parse a function - print side
1815 sub ParseFunctionPrint($)
1819 return if util::has_property($fn, "noprint");
1821 my $env = GenerateFunctionEnv($fn);
1823 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1827 foreach my $e (@{$fn->{ELEMENTS}}) {
1828 DeclareArrayVariables($e);
1831 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1832 pidl "ndr->depth++;";
1834 pidl "if (flags & NDR_SET_VALUES) {";
1835 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1838 pidl "if (flags & NDR_IN) {";
1840 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1841 pidl "ndr->depth++;";
1843 foreach my $e (@{$fn->{ELEMENTS}}) {
1844 if (grep(/in/,@{$e->{DIRECTION}})) {
1845 ParseElementPrint($e, "r->in.$e->{NAME}", $env);
1848 pidl "ndr->depth--;";
1852 pidl "if (flags & NDR_OUT) {";
1854 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1855 pidl "ndr->depth++;";
1856 foreach my $e (@{$fn->{ELEMENTS}}) {
1857 if (grep(/out/,@{$e->{DIRECTION}})) {
1858 ParseElementPrint($e, "r->out.$e->{NAME}", $env);
1861 if ($fn->{RETURN_TYPE}) {
1862 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);";
1864 pidl "ndr->depth--;";
1868 pidl "ndr->depth--;";
1874 #####################################################################
1876 sub ParseFunctionPush($)
1880 return if util::has_property($fn, "nopush");
1882 my $env = GenerateFunctionEnv($fn);
1884 pidl fn_prefix($fn) . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1888 foreach my $e (@{$fn->{ELEMENTS}}) {
1889 DeclareArrayVariables($e);
1892 pidl "if (flags & NDR_IN) {";
1895 foreach my $e (@{$fn->{ELEMENTS}}) {
1896 if (grep(/in/,@{$e->{DIRECTION}})) {
1897 ParseElementPush($e, "ndr", "r->in.", $env, 1, 1);
1904 pidl "if (flags & NDR_OUT) {";
1907 foreach my $e (@{$fn->{ELEMENTS}}) {
1908 if (grep(/out/,@{$e->{DIRECTION}})) {
1909 ParseElementPush($e, "ndr", "r->out.", $env, 1, 1);
1913 if ($fn->{RETURN_TYPE}) {
1914 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1919 pidl "return NT_STATUS_OK;";
1925 sub AllocateArrayLevel($$$$$)
1933 my $var = ParseExpr($e->{NAME}, $env);
1935 check_null_pointer($size);
1936 my $pl = Ndr::GetPrevLevel($e, $l);
1937 if (defined($pl) and
1938 $pl->{TYPE} eq "POINTER" and
1939 $pl->{POINTER_TYPE} eq "ref") {
1940 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1941 pidl "\tNDR_ALLOC_N($ndr, $var, $size);";
1944 pidl "NDR_ALLOC_N($ndr, $var, $size);";
1946 #pidl "memset($var, 0, $size * sizeof(" . $var . "[0]));";
1947 if (grep(/in/,@{$e->{DIRECTION}}) and
1948 grep(/out/,@{$e->{DIRECTION}})) {
1949 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1953 #####################################################################
1955 sub ParseFunctionPull($)
1959 return if util::has_property($fn, "nopull");
1961 my $env = GenerateFunctionEnv($fn);
1963 # pull function args
1964 pidl fn_prefix($fn) . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1968 # declare any internal pointers we need
1969 foreach my $e (@{$fn->{ELEMENTS}}) {
1970 DeclarePtrVariables($e);
1971 DeclareArrayVariables($e);
1974 pidl "if (flags & NDR_IN) {";
1977 # auto-init the out section of a structure. I originally argued that
1978 # this was a bad idea as it hides bugs, but coping correctly
1979 # with initialisation and not wiping ref vars is turning
1980 # out to be too tricky (tridge)
1981 foreach my $e (@{$fn->{ELEMENTS}}) {
1982 next unless grep(/out/, @{$e->{DIRECTION}});
1983 pidl "ZERO_STRUCT(r->out);";
1988 foreach my $e (@{$fn->{ELEMENTS}}) {
1989 next unless (grep(/in/, @{$e->{DIRECTION}}));
1990 ParseElementPull($e, "ndr", "r->in.", $env, 1, 1);
1993 # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's
1994 # own flag rather then be in NDR_IN ?
1996 foreach my $e (@{$fn->{ELEMENTS}}) {
1997 next unless (grep(/out/, @{$e->{DIRECTION}}));
1998 next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and
1999 $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref");
2002 if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") {
2003 my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
2004 check_null_pointer($size);
2006 pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
2008 if (grep(/in/, @{$e->{DIRECTION}})) {
2009 pidl "memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));";
2011 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
2014 pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
2016 if (grep(/in/, @{$e->{DIRECTION}})) {
2017 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
2019 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
2027 pidl "if (flags & NDR_OUT) {";
2030 foreach my $e (@{$fn->{ELEMENTS}}) {
2031 next unless grep(/out/, @{$e->{DIRECTION}});
2032 ParseElementPull($e, "ndr", "r->out.", $env, 1, 1);
2035 if ($fn->{RETURN_TYPE}) {
2036 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
2041 pidl "return NT_STATUS_OK;";
2047 #####################################################################
2048 # produce a function call table
2049 sub FunctionTable($)
2051 my($interface) = shift;
2053 my $uname = uc $interface->{NAME};
2055 $count = $#{$interface->{FUNCTIONS}}+1;
2057 return if ($count == 0);
2059 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
2061 foreach my $d (@{$interface->{FUNCTIONS}}) {
2062 next if not defined($d->{OPNUM});
2064 pidl "\t\t\"$d->{NAME}\",";
2065 pidl "\t\tsizeof(struct $d->{NAME}),";
2066 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
2067 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
2068 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
2072 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
2076 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
2077 foreach my $ep (@{$interface->{ENDPOINTS}}) {
2080 my $endpoint_count = $#{$interface->{ENDPOINTS}}+1;
2085 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
2086 pidl "\t.count\t= $endpoint_count,";
2087 pidl "\t.names\t= $interface->{NAME}\_endpoint_strings";
2091 if (! defined $interface->{PROPERTIES}->{authservice}) {
2092 $interface->{PROPERTIES}->{authservice} = "\"host\"";
2095 my @a = split / /, $interface->{PROPERTIES}->{authservice};
2096 my $authservice_count = $#a + 1;
2098 pidl "static const char * const $interface->{NAME}\_authservice_strings[] = {";
2099 foreach my $ap (@a) {
2105 pidl "static const struct dcerpc_authservice_list $interface->{NAME}\_authservices = {";
2106 pidl "\t.count\t= $endpoint_count,";
2107 pidl "\t.names\t= $interface->{NAME}\_authservice_strings";
2111 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
2112 pidl "\t.name\t\t= \"$interface->{NAME}\",";
2113 pidl "\t.uuid\t\t= DCERPC_$uname\_UUID,";
2114 pidl "\t.if_version\t= DCERPC_$uname\_VERSION,";
2115 pidl "\t.helpstring\t= DCERPC_$uname\_HELPSTRING,";
2116 pidl "\t.num_calls\t= $count,";
2117 pidl "\t.calls\t\t= $interface->{NAME}\_calls,";
2118 pidl "\t.endpoints\t= &$interface->{NAME}\_endpoints,";
2119 pidl "\t.authservices\t= &$interface->{NAME}\_authservices";
2123 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
2125 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
2130 #####################################################################
2131 # parse the interface definitions
2132 sub ParseInterface($$)
2134 my($interface) = shift;
2138 foreach my $d (@{$interface->{TYPEDEFS}}) {
2139 ($needed->{"push_$d->{NAME}"}) && ParseTypedefPush($d);
2140 ($needed->{"pull_$d->{NAME}"}) && ParseTypedefPull($d);
2141 ($needed->{"print_$d->{NAME}"}) && ParseTypedefPrint($d);
2143 # Make sure we don't generate a function twice...
2144 $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} =
2145 $needed->{"print_$d->{NAME}"} = 0;
2147 ($needed->{"ndr_size_$d->{NAME}"}) && ParseTypedefNdrSize($d);
2151 foreach my $d (@{$interface->{FUNCTIONS}}) {
2152 ($needed->{"push_$d->{NAME}"}) && ParseFunctionPush($d);
2153 ($needed->{"pull_$d->{NAME}"}) && ParseFunctionPull($d);
2154 ($needed->{"print_$d->{NAME}"}) && ParseFunctionPrint($d);
2156 # Make sure we don't generate a function twice...
2157 $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} =
2158 $needed->{"print_$d->{NAME}"} = 0;
2161 FunctionTable($interface);
2164 sub RegistrationFunction($$)
2167 my $filename = shift;
2169 $filename =~ /.*\/ndr_(.*).c/;
2171 pidl "NTSTATUS dcerpc_$basename\_init(void)";
2174 pidl "NTSTATUS status = NT_STATUS_OK;";
2175 foreach my $interface (@{$idl}) {
2176 next if $interface->{TYPE} ne "INTERFACE";
2178 my $count = ($#{$interface->{FUNCTIONS}}+1);
2180 next if ($count == 0);
2182 pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
2183 pidl "if (NT_STATUS_IS_ERR(status)) {";
2184 pidl "\treturn status;";
2188 pidl "return status;";
2194 #####################################################################
2195 # parse a parsed IDL structure back into an IDL file
2199 my($filename) = shift;
2202 my $h_filename = $filename;
2205 if ($h_filename =~ /(.*)\.c/) {
2206 $h_filename = "$1.h";
2209 pidl "/* parser auto-generated by pidl */";
2211 pidl "#include \"includes.h\"";
2212 pidl "#include \"$h_filename\"";
2217 foreach my $x (@{$ndr}) {
2218 ($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed);
2221 foreach my $x (@{$ndr}) {
2222 ($x->{TYPE} eq "INTERFACE") && ParseInterface($x, \%needed);
2225 RegistrationFunction($ndr, $filename);
2230 sub NeededFunction($$)
2234 $needed->{"pull_$fn->{NAME}"} = 1;
2235 $needed->{"push_$fn->{NAME}"} = 1;
2236 $needed->{"print_$fn->{NAME}"} = 1;
2237 foreach my $e (@{$fn->{ELEMENTS}}) {
2239 unless(defined($needed->{"pull_$e->{TYPE}"})) {
2240 $needed->{"pull_$e->{TYPE}"} = 1;
2242 unless(defined($needed->{"push_$e->{TYPE}"})) {
2243 $needed->{"push_$e->{TYPE}"} = 1;
2245 unless(defined($needed->{"print_$e->{TYPE}"})) {
2246 $needed->{"print_$e->{TYPE}"} = 1;
2251 sub NeededTypedef($$)
2255 if (util::has_property($t, "public")) {
2256 $needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull");
2257 $needed->{"push_$t->{NAME}"} = not util::has_property($t, "nopush");
2258 $needed->{"print_$t->{NAME}"} = not util::has_property($t, "noprint");
2261 if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") {
2262 if (util::has_property($t, "gensize")) {
2263 $needed->{"ndr_size_$t->{NAME}"} = 1;
2266 for my $e (@{$t->{DATA}->{ELEMENTS}}) {
2267 $e->{PARENT} = $t->{DATA};
2268 if ($needed->{"pull_$t->{NAME}"} and
2269 not defined($needed->{"pull_$e->{TYPE}"})) {
2270 $needed->{"pull_$e->{TYPE}"} = 1;
2272 if ($needed->{"push_$t->{NAME}"} and
2273 not defined($needed->{"push_$e->{TYPE}"})) {
2274 $needed->{"push_$e->{TYPE}"} = 1;
2276 if ($needed->{"print_$t->{NAME}"} and
2277 not defined($needed->{"print_$e->{TYPE}"})) {
2278 $needed->{"print_$e->{TYPE}"} = 1;
2284 #####################################################################
2285 # work out what parse functions are needed
2286 sub NeededInterface($$)
2288 my ($interface) = shift;
2290 foreach my $d (@{$interface->{FUNCTIONS}}) {
2291 NeededFunction($d, $needed);
2293 foreach my $d (reverse @{$interface->{TYPEDEFS}}) {
2294 NeededTypedef($d, $needed);