1 ###################################################
2 # Samba4 parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # released under the GNU GPL
13 # the list of needed functions
16 #####################################################################
17 # parse a properties list
18 sub ParseProperties($)
21 foreach my $d (@{$props}) {
22 if (ref($d) ne "HASH") {
25 foreach my $k (keys %{$d}) {
26 $res .= "[$k($d->{$k})] ";
32 ####################################################################
33 # work out the name of a size_is() variable
38 my($fn) = $e->{PARENT};
40 if (util::is_constant($size)) {
44 if ($fn->{TYPE} ne "FUNCTION") {
48 for my $e2 (@{$fn->{DATA}}) {
49 if ($e2->{NAME} eq $size) {
50 if (util::has_property($e2, "in")) {
53 if (util::has_property($e2, "out")) {
54 return "r->out.$size";
58 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
62 #####################################################################
63 # work out the correct alignment for a structure
64 sub struct_alignment($)
67 # why do we need a minimum alignment of 4 ??
69 for my $e (@{$s->{ELEMENTS}}) {
70 if ($align < util::type_align($e)) {
71 $align = util::type_align($e);
77 #####################################################################
78 # parse an array - push side
79 sub ParseArrayPush($$$)
82 my $var_prefix = shift;
83 my $ndr_flags = shift;
85 my $size = find_size_var($e, util::array_size($e));
87 if (defined $e->{CONFORMANT_SIZE}) {
88 # the conformant size has already been pushed
89 } elsif (!util::is_fixed_array($e)) {
90 # we need to emit the array size
91 $res .= "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
94 if (my $length = util::has_property($e, "length_is")) {
95 $length = find_size_var($e, $length);
96 $res .= "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n";
97 $res .= "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n";
101 if (util::is_scalar_type($e->{TYPE})) {
102 $res .= "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
104 $res .= "\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";
108 #####################################################################
110 sub ParseArrayPrint($$)
113 my $var_prefix = shift;
114 my $size = find_size_var($e, util::array_size($e));
115 my $length = util::has_property($e, "length_is");
117 if (defined $length) {
118 $size = find_size_var($e, $length);
121 if (util::is_scalar_type($e->{TYPE})) {
122 $res .= "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n";
124 $res .= "\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";
128 #####################################################################
129 # parse an array - pull side
130 sub ParseArrayPull($$$)
133 my $var_prefix = shift;
134 my $ndr_flags = shift;
136 my $size = find_size_var($e, util::array_size($e));
137 my $alloc_size = $size;
139 # if this is a conformant array then we use that size to allocate, and make sure
140 # we allocate enough to pull the elements
141 if (defined $e->{CONFORMANT_SIZE}) {
142 $alloc_size = $e->{CONFORMANT_SIZE};
144 $res .= "\tif ($size > $alloc_size) {\n";
145 $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
147 } elsif (!util::is_fixed_array($e)) {
148 # non fixed arrays encode the size just before the array
150 $res .= "\t\tuint32 _array_size;\n";
151 $res .= "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_array_size));\n";
152 $res .= "\t\tif ($size > _array_size) {\n";
153 $res .= "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should be %u\", _array_size, $size);\n";
158 if (util::need_alloc($e) && !util::is_fixed_array($e)) {
159 $res .= "\t\tNDR_ALLOC_N_SIZE(ndr, $var_prefix$e->{NAME}, $alloc_size, sizeof($var_prefix$e->{NAME}\[0]));\n";
162 if (my $length = util::has_property($e, "length_is")) {
163 $length = find_size_var($e, $length);
164 $res .= "\t\tuint32 _offset, _length;\n";
165 $res .= "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_offset));\n";
166 $res .= "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_length));\n";
167 $res .= "\t\tif (_offset != 0) return ndr_pull_error(ndr, NDR_ERR_OFFSET, \"Bad array offset 0x%08x\", _offset);\n";
168 $res .= "\t\tif (_length > $size || _length != $length) return ndr_pull_error(ndr, NDR_ERR_LENGTH, \"Bad array length 0x%08x > size 0x%08x\", _offset, $size);\n";
172 if (util::is_scalar_type($e->{TYPE})) {
173 $res .= "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $var_prefix$e->{NAME}, $size));\n";
175 $res .= "\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";
180 #####################################################################
181 # parse scalars in a structure element
182 sub ParseElementPushScalar($$$)
185 my($var_prefix) = shift;
186 my($ndr_flags) = shift;
187 my $cprefix = util::c_push_prefix($e);
189 if (my $value = util::has_property($e, "value")) {
190 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $value));\n";
191 } elsif (defined $e->{VALUE}) {
192 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $e->{VALUE}));\n";
193 } elsif (util::need_wire_pointer($e)) {
194 $res .= "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
195 } elsif (my $switch = util::has_property($e, "switch_is")) {
196 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
197 } elsif (util::is_builtin_type($e->{TYPE})) {
198 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
200 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
204 #####################################################################
205 # print scalars in a structure element
206 sub ParseElementPrintScalar($$)
209 my($var_prefix) = shift;
210 my $cprefix = util::c_push_prefix($e);
212 if (defined $e->{VALUE}) {
213 $res .= "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $e->{VALUE});\n";
214 } elsif (util::has_direct_buffers($e)) {
215 $res .= "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
216 $res .= "\tndr->depth++;\n";
217 ParseElementPrintBuffer($e, "r->");
218 $res .= "\tndr->depth--;\n";
219 } elsif (my $switch = util::has_property($e, "switch_is")) {
220 ParseElementPrintSwitch($e, $var_prefix, $switch);
222 $res .= "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
226 #####################################################################
227 # parse scalars in a structure element - pull size
228 sub ParseElementPullSwitch($$$$)
231 my($var_prefix) = shift;
232 my($ndr_flags) = shift;
234 my $switch_var = find_size_var($e, $switch);
236 my $cprefix = util::c_pull_prefix($e);
238 $res .= "\t{ uint16 _level;\n";
239 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, &_level, $cprefix$var_prefix$e->{NAME}));\n";
240 $res .= "\tif ((($ndr_flags) & NDR_SCALARS) && (_level != $switch_var)) return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\");\n";
244 #####################################################################
245 # push switch element
246 sub ParseElementPushSwitch($$$$)
249 my($var_prefix) = shift;
250 my($ndr_flags) = shift;
252 my $switch_var = find_size_var($e, $switch);
253 my $cprefix = util::c_push_prefix($e);
255 $res .= "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
258 #####################################################################
259 # print scalars in a structure element
260 sub ParseElementPrintSwitch($$$)
263 my($var_prefix) = shift;
265 my $switch_var = find_size_var($e, $switch);
266 my $cprefix = util::c_push_prefix($e);
268 $res .= "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
272 #####################################################################
273 # parse scalars in a structure element - pull size
274 sub ParseElementPullScalar($$$)
277 my($var_prefix) = shift;
278 my($ndr_flags) = shift;
279 my $cprefix = util::c_pull_prefix($e);
281 if (defined $e->{VALUE}) {
282 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $e->{VALUE}));\n";
283 } elsif (util::need_wire_pointer($e)) {
284 $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
285 $res .= "\tif (_ptr_$e->{NAME}) {\n";
286 $res .= "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
287 $res .= "\t} else {\n";
288 $res .= "\t\t$var_prefix$e->{NAME} = NULL;\n";
290 } elsif (util::need_alloc($e)) {
291 # no scalar component
292 } elsif (my $switch = util::has_property($e, "switch_is")) {
293 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
294 } elsif (util::is_builtin_type($e->{TYPE})) {
295 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
297 $res .= "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
301 #####################################################################
302 # parse buffers in a structure element
303 sub ParseElementPushBuffer($$$)
306 my($var_prefix) = shift;
307 my($ndr_flags) = shift;
308 my $cprefix = util::c_push_prefix($e);
310 if (util::is_pure_scalar($e)) {
314 if (util::need_wire_pointer($e)) {
315 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
318 if (util::array_size($e)) {
319 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
320 } elsif (my $switch = util::has_property($e, "switch_is")) {
321 if ($e->{POINTERS}) {
322 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
324 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
326 } elsif (util::is_builtin_type($e->{TYPE})) {
327 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
328 } elsif ($e->{POINTERS}) {
329 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
331 $res .= "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
334 if (util::need_wire_pointer($e)) {
339 #####################################################################
340 # print buffers in a structure element
341 sub ParseElementPrintBuffer($$)
344 my($var_prefix) = shift;
345 my $cprefix = util::c_push_prefix($e);
347 if (util::is_pure_scalar($e)) {
351 if (util::need_wire_pointer($e)) {
352 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
355 if (util::array_size($e)) {
356 ParseArrayPrint($e, "r->");
357 } elsif (my $switch = util::has_property($e, "switch_is")) {
358 ParseElementPrintSwitch($e, $var_prefix, $switch);
360 $res .= "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
363 if (util::need_wire_pointer($e)) {
369 #####################################################################
370 # parse buffers in a structure element - pull side
371 sub ParseElementPullBuffer($$$)
374 my($var_prefix) = shift;
375 my($ndr_flags) = shift;
376 my $cprefix = util::c_pull_prefix($e);
378 if (util::is_pure_scalar($e)) {
382 if (util::need_wire_pointer($e)) {
383 $res .= "\tif ($var_prefix$e->{NAME}) {\n";
386 if (util::array_size($e)) {
387 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
388 } elsif (my $switch = util::has_property($e, "switch_is")) {
389 if ($e->{POINTERS}) {
390 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
392 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
394 } elsif (util::is_builtin_type($e->{TYPE})) {
395 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
396 } elsif ($e->{POINTERS}) {
397 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
399 $res .= "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
402 if (util::need_wire_pointer($e)) {
407 #####################################################################
409 sub ParseStructPush($)
414 if (! defined $struct->{ELEMENTS}) {
418 # see if the structure contains a conformant array. If it
419 # does, then it must be the last element of the structure, and
420 # we need to push the conformant length early, as it fits on
421 # the wire before the structure (and even before the structure
423 my $e = $struct->{ELEMENTS}[-1];
424 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
425 my $size = find_size_var($e, util::array_size($e));
426 $e->{CONFORMANT_SIZE} = $size;
428 $res .= "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
431 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
433 my $align = struct_alignment($struct);
434 $res .= "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
436 foreach my $e (@{$struct->{ELEMENTS}}) {
437 $e->{PARENT} = $struct;
438 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
441 $res .= "buffers:\n";
442 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
443 foreach my $e (@{$struct->{ELEMENTS}}) {
444 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
450 #####################################################################
451 # generate a struct print function
452 sub ParseStructPrint($)
456 if (! defined $struct->{ELEMENTS}) {
460 $res .= "\tndr->depth++;\n";
461 foreach my $e (@{$struct->{ELEMENTS}}) {
462 ParseElementPrintScalar($e, "r->");
464 $res .= "\tndr->depth--;\n";
467 #####################################################################
468 # parse a struct - pull side
469 sub ParseStructPull($)
474 if (! defined $struct->{ELEMENTS}) {
478 # see if the structure contains a conformant array. If it
479 # does, then it must be the last element of the structure, and
480 # we need to pull the conformant length early, as it fits on
481 # the wire before the structure (and even before the structure
483 my $e = $struct->{ELEMENTS}[-1];
484 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
486 $res .= "\tuint32 _conformant_size;\n";
487 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
490 # declare any internal pointers we need
491 foreach my $e (@{$struct->{ELEMENTS}}) {
492 $e->{PARENT} = $struct;
493 if (util::need_wire_pointer($e)) {
494 $res .= "\tuint32 _ptr_$e->{NAME};\n";
499 if (defined $conform_e) {
500 $res .= "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
503 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
505 my $align = struct_alignment($struct);
506 $res .= "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
508 foreach my $e (@{$struct->{ELEMENTS}}) {
509 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
512 $res .= "buffers:\n";
513 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
514 foreach my $e (@{$struct->{ELEMENTS}}) {
515 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
522 #####################################################################
523 # parse a union - push side
524 sub ParseUnionPush($)
527 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
528 $res .= "\tNDR_CHECK(ndr_push_uint16(ndr, level));\n";
529 $res .= "\tswitch (level) {\n";
530 foreach my $el (@{$e->{DATA}}) {
531 $res .= "\tcase $el->{CASE}:\n";
532 ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
533 $res .= "\tbreak;\n\n";
535 $res .= "\tdefault:\n";
536 $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
538 $res .= "buffers:\n";
539 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
540 $res .= "\tswitch (level) {\n";
541 foreach my $el (@{$e->{DATA}}) {
542 $res .= "\tcase $el->{CASE}:\n";
543 ParseElementPushBuffer($el->{DATA}, "r->", "ndr_flags");
544 $res .= "\tbreak;\n\n";
546 $res .= "\tdefault:\n";
547 $res .= "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
552 #####################################################################
554 sub ParseUnionPrint($)
558 $res .= "\tswitch (level) {\n";
559 foreach my $el (@{$e->{DATA}}) {
560 $res .= "\tcase $el->{CASE}:\n";
561 ParseElementPrintScalar($el->{DATA}, "r->");
562 $res .= "\tbreak;\n\n";
564 $res .= "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
568 #####################################################################
569 # parse a union - pull side
570 sub ParseUnionPull($)
574 $res .= "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
575 $res .= "\tNDR_CHECK(ndr_pull_uint16(ndr, level));\n";
576 $res .= "\tswitch (*level) {\n";
577 foreach my $el (@{$e->{DATA}}) {
578 $res .= "\tcase $el->{CASE}: {\n";
579 my $e2 = $el->{DATA};
580 if ($e2->{POINTERS}) {
581 $res .= "\t\tuint32 _ptr_$e2->{NAME};\n";
583 ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
584 $res .= "\tbreak; }\n\n";
586 $res .= "\tdefault:\n";
587 $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
589 $res .= "buffers:\n";
590 $res .= "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
591 $res .= "\tswitch (*level) {\n";
592 foreach my $el (@{$e->{DATA}}) {
593 $res .= "\tcase $el->{CASE}:\n";
594 ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
595 $res .= "\tbreak;\n\n";
597 $res .= "\tdefault:\n";
598 $res .= "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", *level);\n";
603 #####################################################################
609 if (ref($data) eq "HASH") {
610 ($data->{TYPE} eq "STRUCT") &&
611 ParseStructPush($data);
612 ($data->{TYPE} eq "UNION") &&
613 ParseUnionPush($data);
617 #####################################################################
618 # generate a print function for a type
619 sub ParseTypePrint($)
623 if (ref($data) eq "HASH") {
624 ($data->{TYPE} eq "STRUCT") &&
625 ParseStructPrint($data);
626 ($data->{TYPE} eq "UNION") &&
627 ParseUnionPrint($data);
631 #####################################################################
637 if (ref($data) eq "HASH") {
638 ($data->{TYPE} eq "STRUCT") &&
639 ParseStructPull($data);
640 ($data->{TYPE} eq "UNION") &&
641 ParseUnionPull($data);
645 #####################################################################
646 # parse a typedef - push side
647 sub ParseTypedefPush($)
651 if (! $needed{"push_$e->{NAME}"}) {
652 # print "push_$e->{NAME} not needed\n";
656 if ($e->{DATA}->{TYPE} eq "STRUCT") {
657 $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
659 ParseTypePush($e->{DATA});
660 $res .= "\treturn NT_STATUS_OK;\n";
664 if ($e->{DATA}->{TYPE} eq "UNION") {
665 $res .= "static NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, uint16 level, union $e->{NAME} *r)";
667 ParseTypePush($e->{DATA});
668 $res .= "\treturn NT_STATUS_OK;\n";
674 #####################################################################
675 # parse a typedef - pull side
676 sub ParseTypedefPull($)
680 if (! $needed{"pull_$e->{NAME}"}) {
681 # print "pull_$e->{NAME} not needed\n";
685 if ($e->{DATA}->{TYPE} eq "STRUCT") {
686 $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
688 ParseTypePull($e->{DATA});
689 $res .= "\treturn NT_STATUS_OK;\n";
693 if ($e->{DATA}->{TYPE} eq "UNION") {
694 $res .= "static NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, uint16 *level, union $e->{NAME} *r)";
696 ParseTypePull($e->{DATA});
697 $res .= "\treturn NT_STATUS_OK;\n";
703 #####################################################################
704 # parse a typedef - push side
705 sub ParseTypedefPrint($)
709 if ($e->{DATA}->{TYPE} eq "STRUCT") {
710 $res .= "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
712 $res .= "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
713 ParseTypePrint($e->{DATA});
717 if ($e->{DATA}->{TYPE} eq "UNION") {
718 $res .= "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, uint16 level, union $e->{NAME} *r)";
720 $res .= "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
721 ParseTypePrint($e->{DATA});
727 #####################################################################
729 sub ParseFunctionPush($)
731 my($function) = shift;
734 $res .= "NTSTATUS ndr_push_$function->{NAME}(struct ndr_push *ndr, struct $function->{NAME} *r)\n{\n";
736 foreach my $e (@{$function->{DATA}}) {
737 if (util::has_property($e, "in")) {
738 $e->{PARENT} = $function;
739 if (util::array_size($e)) {
740 $res .= "\tif (r->in.$e->{NAME}) {\n";
741 if (!util::is_scalar_type($e->{TYPE})) {
742 $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
744 ParseArrayPush($e, "r->in.", "ndr_flags");
747 ParseElementPushScalar($e, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
748 if ($e->{POINTERS}) {
749 ParseElementPushBuffer($e, "r->in.", "NDR_SCALARS|NDR_BUFFERS");
755 $res .= "\n\treturn NT_STATUS_OK;\n}\n\n";
758 #####################################################################
760 sub ParseFunctionPull($)
765 $res .= "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, struct $fn->{NAME} *r)\n{\n";
767 # declare any internal pointers we need
768 foreach my $e (@{$fn->{DATA}}) {
769 if (util::has_property($e, "out")) {
770 if (util::need_wire_pointer($e)) {
771 $res .= "\tuint32 _ptr_$e->{NAME};\n";
776 foreach my $e (@{$fn->{DATA}}) {
777 if (util::has_property($e, "out")) {
779 if (util::array_size($e)) {
780 $res .= "\tif (r->out.$e->{NAME}) {\n";
781 if (!util::is_scalar_type($e->{TYPE})) {
782 $res .= "\t\tint ndr_flags = NDR_SCALARS|NDR_BUFFERS;\n";
784 ParseArrayPull($e, "r->out.", "ndr_flags");
787 ParseElementPullScalar($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
788 if ($e->{POINTERS}) {
789 ParseElementPullBuffer($e, "r->out.", "NDR_SCALARS|NDR_BUFFERS");
795 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
796 $res .= "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
800 $res .= "\n\treturn NT_STATUS_OK;\n}\n\n";
803 #####################################################################
804 # parse the interface definitions
805 sub ParseInterface($)
807 my($interface) = shift;
808 my($data) = $interface->{DATA};
809 foreach my $d (@{$data}) {
810 ($d->{TYPE} eq "TYPEDEF") &&
811 ParseTypedefPush($d);
812 ($d->{TYPE} eq "FUNCTION") &&
813 ParseFunctionPush($d);
815 foreach my $d (@{$data}) {
816 ($d->{TYPE} eq "TYPEDEF") &&
817 ParseTypedefPull($d);
818 ($d->{TYPE} eq "FUNCTION") &&
819 ParseFunctionPull($d);
821 foreach my $d (@{$data}) {
822 ($d->{TYPE} eq "TYPEDEF") &&
823 ParseTypedefPrint($d);
827 sub NeededFunction($)
830 $needed{"pull_$fn->{NAME}"} = 1;
831 $needed{"push_$fn->{NAME}"} = 1;
832 foreach my $e (@{$fn->{DATA}}) {
833 if (util::has_property($e, "out")) {
834 $needed{"pull_$e->{TYPE}"} = 1;
836 if (util::has_property($e, "in")) {
837 $needed{"push_$e->{TYPE}"} = 1;
845 if ($t->{DATA}->{TYPE} eq "STRUCT") {
846 for my $e (@{$t->{DATA}->{ELEMENTS}}) {
847 if ($needed{"pull_$t->{NAME}"}) {
848 $needed{"pull_$e->{TYPE}"} = 1;
850 if ($needed{"push_$t->{NAME}"}) {
851 $needed{"push_$e->{TYPE}"} = 1;
855 if ($t->{DATA}->{TYPE} eq "UNION") {
856 for my $e (@{$t->{DATA}->{DATA}}) {
857 if ($needed{"pull_$t->{NAME}"}) {
858 $needed{"pull_$e->{DATA}->{TYPE}"} = 1;
860 if ($needed{"push_$t->{NAME}"}) {
861 $needed{"push_$e->{DATA}->{TYPE}"} = 1;
867 #####################################################################
868 # work out what parse functions are needed
871 my($interface) = shift;
872 my($data) = $interface->{DATA};
873 foreach my $d (@{$data}) {
874 ($d->{TYPE} eq "FUNCTION") &&
877 foreach my $d (reverse @{$data}) {
878 ($d->{TYPE} eq "TYPEDEF") &&
884 #####################################################################
885 # parse a parsed IDL structure back into an IDL file
889 $res = "/* parser auto-generated by pidl */\n\n";
890 $res .= "#include \"includes.h\"\n\n";
891 foreach my $x (@{$idl}) {
892 if ($x->{TYPE} eq "INTERFACE") {