r5426: Warn about embedded ref pointers.
[Samba/gebeck_regimport.git] / source4 / build / pidl / ndr.pm
blob90bbc9c9a91ce1c8965758d396c95dd87ebf282b
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
8 package NdrParser;
10 use strict;
11 use needed;
13 # list of known types
14 my %typedefs;
15 my %typefamily;
17 sub get_typedef($)
19 my $n = shift;
20 return $typedefs{$n};
23 sub RegisterPrimitives()
25 my %type_alignments =
27 "char" => 1,
28 "int8" => 1,
29 "uint8" => 1,
30 "short" => 2,
31 "wchar_t" => 2,
32 "int16" => 2,
33 "uint16" => 2,
34 "long" => 4,
35 "int32" => 4,
36 "uint32" => 4,
37 "dlong" => 4,
38 "udlong" => 4,
39 "udlongr" => 4,
40 "NTTIME" => 4,
41 "NTTIME_1sec" => 4,
42 "time_t" => 4,
43 "DATA_BLOB" => 4,
44 "error_status_t" => 4,
45 "WERROR" => 4,
46 "NTSTATUS" => 4,
47 "boolean32" => 4,
48 "unsigned32" => 4,
49 "ipv4address" => 4,
50 "hyper" => 8,
51 "NTTIME_hyper" => 8
54 foreach my $k (keys %type_alignments) {
55 $typedefs{$k} = {
56 NAME => $k,
57 TYPE => "TYPEDEF",
58 DATA => {
59 TYPE => "SCALAR",
60 ALIGN => $type_alignments{$k}
66 sub is_scalar_type($)
68 my $type = shift;
70 if (my $dt = $typedefs{$type}->{DATA}->{TYPE}) {
71 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
74 return 0;
77 sub pointer_type($)
79 my $e = shift;
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"));
89 return undef;
92 # determine if an element needs a reference pointer on the wire
93 # in its NDR representation
94 sub need_wire_pointer($)
96 my $e = shift;
97 my $pt;
99 return 0 unless ($pt = pointer_type($e));
101 if ($pt ne "ref") {
102 return 1;
103 } else {
104 return 0;
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($)
112 my $e = shift;
113 if (util::has_property($e, "ref")) {
114 return 1;
116 if (is_scalar_type($e->{TYPE}) &&
117 !$e->{POINTERS} &&
118 !util::array_size($e)) {
119 return 1;
121 return 0;
124 # see if a variable needs to be allocated by the NDR subsystem on pull
125 sub need_alloc($)
127 my $e = shift;
129 if (util::has_property($e, "ref")) {
130 return 0;
133 if ($e->{POINTERS} || util::array_size($e)) {
134 return 1;
137 return 0;
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
144 sub c_push_prefix($)
146 my $e = shift;
148 if ($e->{TYPE} =~ "string") {
149 return "";
152 if (is_scalar_type($e->{TYPE}) &&
153 $e->{POINTERS}) {
154 return "*";
156 if (!is_scalar_type($e->{TYPE}) &&
157 !$e->{POINTERS} &&
158 !util::array_size($e)) {
159 return "&";
161 return "";
165 # determine the C prefix used to refer to a variable when passing to a pull
166 # return '&' or ''
167 sub c_pull_prefix($)
169 my $e = shift;
171 if (!$e->{POINTERS} && !util::array_size($e)) {
172 return "&";
175 if ($e->{TYPE} =~ "string") {
176 return "&";
179 return "";
181 my $res = "";
182 my $tabs = "";
183 sub pidl($)
185 my $d = shift;
186 if ($d) {
187 $res .= $tabs;
188 $res .= $d;
190 $res .="\n";
193 sub indent
195 $tabs .= "\t";
198 sub deindent
200 $tabs = substr($tabs, 0, -1);
203 ###################################
204 # find a sibling var in a structure
205 sub find_sibling($$)
207 my($e) = shift;
208 my($name) = shift;
209 my($fn) = $e->{PARENT};
211 if ($name =~ /\*(.*)/) {
212 $name = $1;
215 if ($fn->{TYPE} eq "FUNCTION") {
216 for my $e2 (@{$fn->{ELEMENTS}}) {
217 if ($e2->{NAME} eq $name) {
218 return $e2;
223 for my $e2 (@{$fn->{ELEMENTS}}) {
224 if ($e2->{NAME} eq $name) {
225 return $e2;
228 die "invalid sibling '$name'";
231 ####################################################################
232 # work out the name of a size_is() variable
233 sub ParseExpr($$$)
235 my($e) = shift;
236 my($size) = shift;
237 my($var_prefix) = shift;
239 my($fn) = $e->{PARENT};
241 if (util::is_constant($size)) {
242 return $size;
245 if ($size =~ /ndr->|\(/) {
246 return $size;
249 my $prefix = "";
251 if ($size =~ /\*(.*)/) {
252 $size = $1;
253 $prefix = "*";
256 if ($fn->{TYPE} ne "FUNCTION") {
257 return $prefix . "r->$size";
260 my $e2 = find_sibling($e, $size);
262 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
263 return $prefix . "$var_prefix$size";
265 if (util::has_property($e2, "in")) {
266 return $prefix . "r->in.$size";
268 if (util::has_property($e2, "out")) {
269 return $prefix . "r->out.$size";
272 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
275 #####################################################################
276 # check that a variable we get from ParseExpr isn't a null pointer
277 sub check_null_pointer($)
279 my $size = shift;
280 if ($size =~ /^\*/) {
281 my $size2 = substr($size, 1);
282 pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
286 #####################################################################
287 # check that a variable we get from ParseExpr isn't a null pointer
288 # void return varient
289 sub check_null_pointer_void($)
291 my $size = shift;
292 if ($size =~ /^\*/) {
293 my $size2 = substr($size, 1);
294 pidl "if ($size2 == NULL) return;";
299 #####################################################################
300 # work out is a parse function should be declared static or not
301 sub fn_prefix($)
303 my $fn = shift;
304 if ($fn->{TYPE} eq "TYPEDEF") {
305 if (util::has_property($fn, "public")) {
306 return "";
310 if ($fn->{TYPE} eq "FUNCTION") {
311 if (util::has_property($fn, "public")) {
312 return "";
315 return "static ";
319 ###################################################################
320 # setup any special flags for an element or structure
321 sub start_flags($)
323 my $e = shift;
324 my $flags = util::has_property($e, "flag");
325 if (defined $flags) {
326 pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;";
327 pidl "ndr_set_flags(&ndr->flags, $flags);";
331 ###################################################################
332 # end any special flags for an element or structure
333 sub end_flags($)
335 my $e = shift;
336 my $flags = util::has_property($e, "flag");
337 if (defined $flags) {
338 pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}";
342 #####################################################################
343 # work out the correct alignment for a structure or union
344 sub find_largest_alignment($)
346 my $s = shift;
348 my $align = 1;
349 for my $e (@{$s->{ELEMENTS}}) {
350 my $a = 1;
352 if (need_wire_pointer($e)) {
353 $a = 4;
354 } else {
355 $a = align_type($e->{TYPE});
358 $align = $a if ($align < $a);
361 return $align;
364 #####################################################################
365 # align a type
366 sub align_type
368 my $e = shift;
370 unless (defined($typedefs{$e}) && defined($typedefs{$e}->{DATA}->{TYPE})) {
371 # it must be an external type - all we can do is guess
372 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
373 return 4;
376 my $dt = $typedefs{$e}->{DATA};
378 return $dt->{ALIGN} if ($dt->{ALIGN});
379 return $typefamily{$dt->{TYPE}}->{ALIGN}($dt);
382 #####################################################################
383 # parse an array - push side
384 sub ParseArrayPush($$$)
386 my $e = shift;
387 my $var_prefix = shift;
388 my $ndr_flags = shift;
390 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
392 if (defined $e->{CONFORMANT_SIZE}) {
393 # the conformant size has already been pushed
394 } elsif (!util::is_inline_array($e)) {
395 # we need to emit the array size
396 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
399 if (my $length = util::has_property($e, "length_is")) {
400 $length = ParseExpr($e, $length, $var_prefix);
401 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
402 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
403 $size = $length;
406 if (is_scalar_type($e->{TYPE})) {
407 pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
408 } else {
409 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}));";
413 #####################################################################
414 # print an array
415 sub ParseArrayPrint($$)
417 my $e = shift;
418 my $var_prefix = shift;
419 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
420 my $length = util::has_property($e, "length_is");
422 if (defined $length) {
423 $size = ParseExpr($e, $length, $var_prefix);
426 if (is_scalar_type($e->{TYPE})) {
427 pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);";
428 } else {
429 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});";
433 #####################################################################
434 # check the size_is and length_is constraints
435 sub CheckArraySizes($$)
437 my $e = shift;
438 my $var_prefix = shift;
440 if (!defined $e->{CONFORMANT_SIZE} &&
441 util::has_property($e, "size_is")) {
442 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
443 pidl "if ($var_prefix$e->{NAME}) {";
444 indent;
445 check_null_pointer($size);
446 pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));";
447 deindent;
448 pidl "}";
451 if (my $length = util::has_property($e, "length_is")) {
452 $length = ParseExpr($e, $length, $var_prefix);
453 pidl "if ($var_prefix$e->{NAME}) {";
454 indent;
455 check_null_pointer($length);
456 pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));";
457 deindent;
458 pidl "}";
462 #####################################################################
463 # parse an array - pull side
464 sub ParseArrayPull($$$)
466 my $e = shift;
467 my $var_prefix = shift;
468 my $ndr_flags = shift;
470 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
471 my $alloc_size = $size;
473 # if this is a conformant array then we use that size to allocate, and make sure
474 # we allocate enough to pull the elements
475 if (defined $e->{CONFORMANT_SIZE}) {
476 $alloc_size = $e->{CONFORMANT_SIZE};
477 check_null_pointer($size);
478 pidl "if ($size > $alloc_size) {";
479 indent;
480 pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
481 deindent;
482 pidl "}";
483 } elsif (!util::is_inline_array($e)) {
484 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
485 my $size2 = substr($size, 1);
486 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
489 # non fixed arrays encode the size just before the array
490 pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));";
491 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
494 if ((need_alloc($e) && !util::is_fixed_array($e)) ||
495 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
496 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
497 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
501 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
502 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
503 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
504 indent;
505 pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
506 deindent;
507 pidl "}";
511 if (my $length = util::has_property($e, "length_is")) {
512 pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
513 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
516 check_null_pointer($size);
517 if (is_scalar_type($e->{TYPE})) {
518 pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
519 } else {
520 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}));";
524 #####################################################################
525 # parse scalars in a structure element
526 sub ParseElementPushScalar($$$)
528 my($e) = shift;
529 my($var_prefix) = shift;
530 my($ndr_flags) = shift;
531 my $cprefix = c_push_prefix($e);
532 my $sub_size = util::has_property($e, "subcontext");
534 start_flags($e);
536 if (my $value = util::has_property($e, "value")) {
537 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
540 if (util::has_property($e, "relative")) {
541 pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
542 } elsif (util::is_inline_array($e)) {
543 ParseArrayPush($e, "r->", "NDR_SCALARS");
544 } elsif (need_wire_pointer($e)) {
545 ParseElementPushPtr($e, $var_prefix, $ndr_flags);
546 } elsif (need_alloc($e)) {
547 # no scalar component
548 } elsif (my $switch = util::has_property($e, "switch_is")) {
549 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
550 } elsif (defined $sub_size) {
551 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}));";
552 } else {
553 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
556 end_flags($e);
559 #####################################################################
560 # parse a pointer in a struct element or function
561 sub ParseElementPushPtr($$$)
563 my $e = shift;
564 my $var_prefix = shift;
565 my $ndr_flags = shift;
567 pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
571 #####################################################################
572 # print scalars in a structure element
573 sub ParseElementPrintScalar($$)
575 my($e) = shift;
576 my($var_prefix) = shift;
577 my $cprefix = c_push_prefix($e);
579 if (util::has_property($e, "noprint")) {
580 return;
583 if (my $value = util::has_property($e, "value")) {
584 pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
585 indent;
586 pidl "$cprefix$var_prefix$e->{NAME} = $value;";
587 deindent;
588 pidl "}";
591 if (util::is_fixed_array($e)) {
592 ParseElementPrintBuffer($e, $var_prefix);
593 } elsif ($e->{POINTERS} || util::array_size($e)) {
594 pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});";
595 pidl "ndr->depth++;";
596 ParseElementPrintBuffer($e, $var_prefix);
597 pidl "ndr->depth--;";
598 } elsif (my $switch = util::has_property($e, "switch_is")) {
599 ParseElementPrintSwitch($e, $var_prefix, $switch);
600 } else {
601 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
605 #####################################################################
606 # parse scalars in a structure element - pull size
607 sub ParseElementPullSwitch($$$$)
609 my($e) = shift;
610 my($var_prefix) = shift;
611 my($ndr_flags) = shift;
612 my $switch = shift;
613 my $switch_var = ParseExpr($e, $switch, $var_prefix);
615 my $cprefix = c_pull_prefix($e);
617 my $utype = $typedefs{$e->{TYPE}};
619 check_null_pointer($switch_var);
621 if (!defined $utype ||
622 !util::has_property($utype, "nodiscriminant")) {
623 my $e2 = find_sibling($e, $switch);
624 my $type_decl = util::map_type($e2->{TYPE});
625 pidl "if (($ndr_flags) & NDR_SCALARS) {";
626 indent;
627 if ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "ENUM") {
628 $type_decl = util::enum_type_decl($e2);
629 } elsif ($typedefs{$e2->{TYPE}}->{DATA}->{TYPE} eq "BITMAP") {
630 $type_decl = util::bitmap_type_decl($e2);
632 pidl "$type_decl _level;";
633 pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
634 if ($switch_var =~ /r->in/) {
635 pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
636 indent;
637 } else {
638 pidl "if (_level != $switch_var) {";
639 indent;
641 pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
642 deindent;
643 if ($switch_var =~ /r->/) {
644 pidl "} else { $switch_var = _level; }";
645 } else {
646 pidl "}";
648 deindent;
649 pidl "}";
652 my $sub_size = util::has_property($e, "subcontext");
653 if (defined $sub_size) {
654 pidl "if (($ndr_flags) & NDR_SCALARS) {";
655 indent;
656 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}));";
657 deindent;
658 pidl "}";
659 } else {
660 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
666 #####################################################################
667 # push switch element
668 sub ParseElementPushSwitch($$$$)
670 my($e) = shift;
671 my($var_prefix) = shift;
672 my($ndr_flags) = shift;
673 my $switch = shift;
674 my $switch_var = ParseExpr($e, $switch, $var_prefix);
675 my $cprefix = c_push_prefix($e);
677 check_null_pointer($switch_var);
679 my $utype = $typedefs{$e->{TYPE}};
680 if (!defined $utype ||
681 !util::has_property($utype, "nodiscriminant")) {
682 my $e2 = find_sibling($e, $switch);
683 pidl "if (($ndr_flags) & NDR_SCALARS) {";
684 indent;
685 pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
686 deindent;
687 pidl "}";
690 my $sub_size = util::has_property($e, "subcontext");
691 if (defined $sub_size) {
692 pidl "if(($ndr_flags) & NDR_SCALARS) {";
693 indent;
694 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}));";
695 deindent;
696 pidl "}";
697 } else {
698 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
702 #####################################################################
703 # print scalars in a structure element
704 sub ParseElementPrintSwitch($$$)
706 my($e) = shift;
707 my($var_prefix) = shift;
708 my $switch = shift;
709 my $switch_var = ParseExpr($e, $switch, $var_prefix);
710 my $cprefix = c_push_prefix($e);
712 check_null_pointer_void($switch_var);
714 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});";
718 #####################################################################
719 # parse scalars in a structure element - pull size
720 sub ParseElementPullScalar($$$)
722 my($e) = shift;
723 my($var_prefix) = shift;
724 my($ndr_flags) = shift;
725 my $cprefix = c_pull_prefix($e);
726 my $sub_size = util::has_property($e, "subcontext");
728 start_flags($e);
730 if (util::is_inline_array($e)) {
731 ParseArrayPull($e, "r->", "NDR_SCALARS");
732 } elsif (need_wire_pointer($e)) {
733 ParseElementPullPtr($e, $var_prefix, $ndr_flags);
734 } elsif (need_alloc($e)) {
735 # no scalar component
736 } elsif (my $switch = util::has_property($e, "switch_is")) {
737 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
738 } elsif (defined $sub_size) {
739 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}));";
740 } else {
741 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
743 if (my $range = util::has_property($e, "range")) {
744 my ($low, $high) = split(/ /, $range, 2);
745 pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
746 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
747 pidl "}";
750 end_flags($e);
753 #####################################################################
754 # parse a pointer in a struct element or function
755 sub ParseElementPullPtr($$$)
757 my($e) = shift;
758 my($var_prefix) = shift;
759 my($ndr_flags) = shift;
761 pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
762 pidl "if (_ptr_$e->{NAME}) {";
763 indent;
764 pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});";
765 if (util::has_property($e, "relative")) {
766 pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));";
768 deindent;
769 pidl "} else {";
770 pidl "\t$var_prefix$e->{NAME} = NULL;";
771 pidl "}";
774 #####################################################################
775 # parse buffers in a structure element
776 sub ParseElementPushBuffer($$$)
778 my($e) = shift;
779 my($var_prefix) = shift;
780 my($ndr_flags) = shift;
781 my $cprefix = c_push_prefix($e);
782 my $sub_size = util::has_property($e, "subcontext");
784 if (is_pure_scalar($e)) {
785 return;
788 start_flags($e);
790 if (need_wire_pointer($e)) {
791 pidl "if ($var_prefix$e->{NAME}) {";
792 indent;
793 if (util::has_property($e, "relative")) {
794 pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
798 if (util::is_inline_array($e)) {
799 ParseArrayPush($e, "r->", "NDR_BUFFERS");
800 } elsif (util::array_size($e)) {
801 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
802 } elsif (my $switch = util::has_property($e, "switch_is")) {
803 if ($e->{POINTERS}) {
804 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
805 } else {
806 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
808 } elsif (defined $sub_size) {
809 if ($e->{POINTERS}) {
810 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}));";
812 } elsif ($e->{POINTERS}) {
813 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
814 } else {
815 pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
818 if (need_wire_pointer($e)) {
819 deindent;
820 pidl "}";
823 end_flags($e);
826 #####################################################################
827 # print buffers in a structure element
828 sub ParseElementPrintBuffer($$)
830 my($e) = shift;
831 my($var_prefix) = shift;
832 my $cprefix = c_push_prefix($e);
834 if (need_wire_pointer($e)) {
835 pidl "if ($var_prefix$e->{NAME}) {";
836 indent;
839 if (util::array_size($e)) {
840 ParseArrayPrint($e, $var_prefix)
841 } elsif (my $switch = util::has_property($e, "switch_is")) {
842 ParseElementPrintSwitch($e, $var_prefix, $switch);
843 } else {
844 pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});";
847 if (need_wire_pointer($e)) {
848 deindent;
849 pidl "}";
853 #####################################################################
854 # parse buffers in a structure element - pull side
855 sub ParseElementPullBuffer($$$)
857 my($e) = shift;
858 my($var_prefix) = shift;
859 my($ndr_flags) = shift;
860 my $cprefix = c_pull_prefix($e);
861 my $sub_size = util::has_property($e, "subcontext");
863 if (is_pure_scalar($e)) {
864 return;
867 start_flags($e);
869 if (need_wire_pointer($e)) {
870 pidl "if ($var_prefix$e->{NAME}) {";
871 indent;
872 if (util::has_property($e, "relative")) {
873 pidl "struct ndr_pull_save _relative_save;";
874 pidl "ndr_pull_save(ndr, &_relative_save);";
875 pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
879 if (util::is_inline_array($e)) {
880 ParseArrayPull($e, "r->", "NDR_BUFFERS");
881 } elsif (util::array_size($e)) {
882 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
883 } elsif (my $switch = util::has_property($e, "switch_is")) {
884 if ($e->{POINTERS}) {
885 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
886 } else {
887 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
889 } elsif (defined $sub_size) {
890 if ($e->{POINTERS}) {
891 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}));";
893 } elsif ($e->{POINTERS}) {
894 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
895 } else {
896 pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
899 if (need_wire_pointer($e)) {
900 if (util::has_property($e, "relative")) {
901 pidl "ndr_pull_restore(ndr, &_relative_save);";
903 deindent;
904 pidl "}";
907 end_flags($e);
910 #####################################################################
911 # parse a struct
912 sub ParseStructPush($)
914 my($struct) = shift;
916 if (! defined $struct->{ELEMENTS}) {
917 return;
920 start_flags($struct);
922 # see if the structure contains a conformant array. If it
923 # does, then it must be the last element of the structure, and
924 # we need to push the conformant length early, as it fits on
925 # the wire before the structure (and even before the structure
926 # alignment)
927 my $e = $struct->{ELEMENTS}[-1];
928 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
929 my $size = ParseExpr($e, util::array_size($e), "r->");
930 $e->{CONFORMANT_SIZE} = $size;
931 check_null_pointer($size);
932 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));";
935 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
936 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
937 pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));";
940 pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
942 pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
944 my $align = find_largest_alignment($struct);
945 pidl "NDR_CHECK(ndr_push_align(ndr, $align));";
947 foreach my $e (@{$struct->{ELEMENTS}}) {
948 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
951 pidl "buffers:";
952 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
953 foreach my $e (@{$struct->{ELEMENTS}}) {
954 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
957 pidl "ndr_push_struct_end(ndr);";
959 pidl "done:";
961 end_flags($struct);
964 #####################################################################
965 # generate a push function for an enum
966 sub ParseEnumPush($)
968 my($enum) = shift;
969 my($type_fn) = util::enum_type_fn($enum);
971 start_flags($enum);
973 pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));";
975 end_flags($enum);
978 #####################################################################
979 # generate a pull function for an enum
980 sub ParseEnumPull($)
982 my($enum) = shift;
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;";
987 start_flags($enum);
988 pidl "NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));";
989 pidl "*r = v;";
991 end_flags($enum);
994 #####################################################################
995 # generate a print function for an enum
996 sub ParseEnumPrint($)
998 my($enum) = shift;
1000 pidl "const char *val = NULL;";
1001 pidl "";
1003 start_flags($enum);
1005 pidl "switch (r) {";
1006 indent;
1007 my $els = \@{$enum->{ELEMENTS}};
1008 foreach my $i (0 .. $#{$els}) {
1009 my $e = ${$els}[$i];
1010 chomp $e;
1011 if ($e =~ /^(.*)=/) {
1012 $e = $1;
1014 pidl "case $e: val = \"$e\"; break;";
1017 deindent;
1018 pidl "}";
1020 pidl "ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);";
1022 end_flags($enum);
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));";
1043 end_flags($bitmap);
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));";
1057 pidl "*r = v;";
1059 end_flags($bitmap);
1062 #####################################################################
1063 # generate a print function for an bitmap
1064 sub ParseBitmapPrintElement($$)
1066 my($e) = shift;
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};
1071 my($flag);
1073 if ($e =~ /^(\w+) .*$/) {
1074 $flag = "$1";
1075 } else {
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--;";
1100 end_flags($bitmap);
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}) {
1117 return;
1120 start_flags($struct);
1122 pidl "ndr->depth++;";
1123 foreach my $e (@{$struct->{ELEMENTS}}) {
1124 ParseElementPrintScalar($e, "r->");
1126 pidl "ndr->depth--;";
1128 end_flags($struct);
1131 #####################################################################
1132 # parse a struct - pull side
1133 sub ParseStructPull($)
1135 my($struct) = shift;
1136 my $conform_e;
1138 if (! defined $struct->{ELEMENTS}) {
1139 return;
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
1146 # alignment)
1147 my $e = $struct->{ELEMENTS}[-1];
1148 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
1149 $conform_e = $e;
1152 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1153 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1154 $conform_e = $e;
1157 if (defined $conform_e) {
1158 $conform_e = $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");
1187 pidl "buffers:\n";
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);";
1199 pidl "done:";
1201 end_flags($struct);
1204 #####################################################################
1205 # calculate size of ndr struct
1206 sub ParseStructNdrSize($)
1208 my $t = shift;
1209 my $static = fn_prefix($t);
1210 my $sizevar;
1212 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
1213 pidl "{";
1214 indent;
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});";
1219 deindent;
1220 pidl "}";
1221 pidl "";
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($)
1236 my $t = shift;
1237 my $static = fn_prefix($t);
1238 my $sizevar;
1240 pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
1241 pidl "{";
1242 indent;
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});";
1247 deindent;
1248 pidl "}";
1249 pidl "";;
1252 #####################################################################
1253 # parse a union - push side
1254 sub ParseUnionPush($)
1256 my $e = shift;
1257 my $have_default = 0;
1259 start_flags($e);
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) {";
1269 indent;
1270 foreach my $el (@{$e->{ELEMENTS}}) {
1271 if (util::has_property($el, "default")) {
1272 pidl "default:";
1273 $have_default = 1;
1274 } else {
1275 pidl "case $el->{PROPERTIES}->{case}:";
1278 if ($el->{TYPE} ne "EMPTY") {
1279 indent;
1280 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1281 deindent;
1283 pidl "break;";
1284 pidl "";
1286 if (! $have_default) {
1287 pidl "default:";
1288 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1290 deindent;
1291 pidl "}";
1292 pidl "buffers:";
1293 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1294 pidl "switch (level) {";
1295 indent;
1296 foreach my $el (@{$e->{ELEMENTS}}) {
1297 if (util::has_property($el, "default")) {
1298 pidl "default:";
1299 } else {
1300 pidl "case $el->{PROPERTIES}->{case}:";
1302 if ($el->{TYPE} ne "EMPTY") {
1303 indent;
1304 ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
1305 deindent;
1307 pidl "break;";
1308 pidl "";
1310 if (! $have_default) {
1311 pidl "default:";
1312 pidl "\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1314 deindent;
1315 pidl "}";
1316 pidl "ndr_push_struct_end(ndr);";
1317 pidl "done:";
1318 end_flags($e);
1321 #####################################################################
1322 # print a union
1323 sub ParseUnionPrint($)
1325 my $e = shift;
1326 my $have_default = 0;
1328 start_flags($e);
1330 pidl "switch (level) {";
1331 indent;
1332 foreach my $el (@{$e->{ELEMENTS}}) {
1333 if (util::has_property($el, "default")) {
1334 $have_default = 1;
1335 pidl "default:";
1336 } else {
1337 pidl "case $el->{PROPERTIES}->{case}:";
1339 if ($el->{TYPE} ne "EMPTY") {
1340 indent;
1341 ParseElementPrintScalar($el, "r->");
1342 deindent;
1344 pidl "break;";
1345 pidl "";
1347 if (! $have_default) {
1348 pidl "default:";
1349 pidl "\tndr_print_bad_level(ndr, name, level);";
1351 deindent;
1352 pidl "}";
1354 end_flags($e);
1357 #####################################################################
1358 # parse a union - pull side
1359 sub ParseUnionPull($)
1361 my $e = shift;
1362 my $have_default = 0;
1364 start_flags($e);
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) {";
1374 indent;
1375 foreach my $el (@{$e->{ELEMENTS}}) {
1376 if (util::has_property($el, "default")) {
1377 pidl "default: {";
1378 $have_default = 1;
1379 } else {
1380 pidl "case $el->{PROPERTIES}->{case}: {";
1382 if ($el->{TYPE} ne "EMPTY") {
1383 indent;
1384 if ($el->{POINTERS}) {
1385 pidl "uint32_t _ptr_$el->{NAME};";
1387 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1388 deindent;
1390 pidl "break; }";
1391 pidl "";
1393 if (! $have_default) {
1394 pidl "default:";
1395 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1397 deindent;
1398 pidl "}";
1399 pidl "buffers:";
1400 pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
1401 pidl "switch (level) {";
1402 indent;
1403 foreach my $el (@{$e->{ELEMENTS}}) {
1404 if (util::has_property($el, "default")) {
1405 pidl "default:";
1406 } else {
1407 pidl "case $el->{PROPERTIES}->{case}:";
1409 if ($el->{TYPE} ne "EMPTY") {
1410 indent;
1411 ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
1412 deindent;
1414 pidl "break;";
1415 pidl "";
1417 if (! $have_default) {
1418 pidl "default:";
1419 pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);";
1421 deindent;
1422 pidl "}";
1423 pidl "ndr_pull_struct_end(ndr);";
1424 pidl "done:";
1425 end_flags($e);
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($)
1441 my($e) = shift;
1442 my $static = fn_prefix($e);
1444 if (! needed::is_needed("push_$e->{NAME}")) {
1445 # print "push_$e->{NAME} not needed\n";
1446 return;
1449 my $args;
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)";
1469 pidl "{";
1470 indent;
1471 $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}($e->{DATA});
1472 pidl "return NT_STATUS_OK;";
1473 deindent;
1474 pidl "}";
1475 pidl "";;
1478 #####################################################################
1479 # parse a typedef - pull side
1480 sub ParseTypedefPull($)
1482 my($e) = shift;
1483 my $static = fn_prefix($e);
1485 if (! needed::is_needed("pull_$e->{NAME}")) {
1486 # print "pull_$e->{NAME} not needed\n";
1487 return;
1490 my $args = "";
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)";
1511 pidl "{";
1512 indent;
1513 $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}($e->{DATA});
1514 pidl "return NT_STATUS_OK;";
1515 deindent;
1516 pidl "}";
1517 pidl "";
1520 #####################################################################
1521 # parse a typedef - print side
1522 sub ParseTypedefPrint($)
1524 my($e) = shift;
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)";
1528 pidl "{";
1529 indent;
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)";
1535 pidl "{";
1536 indent;
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)";
1542 pidl "{";
1543 indent;
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)";
1549 pidl "{";
1550 indent;
1553 $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}($e->{DATA});
1554 deindent;
1555 pidl "}";
1558 #####################################################################
1559 ## calculate the size of a structure
1560 sub ParseTypedefNdrSize($)
1562 my($t) = shift;
1563 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1564 return;
1567 $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN}($t);
1570 #####################################################################
1571 # parse a function - print side
1572 sub ParseFunctionPrint($)
1574 my($fn) = shift;
1576 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1577 pidl "{";
1578 indent;
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;";
1584 pidl "}";
1586 pidl "if (flags & NDR_IN) {";
1587 indent;
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--;";
1597 deindent;
1598 pidl "}";
1600 pidl "if (flags & NDR_OUT) {";
1601 indent;
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") {
1610 my $cprefix = "&";
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--;";
1615 deindent;
1616 pidl "}";
1618 pidl "ndr->depth--;";
1619 deindent;
1620 pidl "}";
1621 pidl "";
1624 #####################################################################
1625 # parse a function element
1626 sub ParseFunctionElementPush($$)
1628 my $e = shift;
1629 my $inout = shift;
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}) {";
1635 indent;
1636 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1637 deindent;
1638 pidl "}";
1639 } else {
1640 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1642 } else {
1643 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1645 if ($e->{POINTERS}) {
1646 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1651 #####################################################################
1652 # parse a function
1653 sub ParseFunctionPush($)
1655 my($fn) = shift;
1656 my $static = fn_prefix($fn);
1658 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
1659 pidl "{";
1660 indent;
1662 pidl "if (!(flags & NDR_IN)) goto ndr_out;";
1663 pidl "";
1665 foreach my $e (@{$fn->{ELEMENTS}}) {
1666 if (util::has_property($e, "in")) {
1667 ParseFunctionElementPush($e, "in");
1671 pidl "ndr_out:";
1672 pidl "if (!(flags & NDR_OUT)) goto done;";
1673 pidl "";
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));";
1685 pidl "done:";
1686 pidl "return NT_STATUS_OK;";
1687 deindent;
1688 pidl "}";
1689 pidl "";
1692 #####################################################################
1693 # parse a function element
1694 sub ParseFunctionElementPull($$)
1696 my $e = shift;
1697 my $inout = shift;
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}) {";
1704 indent;
1705 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1706 pidl "if (r->$inout.$e->{NAME}) {";
1707 indent;
1708 } else {
1709 pidl "{";
1710 indent;
1712 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1713 deindent;
1714 pidl "}";
1715 } else {
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});";
1719 pidl "}";
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($)
1736 my $e = shift;
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
1741 # the in side
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};";
1748 } else {
1749 pidl "ZERO_STRUCTP(r->out.$e->{NAME});";
1751 return;
1754 # its an array
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}));";
1760 } else {
1761 pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
1765 #####################################################################
1766 # parse a function
1767 sub ParseFunctionPull($)
1769 my($fn) = shift;
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)";
1774 pidl "{";
1775 indent;
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;";
1785 pidl "";
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);";
1794 pidl "";
1795 last;
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.");
1816 pidl "ndr_out:";
1817 pidl "if (!(flags & NDR_OUT)) goto done;";
1818 pidl "";
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));";
1836 pidl "done:";
1837 pidl "";
1838 pidl "return NT_STATUS_OK;";
1839 deindent;
1840 pidl "}";
1841 pidl "";
1844 #####################################################################
1845 # produce a function call table
1846 sub FunctionTable($)
1848 my($interface) = shift;
1849 my($data) = $interface->{INHERITED_DATA};
1850 my $count = 0;
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") {
1862 pidl "\t{";
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}";
1868 pidl "\t},";
1871 pidl "\t{ NULL, 0, NULL, NULL, NULL }";
1872 pidl "};";
1873 pidl "";
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) {
1885 pidl "\t$ep, ";
1887 pidl "};";
1888 pidl "";
1890 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
1891 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
1892 pidl "};";
1893 pidl "";
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,";
1900 pidl "\t$count,";
1901 pidl "\t$interface->{NAME}\_calls,";
1902 pidl "\t&$interface->{NAME}\_endpoints";
1903 pidl "};";
1904 pidl "";
1906 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)";
1907 pidl "{";
1908 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});";
1909 pidl "}";
1910 pidl "";
1913 #####################################################################
1914 # parse the interface definitions
1915 sub ParseInterface($)
1917 my($interface) = shift;
1918 my($data) = $interface->{DATA};
1920 # Push functions
1921 foreach my $d (@{$data}) {
1922 ($d->{TYPE} eq "TYPEDEF") &&
1923 ParseTypedefPush($d);
1924 ($d->{TYPE} eq "FUNCTION") &&
1925 ParseFunctionPush($d);
1928 # Pull functions
1929 foreach my $d (@{$data}) {
1930 ($d->{TYPE} eq "TYPEDEF") &&
1931 ParseTypedefPull($d);
1932 ($d->{TYPE} eq "FUNCTION") &&
1933 ParseFunctionPull($d);
1936 # Print functions
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);
1948 # Size functions
1949 foreach my $d (@{$data}) {
1950 ($d->{TYPE} eq "TYPEDEF") &&
1951 ParseTypedefNdrSize($d);
1954 FunctionTable($interface);
1957 sub RegistrationFunction($$)
1959 my $idl = shift;
1960 my $filename = shift;
1962 $filename =~ /.*\/ndr_(.*).c/;
1963 my $basename = $1;
1964 pidl "NTSTATUS dcerpc_$basename\_init(void)";
1965 pidl "{";
1966 indent;
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};
1972 my $count = 0;
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;";
1982 pidl "}";
1983 pidl "";
1985 pidl "return status;";
1986 deindent;
1987 pidl "}";
1988 pidl "";
1991 sub CheckPointerTypes($$)
1993 my $s = shift;
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($)
2011 my $x = shift;
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($)
2041 my $x = shift;
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',
2050 'POINTERS' => 0,
2051 'PROPERTIES' => { 'in' => '1' },
2052 'TYPE' => 'ORPCTHIS'
2054 unshift(@{$e->{ELEMENTS}},
2055 { 'NAME' => 'ORPCthat',
2056 'POINTERS' => 0,
2057 'PROPERTIES' => { 'out' => '1' },
2058 'TYPE' => 'ORPCTHAT'
2065 sub Load($)
2067 my $idl = shift;
2069 foreach my $x (@{$idl}) {
2070 LoadInterface($x);
2074 #####################################################################
2075 # parse a parsed IDL structure back into an IDL file
2076 sub Parse($$)
2078 my($idl) = shift;
2079 my($filename) = shift;
2080 my $h_filename = $filename;
2081 $res = "";
2083 Load($idl);
2085 if ($h_filename =~ /(.*)\.c/) {
2086 $h_filename = "$1.h";
2089 pidl "/* parser auto-generated by pidl */";
2090 pidl "";
2091 pidl "#include \"includes.h\"";
2092 pidl "#include \"$h_filename\"";
2093 pidl "";
2095 foreach my $x (@{$idl}) {
2096 if ($x->{TYPE} eq "INTERFACE") {
2097 needed::BuildNeeded($x);
2098 ParseInterface($x);
2102 RegistrationFunction($idl, $filename);
2104 return $res;
2107 RegisterPrimitives();