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,
53 foreach my $k (keys %type_alignments) {
59 ALIGN => $type_alignments{$k}
69 if (my $dt = $typedefs{$type}->{DATA}->{TYPE}) {
70 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
80 return undef unless $e->{POINTERS};
82 return "ref" if (util::has_property($e, "ref"));
83 return "ptr" if (util::has_property($e, "ptr"));
84 return "unique" if (util::has_property($e, "unique"));
85 return "relative" if (util::has_property($e, "relative"));
90 # determine if an element needs a reference pointer on the wire
91 # in its NDR representation
92 sub need_wire_pointer($)
97 return 0 unless ($pt = pointer_type($e));
106 # determine if an element is a pure scalar. pure scalars do not
107 # have a "buffers" section in NDR
108 sub is_pure_scalar($)
111 if (util::has_property($e, "ref")) {
114 if (is_scalar_type($e->{TYPE}) &&
116 !util::array_size($e)) {
122 # see if a variable needs to be allocated by the NDR subsystem on pull
127 if (util::has_property($e, "ref")) {
131 if ($e->{POINTERS} || util::array_size($e)) {
139 # determine the C prefix used to refer to a variable when passing to a push
140 # function. This will be '*' for pointers to scalar types, '' for scalar
141 # types and normal pointers and '&' for pass-by-reference structures
146 if ($e->{TYPE} =~ "string") {
150 if (is_scalar_type($e->{TYPE}) &&
154 if (!is_scalar_type($e->{TYPE}) &&
156 !util::array_size($e)) {
163 # determine the C prefix used to refer to a variable when passing to a pull
169 if (!$e->{POINTERS} && !util::array_size($e)) {
173 if ($e->{TYPE} =~ "string") {
198 $tabs = substr($tabs, 0, -1);
201 ###################################
202 # find a sibling var in a structure
207 my($fn) = $e->{PARENT};
209 if ($name =~ /\*(.*)/) {
213 if ($fn->{TYPE} eq "FUNCTION") {
214 for my $e2 (@{$fn->{ELEMENTS}}) {
215 if ($e2->{NAME} eq $name) {
221 for my $e2 (@{$fn->{ELEMENTS}}) {
222 if ($e2->{NAME} eq $name) {
226 die "invalid sibling '$name'";
229 ####################################################################
230 # work out the name of a size_is() variable
235 my($var_prefix) = shift;
237 my($fn) = $e->{PARENT};
239 if (util::is_constant($size)) {
243 if ($size =~ /ndr->|\(/) {
249 if ($size =~ /\*(.*)/) {
254 if ($fn->{TYPE} ne "FUNCTION") {
255 return $prefix . "r->$size";
258 my $e2 = find_sibling($e, $size);
260 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
261 return $prefix . "$var_prefix$size";
263 if (util::has_property($e2, "in")) {
264 return $prefix . "r->in.$size";
266 if (util::has_property($e2, "out")) {
267 return $prefix . "r->out.$size";
270 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
273 #####################################################################
274 # check that a variable we get from ParseExpr isn't a null pointer
275 sub check_null_pointer($)
278 if ($size =~ /^\*/) {
279 my $size2 = substr($size, 1);
280 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
284 #####################################################################
285 # check that a variable we get from ParseExpr isn't a null pointer
286 # void return varient
287 sub check_null_pointer_void($)
290 if ($size =~ /^\*/) {
291 my $size2 = substr($size, 1);
292 pidl "if ($size2 == NULL) return;";
297 #####################################################################
298 # work out is a parse function should be declared static or not
302 if ($fn->{TYPE} eq "TYPEDEF") {
303 if (util::has_property($fn, "public")) {
308 if ($fn->{TYPE} eq "FUNCTION") {
309 if (util::has_property($fn, "public")) {
317 ###################################################################
318 # setup any special flags for an element or structure
322 my $flags = util::has_property($e, "flag");
323 if (defined $flags) {
324 pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
325 pidl "ndr_set_flags(&ndr->flags, $flags);";
329 ###################################################################
330 # end any special flags for an element or structure
334 my $flags = util::has_property($e, "flag");
335 if (defined $flags) {
336 pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
340 #####################################################################
341 # work out the correct alignment for a structure or union
342 sub find_largest_alignment($)
347 for my $e (@{$s->{ELEMENTS}}) {
350 if (need_wire_pointer($e)) {
353 $a = align_type($e->{TYPE});
356 $align = $a if ($align < $a);
362 #####################################################################
368 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA}->{TYPE})) {
369 # it must be an external type - all we can do is guess
370 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
374 my $dt = $typedefs{$e}->{DATA};
376 return $dt->{ALIGN} if ($dt->{ALIGN});
377 return $typefamily{$dt->{TYPE}}->{ALIGN}($dt);
380 #####################################################################
381 # parse an array - push side
382 sub ParseArrayPush($$$)
385 my $var_prefix = shift;
386 my $ndr_flags = shift;
388 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
390 if (defined $e->{CONFORMANT_SIZE}) {
391 # the conformant size has already been pushed
392 } elsif (!util::is_inline_array($e)) {
393 # we need to emit the array size
394 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
397 if (my $length = util::has_property($e, "length_is")) {
398 $length = ParseExpr($e, $length, $var_prefix);
399 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
400 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
404 if (is_scalar_type($e->{TYPE})) {
405 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
407 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}));";
411 #####################################################################
413 sub ParseArrayPrint($$)
416 my $var_prefix = shift;
417 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
418 my $length = util::has_property($e, "length_is");
420 if (defined $length) {
421 $size = ParseExpr($e, $length, $var_prefix);
424 if (is_scalar_type($e->{TYPE})) {
425 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
427 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});";
431 #####################################################################
432 # check the size_is and length_is constraints
433 sub CheckArraySizes($$)
436 my $var_prefix = shift;
438 if (!defined $e->{CONFORMANT_SIZE} &&
439 util::has_property($e, "size_is")) {
440 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
441 pidl "if ($var_prefix$e->{NAME}) {";
443 check_null_pointer($size);
444 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
449 if (my $length = util::has_property($e, "length_is")) {
450 $length = ParseExpr($e, $length, $var_prefix);
451 pidl "if ($var_prefix$e->{NAME}) {";
453 check_null_pointer($length);
454 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
460 #####################################################################
461 # parse an array - pull side
462 sub ParseArrayPull($$$)
465 my $var_prefix = shift;
466 my $ndr_flags = shift;
468 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
469 my $alloc_size = $size;
471 # if this is a conformant array then we use that size to allocate, and make sure
472 # we allocate enough to pull the elements
473 if (defined $e->{CONFORMANT_SIZE}) {
474 $alloc_size = $e->{CONFORMANT_SIZE};
475 check_null_pointer($size);
476 pidl "if ($size > $alloc_size) {";
478 pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
481 } elsif (!util::is_inline_array($e)) {
482 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
483 my $size2 = substr($size, 1);
484 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
487 # non fixed arrays encode the size just before the array
488 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
489 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
492 if ((need_alloc($e) && !util::is_fixed_array($e)) ||
493 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
494 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
495 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
499 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
500 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
501 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
503 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
509 if (my $length = util::has_property($e, "length_is")) {
510 pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
511 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
514 check_null_pointer($size);
515 if (is_scalar_type($e->{TYPE})) {
516 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
518 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}));";
522 #####################################################################
523 # parse scalars in a structure element
524 sub ParseElementPushScalar($$$)
527 my($var_prefix) = shift;
528 my($ndr_flags) = shift;
529 my $cprefix = c_push_prefix($e);
530 my $sub_size = util::has_property($e, "subcontext");
534 if (my $value = util::has_property($e, "value")) {
535 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
538 if (util::has_property($e, "relative")) {
539 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
540 } elsif (util::is_inline_array($e)) {
541 ParseArrayPush($e, "r->", "NDR_SCALARS");
542 } elsif (need_wire_pointer($e)) {
543 ParseElementPushPtr($e, $var_prefix, $ndr_flags);
544 } elsif (need_alloc($e)) {
545 # no scalar component
546 } elsif (my $switch = util::has_property($e, "switch_is")) {
547 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
548 } elsif (defined $sub_size) {
549 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}));";
551 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
557 #####################################################################
558 # parse a pointer in a struct element or function
559 sub ParseElementPushPtr($$$)
562 my $var_prefix = shift;
563 my $ndr_flags = shift;
565 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
569 #####################################################################
570 # print scalars in a structure element
571 sub ParseElementPrintScalar($$)
574 my($var_prefix) = shift;
575 my $cprefix = c_push_prefix($e);
577 if (util::has_property($e, "noprint")) {
581 if (my $value = util::has_property($e, "value")) {
582 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
584 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
589 if (util::is_fixed_array($e)) {
590 ParseElementPrintBuffer($e, $var_prefix);
591 } elsif ($e->{POINTERS} || util::array_size($e)) {
592 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
593 pidl "ndr->depth++;";
594 ParseElementPrintBuffer($e, $var_prefix);
595 pidl "ndr->depth--;";
596 } elsif (my $switch = util::has_property($e, "switch_is")) {
597 ParseElementPrintSwitch($e, $var_prefix, $switch);
599 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
603 #####################################################################
604 # parse scalars in a structure element - pull size
605 sub ParseElementPullSwitch($$$$)
608 my($var_prefix) = shift;
609 my($ndr_flags) = shift;
611 my $switch_var = ParseExpr($e, $switch, $var_prefix);
613 my $cprefix = c_pull_prefix($e);
615 my $utype = $typedefs{$e->{TYPE}};
617 check_null_pointer($switch_var);
619 if (!defined $utype ||
620 !util::has_property($utype, "nodiscriminant")) {
621 my $e2 = find_sibling($e, $switch);
622 my $type_decl = util::map_type($e2->{TYPE});
623 pidl "if (($ndr_flags) & NDR_SCALARS) {";
625 if ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "ENUM") {
626 $type_decl = util::enum_type_decl($e2);
627 } elsif ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "BITMAP") {
628 $type_decl = util::bitmap_type_decl($e2);
630 pidl "$type_decl _level;";
631 pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
632 if ($switch_var =~ /r->in/) {
633 pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
636 pidl "if (_level != $switch_var) {";
639 pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
641 if ($switch_var =~ /r->/) {
642 pidl "} else { $switch_var = _level; }";
650 my $sub_size = util::has_property($e, "subcontext");
651 if (defined $sub_size) {
652 pidl "if (($ndr_flags) & NDR_SCALARS) {";
654 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}));";
658 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
664 #####################################################################
665 # push switch element
666 sub ParseElementPushSwitch($$$$)
669 my($var_prefix) = shift;
670 my($ndr_flags) = shift;
672 my $switch_var = ParseExpr($e, $switch, $var_prefix);
673 my $cprefix = c_push_prefix($e);
675 check_null_pointer($switch_var);
677 my $utype = $typedefs{$e->{TYPE}};
678 if (!defined $utype ||
679 !util::has_property($utype, "nodiscriminant")) {
680 my $e2 = find_sibling($e, $switch);
681 pidl "if (($ndr_flags) & NDR_SCALARS) {";
683 pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
688 my $sub_size = util::has_property($e, "subcontext");
689 if (defined $sub_size) {
690 pidl "if(($ndr_flags) & NDR_SCALARS) {";
692 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}));";
696 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
700 #####################################################################
701 # print scalars in a structure element
702 sub ParseElementPrintSwitch($$$)
705 my($var_prefix) = shift;
707 my $switch_var = ParseExpr($e, $switch, $var_prefix);
708 my $cprefix = c_push_prefix($e);
710 check_null_pointer_void($switch_var);
712 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
716 #####################################################################
717 # parse scalars in a structure element - pull size
718 sub ParseElementPullScalar($$$)
721 my($var_prefix) = shift;
722 my($ndr_flags) = shift;
723 my $cprefix = c_pull_prefix($e);
724 my $sub_size = util::has_property($e, "subcontext");
728 if (util::is_inline_array($e)) {
729 ParseArrayPull($e, "r->", "NDR_SCALARS");
730 } elsif (need_wire_pointer($e)) {
731 ParseElementPullPtr($e, $var_prefix, $ndr_flags);
732 } elsif (need_alloc($e)) {
733 # no scalar component
734 } elsif (my $switch = util::has_property($e, "switch_is")) {
735 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
736 } elsif (defined $sub_size) {
737 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}));";
739 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
741 if (my $range = util::has_property($e, "range")) {
742 my ($low, $high) = split(/ /, $range, 2);
743 pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
744 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
751 #####################################################################
752 # parse a pointer in a struct element or function
753 sub ParseElementPullPtr($$$)
756 my($var_prefix) = shift;
757 my($ndr_flags) = shift;
759 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
760 pidl "if (_ptr_$e->{NAME}) {";
762 pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
763 if (util::has_property($e, "relative")) {
764 pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
768 pidl "\t$var_prefix$e->{NAME} = NULL;";
772 #####################################################################
773 # parse buffers in a structure element
774 sub ParseElementPushBuffer($$$)
777 my($var_prefix) = shift;
778 my($ndr_flags) = shift;
779 my $cprefix = c_push_prefix($e);
780 my $sub_size = util::has_property($e, "subcontext");
782 if (is_pure_scalar($e)) {
788 if (need_wire_pointer($e)) {
789 pidl "if ($var_prefix$e->{NAME}) {";
791 if (util::has_property($e, "relative")) {
792 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
796 if (util::is_inline_array($e)) {
797 ParseArrayPush($e, "r->", "NDR_BUFFERS");
798 } elsif (util::array_size($e)) {
799 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
800 } elsif (my $switch = util::has_property($e, "switch_is")) {
801 if ($e->{POINTERS}) {
802 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
804 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
806 } elsif (defined $sub_size) {
807 if ($e->{POINTERS}) {
808 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}));";
810 } elsif ($e->{POINTERS}) {
811 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
813 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
816 if (need_wire_pointer($e)) {
824 #####################################################################
825 # print buffers in a structure element
826 sub ParseElementPrintBuffer($$)
829 my($var_prefix) = shift;
830 my $cprefix = c_push_prefix($e);
832 if (need_wire_pointer($e)) {
833 pidl "if ($var_prefix$e->{NAME}) {";
837 if (util::array_size($e)) {
838 ParseArrayPrint($e, $var_prefix)
839 } elsif (my $switch = util::has_property($e, "switch_is")) {
840 ParseElementPrintSwitch($e, $var_prefix, $switch);
842 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
845 if (need_wire_pointer($e)) {
852 #####################################################################
853 # parse buffers in a structure element - pull side
854 sub ParseElementPullBuffer($$$)
857 my($var_prefix) = shift;
858 my($ndr_flags) = shift;
859 my $cprefix = c_pull_prefix($e);
860 my $sub_size = util::has_property($e, "subcontext");
862 if (is_pure_scalar($e)) {
868 if (need_wire_pointer($e)) {
869 pidl "if ($var_prefix$e->{NAME}) {";
871 if (util::has_property($e, "relative")) {
872 pidl "struct ndr_pull_save _relative_save;";
873 pidl "ndr_pull_save(ndr, &_relative_save);";
874 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
878 if (util::is_inline_array($e)) {
879 ParseArrayPull($e, "r->", "NDR_BUFFERS");
880 } elsif (util::array_size($e)) {
881 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
882 } elsif (my $switch = util::has_property($e, "switch_is")) {
883 if ($e->{POINTERS}) {
884 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
886 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
888 } elsif (defined $sub_size) {
889 if ($e->{POINTERS}) {
890 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}));";
892 } elsif ($e->{POINTERS}) {
893 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
895 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
898 if (need_wire_pointer($e)) {
899 if (util::has_property($e, "relative")) {
900 pidl "ndr_pull_restore(ndr, &_relative_save);";
909 #####################################################################
911 sub ParseStructPush($)
915 if (! defined $struct->{ELEMENTS}) {
919 start_flags($struct);
921 # see if the structure contains a conformant array. If it
922 # does, then it must be the last element of the structure, and
923 # we need to push the conformant length early, as it fits on
924 # the wire before the structure (and even before the structure
926 my $e = $struct->{ELEMENTS}[-1];
927 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
928 my $size = ParseExpr($e, util::array_size($e), "r->");
929 $e->{CONFORMANT_SIZE} = $size;
930 check_null_pointer($size);
931 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
934 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
935 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
936 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
939 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
941 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
943 my $align = find_largest_alignment($struct);
944 pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
946 foreach my $e (@{$struct->{ELEMENTS}}) {
947 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
951 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
952 foreach my $e (@{$struct->{ELEMENTS}}) {
953 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
956 pidl "ndr_push_struct_end(ndr);";
964 #####################################################################
965 # generate a push function for an enum
969 my($type_fn) = util::enum_type_fn($enum);
973 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
978 #####################################################################
979 # generate a pull function for an enum
983 my($type_fn) = util::enum_type_fn($enum);
984 my($type_v_decl) = util::map_type(util::enum_type_fn($enum));
986 pidl "$type_v_decl v;";
988 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
994 #####################################################################
995 # generate a print function for an enum
996 sub ParseEnumPrint($)
1000 pidl "const char *val = NULL;";
1005 pidl "switch (r) {";
1007 my $els = \@{$enum->{ELEMENTS}};
1008 foreach my $i (0 .. $#{$els}) {
1009 my $e = ${$els}[$i];
1011 if ($e =~ /^(.*)=/) {
1014 pidl "case $e: val = \"$e\"; break;";
1020 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1025 $typefamily{ENUM} = {
1026 PUSH_FN_BODY => \&ParseEnumPush,
1027 PULL_FN_BODY => \&ParseEnumPull,
1028 PRINT_FN_BODY => \&ParseEnumPrint,
1029 ALIGN => sub { return align_type(util::enum_type_fn(shift)); }
1032 #####################################################################
1033 # generate a push function for a bitmap
1034 sub ParseBitmapPush($)
1036 my($bitmap) = shift;
1037 my($type_fn) = util::bitmap_type_fn($bitmap);
1039 start_flags($bitmap);
1041 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
1046 #####################################################################
1047 # generate a pull function for an bitmap
1048 sub ParseBitmapPull($)
1050 my($bitmap) = shift;
1051 my($type_fn) = util::bitmap_type_fn($bitmap);
1052 my($type_decl) = util::bitmap_type_decl($bitmap);
1054 pidl "$type_decl v;";
1055 start_flags($bitmap);
1056 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
1062 #####################################################################
1063 # generate a print function for an bitmap
1064 sub ParseBitmapPrintElement($$)
1067 my($bitmap) = shift;
1068 my($type_decl) = util::bitmap_type_decl($bitmap);
1069 my($type_fn) = util::bitmap_type_fn($bitmap);
1070 my($name) = $bitmap->{PARENT}->{NAME};
1073 if ($e =~ /^(\w+) .*$/) {
1076 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1079 pidl "ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);";
1082 #####################################################################
1083 # generate a print function for an bitmap
1084 sub ParseBitmapPrint($)
1086 my($bitmap) = shift;
1087 my($type_decl) = util::bitmap_type_decl($bitmap);
1088 my($type_fn) = util::bitmap_type_fn($bitmap);
1090 start_flags($bitmap);
1092 pidl "ndr_print_$type_fn(ndr, name, r);";
1094 pidl "ndr->depth++;";
1095 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1096 ParseBitmapPrintElement($e, $bitmap);
1098 pidl "ndr->depth--;";
1103 $typefamily{BITMAP} = {
1104 PUSH_FN_BODY => \&ParseBitmapPush,
1105 PULL_FN_BODY => \&ParseBitmapPull,
1106 PRINT_FN_BODY => \&ParseBitmapPrint,
1107 ALIGN => sub { return align_type(util::bitmap_type_fn(shift)); }
1110 #####################################################################
1111 # generate a struct print function
1112 sub ParseStructPrint($)
1114 my($struct) = shift;
1116 if (! defined $struct->{ELEMENTS}) {
1120 start_flags($struct);
1122 pidl "ndr->depth++;";
1123 foreach my $e (@{$struct->{ELEMENTS}}) {
1124 ParseElementPrintScalar($e, "r->");
1126 pidl "ndr->depth--;";
1131 #####################################################################
1132 # parse a struct - pull side
1133 sub ParseStructPull($)
1135 my($struct) = shift;
1138 if (! defined $struct->{ELEMENTS}) {
1142 # see if the structure contains a conformant array. If it
1143 # does, then it must be the last element of the structure, and
1144 # we need to pull the conformant length early, as it fits on
1145 # the wire before the structure (and even before the structure
1147 my $e = $struct->{ELEMENTS}[-1];
1148 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
1152 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1153 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1157 if (defined $conform_e) {
1159 pidl "uint32_t _conformant_size;";
1160 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
1163 # declare any internal pointers we need
1164 foreach my $e (@{$struct->{ELEMENTS}}) {
1165 if (need_wire_pointer($e)) {
1166 pidl "uint32_t _ptr_$e->{NAME};";
1170 start_flags($struct);
1172 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1174 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1176 if (defined $conform_e) {
1177 pidl "NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &$conform_e->{CONFORMANT_SIZE}));";
1180 my $align = find_largest_alignment($struct);
1181 pidl "NDR_CHECK(ndr_pull_align(ndr, $align));";
1183 foreach my $e (@{$struct->{ELEMENTS}}) {
1184 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1188 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1189 foreach my $e (@{$struct->{ELEMENTS}}) {
1190 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1193 foreach my $e (@{$struct->{ELEMENTS}}) {
1194 CheckArraySizes($e, "r->");
1197 pidl "ndr_pull_struct_end(ndr);";
1204 #####################################################################
1205 # calculate size of ndr struct
1206 sub ParseStructNdrSize($)
1209 my $static = fn_prefix($t);
1212 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1215 if (my $flags = util::has_property($t, "flag")) {
1216 pidl "flags |= $flags;";
1218 pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
1224 $typefamily{STRUCT} = {
1225 PUSH_FN_BODY => \&ParseStructPush,
1226 PULL_FN_BODY => \&ParseStructPull,
1227 PRINT_FN_BODY => \&ParseStructPrint,
1228 SIZE_FN => \&ParseStructNdrSize,
1229 ALIGN => \&find_largest_alignment
1232 #####################################################################
1233 # calculate size of ndr struct
1234 sub ParseUnionNdrSize($)
1237 my $static = fn_prefix($t);
1240 pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1243 if (my $flags = util::has_property($t, "flag")) {
1244 pidl "flags |= $flags;";
1246 pidl "return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
1252 #####################################################################
1253 # parse a union - push side
1254 sub ParseUnionPush($)
1257 my $have_default = 0;
1261 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1263 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
1265 # my $align = union_alignment($e);
1266 # pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
1268 pidl "switch (level) {";
1270 foreach my $el (@{$e->{ELEMENTS}}) {
1271 if (util::has_property($el, "default")) {
1275 pidl "case $el->{PROPERTIES}->{case}:";
1278 if ($el->{TYPE} ne "EMPTY") {
1280 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1286 if (! $have_default) {
1288 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1293 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1294 pidl "switch (level) {";
1296 foreach my $el (@{$e->{ELEMENTS}}) {
1297 if (util::has_property($el, "default")) {
1300 pidl "case $el->{PROPERTIES}->{case}:";
1302 if ($el->{TYPE} ne "EMPTY") {
1304 ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
1310 if (! $have_default) {
1312 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1316 pidl "ndr_push_struct_end(ndr);";
1321 #####################################################################
1323 sub ParseUnionPrint($)
1326 my $have_default = 0;
1330 pidl "switch (level) {";
1332 foreach my $el (@{$e->{ELEMENTS}}) {
1333 if (util::has_property($el, "default")) {
1337 pidl "case $el->{PROPERTIES}->{case}:";
1339 if ($el->{TYPE} ne "EMPTY") {
1341 ParseElementPrintScalar($el, "r->");
1347 if (! $have_default) {
1349 pidl "\tndr_print_bad_level(ndr, name, level);";
1357 #####################################################################
1358 # parse a union - pull side
1359 sub ParseUnionPull($)
1362 my $have_default = 0;
1366 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
1368 pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
1370 # my $align = union_alignment($e);
1371 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1373 pidl "switch (level) {";
1375 foreach my $el (@{$e->{ELEMENTS}}) {
1376 if (util::has_property($el, "default")) {
1380 pidl "case $el->{PROPERTIES}->{case}: {";
1382 if ($el->{TYPE} ne "EMPTY") {
1384 if ($el->{POINTERS}) {
1385 pidl "uint32_t _ptr_$el->{NAME};";
1387 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1393 if (! $have_default) {
1395 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1400 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1401 pidl "switch (level) {";
1403 foreach my $el (@{$e->{ELEMENTS}}) {
1404 if (util::has_property($el, "default")) {
1407 pidl "case $el->{PROPERTIES}->{case}:";
1409 if ($el->{TYPE} ne "EMPTY") {
1411 ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
1417 if (! $have_default) {
1419 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1423 pidl "ndr_pull_struct_end(ndr);";
1428 $typefamily{UNION} = {
1429 PUSH_FN_BODY => \&ParseUnionPush,
1430 PULL_FN_BODY => \&ParseUnionPull,
1431 PRINT_FN_BODY => \&ParseUnionPrint,
1432 SIZE_FN => \&ParseUnionNdrSize,
1433 ALIGN => \&find_largest_alignment
1437 #####################################################################
1438 # parse a typedef - push side
1439 sub ParseTypedefPush($)
1442 my $static = fn_prefix($e);
1444 if (! needed::is_needed("push_$e->{NAME}")) {
1445 # print "push_$e->{NAME} not needed\n";
1450 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1451 $args = "struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r";
1454 if ($e->{DATA}->{TYPE} eq "UNION") {
1455 $args = "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1458 if ($e->{DATA}->{TYPE} eq "ENUM") {
1459 $args = "struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r";
1462 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1463 my $type_decl = util::bitmap_type_decl($e->{DATA});
1464 $args = "struct ndr_push *ndr, int ndr_flags, $type_decl r";
1467 pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)";
1471 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}($e->{DATA});
1472 pidl "return NT_STATUS_OK;";
1478 #####################################################################
1479 # parse a typedef - pull side
1480 sub ParseTypedefPull($)
1483 my $static = fn_prefix($e);
1485 if (! needed::is_needed("pull_$e->{NAME}")) {
1486 # print "pull_$e->{NAME} not needed\n";
1492 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1493 $args = "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
1496 if ($e->{DATA}->{TYPE} eq "UNION") {
1497 $args = "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
1500 if ($e->{DATA}->{TYPE} eq "ENUM") {
1501 $args = "struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r";
1504 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1505 my $type_decl = util::bitmap_type_decl($e->{DATA});
1506 $args = "struct ndr_pull *ndr, int ndr_flags, $type_decl *r";
1509 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)";
1513 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}($e->{DATA});
1514 pidl "return NT_STATUS_OK;";
1520 #####################################################################
1521 # parse a typedef - print side
1522 sub ParseTypedefPrint($)
1526 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1527 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1530 pidl "ndr_print_struct(ndr, name, \"$e->{NAME}\");";
1533 if ($e->{DATA}->{TYPE} eq "UNION") {
1534 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1537 pidl "ndr_print_union(ndr, name, level, \"$e->{NAME}\");";
1540 if ($e->{DATA}->{TYPE} eq "ENUM") {
1541 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1546 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1547 my $type_decl = util::bitmap_type_decl($e->{DATA});
1548 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1553 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}($e->{DATA});
1558 #####################################################################
1559 ## calculate the size of a structure
1560 sub ParseTypedefNdrSize($)
1563 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1567 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN}($t);
1570 #####################################################################
1571 # parse a function - print side
1572 sub ParseFunctionPrint($)
1576 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1579 pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");";
1580 pidl "ndr->depth++;";
1582 pidl "if (flags & NDR_SET_VALUES) {";
1583 pidl "\tndr->flags |= LIBNDR_PRINT_SET_VALUES;";
1586 pidl "if (flags & NDR_IN) {";
1588 pidl "ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");";
1589 pidl "ndr->depth++;";
1591 foreach my $e (@{$fn->{ELEMENTS}}) {
1592 if (util::has_property($e, "in")) {
1593 ParseElementPrintScalar($e, "r->in.");
1596 pidl "ndr->depth--;";
1600 pidl "if (flags & NDR_OUT) {";
1602 pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");";
1603 pidl "ndr->depth++;";
1604 foreach my $e (@{$fn->{ELEMENTS}}) {
1605 if (util::has_property($e, "out")) {
1606 ParseElementPrintScalar($e, "r->out.");
1609 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1611 $cprefix = "" if (is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
1612 pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);";
1614 pidl "ndr->depth--;";
1618 pidl "ndr->depth--;";
1624 #####################################################################
1625 # parse a function element
1626 sub ParseFunctionElementPush($$)
1631 if (util::array_size($e)) {
1632 if (need_wire_pointer($e)) {
1633 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
1634 pidl "if (r->$inout.$e->{NAME}) {";
1636 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1640 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1643 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1645 if ($e->{POINTERS}) {
1646 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1651 #####################################################################
1653 sub ParseFunctionPush($)
1656 my $static = fn_prefix($fn);
1658 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1662 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1665 foreach my $e (@{$fn->{ELEMENTS}}) {
1666 if (util::has_property($e, "in")) {
1667 ParseFunctionElementPush($e, "in");
1672 pidl "if (!(flags & NDR_OUT)) goto done;";
1675 foreach my $e (@{$fn->{ELEMENTS}}) {
1676 if (util::has_property($e, "out")) {
1677 ParseFunctionElementPush($e, "out");
1681 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1682 pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));";
1686 pidl "return NT_STATUS_OK;";
1692 #####################################################################
1693 # parse a function element
1694 sub ParseFunctionElementPull($$)
1699 if (util::array_size($e)) {
1700 if (need_wire_pointer($e)) {
1701 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
1702 pidl "r->$inout.$e->{NAME} = NULL;";
1703 pidl "if (_ptr_$e->{NAME}) {";
1705 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1706 pidl "if (r->$inout.$e->{NAME}) {";
1712 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1716 if ($inout eq "out" && util::has_property($e, "ref")) {
1717 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
1718 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});";
1721 if ($inout eq "in" && util::has_property($e, "ref")) {
1722 pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});";
1725 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1726 if ($e->{POINTERS}) {
1727 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1732 ############################################################
1733 # allocate ref variables
1734 sub AllocateRefVars($)
1737 my $asize = util::array_size($e);
1739 # note that if the variable is also an "in"
1740 # variable then we copy the initial value from
1743 if (!defined $asize) {
1744 # its a simple variable
1745 pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
1746 if (util::has_property($e, "in")) {
1747 pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
1749 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
1755 my $size = ParseExpr($e, $asize, "r->out.");
1756 check_null_pointer($size);
1757 pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
1758 if (util::has_property($e, "in")) {
1759 pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));";
1761 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1765 #####################################################################
1767 sub ParseFunctionPull($)
1770 my $static = fn_prefix($fn);
1772 # pull function args
1773 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
1777 # declare any internal pointers we need
1778 foreach my $e (@{$fn->{ELEMENTS}}) {
1779 if (need_wire_pointer($e)) {
1780 pidl "uint32_t _ptr_$e->{NAME};";
1784 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1787 # auto-init the out section of a structure. I originally argued that
1788 # this was a bad idea as it hides bugs, but coping correctly
1789 # with initialisation and not wiping ref vars is turning
1790 # out to be too tricky (tridge)
1791 foreach my $e (@{$fn->{ELEMENTS}}) {
1792 if (util::has_property($e, "out")) {
1793 pidl "ZERO_STRUCT(r->out);";
1799 foreach my $e (@{$fn->{ELEMENTS}}) {
1800 if (util::has_property($e, "in")) {
1801 ParseFunctionElementPull($e, "in");
1803 # we need to allocate any reference output variables, so that
1804 # a dcerpc backend can be sure they are non-null
1805 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1806 AllocateRefVars($e);
1810 foreach my $e (@{$fn->{ELEMENTS}}) {
1811 if (util::has_property($e, "in")) {
1812 CheckArraySizes($e, "r->in.");
1817 pidl "if (!(flags & NDR_OUT)) goto done;";
1820 foreach my $e (@{$fn->{ELEMENTS}}) {
1821 if (util::has_property($e, "out")) {
1822 ParseFunctionElementPull($e, "out");
1826 foreach my $e (@{$fn->{ELEMENTS}}) {
1827 if (util::has_property($e, "out")) {
1828 CheckArraySizes($e, "r->out.");
1832 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1833 pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));";
1838 pidl "return NT_STATUS_OK;";
1844 #####################################################################
1845 # produce a function call table
1846 sub FunctionTable($)
1848 my($interface) = shift;
1849 my($data) = $interface->{INHERITED_DATA};
1851 my $uname = uc $interface->{NAME};
1853 foreach my $d (@{$data}) {
1854 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1857 return if ($count == 0);
1859 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {";
1860 foreach my $d (@{$data}) {
1861 if ($d->{TYPE} eq "FUNCTION") {
1863 pidl "\t\t\"$d->{NAME}\",";
1864 pidl "\t\tsizeof(struct $d->{NAME}),";
1865 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},";
1866 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},";
1867 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}";
1871 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
1875 # If no endpoint is set, default to the interface name as a named pipe
1876 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1877 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1880 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1881 my $endpoint_count = $#e + 1;
1883 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {";
1884 foreach my $ep (@e) {
1890 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1891 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1895 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
1896 pidl "\t\"$interface->{NAME}\",";
1897 pidl "\tDCERPC_$uname\_UUID,";
1898 pidl "\tDCERPC_$uname\_VERSION,";
1899 pidl "\tDCERPC_$uname\_HELPSTRING,";
1901 pidl "\t$interface->{NAME}\_calls,";
1902 pidl "\t&$interface->{NAME}\_endpoints";
1906 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
1908 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
1913 #####################################################################
1914 # parse the interface definitions
1915 sub ParseInterface($)
1917 my($interface) = shift;
1918 my($data) = $interface->{DATA};
1921 foreach my $d (@{$data}) {
1922 ($d->{TYPE} eq "TYPEDEF") &&
1923 ParseTypedefPush($d);
1924 ($d->{TYPE} eq "FUNCTION") &&
1925 ParseFunctionPush($d);
1929 foreach my $d (@{$data}) {
1930 ($d->{TYPE} eq "TYPEDEF") &&
1931 ParseTypedefPull($d);
1932 ($d->{TYPE} eq "FUNCTION") &&
1933 ParseFunctionPull($d);
1937 foreach my $d (@{$data}) {
1938 if ($d->{TYPE} eq "TYPEDEF" &&
1939 !util::has_property($d, "noprint")) {
1940 ParseTypedefPrint($d);
1942 if ($d->{TYPE} eq "FUNCTION" &&
1943 !util::has_property($d, "noprint")) {
1944 ParseFunctionPrint($d);
1949 foreach my $d (@{$data}) {
1950 ($d->{TYPE} eq "TYPEDEF") &&
1951 ParseTypedefNdrSize($d);
1954 FunctionTable($interface);
1957 sub RegistrationFunction($$)
1960 my $filename = shift;
1962 $filename =~ /.*\/ndr_(.*).c/;
1964 pidl "NTSTATUS dcerpc_$basename\_init(void)";
1967 pidl "NTSTATUS status = NT_STATUS_OK;";
1968 foreach my $interface (@{$idl}) {
1969 next if $interface->{TYPE} ne "INTERFACE";
1971 my $data = $interface->{INHERITED_DATA};
1973 foreach my $d (@{$data}) {
1974 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1977 next if ($count == 0);
1979 pidl "status = dcerpc_ndr_$interface->{NAME}_init();";
1980 pidl "if (NT_STATUS_IS_ERR(status)) {";
1981 pidl "\treturn status;";
1985 pidl "return status;";
1991 sub CheckPointerTypes($$)
1994 my $default = shift;
1996 foreach my $e (@{$s->{ELEMENTS}}) {
1997 if ($e->{POINTERS}) {
1998 if (not defined(pointer_type($e))) {
1999 $e->{PROPERTIES}->{$default} = 1;
2002 if (pointer_type($e) eq "ptr") {
2003 print "Warning: ptr is not supported by pidl yet\n";
2009 sub LoadInterface($)
2013 if (not util::has_property($x, "pointer_default")) {
2014 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
2015 # and "unique" in Microsoft Extensions mode (default)
2016 $x->{PROPERTIES}->{pointer_default} = "unique";
2019 foreach my $d (@{$x->{DATA}}) {
2020 if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) {
2021 $typedefs{$d->{NAME}} = $d;
2022 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
2023 CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
2026 if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
2027 $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
2030 if ($d->{TYPE} eq "FUNCTION") {
2031 CheckPointerTypes($d,
2032 $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
2038 # Add ORPC specific bits to an interface.
2039 sub InterfaceORPC($)
2042 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
2043 # for 'object' interfaces
2044 if (util::has_property($x, "object")) {
2045 foreach my $e (@{$x->{DATA}}) {
2046 if($e->{TYPE} eq "FUNCTION") {
2047 $e->{PROPERTIES}->{object} = 1;
2048 unshift(@{$e->{ELEMENTS}},
2049 { 'NAME' => 'ORPCthis',
2051 'PROPERTIES' => { 'in' => '1' },
2052 'TYPE' => 'ORPCTHIS'
2054 unshift(@{$e->{ELEMENTS}},
2055 { 'NAME' => 'ORPCthat',
2057 'PROPERTIES' => { 'out' => '1' },
2058 'TYPE' => 'ORPCTHAT'
2069 foreach my $x (@{$idl}) {
2074 #####################################################################
2075 # parse a parsed IDL structure back into an IDL file
2079 my($filename) = shift;
2080 my $h_filename = $filename;
2085 if ($h_filename =~ /(.*)\.c/) {
2086 $h_filename = "$1.h";
2089 pidl "/* parser auto-generated by pidl */";
2091 pidl "#include \"includes.h\"";
2092 pidl "#include \"$h_filename\"";
2095 foreach my $x (@{$idl}) {
2096 if ($x->{TYPE} eq "INTERFACE") {
2097 needed::BuildNeeded($x);
2102 RegistrationFunction($idl, $filename);
2107 RegisterPrimitives();