r5362: Add pointer_default() support to pidl. pointer_default()
[Samba/gebeck_regimport.git] / source4 / build / pidl / ndr.pm
blobf910be623aa3717e3c4c112fa4458a0a5fc8578b
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
6 # released under the GNU GPL
8 package NdrParser;
10 use strict;
11 use needed;
13 # list of known types
14 my %typedefs;
16 my %type_alignments =
18 "char" => 1,
19 "int8" => 1,
20 "uint8" => 1,
21 "short" => 2,
22 "wchar_t" => 2,
23 "int16" => 2,
24 "uint16" => 2,
25 "long" => 4,
26 "int32" => 4,
27 "uint32" => 4,
28 "dlong" => 4,
29 "udlong" => 4,
30 "NTTIME" => 4,
31 "NTTIME_1sec" => 4,
32 "time_t" => 4,
33 "DATA_BLOB" => 4,
34 "error_status_t" => 4,
35 "WERROR" => 4,
36 "boolean32" => 4,
37 "unsigned32" => 4,
38 "ipv4address" => 4,
39 "hyper" => 8,
40 "NTTIME_hyper" => 8
43 foreach my $k (keys %type_alignments) {
44 $typedefs{$k} = {
45 NAME => $k,
46 TYPE => "TYPEDEF",
47 DATA => {
48 TYPE => "SCALAR",
49 ALIGN => $type_alignments{$k}
54 sub is_scalar_type($)
56 my $type = shift;
58 return 1 if (defined($typedefs{$type}) and $typedefs{$type}->{DATA}->{TYPE} eq "SCALAR");
59 return 1 if (util::is_enum($type));
60 return 1 if (util::is_bitmap($type));
62 return 0;
65 sub pointer_type($)
67 my $e = shift;
69 return undef unless $e->{POINTERS};
71 return "ref" if (util::has_property($e, "ref"));
72 return "ptr" if (util::has_property($e, "ptr"));
73 return "unique" if (util::has_property($e, "unique"));
74 return "relative" if (util::has_property($e, "relative"));
76 return undef;
79 # determine if an element needs a reference pointer on the wire
80 # in its NDR representation
81 sub need_wire_pointer($)
83 my $e = shift;
84 my $pt;
86 return 0 unless ($pt = pointer_type($e));
88 if ($pt ne "ref") {
89 return 1;
90 } else {
91 return 0;
95 # determine if an element is a pure scalar. pure scalars do not
96 # have a "buffers" section in NDR
97 sub is_pure_scalar($)
99 my $e = shift;
100 if (util::has_property($e, "ref")) {
101 return 1;
103 if (is_scalar_type($e->{TYPE}) &&
104 !$e->{POINTERS} &&
105 !util::array_size($e)) {
106 return 1;
108 return 0;
111 # see if a variable needs to be allocated by the NDR subsystem on pull
112 sub need_alloc($)
114 my $e = shift;
116 if (util::has_property($e, "ref")) {
117 return 0;
120 if ($e->{POINTERS} || util::array_size($e)) {
121 return 1;
124 return 0;
128 # determine the C prefix used to refer to a variable when passing to a push
129 # function. This will be '*' for pointers to scalar types, '' for scalar
130 # types and normal pointers and '&' for pass-by-reference structures
131 sub c_push_prefix($)
133 my $e = shift;
135 if ($e->{TYPE} =~ "string") {
136 return "";
139 if (is_scalar_type($e->{TYPE}) &&
140 $e->{POINTERS}) {
141 return "*";
143 if (!is_scalar_type($e->{TYPE}) &&
144 !$e->{POINTERS} &&
145 !util::array_size($e)) {
146 return "&";
148 return "";
152 # determine the C prefix used to refer to a variable when passing to a pull
153 # return '&' or ''
154 sub c_pull_prefix($)
156 my $e = shift;
158 if (!$e->{POINTERS} && !util::array_size($e)) {
159 return "&";
162 if ($e->{TYPE} =~ "string") {
163 return "&";
166 return "";
168 my $res = "";
169 sub pidl($)
171 $res .= shift;
174 #####################################################################
175 # parse a properties list
176 sub ParseProperties($)
178 my($props) = shift;
179 foreach my $d (@{$props}) {
180 if (ref($d) ne "HASH") {
181 pidl "[$d] ";
182 } else {
183 foreach my $k (keys %{$d}) {
184 pidl "[$k($d->{$k})] ";
190 ###################################
191 # find a sibling var in a structure
192 sub find_sibling($$)
194 my($e) = shift;
195 my($name) = shift;
196 my($fn) = $e->{PARENT};
198 if ($name =~ /\*(.*)/) {
199 $name = $1;
202 if ($fn->{TYPE} eq "FUNCTION") {
203 for my $e2 (@{$fn->{ELEMENTS}}) {
204 if ($e2->{NAME} eq $name) {
205 return $e2;
210 for my $e2 (@{$fn->{ELEMENTS}}) {
211 if ($e2->{NAME} eq $name) {
212 return $e2;
215 die "invalid sibling '$name'";
218 ####################################################################
219 # work out the name of a size_is() variable
220 sub ParseExpr($$$)
222 my($e) = shift;
223 my($size) = shift;
224 my($var_prefix) = shift;
226 my($fn) = $e->{PARENT};
228 if (util::is_constant($size)) {
229 return $size;
232 if ($size =~ /ndr->|\(/) {
233 return $size;
236 my $prefix = "";
238 if ($size =~ /\*(.*)/) {
239 $size = $1;
240 $prefix = "*";
243 if ($fn->{TYPE} ne "FUNCTION") {
244 return $prefix . "r->$size";
247 my $e2 = find_sibling($e, $size);
249 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
250 return $prefix . "$var_prefix$size";
252 if (util::has_property($e2, "in")) {
253 return $prefix . "r->in.$size";
255 if (util::has_property($e2, "out")) {
256 return $prefix . "r->out.$size";
259 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
262 #####################################################################
263 # check that a variable we get from ParseExpr isn't a null pointer
264 sub check_null_pointer($)
266 my $size = shift;
267 if ($size =~ /^\*/) {
268 my $size2 = substr($size, 1);
269 pidl "\tif ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;\n";
273 #####################################################################
274 # check that a variable we get from ParseExpr isn't a null pointer
275 # void return varient
276 sub check_null_pointer_void($)
278 my $size = shift;
279 if ($size =~ /^\*/) {
280 my $size2 = substr($size, 1);
281 pidl "\tif ($size2 == NULL) return;\n";
286 #####################################################################
287 # work out is a parse function should be declared static or not
288 sub fn_prefix($)
290 my $fn = shift;
291 if ($fn->{TYPE} eq "TYPEDEF") {
292 if (util::has_property($fn, "public")) {
293 return "";
297 if ($fn->{TYPE} eq "FUNCTION") {
298 if (util::has_property($fn, "public")) {
299 return "";
302 return "static ";
306 ###################################################################
307 # setup any special flags for an element or structure
308 sub start_flags($)
310 my $e = shift;
311 my $flags = util::has_property($e, "flag");
312 if (defined $flags) {
313 pidl "\t{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;\n";
314 pidl "\tndr_set_flags(&ndr->flags, $flags);\n";
318 ###################################################################
319 # end any special flags for an element or structure
320 sub end_flags($)
322 my $e = shift;
323 my $flags = util::has_property($e, "flag");
324 if (defined $flags) {
325 pidl "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n";
330 #####################################################################
331 # work out the correct alignment for a structure or union
332 sub struct_alignment
334 my $s = shift;
336 my $align = 1;
337 for my $e (@{$s->{ELEMENTS}}) {
338 my $a = 1;
340 if (need_wire_pointer($e)) {
341 $a = 4;
342 } else {
343 $a = align_type($e->{TYPE});
346 $align = $a if ($align < $a);
349 return $align;
352 #####################################################################
353 # align a type
354 sub align_type
356 my $e = shift;
358 unless (defined($typedefs{$e})) {
359 # it must be an external type - all we can do is guess
360 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
361 return 4;
364 my $dt = $typedefs{$e}->{DATA};
366 return $dt->{ALIGN} if ($dt->{ALIGN});
368 if ($dt->{TYPE} eq "STRUCT") {
369 $dt->{ALIGN} = struct_alignment($dt);
370 } elsif($dt->{TYPE} eq "UNION") {
371 $dt->{ALIGN} = struct_alignment($dt);
372 } elsif ($dt->{TYPE} eq "ENUM") {
373 $dt->{ALIGN} = align_type(util::enum_type_fn(util::get_enum($e)));
374 } elsif ($dt->{TYPE} eq "BITMAP") {
375 $dt->{ALIGN} = align_type(util::bitmap_type_fn(util::get_bitmap($e)));
378 if (not defined($dt->{ALIGN})) {
379 die("Internal pidl error. Unable to determine alignment for data type $dt->{TYPE}!");
382 return $dt->{ALIGN};
385 #####################################################################
386 # parse an array - push side
387 sub ParseArrayPush($$$)
389 my $e = shift;
390 my $var_prefix = shift;
391 my $ndr_flags = shift;
393 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
395 if (defined $e->{CONFORMANT_SIZE}) {
396 # the conformant size has already been pushed
397 } elsif (!util::is_inline_array($e)) {
398 # we need to emit the array size
399 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));\n";
402 if (my $length = util::has_property($e, "length_is")) {
403 $length = ParseExpr($e, $length, $var_prefix);
404 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));\n";
405 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));\n";
406 $size = $length;
409 if (is_scalar_type($e->{TYPE})) {
410 pidl "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
411 } else {
412 pidl "\t\tNDR_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}));\n";
416 #####################################################################
417 # print an array
418 sub ParseArrayPrint($$)
420 my $e = shift;
421 my $var_prefix = shift;
422 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
423 my $length = util::has_property($e, "length_is");
425 if (defined $length) {
426 $size = ParseExpr($e, $length, $var_prefix);
429 if (is_scalar_type($e->{TYPE})) {
430 pidl "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n";
431 } else {
432 pidl "\t\tndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});\n";
436 #####################################################################
437 # check the size_is and length_is constraints
438 sub CheckArraySizes($$)
440 my $e = shift;
441 my $var_prefix = shift;
443 if (!defined $e->{CONFORMANT_SIZE} &&
444 util::has_property($e, "size_is")) {
445 my $size = ParseExpr($e, util::array_size($e), $var_prefix);
446 pidl "\tif ($var_prefix$e->{NAME}) {\n";
447 check_null_pointer($size);
448 pidl "\t\tNDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));\n";
449 pidl "\t}\n";
452 if (my $length = util::has_property($e, "length_is")) {
453 $length = ParseExpr($e, $length, $var_prefix);
454 pidl "\tif ($var_prefix$e->{NAME}) {\n";
455 check_null_pointer($length);
456 pidl "\t\tNDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));\n";
457 pidl "\t}\n";
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 "\tif ($size > $alloc_size) {\n";
479 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
480 pidl "\t}\n";
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); }\n";
487 # non fixed arrays encode the size just before the array
488 pidl "\t\tNDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));\n";
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 "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
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 "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
502 pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
503 pidl "\t}\n";
507 if (my $length = util::has_property($e, "length_is")) {
508 pidl "\t\tNDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));\n";
509 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
512 check_null_pointer($size);
513 if (is_scalar_type($e->{TYPE})) {
514 pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
515 } else {
516 pidl "\t\tNDR_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}));\n";
521 #####################################################################
522 # parse scalars in a structure element
523 sub ParseElementPushScalar($$$)
525 my($e) = shift;
526 my($var_prefix) = shift;
527 my($ndr_flags) = shift;
528 my $cprefix = c_push_prefix($e);
529 my $sub_size = util::has_property($e, "subcontext");
531 start_flags($e);
533 if (my $value = util::has_property($e, "value")) {
534 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
537 if (util::has_property($e, "relative")) {
538 pidl "\tNDR_CHECK(ndr_push_relative1(ndr, $var_prefix$e->{NAME}));\n";
539 } elsif (util::is_inline_array($e)) {
540 ParseArrayPush($e, "r->", "NDR_SCALARS");
541 } elsif (need_wire_pointer($e)) {
542 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
543 } elsif (need_alloc($e)) {
544 # no scalar component
545 } elsif (my $switch = util::has_property($e, "switch_is")) {
546 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
547 } elsif (defined $sub_size) {
548 pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
549 } else {
550 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
553 end_flags($e);
556 #####################################################################
557 # print scalars in a structure element
558 sub ParseElementPrintScalar($$)
560 my($e) = shift;
561 my($var_prefix) = shift;
562 my $cprefix = c_push_prefix($e);
564 if (util::has_property($e, "noprint")) {
565 return;
568 if (my $value = util::has_property($e, "value")) {
569 pidl "\tif (ndr->flags & LIBNDR_PRINT_SET_VALUES) {\n";
570 pidl "\t\t$cprefix$var_prefix$e->{NAME} = $value;\n";
571 pidl "\t}\n";
574 if (util::is_fixed_array($e)) {
575 ParseElementPrintBuffer($e, $var_prefix);
576 } elsif ($e->{POINTERS} || util::array_size($e)) {
577 pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
578 pidl "\tndr->depth++;\n";
579 ParseElementPrintBuffer($e, $var_prefix);
580 pidl "\tndr->depth--;\n";
581 } elsif (my $switch = util::has_property($e, "switch_is")) {
582 ParseElementPrintSwitch($e, $var_prefix, $switch);
583 } else {
584 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
588 #####################################################################
589 # parse scalars in a structure element - pull size
590 sub ParseElementPullSwitch($$$$)
592 my($e) = shift;
593 my($var_prefix) = shift;
594 my($ndr_flags) = shift;
595 my $switch = shift;
596 my $switch_var = ParseExpr($e, $switch, $var_prefix);
598 my $cprefix = c_pull_prefix($e);
600 my $utype = $typedefs{$e->{TYPE}};
602 check_null_pointer($switch_var);
604 if (!defined $utype ||
605 !util::has_property($utype, "nodiscriminant")) {
606 my $e2 = find_sibling($e, $switch);
607 my $type_decl = util::map_type($e2->{TYPE});
608 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
609 if (util::is_enum($e2->{TYPE})) {
610 $type_decl = util::enum_type_decl($e2);
611 } elsif (util::is_bitmap($e2->{TYPE})) {
612 $type_decl = util::bitmap_type_decl($e2);
614 pidl "\t\t$type_decl _level;\n";
615 pidl "\t\tNDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));\n";
616 if ($switch_var =~ /r->in/) {
617 pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n";
618 } else {
619 pidl "\t\tif (_level != $switch_var) {\n";
621 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);\n";
622 pidl "\t\t}\n";
623 if ($switch_var =~ /r->/) {
624 pidl "else { $switch_var = _level; }\n";
626 pidl "\t}\n";
629 my $sub_size = util::has_property($e, "subcontext");
630 if (defined $sub_size) {
631 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
632 pidl "\t\tNDR_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}));\n";
633 pidl "\t}\n";
634 } else {
635 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
641 #####################################################################
642 # push switch element
643 sub ParseElementPushSwitch($$$$)
645 my($e) = shift;
646 my($var_prefix) = shift;
647 my($ndr_flags) = shift;
648 my $switch = shift;
649 my $switch_var = ParseExpr($e, $switch, $var_prefix);
650 my $cprefix = c_push_prefix($e);
652 check_null_pointer($switch_var);
654 my $utype = $typedefs{$e->{TYPE}};
655 if (!defined $utype ||
656 !util::has_property($utype, "nodiscriminant")) {
657 my $e2 = find_sibling($e, $switch);
658 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
659 pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));\n";
660 pidl "\t}\n";
663 my $sub_size = util::has_property($e, "subcontext");
664 if (defined $sub_size) {
665 pidl "\tif(($ndr_flags) & NDR_SCALARS) {\n";
666 pidl "\t\tNDR_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}));\n";
667 pidl "\t}\n";
668 } else {
669 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
673 #####################################################################
674 # print scalars in a structure element
675 sub ParseElementPrintSwitch($$$)
677 my($e) = shift;
678 my($var_prefix) = shift;
679 my $switch = shift;
680 my $switch_var = ParseExpr($e, $switch, $var_prefix);
681 my $cprefix = c_push_prefix($e);
683 check_null_pointer_void($switch_var);
685 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
689 #####################################################################
690 # parse scalars in a structure element - pull size
691 sub ParseElementPullScalar($$$)
693 my($e) = shift;
694 my($var_prefix) = shift;
695 my($ndr_flags) = shift;
696 my $cprefix = c_pull_prefix($e);
697 my $sub_size = util::has_property($e, "subcontext");
699 start_flags($e);
701 if (util::is_inline_array($e)) {
702 ParseArrayPull($e, "r->", "NDR_SCALARS");
703 } elsif (need_wire_pointer($e)) {
704 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
705 pidl "\tif (_ptr_$e->{NAME}) {\n";
706 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
707 if (util::has_property($e, "relative")) {
708 pidl "\t\tNDR_CHECK(ndr_pull_relative1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));\n";
710 pidl "\t} else {\n";
711 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
712 pidl "\t}\n";
713 } elsif (need_alloc($e)) {
714 # no scalar component
715 } elsif (my $switch = util::has_property($e, "switch_is")) {
716 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
717 } elsif (defined $sub_size) {
718 pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
719 } else {
720 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
722 if (my $range = util::has_property($e, "range")) {
723 my ($low, $high) = split(/ /, $range, 2);
724 pidl "\tif ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {\n";
725 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");\n\t}\n";
728 end_flags($e);
731 #####################################################################
732 # parse buffers in a structure element
733 sub ParseElementPushBuffer($$$)
735 my($e) = shift;
736 my($var_prefix) = shift;
737 my($ndr_flags) = shift;
738 my $cprefix = c_push_prefix($e);
739 my $sub_size = util::has_property($e, "subcontext");
741 if (is_pure_scalar($e)) {
742 return;
745 start_flags($e);
747 if (need_wire_pointer($e)) {
748 pidl "\tif ($var_prefix$e->{NAME}) {\n";
749 if (util::has_property($e, "relative")) {
750 pidl "\t\tNDR_CHECK(ndr_push_relative2(ndr, $var_prefix$e->{NAME}));\n";
754 if (util::is_inline_array($e)) {
755 ParseArrayPush($e, "r->", "NDR_BUFFERS");
756 } elsif (util::array_size($e)) {
757 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
758 } elsif (my $switch = util::has_property($e, "switch_is")) {
759 if ($e->{POINTERS}) {
760 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
761 } else {
762 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
764 } elsif (defined $sub_size) {
765 if ($e->{POINTERS}) {
766 pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
768 } elsif ($e->{POINTERS}) {
769 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
770 } else {
771 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
774 if (need_wire_pointer($e)) {
775 pidl "\t}\n";
778 end_flags($e);
781 #####################################################################
782 # print buffers in a structure element
783 sub ParseElementPrintBuffer($$)
785 my($e) = shift;
786 my($var_prefix) = shift;
787 my $cprefix = c_push_prefix($e);
789 if (need_wire_pointer($e)) {
790 pidl "\tif ($var_prefix$e->{NAME}) {\n";
793 if (util::array_size($e)) {
794 ParseArrayPrint($e, $var_prefix)
795 } elsif (my $switch = util::has_property($e, "switch_is")) {
796 ParseElementPrintSwitch($e, $var_prefix, $switch);
797 } else {
798 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
801 if (need_wire_pointer($e)) {
802 pidl "\t}\n";
807 #####################################################################
808 # parse buffers in a structure element - pull side
809 sub ParseElementPullBuffer($$$)
811 my($e) = shift;
812 my($var_prefix) = shift;
813 my($ndr_flags) = shift;
814 my $cprefix = c_pull_prefix($e);
815 my $sub_size = util::has_property($e, "subcontext");
817 if (is_pure_scalar($e)) {
818 return;
821 start_flags($e);
823 if (need_wire_pointer($e)) {
824 pidl "\tif ($var_prefix$e->{NAME}) {\n";
825 if (util::has_property($e, "relative")) {
826 pidl "\t\tstruct ndr_pull_save _relative_save;\n";
827 pidl "\t\tndr_pull_save(ndr, &_relative_save);\n";
828 pidl "\t\tNDR_CHECK(ndr_pull_relative2(ndr, $var_prefix$e->{NAME}));\n";
832 if (util::is_inline_array($e)) {
833 ParseArrayPull($e, "r->", "NDR_BUFFERS");
834 } elsif (util::array_size($e)) {
835 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
836 } elsif (my $switch = util::has_property($e, "switch_is")) {
837 if ($e->{POINTERS}) {
838 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
839 } else {
840 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
842 } elsif (defined $sub_size) {
843 if ($e->{POINTERS}) {
844 pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
846 } elsif ($e->{POINTERS}) {
847 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
848 } else {
849 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
852 if (need_wire_pointer($e)) {
853 if (util::has_property($e, "relative")) {
854 pidl "\t\tndr_pull_restore(ndr, &_relative_save);\n";
856 pidl "\t}\n";
859 end_flags($e);
862 #####################################################################
863 # parse a struct
864 sub ParseStructPush($)
866 my($struct) = shift;
868 if (! defined $struct->{ELEMENTS}) {
869 return;
872 start_flags($struct);
874 # see if the structure contains a conformant array. If it
875 # does, then it must be the last element of the structure, and
876 # we need to push the conformant length early, as it fits on
877 # the wire before the structure (and even before the structure
878 # alignment)
879 my $e = $struct->{ELEMENTS}[-1];
880 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
881 my $size = ParseExpr($e, util::array_size($e), "r->");
882 $e->{CONFORMANT_SIZE} = $size;
883 check_null_pointer($size);
884 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));\n";
887 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
888 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
889 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));\n";
892 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
894 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
896 my $align = struct_alignment($struct);
897 pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
899 foreach my $e (@{$struct->{ELEMENTS}}) {
900 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
903 pidl "buffers:\n";
904 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
905 foreach my $e (@{$struct->{ELEMENTS}}) {
906 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
909 pidl "\tndr_push_struct_end(ndr);\n";
911 pidl "done:\n";
913 end_flags($struct);
917 #####################################################################
918 # generate a push function for an enum
919 sub ParseEnumPush($)
921 my($enum) = shift;
922 my($type_fn) = util::enum_type_fn($enum);
924 start_flags($enum);
926 pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));\n";
928 end_flags($enum);
931 #####################################################################
932 # generate a pull function for an enum
933 sub ParseEnumPull($)
935 my($enum) = shift;
936 my($type_fn) = util::enum_type_fn($enum);
937 my($type_v_decl) = util::map_type(util::enum_type_fn($enum));
939 pidl "\t$type_v_decl v;\n";
940 start_flags($enum);
941 pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));\n";
942 pidl "\t*r = v;\n";
944 end_flags($enum);
947 #####################################################################
948 # generate a print function for an enum
949 sub ParseEnumPrint($)
951 my($enum) = shift;
953 pidl "\tconst char *val = NULL;\n\n";
955 start_flags($enum);
957 pidl "\tswitch (r) {\n";
958 my $els = \@{$enum->{ELEMENTS}};
959 foreach my $i (0 .. $#{$els}) {
960 my $e = ${$els}[$i];
961 chomp $e;
962 if ($e =~ /^(.*)=/) {
963 $e = $1;
965 pidl "\t\tcase $e: val = \"$e\"; break;\n";
968 pidl "\t}\n\n\tndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);\n";
970 end_flags($enum);
974 #####################################################################
975 # generate a push function for a bitmap
976 sub ParseBitmapPush($)
978 my($bitmap) = shift;
979 my($type_fn) = util::bitmap_type_fn($bitmap);
981 start_flags($bitmap);
983 pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));\n";
985 end_flags($bitmap);
988 #####################################################################
989 # generate a pull function for an bitmap
990 sub ParseBitmapPull($)
992 my($bitmap) = shift;
993 my($type_fn) = util::bitmap_type_fn($bitmap);
994 my($type_decl) = util::bitmap_type_decl($bitmap);
996 pidl "\t$type_decl v;\n";
997 start_flags($bitmap);
998 pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));\n";
999 pidl "\t*r = v;\n";
1001 end_flags($bitmap);
1004 #####################################################################
1005 # generate a print function for an bitmap
1006 sub ParseBitmapPrintElement($$)
1008 my($e) = shift;
1009 my($bitmap) = shift;
1010 my($type_decl) = util::bitmap_type_decl($bitmap);
1011 my($type_fn) = util::bitmap_type_fn($bitmap);
1012 my($name) = $bitmap->{PARENT}->{NAME};
1013 my($flag);
1015 if ($e =~ /^(\w+) .*$/) {
1016 $flag = "$1";
1017 } else {
1018 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
1021 pidl "\tndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);\n";
1024 #####################################################################
1025 # generate a print function for an bitmap
1026 sub ParseBitmapPrint($)
1028 my($bitmap) = shift;
1029 my($type_decl) = util::bitmap_type_decl($bitmap);
1030 my($type_fn) = util::bitmap_type_fn($bitmap);
1032 start_flags($bitmap);
1034 pidl "\tndr_print_$type_fn(ndr, name, r);\n";
1036 pidl "\tndr->depth++;\n";
1037 foreach my $e (@{$bitmap->{ELEMENTS}}) {
1038 ParseBitmapPrintElement($e, $bitmap);
1040 pidl "\tndr->depth--;\n";
1042 end_flags($bitmap);
1045 #####################################################################
1046 # generate a struct print function
1047 sub ParseStructPrint($)
1049 my($struct) = shift;
1051 if (! defined $struct->{ELEMENTS}) {
1052 return;
1055 start_flags($struct);
1057 pidl "\tndr->depth++;\n";
1058 foreach my $e (@{$struct->{ELEMENTS}}) {
1059 ParseElementPrintScalar($e, "r->");
1061 pidl "\tndr->depth--;\n";
1063 end_flags($struct);
1066 #####################################################################
1067 # parse a struct - pull side
1068 sub ParseStructPull($)
1070 my($struct) = shift;
1071 my $conform_e;
1073 if (! defined $struct->{ELEMENTS}) {
1074 return;
1077 # see if the structure contains a conformant array. If it
1078 # does, then it must be the last element of the structure, and
1079 # we need to pull the conformant length early, as it fits on
1080 # the wire before the structure (and even before the structure
1081 # alignment)
1082 my $e = $struct->{ELEMENTS}[-1];
1083 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
1084 $conform_e = $e;
1087 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
1088 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
1089 $conform_e = $e;
1092 if (defined $conform_e) {
1093 $conform_e = $e;
1094 pidl "\tuint32_t _conformant_size;\n";
1095 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
1098 # declare any internal pointers we need
1099 foreach my $e (@{$struct->{ELEMENTS}}) {
1100 if (need_wire_pointer($e)) {
1101 pidl "\tuint32_t _ptr_$e->{NAME};\n";
1105 start_flags($struct);
1107 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1109 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1111 if (defined $conform_e) {
1112 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &$conform_e->{CONFORMANT_SIZE}));\n";
1115 my $align = struct_alignment($struct);
1116 pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1118 foreach my $e (@{$struct->{ELEMENTS}}) {
1119 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1122 pidl "buffers:\n";
1123 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1124 foreach my $e (@{$struct->{ELEMENTS}}) {
1125 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1128 foreach my $e (@{$struct->{ELEMENTS}}) {
1129 CheckArraySizes($e, "r->");
1132 pidl "\tndr_pull_struct_end(ndr);\n";
1134 pidl "done:\n";
1136 end_flags($struct);
1139 #####################################################################
1140 # calculate size of ndr struct
1141 sub ParseStructNdrSize($)
1143 my $t = shift;
1144 my $static = fn_prefix($t);
1145 my $sizevar;
1147 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)\n";
1148 pidl "{\n";
1149 if (my $flags = util::has_property($t, "flag")) {
1150 pidl "\tflags |= $flags;\n";
1152 pidl "\treturn ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});\n";
1153 pidl "}\n\n";
1156 #####################################################################
1157 # calculate size of ndr struct
1158 sub ParseUnionNdrSize($)
1160 my $t = shift;
1161 my $static = fn_prefix($t);
1162 my $sizevar;
1164 pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)\n";
1165 pidl "{\n";
1166 if (my $flags = util::has_property($t, "flag")) {
1167 pidl "\tflags |= $flags;\n";
1169 pidl "\treturn ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});\n";
1170 pidl "}\n\n";
1173 #####################################################################
1174 # parse a union - push side
1175 sub ParseUnionPush($)
1177 my $e = shift;
1178 my $have_default = 0;
1180 start_flags($e);
1182 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1184 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
1186 # my $align = union_alignment($e);
1187 # pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
1189 pidl "\tswitch (level) {\n";
1190 foreach my $el (@{$e->{ELEMENTS}}) {
1191 if (util::has_property($el, "default")) {
1192 pidl "\tdefault:\n";
1193 $have_default = 1;
1194 } else {
1195 pidl "\tcase $el->{PROPERTIES}->{case}:\n";
1197 if ($el->{TYPE} ne "EMPTY") {
1198 ParseElementPushScalar($el, "r->", "NDR_SCALARS");
1200 pidl "\tbreak;\n\n";
1202 if (! $have_default) {
1203 pidl "\tdefault:\n";
1204 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1206 pidl "\t}\n";
1207 pidl "buffers:\n";
1208 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1209 pidl "\tswitch (level) {\n";
1210 foreach my $el (@{$e->{ELEMENTS}}) {
1211 if (util::has_property($el, "default")) {
1212 pidl "\tdefault:\n";
1213 } else {
1214 pidl "\tcase $el->{PROPERTIES}->{case}:\n";
1216 if ($el->{TYPE} ne "EMPTY") {
1217 ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
1219 pidl "\tbreak;\n\n";
1221 if (! $have_default) {
1222 pidl "\tdefault:\n";
1223 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1225 pidl "\t}\n";
1226 pidl "\tndr_push_struct_end(ndr);\n";
1227 pidl "done:\n";
1228 end_flags($e);
1231 #####################################################################
1232 # print a union
1233 sub ParseUnionPrint($)
1235 my $e = shift;
1236 my $have_default = 0;
1238 start_flags($e);
1240 pidl "\tswitch (level) {\n";
1241 foreach my $el (@{$e->{ELEMENTS}}) {
1242 if (util::has_property($el, "default")) {
1243 $have_default = 1;
1244 pidl "\tdefault:\n";
1245 } else {
1246 pidl "\tcase $el->{PROPERTIES}->{case}:\n";
1248 if ($el->{TYPE} ne "EMPTY") {
1249 ParseElementPrintScalar($el, "r->");
1251 pidl "\tbreak;\n\n";
1253 if (! $have_default) {
1254 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
1256 pidl "\t}\n";
1258 end_flags($e);
1261 #####################################################################
1262 # parse a union - pull side
1263 sub ParseUnionPull($)
1265 my $e = shift;
1266 my $have_default = 0;
1268 start_flags($e);
1270 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1272 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1274 # my $align = union_alignment($e);
1275 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1277 pidl "\tswitch (level) {\n";
1278 foreach my $el (@{$e->{ELEMENTS}}) {
1279 if (util::has_property($el, "default")) {
1280 pidl "\tdefault: {\n";
1281 $have_default = 1;
1282 } else {
1283 pidl "\tcase $el->{PROPERTIES}->{case}: {\n";
1285 if ($el->{TYPE} ne "EMPTY") {
1286 if ($el->{POINTERS}) {
1287 pidl "\t\tuint32_t _ptr_$el->{NAME};\n";
1289 ParseElementPullScalar($el, "r->", "NDR_SCALARS");
1291 pidl "\tbreak; }\n\n";
1293 if (! $have_default) {
1294 pidl "\tdefault:\n";
1295 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1297 pidl "\t}\n";
1298 pidl "buffers:\n";
1299 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1300 pidl "\tswitch (level) {\n";
1301 foreach my $el (@{$e->{ELEMENTS}}) {
1302 if (util::has_property($el, "default")) {
1303 pidl "\tdefault:\n";
1304 } else {
1305 pidl "\tcase $el->{PROPERTIES}->{case}:\n";
1307 if ($el->{TYPE} ne "EMPTY") {
1308 ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
1310 pidl "\tbreak;\n\n";
1312 if (! $have_default) {
1313 pidl "\tdefault:\n";
1314 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1316 pidl "\t}\n";
1317 pidl "\tndr_pull_struct_end(ndr);\n";
1318 pidl "done:\n";
1319 end_flags($e);
1323 #####################################################################
1324 # parse a type
1325 sub ParseTypePush($)
1327 my($data) = shift;
1329 ($data->{TYPE} eq "STRUCT") &&
1330 ParseStructPush($data);
1331 ($data->{TYPE} eq "UNION") &&
1332 ParseUnionPush($data);
1333 ($data->{TYPE} eq "ENUM") &&
1334 ParseEnumPush($data);
1335 ($data->{TYPE} eq "BITMAP") &&
1336 ParseBitmapPush($data);
1339 #####################################################################
1340 # generate a print function for a type
1341 sub ParseTypePrint($)
1343 my($data) = shift;
1345 ($data->{TYPE} eq "STRUCT") &&
1346 ParseStructPrint($data);
1347 ($data->{TYPE} eq "UNION") &&
1348 ParseUnionPrint($data);
1349 ($data->{TYPE} eq "ENUM") &&
1350 ParseEnumPrint($data);
1351 ($data->{TYPE} eq "BITMAP") &&
1352 ParseBitmapPrint($data);
1355 #####################################################################
1356 # parse a type
1357 sub ParseTypePull($)
1359 my($data) = shift;
1361 ($data->{TYPE} eq "STRUCT") &&
1362 ParseStructPull($data);
1363 ($data->{TYPE} eq "UNION") &&
1364 ParseUnionPull($data);
1365 ($data->{TYPE} eq "ENUM") &&
1366 ParseEnumPull($data);
1367 ($data->{TYPE} eq "BITMAP") &&
1368 ParseBitmapPull($data);
1371 #####################################################################
1372 # parse a typedef - push side
1373 sub ParseTypedefPush($)
1375 my($e) = shift;
1376 my $static = fn_prefix($e);
1378 if (! needed::is_needed("push_$e->{NAME}")) {
1379 # print "push_$e->{NAME} not needed\n";
1380 return;
1383 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1384 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1387 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1388 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
1389 pidl "\n{\n";
1390 ParseTypePush($e->{DATA});
1391 pidl "\treturn NT_STATUS_OK;\n";
1392 pidl "}\n\n";
1395 if ($e->{DATA}->{TYPE} eq "UNION") {
1396 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1397 pidl "\n{\n";
1398 ParseTypePush($e->{DATA});
1399 pidl "\treturn NT_STATUS_OK;\n";
1400 pidl "}\n\n";
1403 if ($e->{DATA}->{TYPE} eq "ENUM") {
1404 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, enum $e->{NAME} r)";
1405 pidl "\n{\n";
1406 ParseTypePush($e->{DATA});
1407 pidl "\treturn NT_STATUS_OK;\n";
1408 pidl "}\n\n";
1411 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1412 my $type_decl = util::bitmap_type_decl($e->{DATA});
1413 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, $type_decl r)";
1414 pidl "\n{\n";
1415 ParseTypePush($e->{DATA});
1416 pidl "\treturn NT_STATUS_OK;\n";
1417 pidl "}\n\n";
1422 #####################################################################
1423 # parse a typedef - pull side
1424 sub ParseTypedefPull($)
1426 my($e) = shift;
1427 my $static = fn_prefix($e);
1429 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1430 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1433 if (! needed::is_needed("pull_$e->{NAME}")) {
1434 # print "pull_$e->{NAME} not needed\n";
1435 return;
1438 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1439 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
1440 pidl "\n{\n";
1441 ParseTypePull($e->{DATA});
1442 pidl "\treturn NT_STATUS_OK;\n";
1443 pidl "}\n\n";
1446 if ($e->{DATA}->{TYPE} eq "UNION") {
1447 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1448 pidl "\n{\n";
1449 ParseTypePull($e->{DATA});
1450 pidl "\treturn NT_STATUS_OK;\n";
1451 pidl "}\n\n";
1454 if ($e->{DATA}->{TYPE} eq "ENUM") {
1455 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, enum $e->{NAME} *r)";
1456 pidl "\n{\n";
1457 ParseTypePull($e->{DATA});
1458 pidl "\treturn NT_STATUS_OK;\n";
1459 pidl "}\n\n";
1462 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1463 my $type_decl = util::bitmap_type_decl($e->{DATA});
1464 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, $type_decl *r)";
1465 pidl "\n{\n";
1466 ParseTypePull($e->{DATA});
1467 pidl "\treturn NT_STATUS_OK;\n";
1468 pidl "}\n\n";
1473 #####################################################################
1474 # parse a typedef - print side
1475 sub ParseTypedefPrint($)
1477 my($e) = shift;
1479 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1480 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1483 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1484 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1485 pidl "\n{\n";
1486 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1487 ParseTypePrint($e->{DATA});
1488 pidl "}\n\n";
1491 if ($e->{DATA}->{TYPE} eq "UNION") {
1492 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1493 pidl "\n{\n";
1494 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1495 ParseTypePrint($e->{DATA});
1496 pidl "}\n\n";
1499 if ($e->{DATA}->{TYPE} eq "ENUM") {
1500 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1501 pidl "\n{\n";
1502 ParseTypePrint($e->{DATA});
1503 pidl "}\n\n";
1506 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1507 my $type_decl = util::bitmap_type_decl($e->{DATA});
1508 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1509 pidl "\n{\n";
1510 ParseTypePrint($e->{DATA});
1511 pidl "}\n\n";
1515 #####################################################################
1516 ## calculate the size of a structure
1517 sub ParseTypedefNdrSize($)
1519 my($t) = shift;
1520 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1521 return;
1524 ($t->{DATA}->{TYPE} eq "STRUCT") &&
1525 ParseStructNdrSize($t);
1527 ($t->{DATA}->{TYPE} eq "UNION") &&
1528 ParseUnionNdrSize($t);
1531 #####################################################################
1532 # parse a function - print side
1533 sub ParseFunctionPrint($)
1535 my($fn) = shift;
1537 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1538 pidl "\n{\n";
1539 pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1540 pidl "\tndr->depth++;\n";
1542 pidl "\tif (flags & NDR_SET_VALUES) {\n";
1543 pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n";
1544 pidl "\t}\n";
1546 pidl "\tif (flags & NDR_IN) {\n";
1547 pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
1548 pidl "\tndr->depth++;\n";
1550 foreach my $e (@{$fn->{ELEMENTS}}) {
1551 if (util::has_property($e, "in")) {
1552 ParseElementPrintScalar($e, "r->in.");
1555 pidl "\tndr->depth--;\n";
1556 pidl "\t}\n";
1558 pidl "\tif (flags & NDR_OUT) {\n";
1559 pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
1560 pidl "\tndr->depth++;\n";
1561 foreach my $e (@{$fn->{ELEMENTS}}) {
1562 if (util::has_property($e, "out")) {
1563 ParseElementPrintScalar($e, "r->out.");
1566 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1567 my $cprefix = "&";
1568 $cprefix = "" if (is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here
1569 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);\n";
1571 pidl "\tndr->depth--;\n";
1572 pidl "\t}\n";
1574 pidl "\tndr->depth--;\n";
1575 pidl "}\n\n";
1579 #####################################################################
1580 # parse a function element
1581 sub ParseFunctionElementPush($$)
1583 my $e = shift;
1584 my $inout = shift;
1586 if (util::array_size($e)) {
1587 if (need_wire_pointer($e)) {
1588 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n";
1589 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1590 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1591 pidl "\t}\n";
1592 } else {
1593 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1595 } else {
1596 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1598 if ($e->{POINTERS}) {
1599 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1604 #####################################################################
1605 # parse a function
1606 sub ParseFunctionPush($)
1608 my($fn) = shift;
1609 my $static = fn_prefix($fn);
1611 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1613 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1615 foreach my $e (@{$fn->{ELEMENTS}}) {
1616 if (util::has_property($e, "in")) {
1617 ParseFunctionElementPush($e, "in");
1621 pidl "\nndr_out:\n";
1622 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1624 foreach my $e (@{$fn->{ELEMENTS}}) {
1625 if (util::has_property($e, "out")) {
1626 ParseFunctionElementPush($e, "out");
1630 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1631 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));\n";
1634 pidl "\ndone:\n";
1635 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1638 #####################################################################
1639 # parse a function element
1640 sub ParseFunctionElementPull($$)
1642 my $e = shift;
1643 my $inout = shift;
1645 if (util::array_size($e)) {
1646 if (need_wire_pointer($e)) {
1647 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
1648 pidl "\tr->$inout.$e->{NAME} = NULL;\n";
1649 pidl "\tif (_ptr_$e->{NAME}) {\n";
1650 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1651 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1652 } else {
1653 pidl "\t{\n";
1655 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1656 pidl "\t}\n";
1657 } else {
1658 if ($inout eq "out" && util::has_property($e, "ref")) {
1659 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n";
1660 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1661 pidl "\t}\n";
1663 if ($inout eq "in" && util::has_property($e, "ref")) {
1664 pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1667 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1668 if ($e->{POINTERS}) {
1669 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1675 ############################################################
1676 # allocate ref variables
1677 sub AllocateRefVars($)
1679 my $e = shift;
1680 my $asize = util::array_size($e);
1682 # note that if the variable is also an "in"
1683 # variable then we copy the initial value from
1684 # the in side
1686 if (!defined $asize) {
1687 # its a simple variable
1688 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1689 if (util::has_property($e, "in")) {
1690 pidl "\t*r->out.$e->{NAME} = *r->in.$e->{NAME};\n";
1691 } else {
1692 pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n";
1694 return;
1697 # its an array
1698 my $size = ParseExpr($e, $asize, "r->out.");
1699 check_null_pointer($size);
1700 pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);\n";
1701 if (util::has_property($e, "in")) {
1702 pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));\n";
1703 } else {
1704 pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n";
1709 #####################################################################
1710 # parse a function
1711 sub ParseFunctionPull($)
1713 my($fn) = shift;
1714 my $static = fn_prefix($fn);
1716 # pull function args
1717 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1719 # declare any internal pointers we need
1720 foreach my $e (@{$fn->{ELEMENTS}}) {
1721 if (need_wire_pointer($e)) {
1722 pidl "\tuint32_t _ptr_$e->{NAME};\n";
1726 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1728 # auto-init the out section of a structure. I originally argued that
1729 # this was a bad idea as it hides bugs, but coping correctly
1730 # with initialisation and not wiping ref vars is turning
1731 # out to be too tricky (tridge)
1732 foreach my $e (@{$fn->{ELEMENTS}}) {
1733 if (util::has_property($e, "out")) {
1734 pidl "\tZERO_STRUCT(r->out);\n\n";
1735 last;
1739 foreach my $e (@{$fn->{ELEMENTS}}) {
1740 if (util::has_property($e, "in")) {
1741 ParseFunctionElementPull($e, "in");
1743 # we need to allocate any reference output variables, so that
1744 # a dcerpc backend can be sure they are non-null
1745 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1746 AllocateRefVars($e);
1750 foreach my $e (@{$fn->{ELEMENTS}}) {
1751 if (util::has_property($e, "in")) {
1752 CheckArraySizes($e, "r->in.");
1756 pidl "\nndr_out:\n";
1757 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1759 foreach my $e (@{$fn->{ELEMENTS}}) {
1760 if (util::has_property($e, "out")) {
1761 ParseFunctionElementPull($e, "out");
1765 foreach my $e (@{$fn->{ELEMENTS}}) {
1766 if (util::has_property($e, "out")) {
1767 CheckArraySizes($e, "r->out.");
1771 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1772 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));\n";
1775 pidl "\ndone:\n";
1776 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1779 #####################################################################
1780 # produce a function call table
1781 sub FunctionTable($)
1783 my($interface) = shift;
1784 my($data) = $interface->{INHERITED_DATA};
1785 my $count = 0;
1786 my $uname = uc $interface->{NAME};
1788 foreach my $d (@{$data}) {
1789 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1792 return if ($count == 0);
1794 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n";
1795 foreach my $d (@{$data}) {
1796 if ($d->{TYPE} eq "FUNCTION") {
1797 pidl "\t{\n";
1798 pidl "\t\t\"$d->{NAME}\",\n";
1799 pidl "\t\tsizeof(struct $d->{NAME}),\n";
1800 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},\n";
1801 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},\n";
1802 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}\n";
1803 pidl "\t},\n";
1806 pidl "\t{ NULL, 0, NULL, NULL, NULL }\n};\n\n";
1808 # If no endpoint is set, default to the interface name as a named pipe
1809 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1810 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1813 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1814 my $endpoint_count = $#e + 1;
1816 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n";
1817 foreach my $ep (@e) {
1818 pidl "\t$ep, \n";
1820 pidl "};\n\n";
1822 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n";
1823 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n";
1824 pidl "};\n\n";
1826 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {\n";
1827 pidl "\t\"$interface->{NAME}\",\n";
1828 pidl "\tDCERPC_$uname\_UUID,\n";
1829 pidl "\tDCERPC_$uname\_VERSION,\n";
1830 pidl "\tDCERPC_$uname\_HELPSTRING,\n";
1831 pidl "\t$count,\n";
1832 pidl "\t$interface->{NAME}\_calls,\n";
1833 pidl "\t&$interface->{NAME}\_endpoints\n";
1834 pidl "};\n\n";
1836 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)\n";
1837 pidl "{\n";
1838 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});\n";
1839 pidl "}\n\n";
1842 #####################################################################
1843 # parse the interface definitions
1844 sub ParseInterface($)
1846 my($interface) = shift;
1847 my($data) = $interface->{DATA};
1849 # Push functions
1850 foreach my $d (@{$data}) {
1851 ($d->{TYPE} eq "TYPEDEF") &&
1852 ParseTypedefPush($d);
1853 ($d->{TYPE} eq "FUNCTION") &&
1854 ParseFunctionPush($d);
1857 # Pull functions
1858 foreach my $d (@{$data}) {
1859 ($d->{TYPE} eq "TYPEDEF") &&
1860 ParseTypedefPull($d);
1861 ($d->{TYPE} eq "FUNCTION") &&
1862 ParseFunctionPull($d);
1865 # Print functions
1866 foreach my $d (@{$data}) {
1867 if ($d->{TYPE} eq "TYPEDEF" &&
1868 !util::has_property($d, "noprint")) {
1869 ParseTypedefPrint($d);
1871 if ($d->{TYPE} eq "FUNCTION" &&
1872 !util::has_property($d, "noprint")) {
1873 ParseFunctionPrint($d);
1877 # Size functions
1878 foreach my $d (@{$data}) {
1879 ($d->{TYPE} eq "TYPEDEF") &&
1880 ParseTypedefNdrSize($d);
1883 FunctionTable($interface);
1886 sub RegistrationFunction($$)
1888 my $idl = shift;
1889 my $filename = shift;
1891 $filename =~ /.*\/ndr_(.*).c/;
1892 my $basename = $1;
1893 pidl "NTSTATUS dcerpc_$basename\_init(void)\n";
1894 pidl "{\n";
1895 pidl "\tNTSTATUS status = NT_STATUS_OK;\n";
1896 foreach my $interface (@{$idl}) {
1897 next if $interface->{TYPE} ne "INTERFACE";
1899 my $data = $interface->{INHERITED_DATA};
1900 my $count = 0;
1901 foreach my $d (@{$data}) {
1902 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1905 next if ($count == 0);
1907 pidl "\tstatus = dcerpc_ndr_$interface->{NAME}_init();\n";
1908 pidl "\tif (NT_STATUS_IS_ERR(status)) {\n";
1909 pidl "\t\treturn status;\n";
1910 pidl "\t}\n\n";
1912 pidl "\treturn status;\n";
1913 pidl "}\n\n";
1916 sub CheckPointerTypes($$)
1918 my $s = shift;
1919 my $default = shift;
1921 foreach my $e (@{$s->{ELEMENTS}}) {
1922 if ($e->{POINTERS}) {
1923 if (not defined(pointer_type($e))) {
1924 $e->{PROPERTIES}->{$default} = 1;
1927 if (pointer_type($e) eq "ptr") {
1928 print "Warning: ptr is not supported by pidl yet\n";
1934 sub LoadInterface($)
1936 my $x = shift;
1938 if (not util::has_property($x, "pointer_default")) {
1939 $x->{PROPERTIES}->{pointer_default} = "ptr";
1942 foreach my $d (@{$x->{DATA}}) {
1943 if ($d->{TYPE} eq "DECLARE" or $d->{TYPE} eq "TYPEDEF") {
1944 $typedefs{$d->{NAME}} = $d;
1945 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
1946 CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default});
1949 if ($d->{TYPE} eq "FUNCTION") {
1950 CheckPointerTypes($d, $x->{PROPERTIES}->{pointer_default});
1955 sub Load($)
1957 my $idl = shift;
1959 foreach my $x (@{$idl}) {
1960 LoadInterface($x);
1964 #####################################################################
1965 # parse a parsed IDL structure back into an IDL file
1966 sub Parse($$)
1968 my($idl) = shift;
1969 my($filename) = shift;
1970 my $h_filename = $filename;
1971 $res = "";
1973 Load($idl);
1975 if ($h_filename =~ /(.*)\.c/) {
1976 $h_filename = "$1.h";
1979 pidl "/* parser auto-generated by pidl */\n\n";
1980 pidl "#include \"includes.h\"\n";
1981 pidl "#include \"$h_filename\"\n\n";
1983 foreach my $x (@{$idl}) {
1984 if ($x->{TYPE} eq "INTERFACE") {
1985 needed::BuildNeeded($x);
1986 ParseInterface($x);
1990 RegistrationFunction($idl, $filename);
1992 return $res;