r4557: support for [flags()] on typedef enum|bitmap
[Samba/gebeck_regimport.git] / source4 / build / pidl / parser.pm
blob077fcd438521d3e2c15eb04e78051255e4c62aa5
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
8 package IdlParser;
10 use strict;
11 use needed;
13 # the list of needed functions
14 my %structs;
16 sub pidl($)
18 print OUT shift;
21 #####################################################################
22 # parse a properties list
23 sub ParseProperties($)
25 my($props) = shift;
26 foreach my $d (@{$props}) {
27 if (ref($d) ne "HASH") {
28 pidl "[$d] ";
29 } else {
30 foreach my $k (keys %{$d}) {
31 pidl "[$k($d->{$k})] ";
37 ###################################
38 # find a sibling var in a structure
39 sub find_sibling($$)
41 my($e) = shift;
42 my($name) = shift;
43 my($fn) = $e->{PARENT};
45 if ($name =~ /\*(.*)/) {
46 $name = $1;
49 if ($fn->{TYPE} eq "FUNCTION") {
50 for my $e2 (@{$fn->{DATA}}) {
51 if ($e2->{NAME} eq $name) {
52 return $e2;
57 for my $e2 (@{$fn->{ELEMENTS}}) {
58 if ($e2->{NAME} eq $name) {
59 return $e2;
62 die "invalid sibling '$name'";
65 ####################################################################
66 # work out the name of a size_is() variable
67 sub find_size_var($$$)
69 my($e) = shift;
70 my($size) = shift;
71 my($var_prefix) = shift;
73 my($fn) = $e->{PARENT};
75 if (util::is_constant($size)) {
76 return $size;
79 if ($size =~ /ndr->|\(/) {
80 return $size;
83 my $prefix = "";
85 if ($size =~ /\*(.*)/) {
86 $size = $1;
87 $prefix = "*";
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($)
113 my $size = shift;
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($)
125 my $size = shift;
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
135 sub fn_prefix($)
137 my $fn = shift;
138 if ($fn->{TYPE} eq "TYPEDEF") {
139 if (util::has_property($fn, "public")) {
140 return "";
144 if ($fn->{TYPE} eq "FUNCTION") {
145 if (util::has_property($fn, "public")) {
146 return "";
149 return "static ";
153 ###################################################################
154 # setup any special flags for an element or structure
155 sub start_flags($)
157 my $e = shift;
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
167 sub end_flags($)
169 my $e = shift;
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
179 sub struct_alignment
181 my $s = shift;
183 my $align = 1;
184 for my $e (@{$s->{ELEMENTS}}) {
185 my $a = 1;
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});
196 } else {
197 $a = util::type_align($e);
200 if ($align < $a) {
201 $align = $a;
205 return $align;
208 #####################################################################
209 # work out the correct alignment for a union
210 sub union_alignment
212 my $u = shift;
214 my $align = 1;
216 foreach my $e (@{$u->{DATA}}) {
217 my $a = 1;
219 if ($e->{TYPE} eq "EMPTY") {
220 next;
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});
231 } else {
232 $a = util::type_align($e->{DATA});
235 if ($align < $a) {
236 $align = $a;
240 return $align;
243 #####################################################################
244 # parse an array - push side
245 sub ParseArrayPush($$$)
247 my $e = shift;
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";
264 $size = $length;
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";
269 } else {
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 #####################################################################
275 # print an array
276 sub ParseArrayPrint($$)
278 my $e = shift;
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";
289 } else {
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($$)
298 my $e = shift;
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";
307 pidl "\t}\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";
315 pidl "\t}\n";
320 #####################################################################
321 # parse an array - pull side
322 sub ParseArrayPull($$$)
324 my $e = shift;
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";
338 pidl "\t}\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";
361 pidl "\t}\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";
373 } else {
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($$$)
383 my($e) = shift;
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");
389 start_flags($e);
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";
408 } else {
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";
413 } else {
414 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
417 end_flags($e);
420 #####################################################################
421 # print scalars in a structure element
422 sub ParseElementPrintScalar($$)
424 my($e) = shift;
425 my($var_prefix) = shift;
426 my $cprefix = util::c_push_prefix($e);
428 if (util::has_property($e, "noprint")) {
429 return;
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";
435 pidl "\t}\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);
447 } else {
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($$$$)
456 my($e) = shift;
457 my($var_prefix) = shift;
458 my($ndr_flags) = shift;
459 my $switch = 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 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
473 if (util::is_enum($e2->{TYPE})) {
474 $type_decl = util::enum_type_decl($e2);
475 } elsif (util::is_bitmap($e2->{TYPE})) {
476 $type_decl = util::bitmap_type_decl($e2);
478 pidl "\t\t$type_decl _level;\n";
479 pidl "\t\tNDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, &_level));\n";
480 if ($switch_var =~ /r->in/) {
481 pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n";
482 } else {
483 pidl "\t\tif (_level != $switch_var) {\n";
485 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);\n";
486 pidl "\t\t}\n";
487 if ($switch_var =~ /r->/) {
488 pidl "else { $switch_var = _level; }\n";
490 pidl "\t}\n";
493 my $sub_size = util::has_property($e, "subcontext");
494 if (defined $sub_size) {
495 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
496 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";
497 pidl "\t}\n";
498 } else {
499 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
505 #####################################################################
506 # push switch element
507 sub ParseElementPushSwitch($$$$)
509 my($e) = shift;
510 my($var_prefix) = shift;
511 my($ndr_flags) = shift;
512 my $switch = shift;
513 my $switch_var = find_size_var($e, $switch, $var_prefix);
514 my $cprefix = util::c_push_prefix($e);
516 check_null_pointer($switch_var);
518 my $utype = $structs{$e->{TYPE}};
519 if (!defined $utype ||
520 !util::has_property($utype, "nodiscriminant")) {
521 my $e2 = find_sibling($e, $switch);
522 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
523 pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, $switch_var));\n";
524 pidl "\t}\n";
527 my $sub_size = util::has_property($e, "subcontext");
528 if (defined $sub_size) {
529 pidl "\tif(($ndr_flags) & NDR_SCALARS) {\n";
530 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";
531 pidl "\t}\n";
532 } else {
533 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
537 #####################################################################
538 # print scalars in a structure element
539 sub ParseElementPrintSwitch($$$)
541 my($e) = shift;
542 my($var_prefix) = shift;
543 my $switch = shift;
544 my $switch_var = find_size_var($e, $switch, $var_prefix);
545 my $cprefix = util::c_push_prefix($e);
547 check_null_pointer_void($switch_var);
549 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
553 #####################################################################
554 # parse scalars in a structure element - pull size
555 sub ParseElementPullScalar($$$)
557 my($e) = shift;
558 my($var_prefix) = shift;
559 my($ndr_flags) = shift;
560 my $cprefix = util::c_pull_prefix($e);
561 my $sub_size = util::has_property($e, "subcontext");
563 start_flags($e);
565 if (util::is_inline_array($e)) {
566 ParseArrayPull($e, "r->", "NDR_SCALARS");
567 } elsif (util::need_wire_pointer($e)) {
568 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
569 pidl "\tif (_ptr_$e->{NAME}) {\n";
570 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
571 if (util::has_property($e, "relative")) {
572 pidl "\t\tNDR_CHECK(ndr_pull_relative1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));\n";
574 pidl "\t} else {\n";
575 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
576 pidl "\t}\n";
577 } elsif (util::need_alloc($e)) {
578 # no scalar component
579 } elsif (my $switch = util::has_property($e, "switch_is")) {
580 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
581 } elsif (defined $sub_size) {
582 if (util::is_builtin_type($e->{TYPE})) {
583 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
584 } else {
585 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";
587 } elsif (util::is_builtin_type($e->{TYPE})) {
588 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
589 } else {
590 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
592 if (my $range = util::has_property($e, "range")) {
593 my ($low, $high) = split(/ /, $range, 2);
594 pidl "\tif ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {\n";
595 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");\n\t}\n";
598 end_flags($e);
601 #####################################################################
602 # parse buffers in a structure element
603 sub ParseElementPushBuffer($$$)
605 my($e) = shift;
606 my($var_prefix) = shift;
607 my($ndr_flags) = shift;
608 my $cprefix = util::c_push_prefix($e);
609 my $sub_size = util::has_property($e, "subcontext");
611 if (util::is_pure_scalar($e)) {
612 return;
615 start_flags($e);
617 if (util::need_wire_pointer($e)) {
618 pidl "\tif ($var_prefix$e->{NAME}) {\n";
619 if (util::has_property($e, "relative")) {
620 pidl "\t\tNDR_CHECK(ndr_push_relative2(ndr, $var_prefix$e->{NAME}));\n";
624 if (util::is_inline_array($e)) {
625 ParseArrayPush($e, "r->", "NDR_BUFFERS");
626 } elsif (util::array_size($e)) {
627 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
628 } elsif (my $switch = util::has_property($e, "switch_is")) {
629 if ($e->{POINTERS}) {
630 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
631 } else {
632 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
634 } elsif (defined $sub_size) {
635 if ($e->{POINTERS}) {
636 if (util::is_builtin_type($e->{TYPE})) {
637 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
638 } else {
639 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";
642 } elsif (util::is_builtin_type($e->{TYPE})) {
643 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
644 } elsif ($e->{POINTERS}) {
645 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
646 } else {
647 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
650 if (util::need_wire_pointer($e)) {
651 pidl "\t}\n";
654 end_flags($e);
657 #####################################################################
658 # print buffers in a structure element
659 sub ParseElementPrintBuffer($$)
661 my($e) = shift;
662 my($var_prefix) = shift;
663 my $cprefix = util::c_push_prefix($e);
665 if (util::need_wire_pointer($e)) {
666 pidl "\tif ($var_prefix$e->{NAME}) {\n";
669 if (util::array_size($e)) {
670 ParseArrayPrint($e, $var_prefix)
671 } elsif (my $switch = util::has_property($e, "switch_is")) {
672 ParseElementPrintSwitch($e, $var_prefix, $switch);
673 } else {
674 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
677 if (util::need_wire_pointer($e)) {
678 pidl "\t}\n";
683 #####################################################################
684 # parse buffers in a structure element - pull side
685 sub ParseElementPullBuffer($$$)
687 my($e) = shift;
688 my($var_prefix) = shift;
689 my($ndr_flags) = shift;
690 my $cprefix = util::c_pull_prefix($e);
691 my $sub_size = util::has_property($e, "subcontext");
693 if (util::is_pure_scalar($e)) {
694 return;
697 start_flags($e);
699 if (util::need_wire_pointer($e)) {
700 pidl "\tif ($var_prefix$e->{NAME}) {\n";
701 if (util::has_property($e, "relative")) {
702 pidl "\t\tstruct ndr_pull_save _relative_save;\n";
703 pidl "\t\tndr_pull_save(ndr, &_relative_save);\n";
704 pidl "\t\tNDR_CHECK(ndr_pull_relative2(ndr, $var_prefix$e->{NAME}));\n";
708 if (util::is_inline_array($e)) {
709 ParseArrayPull($e, "r->", "NDR_BUFFERS");
710 } elsif (util::array_size($e)) {
711 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
712 } elsif (my $switch = util::has_property($e, "switch_is")) {
713 if ($e->{POINTERS}) {
714 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
715 } else {
716 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
718 } elsif (defined $sub_size) {
719 if ($e->{POINTERS}) {
720 if (util::is_builtin_type($e->{TYPE})) {
721 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
722 } else {
723 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";
726 } elsif (util::is_builtin_type($e->{TYPE})) {
727 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
728 } elsif ($e->{POINTERS}) {
729 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
730 } else {
731 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
734 if (util::need_wire_pointer($e)) {
735 if (util::has_property($e, "relative")) {
736 pidl "\t\tndr_pull_restore(ndr, &_relative_save);\n";
738 pidl "\t}\n";
741 end_flags($e);
744 #####################################################################
745 # parse a struct
746 sub ParseStructPush($)
748 my($struct) = shift;
750 if (! defined $struct->{ELEMENTS}) {
751 return;
754 start_flags($struct);
756 # see if the structure contains a conformant array. If it
757 # does, then it must be the last element of the structure, and
758 # we need to push the conformant length early, as it fits on
759 # the wire before the structure (and even before the structure
760 # alignment)
761 my $e = $struct->{ELEMENTS}[-1];
762 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
763 my $size = find_size_var($e, util::array_size($e), "r->");
764 $e->{CONFORMANT_SIZE} = $size;
765 check_null_pointer($size);
766 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
769 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
770 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
771 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, ndr_string_array_size(ndr, r->$e->{NAME})));\n";
774 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
776 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
778 my $align = struct_alignment($struct);
779 pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
781 foreach my $e (@{$struct->{ELEMENTS}}) {
782 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
785 pidl "buffers:\n";
786 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
787 foreach my $e (@{$struct->{ELEMENTS}}) {
788 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
791 pidl "\tndr_push_struct_end(ndr);\n";
793 pidl "done:\n";
795 end_flags($struct);
799 #####################################################################
800 # generate a push function for an enum
801 sub ParseEnumPush($)
803 my($enum) = shift;
804 my($type_fn) = util::enum_type_fn($enum);
806 start_flags($enum);
808 pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
810 end_flags($enum);
813 #####################################################################
814 # generate a pull function for an enum
815 sub ParseEnumPull($)
817 my($enum) = shift;
818 my($type_fn) = util::enum_type_fn($enum);
820 pidl "\t$type_fn v;\n";
821 start_flags($enum);
822 pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
823 pidl "\t*r = v;\n";
825 end_flags($enum);
828 #####################################################################
829 # generate a print function for an enum
830 sub ParseEnumPrint($)
832 my($enum) = shift;
834 pidl "\tconst char *val = NULL;\n\n";
836 start_flags($enum);
838 pidl "\tswitch (r) {\n";
839 my $els = \@{$enum->{ELEMENTS}};
840 foreach my $i (0 .. $#{$els}) {
841 my $e = ${$els}[$i];
842 chomp $e;
843 if ($e =~ /^(.*)=/) {
844 $e = $1;
846 pidl "\t\tcase $e: val = \"$e\"; break;\n";
849 pidl "\t}\n\n\tndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);\n";
851 end_flags($enum);
855 #####################################################################
856 # generate a push function for a bitmap
857 sub ParseBitmapPush($)
859 my($bitmap) = shift;
860 my($type_fn) = util::bitmap_type_fn($bitmap);
862 start_flags($bitmap);
864 pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
866 end_flags($bitmap);
869 #####################################################################
870 # generate a pull function for an bitmap
871 sub ParseBitmapPull($)
873 my($bitmap) = shift;
874 my($type_fn) = util::bitmap_type_fn($bitmap);
876 pidl "\t$type_fn v;\n";
877 start_flags($bitmap);
878 pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
879 pidl "\t*r = v;\n";
881 end_flags($bitmap);
884 #####################################################################
885 # generate a print function for an bitmap
886 sub ParseBintmapPrintElement($$)
888 my($e) = shift;
889 my($bitmap) = shift;
890 my($type_decl) = util::bitmap_type_decl($bitmap);
891 my($type_fn) = util::bitmap_type_fn($bitmap);
892 my($name) = $bitmap->{PARENT}->{NAME};
893 my($flag);
895 if ($e =~ /^(\w+) .*$/) {
896 $flag = "$1";
897 } else {
898 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
901 pidl "\tndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);\n";
904 #####################################################################
905 # generate a print function for an bitmap
906 sub ParseBitmapPrint($)
908 my($bitmap) = shift;
909 my($type_decl) = util::bitmap_type_decl($bitmap);
910 my($type_fn) = util::bitmap_type_fn($bitmap);
912 start_flags($bitmap);
914 pidl "\tndr_print_$type_fn(ndr, name, r);\n";
916 pidl "\tndr->depth++;\n";
917 foreach my $e (@{$bitmap->{ELEMENTS}}) {
918 ParseBintmapPrintElement($e, $bitmap);
920 pidl "\tndr->depth--;\n";
922 end_flags($bitmap);
925 #####################################################################
926 # generate a struct print function
927 sub ParseStructPrint($)
929 my($struct) = shift;
931 if (! defined $struct->{ELEMENTS}) {
932 return;
935 start_flags($struct);
937 pidl "\tndr->depth++;\n";
938 foreach my $e (@{$struct->{ELEMENTS}}) {
939 ParseElementPrintScalar($e, "r->");
941 pidl "\tndr->depth--;\n";
943 end_flags($struct);
946 #####################################################################
947 # parse a struct - pull side
948 sub ParseStructPull($)
950 my($struct) = shift;
951 my $conform_e;
953 if (! defined $struct->{ELEMENTS}) {
954 return;
957 # see if the structure contains a conformant array. If it
958 # does, then it must be the last element of the structure, and
959 # we need to pull the conformant length early, as it fits on
960 # the wire before the structure (and even before the structure
961 # alignment)
962 my $e = $struct->{ELEMENTS}[-1];
963 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
964 $conform_e = $e;
967 if (defined $e->{TYPE} && $e->{TYPE} eq "string"
968 && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
969 $conform_e = $e;
972 if (defined $conform_e) {
973 $conform_e = $e;
974 pidl "\tuint32_t _conformant_size;\n";
975 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
978 # declare any internal pointers we need
979 foreach my $e (@{$struct->{ELEMENTS}}) {
980 if (util::need_wire_pointer($e)) {
981 pidl "\tuint32_t _ptr_$e->{NAME};\n";
985 start_flags($struct);
987 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
989 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
991 if (defined $conform_e) {
992 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
995 my $align = struct_alignment($struct);
996 pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
998 foreach my $e (@{$struct->{ELEMENTS}}) {
999 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1002 pidl "buffers:\n";
1003 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1004 foreach my $e (@{$struct->{ELEMENTS}}) {
1005 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1008 foreach my $e (@{$struct->{ELEMENTS}}) {
1009 CheckArraySizes($e, "r->");
1012 pidl "\tndr_pull_struct_end(ndr);\n";
1014 pidl "done:\n";
1016 end_flags($struct);
1019 #####################################################################
1020 # calculate size of ndr struct
1021 sub ParseStructNdrSize($)
1023 my $t = shift;
1024 my $static = fn_prefix($t);
1025 my $sizevar;
1027 pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)\n";
1028 pidl "{\n";
1029 if (my $flags = util::has_property($t, "flag")) {
1030 pidl "\tflags |= $flags;\n";
1032 pidl "\treturn ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});\n";
1033 pidl "}\n\n";
1036 #####################################################################
1037 # parse a union - push side
1038 sub ParseUnionPush($)
1040 my $e = shift;
1041 my $have_default = 0;
1043 start_flags($e);
1045 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1047 pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
1049 # my $align = union_alignment($e);
1050 # pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
1052 pidl "\tswitch (level) {\n";
1053 foreach my $el (@{$e->{DATA}}) {
1054 if ($el->{CASE} eq "default") {
1055 pidl "\tdefault:\n";
1056 $have_default = 1;
1057 } else {
1058 pidl "\tcase $el->{CASE}:\n";
1060 if ($el->{TYPE} eq "UNION_ELEMENT") {
1061 ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
1063 pidl "\tbreak;\n\n";
1065 if (! $have_default) {
1066 pidl "\tdefault:\n";
1067 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1069 pidl "\t}\n";
1070 pidl "buffers:\n";
1071 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1072 pidl "\tswitch (level) {\n";
1073 foreach my $el (@{$e->{DATA}}) {
1074 if ($el->{CASE} eq "default") {
1075 pidl "\tdefault:\n";
1076 } else {
1077 pidl "\tcase $el->{CASE}:\n";
1079 if ($el->{TYPE} eq "UNION_ELEMENT") {
1080 ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
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";
1088 pidl "\t}\n";
1089 pidl "\tndr_push_struct_end(ndr);\n";
1090 pidl "done:\n";
1091 end_flags($e);
1094 #####################################################################
1095 # print a union
1096 sub ParseUnionPrint($)
1098 my $e = shift;
1099 my $have_default = 0;
1101 start_flags($e);
1103 pidl "\tswitch (level) {\n";
1104 foreach my $el (@{$e->{DATA}}) {
1105 if ($el->{CASE} eq "default") {
1106 $have_default = 1;
1107 pidl "\tdefault:\n";
1108 } else {
1109 pidl "\tcase $el->{CASE}:\n";
1111 if ($el->{TYPE} eq "UNION_ELEMENT") {
1112 ParseElementPrintScalar($el->{DATA}, "r->");
1114 pidl "\tbreak;\n\n";
1116 if (! $have_default) {
1117 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
1119 pidl "\t}\n";
1121 end_flags($e);
1124 #####################################################################
1125 # parse a union - pull side
1126 sub ParseUnionPull($)
1128 my $e = shift;
1129 my $have_default = 0;
1131 start_flags($e);
1133 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1135 pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1137 # my $align = union_alignment($e);
1138 # pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1140 pidl "\tswitch (level) {\n";
1141 foreach my $el (@{$e->{DATA}}) {
1142 if ($el->{CASE} eq "default") {
1143 pidl "\tdefault: {\n";
1144 $have_default = 1;
1145 } else {
1146 pidl "\tcase $el->{CASE}: {\n";
1148 if ($el->{TYPE} eq "UNION_ELEMENT") {
1149 my $e2 = $el->{DATA};
1150 if ($e2->{POINTERS}) {
1151 pidl "\t\tuint32_t _ptr_$e2->{NAME};\n";
1153 ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
1155 pidl "\tbreak; }\n\n";
1157 if (! $have_default) {
1158 pidl "\tdefault:\n";
1159 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1161 pidl "\t}\n";
1162 pidl "buffers:\n";
1163 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1164 pidl "\tswitch (level) {\n";
1165 foreach my $el (@{$e->{DATA}}) {
1166 if ($el->{CASE} eq "default") {
1167 pidl "\tdefault:\n";
1168 } else {
1169 pidl "\tcase $el->{CASE}:\n";
1171 if ($el->{TYPE} eq "UNION_ELEMENT") {
1172 ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
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";
1180 pidl "\t}\n";
1181 pidl "\tndr_pull_struct_end(ndr);\n";
1182 pidl "done:\n";
1183 end_flags($e);
1187 #####################################################################
1188 # parse a type
1189 sub ParseTypePush($)
1191 my($data) = shift;
1193 if (ref($data) eq "HASH") {
1194 ($data->{TYPE} eq "STRUCT") &&
1195 ParseStructPush($data);
1196 ($data->{TYPE} eq "UNION") &&
1197 ParseUnionPush($data);
1198 ($data->{TYPE} eq "ENUM") &&
1199 ParseEnumPush($data);
1200 ($data->{TYPE} eq "BITMAP") &&
1201 ParseBitmapPush($data);
1205 #####################################################################
1206 # generate a print function for a type
1207 sub ParseTypePrint($)
1209 my($data) = shift;
1211 if (ref($data) eq "HASH") {
1212 ($data->{TYPE} eq "STRUCT") &&
1213 ParseStructPrint($data);
1214 ($data->{TYPE} eq "UNION") &&
1215 ParseUnionPrint($data);
1216 ($data->{TYPE} eq "ENUM") &&
1217 ParseEnumPrint($data);
1218 ($data->{TYPE} eq "BITMAP") &&
1219 ParseBitmapPrint($data);
1223 #####################################################################
1224 # parse a type
1225 sub ParseTypePull($)
1227 my($data) = shift;
1229 if (ref($data) eq "HASH") {
1230 ($data->{TYPE} eq "STRUCT") &&
1231 ParseStructPull($data);
1232 ($data->{TYPE} eq "UNION") &&
1233 ParseUnionPull($data);
1234 ($data->{TYPE} eq "ENUM") &&
1235 ParseEnumPull($data);
1236 ($data->{TYPE} eq "BITMAP") &&
1237 ParseBitmapPull($data);
1241 #####################################################################
1242 # parse a typedef - push side
1243 sub ParseTypedefPush($)
1245 my($e) = shift;
1246 my $static = fn_prefix($e);
1248 if (! needed::is_needed("push_$e->{NAME}")) {
1249 # print "push_$e->{NAME} not needed\n";
1250 return;
1253 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1254 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1257 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1258 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
1259 pidl "\n{\n";
1260 ParseTypePush($e->{DATA});
1261 pidl "\treturn NT_STATUS_OK;\n";
1262 pidl "}\n\n";
1265 if ($e->{DATA}->{TYPE} eq "UNION") {
1266 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1267 pidl "\n{\n";
1268 ParseTypePush($e->{DATA});
1269 pidl "\treturn NT_STATUS_OK;\n";
1270 pidl "}\n\n";
1273 if ($e->{DATA}->{TYPE} eq "ENUM") {
1274 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, enum $e->{NAME} r)";
1275 pidl "\n{\n";
1276 ParseTypePush($e->{DATA});
1277 pidl "\treturn NT_STATUS_OK;\n";
1278 pidl "}\n\n";
1281 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1282 my $type_decl = util::bitmap_type_fn($e->{DATA});
1283 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, $type_decl r)";
1284 pidl "\n{\n";
1285 ParseTypePush($e->{DATA});
1286 pidl "\treturn NT_STATUS_OK;\n";
1287 pidl "}\n\n";
1292 #####################################################################
1293 # parse a typedef - pull side
1294 sub ParseTypedefPull($)
1296 my($e) = shift;
1297 my $static = fn_prefix($e);
1299 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1300 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1303 if (! needed::is_needed("pull_$e->{NAME}")) {
1304 # print "pull_$e->{NAME} not needed\n";
1305 return;
1308 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1309 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
1310 pidl "\n{\n";
1311 ParseTypePull($e->{DATA});
1312 pidl "\treturn NT_STATUS_OK;\n";
1313 pidl "}\n\n";
1316 if ($e->{DATA}->{TYPE} eq "UNION") {
1317 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1318 pidl "\n{\n";
1319 ParseTypePull($e->{DATA});
1320 pidl "\treturn NT_STATUS_OK;\n";
1321 pidl "}\n\n";
1324 if ($e->{DATA}->{TYPE} eq "ENUM") {
1325 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, enum $e->{NAME} *r)";
1326 pidl "\n{\n";
1327 ParseTypePull($e->{DATA});
1328 pidl "\treturn NT_STATUS_OK;\n";
1329 pidl "}\n\n";
1332 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1333 my $type_decl = util::bitmap_type_fn($e->{DATA});
1334 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, $type_decl *r)";
1335 pidl "\n{\n";
1336 ParseTypePull($e->{DATA});
1337 pidl "\treturn NT_STATUS_OK;\n";
1338 pidl "}\n\n";
1343 #####################################################################
1344 # parse a typedef - print side
1345 sub ParseTypedefPrint($)
1347 my($e) = shift;
1349 if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1350 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1353 if ($e->{DATA}->{TYPE} eq "STRUCT") {
1354 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1355 pidl "\n{\n";
1356 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1357 ParseTypePrint($e->{DATA});
1358 pidl "}\n\n";
1361 if ($e->{DATA}->{TYPE} eq "UNION") {
1362 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1363 pidl "\n{\n";
1364 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1365 ParseTypePrint($e->{DATA});
1366 pidl "}\n\n";
1369 if ($e->{DATA}->{TYPE} eq "ENUM") {
1370 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1371 pidl "\n{\n";
1372 ParseTypePrint($e->{DATA});
1373 pidl "}\n\n";
1376 if ($e->{DATA}->{TYPE} eq "BITMAP") {
1377 my $type_decl = util::bitmap_type_fn($e->{DATA});
1378 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1379 pidl "\n{\n";
1380 ParseTypePrint($e->{DATA});
1381 pidl "}\n\n";
1385 #####################################################################
1386 ## calculate the size of a structure
1387 sub ParseTypedefNdrSize($)
1389 my($t) = shift;
1390 if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1391 return;
1394 ($t->{DATA}->{TYPE} eq "STRUCT") &&
1395 ParseStructNdrSize($t);
1398 #####################################################################
1399 # parse a function - print side
1400 sub ParseFunctionPrint($)
1402 my($fn) = shift;
1404 pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1405 pidl "\n{\n";
1406 pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1407 pidl "\tndr->depth++;\n";
1409 pidl "\tif (flags & NDR_SET_VALUES) {\n";
1410 pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n";
1411 pidl "\t}\n";
1413 pidl "\tif (flags & NDR_IN) {\n";
1414 pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
1415 pidl "\tndr->depth++;\n";
1416 foreach my $e (@{$fn->{DATA}}) {
1417 if (util::has_property($e, "in")) {
1418 ParseElementPrintScalar($e, "r->in.");
1421 pidl "\tndr->depth--;\n";
1422 pidl "\t}\n";
1424 pidl "\tif (flags & NDR_OUT) {\n";
1425 pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
1426 pidl "\tndr->depth++;\n";
1427 foreach my $e (@{$fn->{DATA}}) {
1428 if (util::has_property($e, "out")) {
1429 ParseElementPrintScalar($e, "r->out.");
1432 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1433 if (util::is_scalar_type($fn->{RETURN_TYPE})) {
1434 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);\n";
1435 } else {
1436 pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
1439 pidl "\tndr->depth--;\n";
1440 pidl "\t}\n";
1442 pidl "\tndr->depth--;\n";
1443 pidl "}\n\n";
1447 #####################################################################
1448 # parse a function element
1449 sub ParseFunctionElementPush($$)
1451 my $e = shift;
1452 my $inout = shift;
1454 if (util::array_size($e)) {
1455 if (util::need_wire_pointer($e)) {
1456 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n";
1457 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1458 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1459 pidl "\t}\n";
1460 } else {
1461 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1463 } else {
1464 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1465 if ($e->{POINTERS}) {
1466 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1471 #####################################################################
1472 # parse a function
1473 sub ParseFunctionPush($)
1475 my($fn) = shift;
1476 my $static = fn_prefix($fn);
1478 pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1480 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1482 foreach my $e (@{$fn->{DATA}}) {
1483 if (util::has_property($e, "in")) {
1484 ParseFunctionElementPush($e, "in");
1488 pidl "\nndr_out:\n";
1489 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1491 foreach my $e (@{$fn->{DATA}}) {
1492 if (util::has_property($e, "out")) {
1493 ParseFunctionElementPush($e, "out");
1497 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1498 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n";
1501 pidl "\ndone:\n";
1502 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1505 #####################################################################
1506 # parse a function element
1507 sub ParseFunctionElementPull($$)
1509 my $e = shift;
1510 my $inout = shift;
1512 if (util::array_size($e)) {
1513 if (util::need_wire_pointer($e)) {
1514 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
1515 pidl "\tr->$inout.$e->{NAME} = NULL;\n";
1516 pidl "\tif (_ptr_$e->{NAME}) {\n";
1517 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1518 pidl "\tif (r->$inout.$e->{NAME}) {\n";
1519 } else {
1520 pidl "\t{\n";
1522 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1523 pidl "\t}\n";
1524 } else {
1525 if ($inout eq "out" && util::has_property($e, "ref")) {
1526 pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n";
1527 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1528 pidl "\t}\n";
1530 if ($inout eq "in" && util::has_property($e, "ref")) {
1531 pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1534 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1535 if ($e->{POINTERS}) {
1536 ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1542 ############################################################
1543 # allocate ref variables
1544 sub AllocateRefVars($)
1546 my $e = shift;
1547 my $asize = util::array_size($e);
1549 # note that if the variable is also an "in"
1550 # variable then we copy the initial value from
1551 # the in side
1553 if (!defined $asize) {
1554 # its a simple variable
1555 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1556 if (util::has_property($e, "in")) {
1557 pidl "\t*r->out.$e->{NAME} = *r->in.$e->{NAME};\n";
1558 } else {
1559 pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n";
1561 return;
1564 # its an array
1565 my $size = find_size_var($e, $asize, "r->out.");
1566 check_null_pointer($size);
1567 pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);\n";
1568 if (util::has_property($e, "in")) {
1569 pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));\n";
1570 } else {
1571 pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n";
1576 #####################################################################
1577 # parse a function
1578 sub ParseFunctionPull($)
1580 my($fn) = shift;
1581 my $static = fn_prefix($fn);
1583 # pull function args
1584 pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1586 # declare any internal pointers we need
1587 foreach my $e (@{$fn->{DATA}}) {
1588 if (util::need_wire_pointer($e)) {
1589 pidl "\tuint32_t _ptr_$e->{NAME};\n";
1593 pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1595 # auto-init the out section of a structure. I originally argued that
1596 # this was a bad idea as it hides bugs, but coping correctly
1597 # with initialisation and not wiping ref vars is turning
1598 # out to be too tricky (tridge)
1599 foreach my $e (@{$fn->{DATA}}) {
1600 if (util::has_property($e, "out")) {
1601 pidl "\tZERO_STRUCT(r->out);\n\n";
1602 last;
1606 foreach my $e (@{$fn->{DATA}}) {
1607 if (util::has_property($e, "in")) {
1608 ParseFunctionElementPull($e, "in");
1610 # we need to allocate any reference output variables, so that
1611 # a dcerpc backend can be sure they are non-null
1612 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1613 AllocateRefVars($e);
1617 foreach my $e (@{$fn->{DATA}}) {
1618 if (util::has_property($e, "in")) {
1619 CheckArraySizes($e, "r->in.");
1623 pidl "\nndr_out:\n";
1624 pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1626 foreach my $e (@{$fn->{DATA}}) {
1627 if (util::has_property($e, "out")) {
1628 ParseFunctionElementPull($e, "out");
1632 foreach my $e (@{$fn->{DATA}}) {
1633 if (util::has_property($e, "out")) {
1634 CheckArraySizes($e, "r->out.");
1638 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1639 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
1642 pidl "\ndone:\n";
1643 pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1646 #####################################################################
1647 # produce a function call table
1648 sub FunctionTable($)
1650 my($interface) = shift;
1651 my($data) = $interface->{INHERITED_DATA};
1652 my $count = 0;
1653 my $uname = uc $interface->{NAME};
1655 foreach my $d (@{$data}) {
1656 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1659 return if ($count == 0);
1661 pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n";
1662 foreach my $d (@{$data}) {
1663 if ($d->{TYPE} eq "FUNCTION") {
1664 pidl "\t{\n";
1665 pidl "\t\t\"$d->{NAME}\",\n";
1666 pidl "\t\tsizeof(struct $d->{NAME}),\n";
1667 pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},\n";
1668 pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},\n";
1669 pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}\n";
1670 pidl "\t},\n";
1673 pidl "\t{ NULL, 0, NULL, NULL }\n};\n\n";
1675 # If no endpoint is set, default to the interface name as a named pipe
1676 if (! defined $interface->{PROPERTIES}->{endpoint}) {
1677 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1680 my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1681 my $endpoint_count = $#e + 1;
1683 pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n";
1684 foreach my $ep (@e) {
1685 pidl "\t$ep, \n";
1687 pidl "};\n\n";
1689 pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n";
1690 pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n";
1691 pidl "};\n\n";
1693 pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {\n";
1694 pidl "\t\"$interface->{NAME}\",\n";
1695 pidl "\tDCERPC_$uname\_UUID,\n";
1696 pidl "\tDCERPC_$uname\_VERSION,\n";
1697 pidl "\tDCERPC_$uname\_HELPSTRING,\n";
1698 pidl "\t$count,\n";
1699 pidl "\t$interface->{NAME}\_calls,\n";
1700 pidl "\t&$interface->{NAME}\_endpoints\n";
1701 pidl "};\n\n";
1703 pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)\n";
1704 pidl "{\n";
1705 pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});\n";
1706 pidl "}\n\n";
1709 #####################################################################
1710 # parse the interface definitions
1711 sub ParseInterface($)
1713 my($interface) = shift;
1714 my($data) = $interface->{DATA};
1716 foreach my $d (@{$data}) {
1717 if ($d->{TYPE} eq "DECLARE") {
1718 $structs{$d->{NAME}} = $d;
1720 if ($d->{TYPE} eq "TYPEDEF") {
1721 $structs{$d->{NAME}} = $d;
1725 foreach my $d (@{$data}) {
1726 ($d->{TYPE} eq "TYPEDEF") &&
1727 ParseTypedefPush($d);
1728 ($d->{TYPE} eq "FUNCTION") &&
1729 ParseFunctionPush($d);
1731 foreach my $d (@{$data}) {
1732 ($d->{TYPE} eq "TYPEDEF") &&
1733 ParseTypedefPull($d);
1734 ($d->{TYPE} eq "FUNCTION") &&
1735 ParseFunctionPull($d);
1737 foreach my $d (@{$data}) {
1738 if ($d->{TYPE} eq "TYPEDEF" &&
1739 !util::has_property($d, "noprint")) {
1740 ParseTypedefPrint($d);
1742 if ($d->{TYPE} eq "FUNCTION" &&
1743 !util::has_property($d, "noprint")) {
1744 ParseFunctionPrint($d);
1748 foreach my $d (@{$data}) {
1749 ($d->{TYPE} eq "TYPEDEF") &&
1750 ParseTypedefNdrSize($d);
1753 FunctionTable($interface);
1756 sub RegistrationFunction($$)
1758 my $idl = shift;
1759 my $filename = shift;
1761 $filename =~ /.*\/ndr_(.*).c/;
1762 my $basename = $1;
1763 pidl "NTSTATUS dcerpc_$basename\_init(void)\n";
1764 pidl "{\n";
1765 pidl "\tNTSTATUS status = NT_STATUS_OK;\n";
1766 foreach my $interface (@{$idl}) {
1767 next if $interface->{TYPE} ne "INTERFACE";
1769 my $data = $interface->{INHERITED_DATA};
1770 my $count = 0;
1771 foreach my $d (@{$data}) {
1772 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1775 next if ($count == 0);
1777 pidl "\tstatus = dcerpc_ndr_$interface->{NAME}_init();\n";
1778 pidl "\tif (NT_STATUS_IS_ERR(status)) {\n";
1779 pidl "\t\treturn status;\n";
1780 pidl "\t}\n\n";
1782 pidl "\treturn status;\n";
1783 pidl "}\n\n";
1786 #####################################################################
1787 # parse a parsed IDL structure back into an IDL file
1788 sub Parse($$)
1790 my($idl) = shift;
1791 my($filename) = shift;
1792 my $h_filename = $filename;
1794 if ($h_filename =~ /(.*)\.c/) {
1795 $h_filename = "$1.h";
1798 open(OUT, ">$filename") || die "can't open $filename";
1800 pidl "/* parser auto-generated by pidl */\n\n";
1801 pidl "#include \"includes.h\"\n";
1802 pidl "#include \"$h_filename\"\n\n";
1804 foreach my $x (@{$idl}) {
1805 if ($x->{TYPE} eq "INTERFACE") {
1806 needed::BuildNeeded($x);
1807 ParseInterface($x);
1811 RegistrationFunction($idl, $filename);
1813 close(OUT);