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
23 sub RegisterPrimitives()
44 "error_status_t" => 4,
54 foreach my $k (keys %type_alignments) {
60 ALIGN => $type_alignments{$k}
70 if (my $dt = $typedefs{$type}->{DATA}->{TYPE}) {
71 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
81 return undef unless $e->{POINTERS};
83 return "ref" if (util::has_property($e, "ref"));
84 return "ptr" if (util::has_property($e, "ptr"));
85 return "unique" if (util::has_property($e, "unique"));
86 return "relative" if (util::has_property($e, "relative"));
87 return "ignore" if (util::has_property($e, "ignore"));
92 # determine if an element needs a reference pointer on the wire
93 # in its NDR representation
94 sub need_wire_pointer($)
99 return 0 unless ($pt = pointer_type($e));
108 # determine if an element is a pure scalar. pure scalars do not
109 # have a "buffers" section in NDR
110 sub is_pure_scalar($)
113 if (util::has_property($e, "ref")) {
116 if (is_scalar_type($e->{TYPE}) &&
118 !util::array_size($e)) {
124 # see if a variable needs to be allocated by the NDR subsystem on pull
129 if (util::has_property($e, "ref")) {
133 if ($e->{POINTERS} || util::array_size($e)) {
141 # determine the C prefix used to refer to a variable when passing to a push
142 # function. This will be '*' for pointers to scalar types, '' for scalar
143 # types and normal pointers and '&' for pass-by-reference structures
148 if ($e->{TYPE} =~ "string") {
152 if (is_scalar_type($e->{TYPE}) &&
156 if (!is_scalar_type($e->{TYPE}) &&
158 !util::array_size($e)) {
165 # determine the C prefix used to refer to a variable when passing to a pull
171 if (!$e->{POINTERS} && !util::array_size($e)) {
175 if ($e->{TYPE} =~ "string") {
200 $tabs = substr($tabs, 0, -1);
203 ###################################
204 # find a sibling var in a structure
209 my($fn) = $e->{PARENT};
211 if ($name =~ /\*(.*)/) {
215 for my $e2 (@{$fn->{ELEMENTS}}) {
216 return $e2 if ($e2->{NAME} eq $name);
219 die "invalid sibling '$name'";
222 ####################################################################
223 # work out the name of a size_is() variable
228 my($var_prefix) = shift;
230 my($fn) = $e->{PARENT};
232 return $size if (util::is_constant($size));
234 return $size if ($size =~ /ndr->|\(/);
238 if ($size =~ /\*(.*)/) {
243 if ($fn->{TYPE} ne "FUNCTION") {
244 return $prefix . "r->$size";
247 my $e2 = find_sibling($e, $size);
249 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
250 return $prefix . "$var_prefix$size";
253 if (util::has_property($e2, "in")) {
254 return $prefix . "r->in.$size";
257 if (util::has_property($e2, "out")) {
258 return $prefix . "r->out.$size";
261 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
264 #####################################################################
265 # check that a variable we get from ParseExpr isn't a null pointer
266 sub check_null_pointer($)
269 if ($size =~ /^\*/) {
270 my $size2 = substr($size, 1);
271 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
275 #####################################################################
276 # check that a variable we get from ParseExpr isn't a null pointer
277 # void return varient
278 sub check_null_pointer_void($)
281 if ($size =~ /^\*/) {
282 my $size2 = substr($size, 1);
283 pidl "if ($size2 == NULL) return;";
287 #####################################################################
288 # work out is a parse function should be declared static or not
292 if ($fn->{TYPE} eq "TYPEDEF") {
293 if (util::has_property($fn, "public")) {
298 if ($fn->{TYPE} eq "FUNCTION") {
299 if (util::has_property($fn, "public")) {
306 ###################################################################
307 # setup any special flags for an element or structure
311 my $flags = util::has_property($e, "flag");
312 if (defined $flags) {
313 pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
314 pidl "ndr_set_flags(&ndr->flags, $flags);";
318 ###################################################################
319 # end any special flags for an element or structure
323 my $flags = util::has_property($e, "flag");
324 if (defined $flags) {
325 pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
329 #####################################################################
330 # work out the correct alignment for a structure or union
331 sub find_largest_alignment($)
336 for my $e (@{$s->{ELEMENTS}}) {
339 if (need_wire_pointer($e)) {
342 $a = align_type($e->{TYPE});
345 $align = $a if ($align < $a);
351 #####################################################################
357 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA}->{TYPE})) {
358 # it must be an external type - all we can do is guess
359 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
363 my $dt = $typedefs{$e}->{DATA};
365 return $dt->{ALIGN} if ($dt->{ALIGN});
366 return $typefamily{$dt->{TYPE}}->{ALIGN}->($dt);
369 #####################################################################
370 # parse an array - push side
371 sub ParseArrayPush($$$)
374 my $var_prefix = shift;
375 my $ndr_flags = shift;
377 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
379 if (defined $e->{CONFORMANT_SIZE}) {
380 # the conformant size has already been pushed
381 } elsif (!util::is_inline_array($e)) {
382 # we need to emit the array size
383 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
386 if (my $length = util::has_property($e, "length_is")) {
387 $length = ParseExpr($e, $length, $var_prefix);
388 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
389 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
393 if (is_scalar_type($e->{TYPE})) {
394 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
396 pidl "NDR_CHECK(ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
400 #####################################################################
402 sub ParseArrayPrint($$)
405 my $var_prefix = shift;
406 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
407 my $length = util::has_property($e, "length_is");
409 if (defined $length) {
410 $size = ParseExpr($e, $length, $var_prefix);
413 if (is_scalar_type($e->{TYPE})) {
414 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
416 pidl "ndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});";
420 #####################################################################
421 # check the size_is and length_is constraints
422 sub CheckArraySizes($$)
425 my $var_prefix = shift;
427 if (!defined $e->{CONFORMANT_SIZE} &&
428 util::has_property($e, "size_is")) {
429 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
430 pidl "if ($var_prefix$e->{NAME}) {";
432 check_null_pointer($size);
433 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
438 if (my $length = util::has_property($e, "length_is")) {
439 $length = ParseExpr($e, $length, $var_prefix);
440 pidl "if ($var_prefix$e->{NAME}) {";
442 check_null_pointer($length);
443 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
449 #####################################################################
450 # parse an array - pull side
451 sub ParseArrayPull($$$)
454 my $var_prefix = shift;
455 my $ndr_flags = shift;
457 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
458 my $alloc_size = $size;
460 # if this is a conformant array then we use that size to allocate, and make sure
461 # we allocate enough to pull the elements
462 if (defined $e->{CONFORMANT_SIZE}) {
463 $alloc_size = $e->{CONFORMANT_SIZE};
464 check_null_pointer($size);
465 pidl "if ($size > $alloc_size) {";
467 pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
470 } elsif (!util::is_inline_array($e)) {
471 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
472 my $size2 = substr($size, 1);
473 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
476 # non fixed arrays encode the size just before the array
477 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
478 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
481 if ((need_alloc($e) && !util::is_fixed_array($e)) ||
482 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
483 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
484 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
488 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
489 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
490 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
492 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
498 if (my $length = util::has_property($e, "length_is")) {
499 pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
500 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
503 check_null_pointer($size);
504 if (is_scalar_type($e->{TYPE})) {
505 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
507 pidl "NDR_CHECK(ndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
511 #####################################################################
512 # parse scalars in a structure element
513 sub ParseElementPushScalar($$$)
516 my($var_prefix) = shift;
517 my($ndr_flags) = shift;
518 my $cprefix = c_push_prefix($e);
519 my $sub_size = util::has_property($e, "subcontext");
523 if (my $value = util::has_property($e, "value")) {
524 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
527 if (util::has_property($e, "relative")) {
528 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
529 } elsif (util::is_inline_array($e)) {
530 ParseArrayPush($e, "r->", "NDR_SCALARS");
531 } elsif (need_wire_pointer($e)) {
532 ParseElementPushPtr($e, $var_prefix, $ndr_flags);
533 } elsif (need_alloc($e)) {
534 # no scalar component
535 } elsif (my $switch = util::has_property($e, "switch_is")) {
536 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
537 } elsif (defined $sub_size) {
538 pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
540 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
546 #####################################################################
547 # parse a pointer in a struct element or function
548 sub ParseElementPushPtr($$$)
551 my $var_prefix = shift;
552 my $ndr_flags = shift;
554 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
558 #####################################################################
559 # print scalars in a structure element
560 sub ParseElementPrintScalar($$)
563 my($var_prefix) = shift;
564 my $cprefix = c_push_prefix($e);
566 if (util::has_property($e, "noprint")) {
570 if (my $value = util::has_property($e, "value")) {
571 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
573 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
578 if (util::is_fixed_array($e)) {
579 ParseElementPrintBuffer($e, $var_prefix);
580 } elsif ($e->{POINTERS} || util::array_size($e)) {
581 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
582 pidl "ndr->depth++;";
583 ParseElementPrintBuffer($e, $var_prefix);
584 pidl "ndr->depth--;";
585 } elsif (my $switch = util::has_property($e, "switch_is")) {
586 ParseElementPrintSwitch($e, $var_prefix, $switch);
588 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
592 #####################################################################
593 # parse scalars in a structure element - pull size
594 sub ParseElementPullSwitch($$$$)
597 my($var_prefix) = shift;
598 my($ndr_flags) = shift;
600 my $switch_var = ParseExpr($e, $switch, $var_prefix);
602 my $cprefix = c_pull_prefix($e);
604 my $utype = $typedefs{$e->{TYPE}};
606 check_null_pointer($switch_var);
608 if (!defined $utype ||
609 !util::has_property($utype, "nodiscriminant")) {
610 my $e2 = find_sibling($e, $switch);
611 my $type_decl = util::map_type($e2->{TYPE});
612 pidl "if (($ndr_flags) & NDR_SCALARS) {";
614 if ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "ENUM") {
615 $type_decl = util::enum_type_decl($e2);
616 } elsif ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "BITMAP") {
617 $type_decl = util::bitmap_type_decl($e2);
619 pidl "$type_decl _level;";
620 pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
621 if ($switch_var =~ /r->in/) {
622 pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
625 pidl "if (_level != $switch_var) {";
628 pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
630 if ($switch_var =~ /r->/) {
631 pidl "} else { $switch_var = _level; }";
639 my $sub_size = util::has_property($e, "subcontext");
640 if (defined $sub_size) {
641 pidl "if (($ndr_flags) & NDR_SCALARS) {";
643 pidl "NDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));";
647 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
653 #####################################################################
654 # push switch element
655 sub ParseElementPushSwitch($$$$)
658 my($var_prefix) = shift;
659 my($ndr_flags) = shift;
661 my $switch_var = ParseExpr($e, $switch, $var_prefix);
662 my $cprefix = c_push_prefix($e);
664 check_null_pointer($switch_var);
666 my $utype = $typedefs{$e->{TYPE}};
667 if (!defined $utype ||
668 !util::has_property($utype, "nodiscriminant")) {
669 my $e2 = find_sibling($e, $switch);
670 pidl "if (($ndr_flags) & NDR_SCALARS) {";
672 pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
677 my $sub_size = util::has_property($e, "subcontext");
678 if (defined $sub_size) {
679 pidl "if(($ndr_flags) & NDR_SCALARS) {";
681 pidl "NDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));";
685 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
689 #####################################################################
690 # print scalars in a structure element
691 sub ParseElementPrintSwitch($$$)
694 my($var_prefix) = shift;
696 my $switch_var = ParseExpr($e, $switch, $var_prefix);
697 my $cprefix = c_push_prefix($e);
699 check_null_pointer_void($switch_var);
701 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
705 #####################################################################
706 # parse scalars in a structure element - pull size
707 sub ParseElementPullScalar($$$)
710 my($var_prefix) = shift;
711 my($ndr_flags) = shift;
712 my $cprefix = c_pull_prefix($e);
713 my $sub_size = util::has_property($e, "subcontext");
717 if (util::is_inline_array($e)) {
718 ParseArrayPull($e, "r->", "NDR_SCALARS");
719 } elsif (need_wire_pointer($e)) {
720 ParseElementPullPtr($e, $var_prefix, $ndr_flags);
721 } elsif (need_alloc($e)) {
722 # no scalar component
723 } elsif (my $switch = util::has_property($e, "switch_is")) {
724 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
725 } elsif (defined $sub_size) {
726 pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
728 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
730 if (my $range = util::has_property($e, "range")) {
731 my ($low, $high) = split(/ /, $range, 2);
732 pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
733 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
740 #####################################################################
741 # parse a pointer in a struct element or function
742 sub ParseElementPullPtr($$$)
745 my($var_prefix) = shift;
746 my($ndr_flags) = shift;
748 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
749 pidl "if (_ptr_$e->{NAME}) {";
751 pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
752 if (util::has_property($e, "relative")) {
753 pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
757 pidl "\t$var_prefix$e->{NAME} = NULL;";
761 #####################################################################
762 # parse buffers in a structure element
763 sub ParseElementPushBuffer($$$)
766 my($var_prefix) = shift;
767 my($ndr_flags) = shift;
768 my $cprefix = c_push_prefix($e);
769 my $sub_size = util::has_property($e, "subcontext");
771 if (is_pure_scalar($e)) {
777 if (need_wire_pointer($e)) {
778 pidl "if ($var_prefix$e->{NAME}) {";
780 if (util::has_property($e, "relative")) {
781 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
785 if (util::is_inline_array($e)) {
786 ParseArrayPush($e, "r->", "NDR_BUFFERS");
787 } elsif (util::array_size($e)) {
788 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
789 } elsif (my $switch = util::has_property($e, "switch_is")) {
790 if ($e->{POINTERS}) {
791 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
793 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
795 } elsif (defined $sub_size) {
796 if ($e->{POINTERS}) {
797 pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
799 } elsif ($e->{POINTERS}) {
800 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
802 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
805 if (need_wire_pointer($e)) {
813 #####################################################################
814 # print buffers in a structure element
815 sub ParseElementPrintBuffer($$)
818 my($var_prefix) = shift;
819 my $cprefix = c_push_prefix($e);
821 if (need_wire_pointer($e)) {
822 pidl "if ($var_prefix$e->{NAME}) {";
826 if (util::array_size($e)) {
827 ParseArrayPrint($e, $var_prefix)
828 } elsif (my $switch = util::has_property($e, "switch_is")) {
829 ParseElementPrintSwitch($e, $var_prefix, $switch);
831 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
834 if (need_wire_pointer($e)) {
840 #####################################################################
841 # parse buffers in a structure element - pull side
842 sub ParseElementPullBuffer($$$)
845 my($var_prefix) = shift;
846 my($ndr_flags) = shift;
847 my $cprefix = c_pull_prefix($e);
848 my $sub_size = util::has_property($e, "subcontext");
850 if (is_pure_scalar($e)) {
856 if (need_wire_pointer($e)) {
857 pidl "if ($var_prefix$e->{NAME}) {";
859 if (util::has_property($e, "relative")) {
860 pidl "struct ndr_pull_save _relative_save;";
861 pidl "ndr_pull_save(ndr, &_relative_save);";
862 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
866 if (util::is_inline_array($e)) {
867 ParseArrayPull($e, "r->", "NDR_BUFFERS");
868 } elsif (util::array_size($e)) {
869 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
870 } elsif (my $switch = util::has_property($e, "switch_is")) {
871 if ($e->{POINTERS}) {
872 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
874 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
876 } elsif (defined $sub_size) {
877 if ($e->{POINTERS}) {
878 pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
880 } elsif ($e->{POINTERS}) {
881 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
883 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
886 if (need_wire_pointer($e)) {
887 if (util::has_property($e, "relative")) {
888 pidl "ndr_pull_restore(ndr, &_relative_save);";
897 #####################################################################
899 sub ParseStructPush($)
903 return unless defined($struct->{ELEMENTS});
905 start_flags($struct);
907 # see if the structure contains a conformant array. If it
908 # does, then it must be the last element of the structure, and
909 # we need to push the conformant length early, as it fits on
910 # the wire before the structure (and even before the structure
912 my $e = $struct->{ELEMENTS}[-1];
913 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
914 my $size = ParseExpr($e, util::array_size($e), "r->");
915 $e->{CONFORMANT_SIZE} = $size;
916 check_null_pointer($size);
917 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
920 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
921 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
922 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
925 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
927 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
929 my $align = find_largest_alignment($struct);
930 pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
932 foreach my $e (@{$struct->{ELEMENTS}}) {
933 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
937 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
938 foreach my $e (@{$struct->{ELEMENTS}}) {
939 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
942 pidl "ndr_push_struct_end(ndr);";
949 #####################################################################
950 # generate a push function for an enum
954 my($type_fn) = util::enum_type_fn($enum);
958 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
963 #####################################################################
964 # generate a pull function for an enum
968 my($type_fn) = util::enum_type_fn($enum);
969 my($type_v_decl) = util::map_type(util::enum_type_fn($enum));
971 pidl "$type_v_decl v;";
973 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
979 #####################################################################
980 # generate a print function for an enum
981 sub ParseEnumPrint($)
985 pidl "const char *val = NULL;";
992 my $els = \@{$enum->{ELEMENTS}};
993 foreach my $i (0 .. $#{$els}) {
996 if ($e =~ /^(.*)=/) {
999 pidl "case $e: val = \"$e\"; break;";
1005 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1010 $typefamily{ENUM} = {
1011 PUSH_FN_BODY => \&ParseEnumPush,
1012 PULL_FN_BODY => \&ParseEnumPull,
1013 PRINT_FN_BODY => \&ParseEnumPrint,
1014 ALIGN => sub { return align_type(util::enum_type_fn(shift)); }
1017 #####################################################################
1018 # generate a push function for a bitmap
1019 sub ParseBitmapPush($)
1021 my($bitmap) = shift;
1022 my($type_fn) = util::bitmap_type_fn($bitmap);
1024 start_flags($bitmap);
1026 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1031 #####################################################################
1032 # generate a pull function for an bitmap
1033 sub ParseBitmapPull($)
1035 my($bitmap) = shift;
1036 my($type_fn) = util::bitmap_type_fn($bitmap);
1037 my($type_decl) = util::bitmap_type_decl($bitmap);
1039 pidl "$type_decl v;";
1040 start_flags($bitmap);
1041 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1047 #####################################################################
1048 # generate a print function for an bitmap
1049 sub ParseBitmapPrintElement($$)
1052 my($bitmap) = shift;
1053 my($type_decl) = util::bitmap_type_decl($bitmap);
1054 my($type_fn) = util::bitmap_type_fn($bitmap);
1055 my($name) = $bitmap->{PARENT}->{NAME};
1058 if ($e =~ /^(\w+) .*$/) {
1061 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1064 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1067 #####################################################################
1068 # generate a print function for an bitmap
1069 sub ParseBitmapPrint($)
1071 my($bitmap) = shift;
1072 my($type_decl) = util::bitmap_type_decl($bitmap);
1073 my($type_fn) = util::bitmap_type_fn($bitmap);
1075 start_flags($bitmap);
1077 pidl "ndr_print_$type_fn(ndr, name, r);";
1079 pidl "ndr->depth++;";
1080 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1081 ParseBitmapPrintElement($e, $bitmap);
1083 pidl "ndr->depth--;";
1088 $typefamily{BITMAP} = {
1089 PUSH_FN_BODY => \&ParseBitmapPush,
1090 PULL_FN_BODY => \&ParseBitmapPull,
1091 PRINT_FN_BODY => \&ParseBitmapPrint,
1092 ALIGN => sub { return align_type(util::bitmap_type_fn(shift)); }
1095 #####################################################################
1096 # generate a struct print function
1097 sub ParseStructPrint($)
1099 my($struct) = shift;
1100 my($name) = $struct->{PARENT}->{NAME};
1102 return unless defined $struct->{ELEMENTS};
1104 pidl "ndr_print_struct(ndr, name, \"$name\");";
1106 start_flags($struct);
1108 pidl "ndr->depth++;";
1109 foreach my $e (@{$struct->{ELEMENTS}}) {
1110 ParseElementPrintScalar($e, "r->");
1112 pidl "ndr->depth--;";
1117 #####################################################################
1118 # parse a struct - pull side
1119 sub ParseStructPull($)
1121 my($struct) = shift;
1124 return unless defined $struct->{ELEMENTS};
1126 # see if the structure contains a conformant array. If it
1127 # does, then it must be the last element of the structure, and
1128 # we need to pull the conformant length early, as it fits on
1129 # the wire before the structure (and even before the structure
1131 my $e = $struct->{ELEMENTS}[-1];
1132 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
1136 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1137 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1141 if (defined $conform_e) {
1143 pidl "uint32_t _conformant_size;";
1144 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
1147 # declare any internal pointers we need
1148 foreach my $e (@{$struct->{ELEMENTS}}) {
1149 if (need_wire_pointer($e)) {
1150 pidl "uint32_t _ptr_$e->{NAME};";
1154 start_flags($struct);
1156 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1158 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1160 if (defined $conform_e) {
1161 pidl "NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &$conform_e->{CONFORMANT_SIZE}));";
1164 my $align = find_largest_alignment($struct);
1165 pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
1167 foreach my $e (@{$struct->{ELEMENTS}}) {
1168 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1172 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1173 foreach my $e (@{$struct->{ELEMENTS}}) {
1174 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1177 foreach my $e (@{$struct->{ELEMENTS}}) {
1178 CheckArraySizes($e, "r->");
1181 pidl "ndr_pull_struct_end(ndr);";
1188 #####################################################################
1189 # calculate size of ndr struct
1190 sub ParseStructNdrSize($)
1193 my $static = fn_prefix($t);
1196 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1199 if (my $flags = util::has_property($t, "flag")) {
1200 pidl "flags |= $flags;";
1202 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1208 $typefamily{STRUCT} = {
1209 PUSH_FN_BODY => \&ParseStructPush,
1210 PULL_FN_BODY => \&ParseStructPull,
1211 PRINT_FN_BODY => \&ParseStructPrint,
1212 SIZE_FN => \&ParseStructNdrSize,
1213 ALIGN => \&find_largest_alignment
1216 #####################################################################
1217 # calculate size of ndr struct
1218 sub ParseUnionNdrSize($)
1221 my $static = fn_prefix($t);
1224 pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1227 if (my $flags = util::has_property($t, "flag")) {
1228 pidl "flags |= $flags;";
1230 pidl "return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1236 #####################################################################
1237 # parse a union - push side
1238 sub ParseUnionPush($)
1241 my $have_default = 0;
1245 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1247 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1249 # my $align = union_alignment($e);
1250 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1252 pidl "switch (level) {";
1254 foreach my $el (@{$e->{ELEMENTS}}) {
1255 if (util::has_property($el, "default")) {
1259 pidl "case $el->{PROPERTIES}->{case}:";
1262 if ($el->{TYPE} ne "EMPTY") {
1264 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1270 if (! $have_default) {
1272 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1277 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1278 pidl "switch (level) {";
1280 foreach my $el (@{$e->{ELEMENTS}}) {
1281 if (util::has_property($el, "default")) {
1284 pidl "case $el->{PROPERTIES}->{case}:";
1286 if ($el->{TYPE} ne "EMPTY") {
1288 ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
1294 if (! $have_default) {
1296 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1300 pidl "ndr_push_struct_end(ndr);";
1305 #####################################################################
1307 sub ParseUnionPrint($)
1310 my $have_default = 0;
1311 my($name) = $e->{PARENT}->{NAME};
1313 pidl "ndr_print_union(ndr, name, level, \"$name\");";
1316 pidl "switch (level) {";
1318 foreach my $el (@{$e->{ELEMENTS}}) {
1319 if (util::has_property($el, "default")) {
1323 pidl "case $el->{PROPERTIES}->{case}:";
1325 if ($el->{TYPE} ne "EMPTY") {
1327 ParseElementPrintScalar($el, "r->");
1333 if (! $have_default) {
1335 pidl "\tndr_print_bad_level(ndr, name, level);";
1343 #####################################################################
1344 # parse a union - pull side
1345 sub ParseUnionPull($)
1348 my $have_default = 0;
1352 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1354 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1356 # my $align = union_alignment($e);
1357 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1359 pidl "switch (level) {";
1361 foreach my $el (@{$e->{ELEMENTS}}) {
1362 if (util::has_property($el, "default")) {
1366 pidl "case $el->{PROPERTIES}->{case}: {";
1368 if ($el->{TYPE} ne "EMPTY") {
1370 if ($el->{POINTERS}) {
1371 pidl "uint32_t _ptr_$el->{NAME};";
1373 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1379 if (! $have_default) {
1381 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1386 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1387 pidl "switch (level) {";
1389 foreach my $el (@{$e->{ELEMENTS}}) {
1390 if (util::has_property($el, "default")) {
1393 pidl "case $el->{PROPERTIES}->{case}:";
1395 if ($el->{TYPE} ne "EMPTY") {
1397 ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
1403 if (! $have_default) {
1405 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1409 pidl "ndr_pull_struct_end(ndr);";
1414 $typefamily{UNION} = {
1415 PUSH_FN_BODY => \&ParseUnionPush,
1416 PULL_FN_BODY => \&ParseUnionPull,
1417 PRINT_FN_BODY => \&ParseUnionPrint,
1418 SIZE_FN => \&ParseUnionNdrSize,
1419 ALIGN => \&find_largest_alignment
1423 #####################################################################
1424 # parse a typedef - push side
1425 sub ParseTypedefPush($)
1428 my $static = fn_prefix($e);
1430 if (! needed::is_needed("push_$e->{NAME}")) {
1431 # print "push_$e->{NAME} not needed\n";
1436 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1437 $args = "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1440 if ($e->{DATA}->{TYPE} eq "UNION") {
1441 $args = "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1444 if ($e->{DATA}->{TYPE} eq "ENUM") {
1445 $args = "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1448 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1449 my $type_decl = util::bitmap_type_decl($e->{DATA});
1450 $args = "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1453 pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1457 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA});
1458 pidl "return NT_STATUS_OK;";
1464 #####################################################################
1465 # parse a typedef - pull side
1466 sub ParseTypedefPull($)
1469 my $static = fn_prefix($e);
1471 if (! needed::is_needed("pull_$e->{NAME}")) {
1472 # print "pull_$e->{NAME} not needed\n";
1478 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1479 $args = "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1482 if ($e->{DATA}->{TYPE} eq "UNION") {
1483 $args = "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1486 if ($e->{DATA}->{TYPE} eq "ENUM") {
1487 $args = "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1490 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1491 my $type_decl = util::bitmap_type_decl($e->{DATA});
1492 $args = "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1495 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1499 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA});
1500 pidl "return NT_STATUS_OK;";
1506 #####################################################################
1507 # parse a typedef - print side
1508 sub ParseTypedefPrint($)
1512 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1513 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1516 if ($e->{DATA}->{TYPE} eq "UNION") {
1517 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1520 if ($e->{DATA}->{TYPE} eq "ENUM") {
1521 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1524 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1525 my $type_decl = util::bitmap_type_decl($e->{DATA});
1526 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1531 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA});
1536 #####################################################################
1537 ## calculate the size of a structure
1538 sub ParseTypedefNdrSize($)
1541 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1545 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN}($t);
1548 #####################################################################
1549 # parse a function - print side
1550 sub ParseFunctionPrint($)
1554 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1557 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1558 pidl "ndr->depth++;";
1560 pidl "if (flags & NDR_SET_VALUES) {";
1561 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1564 pidl "if (flags & NDR_IN) {";
1566 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1567 pidl "ndr->depth++;";
1569 foreach my $e (@{$fn->{ELEMENTS}}) {
1570 if (util::has_property($e, "in")) {
1571 ParseElementPrintScalar($e, "r->in.");
1574 pidl "ndr->depth--;";
1578 pidl "if (flags & NDR_OUT) {";
1580 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1581 pidl "ndr->depth++;";
1582 foreach my $e (@{$fn->{ELEMENTS}}) {
1583 if (util::has_property($e, "out")) {
1584 ParseElementPrintScalar($e, "r->out.");
1587 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1589 $cprefix = "" if (is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
1590 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1592 pidl "ndr->depth--;";
1596 pidl "ndr->depth--;";
1602 #####################################################################
1603 # parse a function element
1604 sub ParseFunctionElementPush($$)
1609 if (util::array_size($e)) {
1610 if (need_wire_pointer($e)) {
1611 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1612 pidl "if (r->$inout.$e->{NAME}) {";
1614 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1618 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1621 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1623 if ($e->{POINTERS}) {
1624 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1629 #####################################################################
1631 sub ParseFunctionPush($)
1634 my $static = fn_prefix($fn);
1636 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1640 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1643 foreach my $e (@{$fn->{ELEMENTS}}) {
1644 if (util::has_property($e, "in")) {
1645 ParseFunctionElementPush($e, "in");
1650 pidl "if (!(flags & NDR_OUT)) goto done;";
1653 foreach my $e (@{$fn->{ELEMENTS}}) {
1654 if (util::has_property($e, "out")) {
1655 ParseFunctionElementPush($e, "out");
1659 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1660 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1664 pidl "return NT_STATUS_OK;";
1670 #####################################################################
1671 # parse a function element
1672 sub ParseFunctionElementPull($$)
1677 if (util::array_size($e)) {
1678 if (need_wire_pointer($e)) {
1679 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1680 pidl "r->$inout.$e->{NAME} = NULL;";
1681 pidl "if (_ptr_$e->{NAME}) {";
1683 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1684 pidl "if (r->$inout.$e->{NAME}) {";
1690 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1694 if ($inout eq "out" && util::has_property($e, "ref")) {
1695 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1696 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1699 if ($inout eq "in" && util::has_property($e, "ref")) {
1700 pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
1703 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1704 if ($e->{POINTERS}) {
1705 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1710 ############################################################
1711 # allocate ref variables
1712 sub AllocateRefVars($)
1715 my $asize = util::array_size($e);
1717 # note that if the variable is also an "in"
1718 # variable then we copy the initial value from
1721 if (!defined $asize) {
1722 # its a simple variable
1723 pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
1724 if (util::has_property($e, "in")) {
1725 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1727 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
1733 my $size = ParseExpr($e, $asize, "r->out.");
1734 check_null_pointer($size);
1735 pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1736 if (util::has_property($e, "in")) {
1737 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1739 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1743 #####################################################################
1745 sub ParseFunctionPull($)
1748 my $static = fn_prefix($fn);
1750 # pull function args
1751 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1755 # declare any internal pointers we need
1756 foreach my $e (@{$fn->{ELEMENTS}}) {
1757 if (need_wire_pointer($e)) {
1758 pidl "uint32_t _ptr_$e->{NAME};";
1762 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1765 # auto-init the out section of a structure. I originally argued that
1766 # this was a bad idea as it hides bugs, but coping correctly
1767 # with initialisation and not wiping ref vars is turning
1768 # out to be too tricky (tridge)
1769 foreach my $e (@{$fn->{ELEMENTS}}) {
1770 if (util::has_property($e, "out")) {
1771 pidl "ZERO_STRUCT(r->out);";
1777 foreach my $e (@{$fn->{ELEMENTS}}) {
1778 if (util::has_property($e, "in")) {
1779 ParseFunctionElementPull($e, "in");
1781 # we need to allocate any reference output variables, so that
1782 # a dcerpc backend can be sure they are non-null
1783 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1784 AllocateRefVars($e);
1788 foreach my $e (@{$fn->{ELEMENTS}}) {
1789 if (util::has_property($e, "in")) {
1790 CheckArraySizes($e, "r->in.");
1795 pidl "if (!(flags & NDR_OUT)) goto done;";
1798 foreach my $e (@{$fn->{ELEMENTS}}) {
1799 if (util::has_property($e, "out")) {
1800 ParseFunctionElementPull($e, "out");
1804 foreach my $e (@{$fn->{ELEMENTS}}) {
1805 if (util::has_property($e, "out")) {
1806 CheckArraySizes($e, "r->out.");
1810 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1811 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1816 pidl "return NT_STATUS_OK;";
1822 #####################################################################
1823 # produce a function call table
1824 sub FunctionTable($)
1826 my($interface) = shift;
1827 my($data) = $interface->{INHERITED_DATA};
1829 my $uname = uc $interface->{NAME};
1831 foreach my $d (@{$data}) {
1832 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1835 return if ($count == 0);
1837 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1838 foreach my $d (@{$data}) {
1839 if ($d->{TYPE} eq "FUNCTION") {
1841 pidl "\t\t\"$d->{NAME}\",";
1842 pidl "\t\tsizeof(struct $d->{NAME}),";
1843 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1844 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1845 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1849 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
1853 # If no endpoint is set, default to the interface name as a named pipe
1854 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1855 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1858 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1859 my $endpoint_count = $#e + 1;
1861 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
1862 foreach my $ep (@e) {
1868 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1869 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1873 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
1874 pidl "\t\"$interface->{NAME}\",";
1875 pidl "\tDCERPC_$uname\_UUID,";
1876 pidl "\tDCERPC_$uname\_VERSION,";
1877 pidl "\tDCERPC_$uname\_HELPSTRING,";
1879 pidl "\t$interface->{NAME}\_calls,";
1880 pidl "\t&$interface->{NAME}\_endpoints";
1884 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
1886 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
1891 #####################################################################
1892 # parse the interface definitions
1893 sub ParseInterface($)
1895 my($interface) = shift;
1896 my($data) = $interface->{DATA};
1899 foreach my $d (@{$data}) {
1900 ($d->{TYPE} eq "TYPEDEF") &&
1901 ParseTypedefPush($d);
1902 ($d->{TYPE} eq "FUNCTION") &&
1903 ParseFunctionPush($d);
1907 foreach my $d (@{$data}) {
1908 ($d->{TYPE} eq "TYPEDEF") &&
1909 ParseTypedefPull($d);
1910 ($d->{TYPE} eq "FUNCTION") &&
1911 ParseFunctionPull($d);
1915 foreach my $d (@{$data}) {
1916 if ($d->{TYPE} eq "TYPEDEF" &&
1917 !util::has_property($d, "noprint")) {
1918 ParseTypedefPrint($d);
1920 if ($d->{TYPE} eq "FUNCTION" &&
1921 !util::has_property($d, "noprint")) {
1922 ParseFunctionPrint($d);
1927 foreach my $d (@{$data}) {
1928 ($d->{TYPE} eq "TYPEDEF") &&
1929 ParseTypedefNdrSize($d);
1932 FunctionTable($interface);
1935 sub RegistrationFunction($$)
1938 my $filename = shift;
1940 $filename =~ /.*\/ndr_(.*).c/;
1942 pidl "NTSTATUS dcerpc_$basename\_init(void)";
1945 pidl "NTSTATUS status = NT_STATUS_OK;";
1946 foreach my $interface (@{$idl}) {
1947 next if $interface->{TYPE} ne "INTERFACE";
1949 my $data = $interface->{INHERITED_DATA};
1951 foreach my $d (@{$data}) {
1952 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1955 next if ($count == 0);
1957 pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
1958 pidl "if (NT_STATUS_IS_ERR(status)) {";
1959 pidl "\treturn status;";
1963 pidl "return status;";
1969 sub CheckPointerTypes($$)
1972 my $default = shift;
1974 foreach my $e (@{$s->{ELEMENTS}}) {
1975 if ($e->{POINTERS}) {
1976 if (not defined(pointer_type($e))) {
1977 $e->{PROPERTIES}->{$default} = 1;
1980 if (pointer_type($e) eq "ptr") {
1981 print "Warning: ptr is not supported by pidl yet\n";
1987 sub LoadInterface($)
1991 if (not util::has_property($x, "pointer_default")) {
1992 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
1993 # and "unique" in Microsoft Extensions mode (default)
1994 $x->{PROPERTIES}->{pointer_default} = "unique";
1997 foreach my $d (@{$x->{DATA}}) {
1998 if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
1999 $typedefs{$d->{NAME}} = $d;
2000 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
2001 CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
2004 if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
2005 $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
2008 if ($d->{TYPE} eq "FUNCTION") {
2009 CheckPointerTypes($d,
2010 $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
2016 # Add ORPC specific bits to an interface.
2017 sub InterfaceORPC($)
2020 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
2021 # for 'object' interfaces
2022 if (util::has_property($x, "object")) {
2023 foreach my $e (@{$x->{DATA}}) {
2024 if($e->{TYPE} eq "FUNCTION") {
2025 $e->{PROPERTIES}->{object} = 1;
2026 unshift(@{$e->{ELEMENTS}},
2027 { 'NAME' => 'ORPCthis',
2029 'PROPERTIES' => { 'in' => '1' },
2030 'TYPE' => 'ORPCTHIS'
2032 unshift(@{$e->{ELEMENTS}},
2033 { 'NAME' => 'ORPCthat',
2035 'PROPERTIES' => { 'out' => '1' },
2036 'TYPE' => 'ORPCTHAT'
2047 foreach my $x (@{$idl}) {
2052 #####################################################################
2053 # parse a parsed IDL structure back into an IDL file
2057 my($filename) = shift;
2058 my $h_filename = $filename;
2063 if ($h_filename =~ /(.*)\.c/) {
2064 $h_filename = "$1.h";
2067 pidl "/* parser auto-generated by pidl */";
2069 pidl "#include \"includes.h\"";
2070 pidl "#include \"$h_filename\"";
2073 foreach my $x (@{$idl}) {
2074 if ($x->{TYPE} eq "INTERFACE") {
2075 needed::BuildNeeded($x);
2080 RegistrationFunction($idl, $filename);
2085 RegisterPrimitives();