1 ###################################################
2 # Samba4 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
13 # the list of needed functions
21 #####################################################################
22 # parse a properties list
23 sub ParseProperties($)
26 foreach my $d (@{$props}) {
27 if (ref($d) ne "HASH") {
30 foreach my $k (keys %{$d}) {
31 pidl "[$k($d->{$k})] ";
37 ###################################
38 # find a sibling var in a structure
43 my($fn) = $e->{PARENT};
45 if ($name =~ /\*(.*)/) {
49 if ($fn->{TYPE} eq "FUNCTION") {
50 for my $e2 (@{$fn->{DATA}}) {
51 if ($e2->{NAME} eq $name) {
57 for my $e2 (@{$fn->{ELEMENTS}}) {
58 if ($e2->{NAME} eq $name) {
62 die "invalid sibling '$name'";
65 ####################################################################
66 # work out the name of a size_is() variable
67 sub find_size_var($$$)
71 my($var_prefix) = shift;
73 my($fn) = $e->{PARENT};
75 if (util::is_constant($size)) {
79 if ($size =~ /ndr->|\(/) {
85 if ($size =~ /\*(.*)/) {
90 if ($fn->{TYPE} ne "FUNCTION") {
91 return $prefix . "r->$size";
94 my $e2 = find_sibling($e, $size);
96 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
97 return $prefix . "$var_prefix$size";
99 if (util::has_property($e2, "in")) {
100 return $prefix . "r->in.$size";
102 if (util::has_property($e2, "out")) {
103 return $prefix . "r->out.$size";
106 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
109 #####################################################################
110 # check that a variable we get from find_size_var isn't a null pointer
111 sub check_null_pointer($)
114 if ($size =~ /^\*/) {
115 my $size2 = substr($size, 1);
116 pidl "\tif ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;\n";
120 #####################################################################
121 # check that a variable we get from find_size_var isn't a null pointer
122 # void return varient
123 sub check_null_pointer_void($)
126 if ($size =~ /^\*/) {
127 my $size2 = substr($size, 1);
128 pidl "\tif ($size2 == NULL) return;\n";
133 #####################################################################
134 # work out is a parse function should be declared static or not
138 if ($fn->{TYPE} eq "TYPEDEF") {
139 if (util::has_property($fn, "public")) {
144 if ($fn->{TYPE} eq "FUNCTION") {
145 if (util::has_property($fn, "public")) {
153 ###################################################################
154 # setup any special flags for an element or structure
158 my $flags = util::has_property($e, "flag");
159 if (defined $flags) {
160 pidl "\t{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;\n";
161 pidl "\tndr_set_flags(&ndr->flags, $flags);\n";
165 ###################################################################
166 # end any special flags for an element or structure
170 my $flags = util::has_property($e, "flag");
171 if (defined $flags) {
172 pidl "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n";
177 #####################################################################
178 # work out the correct alignment for a structure
184 for my $e (@{$s->{ELEMENTS}}) {
187 if (!util::need_wire_pointer($e)
188 && defined $structs{$e->{TYPE}}) {
189 if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") {
190 $a = struct_alignment($structs{$e->{TYPE}}->{DATA});
191 } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") {
192 if (defined $structs{$e->{TYPE}}->{DATA}) {
193 $a = union_alignment($structs{$e->{TYPE}}->{DATA});
197 $a = util::type_align($e);
208 #####################################################################
209 # work out the correct alignment for a union
216 foreach my $e (@{$u->{DATA}}) {
219 if ($e->{TYPE} eq "EMPTY") {
223 if (!util::need_wire_pointer($e)
224 && defined $structs{$e->{DATA}->{TYPE}}) {
225 my $s = $structs{$e->{DATA}->{TYPE}};
226 if ($s->{DATA}->{TYPE} eq "STRUCT") {
227 $a = struct_alignment($s->{DATA});
228 } elsif ($s->{DATA}->{TYPE} eq "UNION") {
229 $a = union_alignment($s->{DATA});
232 $a = util::type_align($e->{DATA});
243 #####################################################################
244 # parse an array - push side
245 sub ParseArrayPush($$$)
248 my $var_prefix = shift;
249 my $ndr_flags = shift;
251 my $size = find_size_var($e, util::array_size($e), $var_prefix);
253 if (defined $e->{CONFORMANT_SIZE}) {
254 # the conformant size has already been pushed
255 } elsif (!util::is_inline_array($e)) {
256 # we need to emit the array size
257 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
260 if (my $length = util::has_property($e, "length_is")) {
261 $length = find_size_var($e, $length, $var_prefix);
262 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n";
263 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n";
267 if (util::is_scalar_type($e->{TYPE})) {
268 pidl "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
270 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";
274 #####################################################################
276 sub ParseArrayPrint($$)
279 my $var_prefix = shift;
280 my $size = find_size_var($e, util::array_size($e), $var_prefix);
281 my $length = util::has_property($e, "length_is");
283 if (defined $length) {
284 $size = find_size_var($e, $length, $var_prefix);
287 if (util::is_scalar_type($e->{TYPE})) {
288 pidl "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n";
290 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";
294 #####################################################################
295 # check the size_is and length_is constraints
296 sub CheckArraySizes($$)
299 my $var_prefix = shift;
301 if (!defined $e->{CONFORMANT_SIZE} &&
302 util::has_property($e, "size_is")) {
303 my $size = find_size_var($e, util::array_size($e), $var_prefix);
304 pidl "\tif ($var_prefix$e->{NAME}) {\n";
305 check_null_pointer($size);
306 pidl "\t\tNDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));\n";
310 if (my $length = util::has_property($e, "length_is")) {
311 $length = find_size_var($e, $length, $var_prefix);
312 pidl "\tif ($var_prefix$e->{NAME}) {\n";
313 check_null_pointer($length);
314 pidl "\t\tNDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));\n";
320 #####################################################################
321 # parse an array - pull side
322 sub ParseArrayPull($$$)
325 my $var_prefix = shift;
326 my $ndr_flags = shift;
328 my $size = find_size_var($e, util::array_size($e), $var_prefix);
329 my $alloc_size = $size;
331 # if this is a conformant array then we use that size to allocate, and make sure
332 # we allocate enough to pull the elements
333 if (defined $e->{CONFORMANT_SIZE}) {
334 $alloc_size = $e->{CONFORMANT_SIZE};
335 check_null_pointer($size);
336 pidl "\tif ($size > $alloc_size) {\n";
337 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
339 } elsif (!util::is_inline_array($e)) {
340 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
341 my $size2 = substr($size, 1);
342 pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n";
345 # non fixed arrays encode the size just before the array
346 pidl "\t\tNDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));\n";
347 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
350 if ((util::need_alloc($e) && !util::is_fixed_array($e)) ||
351 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
352 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
353 pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
357 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
358 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
359 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
360 pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
365 if (my $length = util::has_property($e, "length_is")) {
366 pidl "\t\tNDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));\n";
367 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
370 check_null_pointer($size);
371 if (util::is_scalar_type($e->{TYPE})) {
372 pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
374 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";
379 #####################################################################
380 # parse scalars in a structure element
381 sub ParseElementPushScalar($$$)
384 my($var_prefix) = shift;
385 my($ndr_flags) = shift;
386 my $cprefix = util::c_push_prefix($e);
387 my $sub_size = util::has_property($e, "subcontext");
391 if (my $value = util::has_property($e, "value")) {
392 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
395 if (util::has_property($e, "relative")) {
396 pidl "\tNDR_CHECK(ndr_push_relative1(ndr, $var_prefix$e->{NAME}));\n";
397 } elsif (util::is_inline_array($e)) {
398 ParseArrayPush($e, "r->", "NDR_SCALARS");
399 } elsif (util::need_wire_pointer($e)) {
400 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
401 } elsif (util::need_alloc($e)) {
402 # no scalar component
403 } elsif (my $switch = util::has_property($e, "switch_is")) {
404 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
405 } elsif (defined $sub_size) {
406 if (util::is_builtin_type($e->{TYPE})) {
407 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
409 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";
411 } elsif (util::is_builtin_type($e->{TYPE})) {
412 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
414 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
420 #####################################################################
421 # print scalars in a structure element
422 sub ParseElementPrintScalar($$)
425 my($var_prefix) = shift;
426 my $cprefix = util::c_push_prefix($e);
428 if (util::has_property($e, "noprint")) {
432 if (my $value = util::has_property($e, "value")) {
433 pidl "\tif (ndr->flags & LIBNDR_PRINT_SET_VALUES) {\n";
434 pidl "\t\t$cprefix$var_prefix$e->{NAME} = $value;\n";
438 if (util::is_fixed_array($e)) {
439 ParseElementPrintBuffer($e, $var_prefix);
440 } elsif (util::has_direct_buffers($e)) {
441 pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
442 pidl "\tndr->depth++;\n";
443 ParseElementPrintBuffer($e, $var_prefix);
444 pidl "\tndr->depth--;\n";
445 } elsif (my $switch = util::has_property($e, "switch_is")) {
446 ParseElementPrintSwitch($e, $var_prefix, $switch);
448 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
452 #####################################################################
453 # parse scalars in a structure element - pull size
454 sub ParseElementPullSwitch($$$$)
457 my($var_prefix) = shift;
458 my($ndr_flags) = shift;
460 my $switch_var = find_size_var($e, $switch, $var_prefix);
462 my $cprefix = util::c_pull_prefix($e);
464 my $utype = $structs{$e->{TYPE}};
466 check_null_pointer($switch_var);
468 if (!defined $utype ||
469 !util::has_property($utype, "nodiscriminant")) {
470 my $e2 = find_sibling($e, $switch);
471 my $type_decl = $e2->{TYPE};
472 my $type_fn = $e2->{TYPE};
473 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
474 if (util::is_enum($e2->{TYPE})) {
475 $type_decl = util::enum_type_decl($e2);
476 $type_fn = util::enum_type_fn($e2);
477 } elsif (util::is_bitmap($e2->{TYPE})) {
478 $type_decl = util::bitmap_type_decl($e2);
479 $type_fn = util::bitmap_type_fn($e2);
481 pidl "\t\t$type_decl _level;\n";
482 pidl "\t\tNDR_CHECK(ndr_pull_$type_fn(ndr, &_level));\n";
483 if ($switch_var =~ /r->in/) {
484 pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n";
486 pidl "\t\tif (_level != $switch_var) {\n";
488 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);\n";
490 if ($switch_var =~ /r->/) {
491 pidl "else { $switch_var = _level; }\n";
496 my $sub_size = util::has_property($e, "subcontext");
497 if (defined $sub_size) {
498 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
499 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";
502 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
508 #####################################################################
509 # push switch element
510 sub ParseElementPushSwitch($$$$)
513 my($var_prefix) = shift;
514 my($ndr_flags) = shift;
516 my $switch_var = find_size_var($e, $switch, $var_prefix);
517 my $cprefix = util::c_push_prefix($e);
519 check_null_pointer($switch_var);
521 my $utype = $structs{$e->{TYPE}};
522 if (!defined $utype ||
523 !util::has_property($utype, "nodiscriminant")) {
524 my $e2 = find_sibling($e, $switch);
525 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
526 pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, $switch_var));\n";
530 my $sub_size = util::has_property($e, "subcontext");
531 if (defined $sub_size) {
532 pidl "\tif(($ndr_flags) & NDR_SCALARS) {\n";
533 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";
536 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
540 #####################################################################
541 # print scalars in a structure element
542 sub ParseElementPrintSwitch($$$)
545 my($var_prefix) = shift;
547 my $switch_var = find_size_var($e, $switch, $var_prefix);
548 my $cprefix = util::c_push_prefix($e);
550 check_null_pointer_void($switch_var);
552 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
556 #####################################################################
557 # parse scalars in a structure element - pull size
558 sub ParseElementPullScalar($$$)
561 my($var_prefix) = shift;
562 my($ndr_flags) = shift;
563 my $cprefix = util::c_pull_prefix($e);
564 my $sub_size = util::has_property($e, "subcontext");
568 if (util::is_inline_array($e)) {
569 ParseArrayPull($e, "r->", "NDR_SCALARS");
570 } elsif (util::need_wire_pointer($e)) {
571 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
572 pidl "\tif (_ptr_$e->{NAME}) {\n";
573 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
574 if (util::has_property($e, "relative")) {
575 pidl "\t\tNDR_CHECK(ndr_pull_relative1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));\n";
578 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
580 } elsif (util::need_alloc($e)) {
581 # no scalar component
582 } elsif (my $switch = util::has_property($e, "switch_is")) {
583 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
584 } elsif (defined $sub_size) {
585 if (util::is_builtin_type($e->{TYPE})) {
586 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
588 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";
590 } elsif (util::is_builtin_type($e->{TYPE})) {
591 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
593 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
595 if (my $range = util::has_property($e, "range")) {
596 my ($low, $high) = split(/ /, $range, 2);
597 pidl "\tif ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {\n";
598 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");\n\t}\n";
604 #####################################################################
605 # parse buffers in a structure element
606 sub ParseElementPushBuffer($$$)
609 my($var_prefix) = shift;
610 my($ndr_flags) = shift;
611 my $cprefix = util::c_push_prefix($e);
612 my $sub_size = util::has_property($e, "subcontext");
614 if (util::is_pure_scalar($e)) {
620 if (util::need_wire_pointer($e)) {
621 pidl "\tif ($var_prefix$e->{NAME}) {\n";
622 if (util::has_property($e, "relative")) {
623 pidl "\t\tNDR_CHECK(ndr_push_relative2(ndr, $var_prefix$e->{NAME}));\n";
627 if (util::is_inline_array($e)) {
628 ParseArrayPush($e, "r->", "NDR_BUFFERS");
629 } elsif (util::array_size($e)) {
630 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
631 } elsif (my $switch = util::has_property($e, "switch_is")) {
632 if ($e->{POINTERS}) {
633 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
635 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
637 } elsif (defined $sub_size) {
638 if ($e->{POINTERS}) {
639 if (util::is_builtin_type($e->{TYPE})) {
640 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
642 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";
645 } elsif (util::is_builtin_type($e->{TYPE})) {
646 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
647 } elsif ($e->{POINTERS}) {
648 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
650 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
653 if (util::need_wire_pointer($e)) {
660 #####################################################################
661 # print buffers in a structure element
662 sub ParseElementPrintBuffer($$)
665 my($var_prefix) = shift;
666 my $cprefix = util::c_push_prefix($e);
668 if (util::need_wire_pointer($e)) {
669 pidl "\tif ($var_prefix$e->{NAME}) {\n";
672 if (util::array_size($e)) {
673 ParseArrayPrint($e, $var_prefix)
674 } elsif (my $switch = util::has_property($e, "switch_is")) {
675 ParseElementPrintSwitch($e, $var_prefix, $switch);
677 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
680 if (util::need_wire_pointer($e)) {
686 #####################################################################
687 # parse buffers in a structure element - pull side
688 sub ParseElementPullBuffer($$$)
691 my($var_prefix) = shift;
692 my($ndr_flags) = shift;
693 my $cprefix = util::c_pull_prefix($e);
694 my $sub_size = util::has_property($e, "subcontext");
696 if (util::is_pure_scalar($e)) {
702 if (util::need_wire_pointer($e)) {
703 pidl "\tif ($var_prefix$e->{NAME}) {\n";
704 if (util::has_property($e, "relative")) {
705 pidl "\t\tstruct ndr_pull_save _relative_save;\n";
706 pidl "\t\tndr_pull_save(ndr, &_relative_save);\n";
707 pidl "\t\tNDR_CHECK(ndr_pull_relative2(ndr, $var_prefix$e->{NAME}));\n";
711 if (util::is_inline_array($e)) {
712 ParseArrayPull($e, "r->", "NDR_BUFFERS");
713 } elsif (util::array_size($e)) {
714 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
715 } elsif (my $switch = util::has_property($e, "switch_is")) {
716 if ($e->{POINTERS}) {
717 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
719 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
721 } elsif (defined $sub_size) {
722 if ($e->{POINTERS}) {
723 if (util::is_builtin_type($e->{TYPE})) {
724 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
726 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";
729 } elsif (util::is_builtin_type($e->{TYPE})) {
730 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
731 } elsif ($e->{POINTERS}) {
732 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
734 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
737 if (util::need_wire_pointer($e)) {
738 if (util::has_property($e, "relative")) {
739 pidl "\t\tndr_pull_restore(ndr, &_relative_save);\n";
747 #####################################################################
749 sub ParseStructPush($)
753 if (! defined $struct->{ELEMENTS}) {
757 start_flags($struct);
759 # see if the structure contains a conformant array. If it
760 # does, then it must be the last element of the structure, and
761 # we need to push the conformant length early, as it fits on
762 # the wire before the structure (and even before the structure
764 my $e = $struct->{ELEMENTS}[-1];
765 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
766 my $size = find_size_var($e, util::array_size($e), "r->");
767 $e->{CONFORMANT_SIZE} = $size;
768 check_null_pointer($size);
769 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
772 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
773 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
774 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, ndr_string_array_size(ndr, r->$e->{NAME})));\n";
777 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
779 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
781 my $align = struct_alignment($struct);
782 pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
784 foreach my $e (@{$struct->{ELEMENTS}}) {
785 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
789 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
790 foreach my $e (@{$struct->{ELEMENTS}}) {
791 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
794 pidl "\tndr_push_struct_end(ndr);\n";
802 #####################################################################
803 # generate a push function for an enum
810 if (util::has_property($enum->{PARENT}, "v1_enum")) {
811 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, r));\n";
812 } elsif (util::has_property($enum->{PARENT}, "enum8bit")) {
813 pidl "\tNDR_CHECK(ndr_push_uint8(ndr, r));\n";
815 pidl "\tNDR_CHECK(ndr_push_uint16(ndr, r));\n";
821 #####################################################################
822 # generate a pull function for an enum
829 if (util::has_property($enum->{PARENT}, "v1_enum")) {
830 pidl "\tuint32_t v;\n";
831 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &v));\n";
832 } elsif (util::has_property($enum->{PARENT}, "enum8bit")) {
833 pidl "\tuint8_t v;\n";
834 pidl "\tNDR_CHECK(ndr_pull_uint8(ndr, &v));\n";
836 pidl "\tuint16_t v;\n";
837 pidl "\tNDR_CHECK(ndr_pull_uint16(ndr, &v));\n";
844 #####################################################################
845 # generate a print function for an enum
846 sub ParseEnumPrint($)
852 pidl "\tconst char *val = NULL;\n\n";
854 pidl "\tswitch (r) {\n";
855 my $els = \@{$enum->{ELEMENTS}};
856 foreach my $i (0 .. $#{$els}) {
859 if ($e =~ /^(.*)=/) {
862 pidl "\t\tcase $e: val = \"$e\"; break;\n";
865 pidl "\t}\n\n\tndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);\n";
871 #####################################################################
872 # generate a push function for a bitmap
873 sub ParseBitmapPush($)
876 my($type_decl) = util::bitmap_type_decl($bitmap);
877 my($type_fn) = util::bitmap_type_fn($bitmap);
879 start_flags($bitmap);
881 pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
886 #####################################################################
887 # generate a pull function for an bitmap
888 sub ParseBitmapPull($)
891 my($type_decl) = util::bitmap_type_decl($bitmap);
892 my($type_fn) = util::bitmap_type_fn($bitmap);
894 start_flags($bitmap);
896 pidl "\t$type_decl v;\n";
897 pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
903 #####################################################################
904 # generate a print function for an bitmap
905 sub ParseBintmapPrintElement($$)
909 my($type_decl) = util::bitmap_type_decl($bitmap);
910 my($type_fn) = util::bitmap_type_fn($bitmap);
911 my($name) = $bitmap->{PARENT}->{NAME};
914 if ($e =~ /^(\w+) .*$/) {
917 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
920 pidl "\tndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);\n";
923 #####################################################################
924 # generate a print function for an bitmap
925 sub ParseBitmapPrint($)
928 my($type_decl) = util::bitmap_type_decl($bitmap);
929 my($type_fn) = util::bitmap_type_fn($bitmap);
931 start_flags($bitmap);
933 pidl "\tndr_print_$type_fn(ndr, name, r);\n";
935 pidl "\tndr->depth++;\n";
936 foreach my $e (@{$bitmap->{ELEMENTS}}) {
937 ParseBintmapPrintElement($e, $bitmap);
939 pidl "\tndr->depth--;\n";
944 #####################################################################
945 # generate a struct print function
946 sub ParseStructPrint($)
950 if (! defined $struct->{ELEMENTS}) {
954 start_flags($struct);
956 pidl "\tndr->depth++;\n";
957 foreach my $e (@{$struct->{ELEMENTS}}) {
958 ParseElementPrintScalar($e, "r->");
960 pidl "\tndr->depth--;\n";
965 #####################################################################
966 # parse a struct - pull side
967 sub ParseStructPull($)
972 if (! defined $struct->{ELEMENTS}) {
976 # see if the structure contains a conformant array. If it
977 # does, then it must be the last element of the structure, and
978 # we need to pull the conformant length early, as it fits on
979 # the wire before the structure (and even before the structure
981 my $e = $struct->{ELEMENTS}[-1];
982 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
986 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
987 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
991 if (defined $conform_e) {
993 pidl "\tuint32_t _conformant_size;\n";
994 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
997 # declare any internal pointers we need
998 foreach my $e (@{$struct->{ELEMENTS}}) {
999 if (util::need_wire_pointer($e)) {
1000 pidl "\tuint32_t _ptr_$e->{NAME};\n";
1004 start_flags($struct);
1006 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1008 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1010 if (defined $conform_e) {
1011 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
1014 my $align = struct_alignment($struct);
1015 pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1017 foreach my $e (@{$struct->{ELEMENTS}}) {
1018 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1022 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1023 foreach my $e (@{$struct->{ELEMENTS}}) {
1024 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1027 foreach my $e (@{$struct->{ELEMENTS}}) {
1028 CheckArraySizes($e, "r->");
1031 pidl "\tndr_pull_struct_end(ndr);\n";
1038 #####################################################################
1039 # calculate size of ndr struct
1040 sub ParseStructNdrSize($)
1043 my $static = fn_prefix($t);
1046 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)\n";
1048 if (my $flags = util::has_property($t, "flag")) {
1049 pidl "\tflags |= $flags;\n";
1051 pidl "\treturn ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});\n";
1055 #####################################################################
1056 # parse a union - push side
1057 sub ParseUnionPush($)
1060 my $have_default = 0;
1064 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1066 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
1068 # my $align = union_alignment($e);
1069 # pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
1071 pidl "\tswitch (level) {\n";
1072 foreach my $el (@{$e->{DATA}}) {
1073 if ($el->{CASE} eq "default") {
1074 pidl "\tdefault:\n";
1077 pidl "\tcase $el->{CASE}:\n";
1079 if ($el->{TYPE} eq "UNION_ELEMENT") {
1080 ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
1082 pidl "\tbreak;\n\n";
1084 if (! $have_default) {
1085 pidl "\tdefault:\n";
1086 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1090 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1091 pidl "\tswitch (level) {\n";
1092 foreach my $el (@{$e->{DATA}}) {
1093 if ($el->{CASE} eq "default") {
1094 pidl "\tdefault:\n";
1096 pidl "\tcase $el->{CASE}:\n";
1098 if ($el->{TYPE} eq "UNION_ELEMENT") {
1099 ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1101 pidl "\tbreak;\n\n";
1103 if (! $have_default) {
1104 pidl "\tdefault:\n";
1105 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1108 pidl "\tndr_push_struct_end(ndr);\n";
1113 #####################################################################
1115 sub ParseUnionPrint($)
1118 my $have_default = 0;
1122 pidl "\tswitch (level) {\n";
1123 foreach my $el (@{$e->{DATA}}) {
1124 if ($el->{CASE} eq "default") {
1126 pidl "\tdefault:\n";
1128 pidl "\tcase $el->{CASE}:\n";
1130 if ($el->{TYPE} eq "UNION_ELEMENT") {
1131 ParseElementPrintScalar($el->{DATA}, "r->");
1133 pidl "\tbreak;\n\n";
1135 if (! $have_default) {
1136 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
1143 #####################################################################
1144 # parse a union - pull side
1145 sub ParseUnionPull($)
1148 my $have_default = 0;
1152 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1154 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1156 # my $align = union_alignment($e);
1157 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1159 pidl "\tswitch (level) {\n";
1160 foreach my $el (@{$e->{DATA}}) {
1161 if ($el->{CASE} eq "default") {
1162 pidl "\tdefault: {\n";
1165 pidl "\tcase $el->{CASE}: {\n";
1167 if ($el->{TYPE} eq "UNION_ELEMENT") {
1168 my $e2 = $el->{DATA};
1169 if ($e2->{POINTERS}) {
1170 pidl "\t\tuint32_t _ptr_$e2->{NAME};\n";
1172 ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
1174 pidl "\tbreak; }\n\n";
1176 if (! $have_default) {
1177 pidl "\tdefault:\n";
1178 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1182 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1183 pidl "\tswitch (level) {\n";
1184 foreach my $el (@{$e->{DATA}}) {
1185 if ($el->{CASE} eq "default") {
1186 pidl "\tdefault:\n";
1188 pidl "\tcase $el->{CASE}:\n";
1190 if ($el->{TYPE} eq "UNION_ELEMENT") {
1191 ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1193 pidl "\tbreak;\n\n";
1195 if (! $have_default) {
1196 pidl "\tdefault:\n";
1197 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1200 pidl "\tndr_pull_struct_end(ndr);\n";
1206 #####################################################################
1208 sub ParseTypePush($)
1212 if (ref($data) eq "HASH") {
1213 ($data->{TYPE} eq "STRUCT") &&
1214 ParseStructPush($data);
1215 ($data->{TYPE} eq "UNION") &&
1216 ParseUnionPush($data);
1217 ($data->{TYPE} eq "ENUM") &&
1218 ParseEnumPush($data);
1219 ($data->{TYPE} eq "BITMAP") &&
1220 ParseBitmapPush($data);
1224 #####################################################################
1225 # generate a print function for a type
1226 sub ParseTypePrint($)
1230 if (ref($data) eq "HASH") {
1231 ($data->{TYPE} eq "STRUCT") &&
1232 ParseStructPrint($data);
1233 ($data->{TYPE} eq "UNION") &&
1234 ParseUnionPrint($data);
1235 ($data->{TYPE} eq "ENUM") &&
1236 ParseEnumPrint($data);
1237 ($data->{TYPE} eq "BITMAP") &&
1238 ParseBitmapPrint($data);
1242 #####################################################################
1244 sub ParseTypePull($)
1248 if (ref($data) eq "HASH") {
1249 ($data->{TYPE} eq "STRUCT") &&
1250 ParseStructPull($data);
1251 ($data->{TYPE} eq "UNION") &&
1252 ParseUnionPull($data);
1253 ($data->{TYPE} eq "ENUM") &&
1254 ParseEnumPull($data);
1255 ($data->{TYPE} eq "BITMAP") &&
1256 ParseBitmapPull($data);
1260 #####################################################################
1261 # parse a typedef - push side
1262 sub ParseTypedefPush($)
1265 my $static = fn_prefix($e);
1267 if (! needed::is_needed("push_$e->{NAME}")) {
1268 # print "push_$e->{NAME} not needed\n";
1272 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1273 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1276 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1277 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
1279 ParseTypePush($e->{DATA});
1280 pidl "\treturn NT_STATUS_OK;\n";
1284 if ($e->{DATA}->{TYPE} eq "UNION") {
1285 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1287 ParseTypePush($e->{DATA});
1288 pidl "\treturn NT_STATUS_OK;\n";
1292 if ($e->{DATA}->{TYPE} eq "ENUM") {
1293 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, enum $e->{NAME} r)";
1295 ParseTypePush($e->{DATA});
1296 pidl "\treturn NT_STATUS_OK;\n";
1300 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1301 my $type_decl = util::bitmap_type_fn($e->{DATA});
1302 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, $type_decl r)";
1304 ParseTypePush($e->{DATA});
1305 pidl "\treturn NT_STATUS_OK;\n";
1311 #####################################################################
1312 # parse a typedef - pull side
1313 sub ParseTypedefPull($)
1316 my $static = fn_prefix($e);
1318 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1319 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1322 if (! needed::is_needed("pull_$e->{NAME}")) {
1323 # print "pull_$e->{NAME} not needed\n";
1327 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1328 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
1330 ParseTypePull($e->{DATA});
1331 pidl "\treturn NT_STATUS_OK;\n";
1335 if ($e->{DATA}->{TYPE} eq "UNION") {
1336 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1338 ParseTypePull($e->{DATA});
1339 pidl "\treturn NT_STATUS_OK;\n";
1343 if ($e->{DATA}->{TYPE} eq "ENUM") {
1344 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, enum $e->{NAME} *r)";
1346 ParseTypePull($e->{DATA});
1347 pidl "\treturn NT_STATUS_OK;\n";
1351 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1352 my $type_decl = util::bitmap_type_fn($e->{DATA});
1353 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, $type_decl *r)";
1355 ParseTypePull($e->{DATA});
1356 pidl "\treturn NT_STATUS_OK;\n";
1362 #####################################################################
1363 # parse a typedef - print side
1364 sub ParseTypedefPrint($)
1368 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1369 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1372 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1373 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1375 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1376 ParseTypePrint($e->{DATA});
1380 if ($e->{DATA}->{TYPE} eq "UNION") {
1381 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1383 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1384 ParseTypePrint($e->{DATA});
1388 if ($e->{DATA}->{TYPE} eq "ENUM") {
1389 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1391 ParseTypePrint($e->{DATA});
1395 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1396 my $type_decl = util::bitmap_type_fn($e->{DATA});
1397 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1399 ParseTypePrint($e->{DATA});
1404 #####################################################################
1405 ## calculate the size of a structure
1406 sub ParseTypedefNdrSize($)
1409 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1413 ($t->{DATA}->{TYPE} eq "STRUCT") &&
1414 ParseStructNdrSize($t);
1417 #####################################################################
1418 # parse a function - print side
1419 sub ParseFunctionPrint($)
1423 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1425 pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1426 pidl "\tndr->depth++;\n";
1428 pidl "\tif (flags & NDR_SET_VALUES) {\n";
1429 pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n";
1432 pidl "\tif (flags & NDR_IN) {\n";
1433 pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
1434 pidl "\tndr->depth++;\n";
1435 foreach my $e (@{$fn->{DATA}}) {
1436 if (util::has_property($e, "in")) {
1437 ParseElementPrintScalar($e, "r->in.");
1440 pidl "\tndr->depth--;\n";
1443 pidl "\tif (flags & NDR_OUT) {\n";
1444 pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
1445 pidl "\tndr->depth++;\n";
1446 foreach my $e (@{$fn->{DATA}}) {
1447 if (util::has_property($e, "out")) {
1448 ParseElementPrintScalar($e, "r->out.");
1451 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1452 if (util::is_scalar_type($fn->{RETURN_TYPE})) {
1453 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);\n";
1455 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
1458 pidl "\tndr->depth--;\n";
1461 pidl "\tndr->depth--;\n";
1466 #####################################################################
1467 # parse a function element
1468 sub ParseFunctionElementPush($$)
1473 if (util::array_size($e)) {
1474 if (util::need_wire_pointer($e)) {
1475 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n";
1476 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1477 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1480 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1483 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1484 if ($e->{POINTERS}) {
1485 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1490 #####################################################################
1492 sub ParseFunctionPush($)
1495 my $static = fn_prefix($fn);
1497 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1499 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1501 foreach my $e (@{$fn->{DATA}}) {
1502 if (util::has_property($e, "in")) {
1503 ParseFunctionElementPush($e, "in");
1507 pidl "\nndr_out:\n";
1508 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1510 foreach my $e (@{$fn->{DATA}}) {
1511 if (util::has_property($e, "out")) {
1512 ParseFunctionElementPush($e, "out");
1516 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1517 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n";
1521 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1524 #####################################################################
1525 # parse a function element
1526 sub ParseFunctionElementPull($$)
1531 if (util::array_size($e)) {
1532 if (util::need_wire_pointer($e)) {
1533 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
1534 pidl "\tr->$inout.$e->{NAME} = NULL;\n";
1535 pidl "\tif (_ptr_$e->{NAME}) {\n";
1536 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1537 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1541 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1544 if ($inout eq "out" && util::has_property($e, "ref")) {
1545 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n";
1546 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1549 if ($inout eq "in" && util::has_property($e, "ref")) {
1550 pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1553 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1554 if ($e->{POINTERS}) {
1555 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1561 ############################################################
1562 # allocate ref variables
1563 sub AllocateRefVars($)
1566 my $asize = util::array_size($e);
1568 # note that if the variable is also an "in"
1569 # variable then we copy the initial value from
1572 if (!defined $asize) {
1573 # its a simple variable
1574 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1575 if (util::has_property($e, "in")) {
1576 pidl "\t*r->out.$e->{NAME} = *r->in.$e->{NAME};\n";
1578 pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n";
1584 my $size = find_size_var($e, $asize, "r->out.");
1585 check_null_pointer($size);
1586 pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);\n";
1587 if (util::has_property($e, "in")) {
1588 pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));\n";
1590 pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n";
1595 #####################################################################
1597 sub ParseFunctionPull($)
1600 my $static = fn_prefix($fn);
1602 # pull function args
1603 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1605 # declare any internal pointers we need
1606 foreach my $e (@{$fn->{DATA}}) {
1607 if (util::need_wire_pointer($e)) {
1608 pidl "\tuint32_t _ptr_$e->{NAME};\n";
1612 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1614 # auto-init the out section of a structure. I originally argued that
1615 # this was a bad idea as it hides bugs, but coping correctly
1616 # with initialisation and not wiping ref vars is turning
1617 # out to be too tricky (tridge)
1618 foreach my $e (@{$fn->{DATA}}) {
1619 if (util::has_property($e, "out")) {
1620 pidl "\tZERO_STRUCT(r->out);\n\n";
1625 foreach my $e (@{$fn->{DATA}}) {
1626 if (util::has_property($e, "in")) {
1627 ParseFunctionElementPull($e, "in");
1629 # we need to allocate any reference output variables, so that
1630 # a dcerpc backend can be sure they are non-null
1631 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1632 AllocateRefVars($e);
1636 foreach my $e (@{$fn->{DATA}}) {
1637 if (util::has_property($e, "in")) {
1638 CheckArraySizes($e, "r->in.");
1642 pidl "\nndr_out:\n";
1643 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1645 foreach my $e (@{$fn->{DATA}}) {
1646 if (util::has_property($e, "out")) {
1647 ParseFunctionElementPull($e, "out");
1651 foreach my $e (@{$fn->{DATA}}) {
1652 if (util::has_property($e, "out")) {
1653 CheckArraySizes($e, "r->out.");
1657 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1658 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
1662 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1665 #####################################################################
1666 # produce a function call table
1667 sub FunctionTable($)
1669 my($interface) = shift;
1670 my($data) = $interface->{INHERITED_DATA};
1672 my $uname = uc $interface->{NAME};
1674 foreach my $d (@{$data}) {
1675 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1678 return if ($count == 0);
1680 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n";
1681 foreach my $d (@{$data}) {
1682 if ($d->{TYPE} eq "FUNCTION") {
1684 pidl "\t\t\"$d->{NAME}\",\n";
1685 pidl "\t\tsizeof(struct $d->{NAME}),\n";
1686 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},\n";
1687 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},\n";
1688 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}\n";
1692 pidl "\t{ NULL, 0, NULL, NULL }\n};\n\n";
1694 # If no endpoint is set, default to the interface name as a named pipe
1695 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1696 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1699 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1700 my $endpoint_count = $#e + 1;
1702 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n";
1703 foreach my $ep (@e) {
1708 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n";
1709 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n";
1712 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {\n";
1713 pidl "\t\"$interface->{NAME}\",\n";
1714 pidl "\tDCERPC_$uname\_UUID,\n";
1715 pidl "\tDCERPC_$uname\_VERSION,\n";
1716 pidl "\tDCERPC_$uname\_HELPSTRING,\n";
1718 pidl "\t$interface->{NAME}\_calls,\n";
1719 pidl "\t&$interface->{NAME}\_endpoints\n";
1722 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)\n";
1724 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});\n";
1728 #####################################################################
1729 # parse the interface definitions
1730 sub ParseInterface($)
1732 my($interface) = shift;
1733 my($data) = $interface->{DATA};
1735 foreach my $d (@{$data}) {
1736 if ($d->{TYPE} eq "TYPEDEF") {
1737 $structs{$d->{NAME}} = $d;
1741 foreach my $d (@{$data}) {
1742 ($d->{TYPE} eq "TYPEDEF") &&
1743 ParseTypedefPush($d);
1744 ($d->{TYPE} eq "FUNCTION") &&
1745 ParseFunctionPush($d);
1747 foreach my $d (@{$data}) {
1748 ($d->{TYPE} eq "TYPEDEF") &&
1749 ParseTypedefPull($d);
1750 ($d->{TYPE} eq "FUNCTION") &&
1751 ParseFunctionPull($d);
1753 foreach my $d (@{$data}) {
1754 if ($d->{TYPE} eq "TYPEDEF" &&
1755 !util::has_property($d, "noprint")) {
1756 ParseTypedefPrint($d);
1758 if ($d->{TYPE} eq "FUNCTION" &&
1759 !util::has_property($d, "noprint")) {
1760 ParseFunctionPrint($d);
1764 foreach my $d (@{$data}) {
1765 ($d->{TYPE} eq "TYPEDEF") &&
1766 ParseTypedefNdrSize($d);
1769 FunctionTable($interface);
1772 sub RegistrationFunction($$)
1775 my $filename = shift;
1777 $filename =~ /.*\/ndr_(.*).c/;
1779 pidl "NTSTATUS dcerpc_$basename\_init(void)\n";
1781 pidl "\tNTSTATUS status = NT_STATUS_OK;\n";
1782 foreach my $interface (@{$idl}) {
1783 next if $interface->{TYPE} ne "INTERFACE";
1785 my $data = $interface->{INHERITED_DATA};
1787 foreach my $d (@{$data}) {
1788 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1791 next if ($count == 0);
1793 pidl "\tstatus = dcerpc_ndr_$interface->{NAME}_init();\n";
1794 pidl "\tif (NT_STATUS_IS_ERR(status)) {\n";
1795 pidl "\t\treturn status;\n";
1798 pidl "\treturn status;\n";
1802 #####################################################################
1803 # parse a parsed IDL structure back into an IDL file
1807 my($filename) = shift;
1808 my $h_filename = $filename;
1810 if ($h_filename =~ /(.*)\.c/) {
1811 $h_filename = "$1.h";
1814 open(OUT, ">$filename") || die "can't open $filename";
1816 pidl "/* parser auto-generated by pidl */\n\n";
1817 pidl "#include \"includes.h\"\n";
1818 pidl "#include \"$h_filename\"\n\n";
1820 foreach my $x (@{$idl}) {
1821 if ($x->{TYPE} eq "INTERFACE") {
1822 needed::BuildNeeded($x);
1827 RegistrationFunction($idl, $filename);