00d48270deb81ef3a85d953090bc02d5dfaac420
[samba.git] / source4 / build / pidl / parser.pm
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
7
8 package IdlParser;
9
10 use strict;
11 use needed;
12
13 # the list of needed functions
14 my %structs;
15
16 sub pidl($)
17 {
18         print OUT shift;
19 }
20
21 #####################################################################
22 # parse a properties list
23 sub ParseProperties($)
24 {
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})] ";
32             }
33         }
34     }
35 }
36
37 ###################################
38 # find a sibling var in a structure
39 sub find_sibling($$)
40 {
41         my($e) = shift;
42         my($name) = shift;
43         my($fn) = $e->{PARENT};
44
45         if ($name =~ /\*(.*)/) {
46                 $name = $1;
47         }
48
49         if ($fn->{TYPE} eq "FUNCTION") {
50                 for my $e2 (@{$fn->{DATA}}) {
51                         if ($e2->{NAME} eq $name) {
52                                 return $e2;
53                         }
54                 }
55         }
56
57         for my $e2 (@{$fn->{ELEMENTS}}) {
58                 if ($e2->{NAME} eq $name) {
59                         return $e2;
60                 }
61         }
62         die "invalid sibling '$name'";
63 }
64
65 ####################################################################
66 # work out the name of a size_is() variable
67 sub find_size_var($$$)
68 {
69         my($e) = shift;
70         my($size) = shift;
71         my($var_prefix) = shift;
72
73         my($fn) = $e->{PARENT};
74
75         if (util::is_constant($size)) {
76                 return $size;
77         }
78
79         if ($size =~ /ndr->|\(/) {
80                 return $size;
81         }
82
83         my $prefix = "";
84
85         if ($size =~ /\*(.*)/) {
86                 $size = $1;
87                 $prefix = "*";
88         }
89
90         if ($fn->{TYPE} ne "FUNCTION") {
91                 return $prefix . "r->$size";
92         }
93
94         my $e2 = find_sibling($e, $size);
95
96         if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
97                 return $prefix . "$var_prefix$size";
98         }
99         if (util::has_property($e2, "in")) {
100                 return $prefix . "r->in.$size";
101         }
102         if (util::has_property($e2, "out")) {
103                 return $prefix . "r->out.$size";
104         }
105
106         die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
107 }
108
109 #####################################################################
110 # check that a variable we get from find_size_var isn't a null pointer
111 sub check_null_pointer($)
112 {
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";
117         }
118 }
119
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($)
124 {
125         my $size = shift;
126         if ($size =~ /^\*/) {
127                 my $size2 = substr($size, 1);
128                 pidl "\tif ($size2 == NULL) return;\n";
129         }
130 }
131
132
133 #####################################################################
134 # work out is a parse function should be declared static or not
135 sub fn_prefix($)
136 {
137         my $fn = shift;
138         if ($fn->{TYPE} eq "TYPEDEF") {
139                 if (util::has_property($fn, "public")) {
140                         return "";
141                 }
142         }
143
144         if ($fn->{TYPE} eq "FUNCTION") {
145                 if (util::has_property($fn, "public")) {
146                         return "";
147                 }
148         }
149         return "static ";
150 }
151
152
153 ###################################################################
154 # setup any special flags for an element or structure
155 sub start_flags($)
156 {
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";
162         }
163 }
164
165 ###################################################################
166 # end any special flags for an element or structure
167 sub end_flags($)
168 {
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";
173         }
174 }
175
176
177 #####################################################################
178 # work out the correct alignment for a structure
179 sub struct_alignment
180 {
181         my $s = shift;
182
183         my $align = 1;
184         for my $e (@{$s->{ELEMENTS}}) {
185                 my $a = 1;
186
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});
194                                 }
195                         }
196                 } else {
197                         $a = util::type_align($e);
198                 }
199
200                 if ($align < $a) {
201                         $align = $a;
202                 }
203         }
204
205         return $align;
206 }
207
208 #####################################################################
209 # work out the correct alignment for a union
210 sub union_alignment
211 {
212         my $u = shift;
213
214         my $align = 1;
215
216         foreach my $e (@{$u->{DATA}}) {
217                 my $a = 1;
218
219                 if ($e->{TYPE} eq "EMPTY") {
220                         next;
221                 }
222
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});
230                         }
231                 } else {
232                         $a = util::type_align($e->{DATA});
233                 }
234
235                 if ($align < $a) {
236                         $align = $a;
237                 }
238         }
239
240         return $align;
241 }
242
243 #####################################################################
244 # parse an array - push side
245 sub ParseArrayPush($$$)
246 {
247         my $e = shift;
248         my $var_prefix = shift;
249         my $ndr_flags = shift;
250
251         my $size = find_size_var($e, util::array_size($e), $var_prefix);
252
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";
258         }
259
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;
265         }
266
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";
271         }
272 }
273
274 #####################################################################
275 # print an array
276 sub ParseArrayPrint($$)
277 {
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");
282
283         if (defined $length) {
284                 $size = find_size_var($e, $length, $var_prefix);
285         }
286
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";
291         }
292 }
293
294 #####################################################################
295 # check the size_is and length_is constraints
296 sub CheckArraySizes($$)
297 {
298         my $e = shift;
299         my $var_prefix = shift;
300
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";
308         }
309
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";
316         }
317 }
318
319
320 #####################################################################
321 # parse an array - pull side
322 sub ParseArrayPull($$$)
323 {
324         my $e = shift;
325         my $var_prefix = shift;
326         my $ndr_flags = shift;
327
328         my $size = find_size_var($e, util::array_size($e), $var_prefix);
329         my $alloc_size = $size;
330
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";
343                 }
344
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})";
348         }
349
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";
354                 }
355         }
356
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";
362                 }
363         }
364
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})";
368         }
369
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";
375         }
376 }
377
378
379 #####################################################################
380 # parse scalars in a structure element
381 sub ParseElementPushScalar($$$)
382 {
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");
388
389         start_flags($e);
390
391         if (my $value = util::has_property($e, "value")) {
392                 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
393         }
394
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";
410                 }
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";
415         }
416
417         end_flags($e);
418 }
419
420 #####################################################################
421 # print scalars in a structure element
422 sub ParseElementPrintScalar($$)
423 {
424         my($e) = shift;
425         my($var_prefix) = shift;
426         my $cprefix = util::c_push_prefix($e);
427
428         if (util::has_property($e, "noprint")) {
429                 return;
430         }
431
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";
436         }
437
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";
449         }
450 }
451
452 #####################################################################
453 # parse scalars in a structure element - pull size
454 sub ParseElementPullSwitch($$$$)
455 {
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);
461
462         my $cprefix = util::c_pull_prefix($e);
463
464         my $utype = $structs{$e->{TYPE}};
465
466         check_null_pointer($switch_var);
467
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);
480                 }
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";
485                 } else {
486                         pidl "\t\tif (_level != $switch_var) {\n";
487                 }
488                 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);\n";
489                 pidl "\t\t}\n";
490                 if ($switch_var =~ /r->/) {
491                         pidl "else { $switch_var = _level; }\n";
492                 }
493                 pidl "\t}\n";
494         }
495
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";
500                 pidl "\t}\n";
501         } else {
502                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
503         }
504
505
506 }
507
508 #####################################################################
509 # push switch element
510 sub ParseElementPushSwitch($$$$)
511 {
512         my($e) = shift;
513         my($var_prefix) = shift;
514         my($ndr_flags) = shift;
515         my $switch = shift;
516         my $switch_var = find_size_var($e, $switch, $var_prefix);
517         my $cprefix = util::c_push_prefix($e);
518
519         check_null_pointer($switch_var);
520
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";
527                 pidl "\t}\n";
528         }
529
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";
534                 pidl "\t}\n";
535         } else {
536                 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
537         }
538 }
539
540 #####################################################################
541 # print scalars in a structure element 
542 sub ParseElementPrintSwitch($$$)
543 {
544         my($e) = shift;
545         my($var_prefix) = shift;
546         my $switch = shift;
547         my $switch_var = find_size_var($e, $switch, $var_prefix);
548         my $cprefix = util::c_push_prefix($e);
549
550         check_null_pointer_void($switch_var);
551
552         pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
553 }
554
555
556 #####################################################################
557 # parse scalars in a structure element - pull size
558 sub ParseElementPullScalar($$$)
559 {
560         my($e) = shift;
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");
565
566         start_flags($e);
567
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";
576                 }
577                 pidl "\t} else {\n";
578                 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
579                 pidl "\t}\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";
587                 } else {
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";
589                 }
590         } elsif (util::is_builtin_type($e->{TYPE})) {
591                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
592         } else {
593                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
594         }
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";
599         }
600
601         end_flags($e);
602 }
603
604 #####################################################################
605 # parse buffers in a structure element
606 sub ParseElementPushBuffer($$$)
607 {
608         my($e) = shift;
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");
613
614         if (util::is_pure_scalar($e)) {
615                 return;
616         }
617
618         start_flags($e);
619
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";
624                 }
625         }
626             
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);
634                 } else {
635                         ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
636                 }
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";
641                         } else {
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";
643                         }
644                 }
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";
649         } else {
650                 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
651         }
652
653         if (util::need_wire_pointer($e)) {
654                 pidl "\t}\n";
655         }       
656
657         end_flags($e);
658 }
659
660 #####################################################################
661 # print buffers in a structure element
662 sub ParseElementPrintBuffer($$)
663 {
664         my($e) = shift;
665         my($var_prefix) = shift;
666         my $cprefix = util::c_push_prefix($e);
667
668         if (util::need_wire_pointer($e)) {
669                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
670         }
671             
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);
676         } else {
677                 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
678         }
679
680         if (util::need_wire_pointer($e)) {
681                 pidl "\t}\n";
682         }       
683 }
684
685
686 #####################################################################
687 # parse buffers in a structure element - pull side
688 sub ParseElementPullBuffer($$$)
689 {
690         my($e) = shift;
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");
695
696         if (util::is_pure_scalar($e)) {
697                 return;
698         }
699
700         start_flags($e);
701
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";
708                 }
709         }
710             
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);
718                 } else {
719                         ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
720                 }
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";
725                         } else {
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";
727                         }
728                 }
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";
733         } else {
734                 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
735         }
736
737         if (util::need_wire_pointer($e)) {
738                 if (util::has_property($e, "relative")) {
739                         pidl "\t\tndr_pull_restore(ndr, &_relative_save);\n";
740                 }
741                 pidl "\t}\n";
742         }       
743
744         end_flags($e);
745 }
746
747 #####################################################################
748 # parse a struct
749 sub ParseStructPush($)
750 {
751         my($struct) = shift;
752         
753         if (! defined $struct->{ELEMENTS}) {
754                 return;
755         }
756
757         start_flags($struct);
758
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
763         # alignment)
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";
770         }
771
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";
775         }
776
777         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
778
779         pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
780
781         my $align = struct_alignment($struct);
782         pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
783
784         foreach my $e (@{$struct->{ELEMENTS}}) {
785                 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
786         }       
787
788         pidl "buffers:\n";
789         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
790         foreach my $e (@{$struct->{ELEMENTS}}) {
791                 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
792         }
793
794         pidl "\tndr_push_struct_end(ndr);\n";
795
796         pidl "done:\n";
797
798         end_flags($struct);
799 }
800
801
802 #####################################################################
803 # generate a push function for an enum
804 sub ParseEnumPush($)
805 {
806         my($enum) = shift;
807
808         start_flags($enum);
809
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";
814         } else {
815                 pidl "\tNDR_CHECK(ndr_push_uint16(ndr, r));\n";
816         }
817
818         end_flags($enum);
819 }
820
821 #####################################################################
822 # generate a pull function for an enum
823 sub ParseEnumPull($)
824 {
825         my($enum) = shift;
826
827         start_flags($enum);
828
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";
835         } else {
836                 pidl "\tuint16_t v;\n";
837                 pidl "\tNDR_CHECK(ndr_pull_uint16(ndr, &v));\n";
838         }
839         pidl "\t*r = v;\n";
840
841         end_flags($enum);
842 }
843
844 #####################################################################
845 # generate a print function for an enum
846 sub ParseEnumPrint($)
847 {
848         my($enum) = shift;
849
850         start_flags($enum);
851
852         pidl "\tconst char *val = NULL;\n\n";
853
854         pidl "\tswitch (r) {\n";
855         my $els = \@{$enum->{ELEMENTS}};
856         foreach my $i (0 .. $#{$els}) {
857                 my $e = ${$els}[$i];
858                 chomp $e;
859                 if ($e =~ /^(.*)=/) {
860                         $e = $1;
861                 }
862                 pidl "\t\tcase $e: val = \"$e\"; break;\n";
863         }
864
865         pidl "\t}\n\n\tndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);\n";
866
867         end_flags($enum);
868 }
869
870
871 #####################################################################
872 # generate a push function for a bitmap
873 sub ParseBitmapPush($)
874 {
875         my($bitmap) = shift;
876         my($type_decl) = util::bitmap_type_decl($bitmap);
877         my($type_fn) = util::bitmap_type_fn($bitmap);
878
879         start_flags($bitmap);
880
881         pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
882
883         end_flags($bitmap);
884 }
885
886 #####################################################################
887 # generate a pull function for an bitmap
888 sub ParseBitmapPull($)
889 {
890         my($bitmap) = shift;
891         my($type_decl) = util::bitmap_type_decl($bitmap);
892         my($type_fn) = util::bitmap_type_fn($bitmap);
893
894         start_flags($bitmap);
895
896         pidl "\t$type_decl v;\n";
897         pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
898         pidl "\t*r = v;\n";
899
900         end_flags($bitmap);
901 }
902
903 #####################################################################
904 # generate a print function for an bitmap
905 sub ParseBintmapPrintElement($$)
906 {
907         my($e) = shift;
908         my($bitmap) = shift;
909         my($type_decl) = util::bitmap_type_decl($bitmap);
910         my($type_fn) = util::bitmap_type_fn($bitmap);
911         my($name) = $bitmap->{PARENT}->{NAME};
912         my($flag);
913
914         if ($e =~ /^(\w+) .*$/) {
915                 $flag = "$1";
916         } else {
917                 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
918         }
919
920         pidl "\tndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);\n";
921 }
922
923 #####################################################################
924 # generate a print function for an bitmap
925 sub ParseBitmapPrint($)
926 {
927         my($bitmap) = shift;
928         my($type_decl) = util::bitmap_type_decl($bitmap);
929         my($type_fn) = util::bitmap_type_fn($bitmap);
930
931         start_flags($bitmap);
932
933         pidl "\tndr_print_$type_fn(ndr, name, r);\n";
934
935         pidl "\tndr->depth++;\n";
936         foreach my $e (@{$bitmap->{ELEMENTS}}) {
937                 ParseBintmapPrintElement($e, $bitmap);
938         }
939         pidl "\tndr->depth--;\n";
940
941         end_flags($bitmap);
942 }
943
944 #####################################################################
945 # generate a struct print function
946 sub ParseStructPrint($)
947 {
948         my($struct) = shift;
949
950         if (! defined $struct->{ELEMENTS}) {
951                 return;
952         }
953
954         start_flags($struct);
955
956         pidl "\tndr->depth++;\n";
957         foreach my $e (@{$struct->{ELEMENTS}}) {
958                 ParseElementPrintScalar($e, "r->");
959         }
960         pidl "\tndr->depth--;\n";
961
962         end_flags($struct);
963 }
964
965 #####################################################################
966 # parse a struct - pull side
967 sub ParseStructPull($)
968 {
969         my($struct) = shift;
970         my $conform_e;
971
972         if (! defined $struct->{ELEMENTS}) {
973                 return;
974         }
975
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
980         # alignment)
981         my $e = $struct->{ELEMENTS}[-1];
982         if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
983                 $conform_e = $e;
984         }
985
986         if (defined $e->{TYPE} && $e->{TYPE} eq "string"
987             &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
988                 $conform_e = $e;
989         }
990
991         if (defined $conform_e) {
992                 $conform_e = $e;
993                 pidl "\tuint32_t _conformant_size;\n";
994                 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
995         }
996
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";
1001                 }
1002         }
1003
1004         start_flags($struct);
1005
1006         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1007
1008         pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1009
1010         if (defined $conform_e) {
1011                 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
1012         }
1013
1014         my $align = struct_alignment($struct);
1015         pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1016
1017         foreach my $e (@{$struct->{ELEMENTS}}) {
1018                 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1019         }       
1020
1021         pidl "buffers:\n";
1022         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1023         foreach my $e (@{$struct->{ELEMENTS}}) {
1024                 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1025         }
1026
1027         foreach my $e (@{$struct->{ELEMENTS}}) {
1028                 CheckArraySizes($e, "r->");
1029         }
1030
1031         pidl "\tndr_pull_struct_end(ndr);\n";
1032
1033         pidl "done:\n";
1034
1035         end_flags($struct);
1036 }
1037
1038 #####################################################################
1039 # calculate size of ndr struct
1040 sub ParseStructNdrSize($)
1041 {
1042         my $t = shift;
1043         my $static = fn_prefix($t);
1044         my $sizevar;
1045
1046         pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)\n";
1047         pidl "{\n";
1048         if (my $flags = util::has_property($t, "flag")) {
1049                 pidl "\tflags |= $flags;\n";
1050         }
1051         pidl "\treturn ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});\n";
1052         pidl "}\n\n";
1053 }
1054
1055 #####################################################################
1056 # parse a union - push side
1057 sub ParseUnionPush($)
1058 {
1059         my $e = shift;
1060         my $have_default = 0;
1061
1062         start_flags($e);
1063
1064         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1065
1066         pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
1067
1068 #       my $align = union_alignment($e);
1069 #       pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
1070
1071         pidl "\tswitch (level) {\n";
1072         foreach my $el (@{$e->{DATA}}) {
1073                 if ($el->{CASE} eq "default") {
1074                         pidl "\tdefault:\n";
1075                         $have_default = 1;
1076                 } else {
1077                         pidl "\tcase $el->{CASE}:\n";
1078                 }
1079                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1080                         ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
1081                 }
1082                 pidl "\tbreak;\n\n";
1083         }
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";
1087         }
1088         pidl "\t}\n";
1089         pidl "buffers:\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";
1095                 } else {
1096                         pidl "\tcase $el->{CASE}:\n";
1097                 }
1098                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1099                         ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1100                 }
1101                 pidl "\tbreak;\n\n";
1102         }
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";
1106         }
1107         pidl "\t}\n";
1108         pidl "\tndr_push_struct_end(ndr);\n";
1109         pidl "done:\n";
1110         end_flags($e);
1111 }
1112
1113 #####################################################################
1114 # print a union
1115 sub ParseUnionPrint($)
1116 {
1117         my $e = shift;
1118         my $have_default = 0;
1119
1120         start_flags($e);
1121
1122         pidl "\tswitch (level) {\n";
1123         foreach my $el (@{$e->{DATA}}) {
1124                 if ($el->{CASE} eq "default") {
1125                         $have_default = 1;
1126                         pidl "\tdefault:\n";
1127                 } else {
1128                         pidl "\tcase $el->{CASE}:\n";
1129                 }
1130                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1131                         ParseElementPrintScalar($el->{DATA}, "r->");
1132                 }
1133                 pidl "\tbreak;\n\n";
1134         }
1135         if (! $have_default) {
1136                 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
1137         }
1138         pidl "\t}\n";
1139
1140         end_flags($e);
1141 }
1142
1143 #####################################################################
1144 # parse a union - pull side
1145 sub ParseUnionPull($)
1146 {
1147         my $e = shift;
1148         my $have_default = 0;
1149
1150         start_flags($e);
1151
1152         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1153
1154         pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1155
1156 #       my $align = union_alignment($e);
1157 #       pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1158
1159         pidl "\tswitch (level) {\n";
1160         foreach my $el (@{$e->{DATA}}) {
1161                 if ($el->{CASE} eq "default") {
1162                         pidl "\tdefault: {\n";
1163                         $have_default = 1;
1164                 } else {
1165                         pidl "\tcase $el->{CASE}: {\n";
1166                 }
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";
1171                         }
1172                         ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
1173                 }
1174                 pidl "\tbreak; }\n\n";
1175         }
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";
1179         }
1180         pidl "\t}\n";
1181         pidl "buffers:\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";
1187                 } else {
1188                         pidl "\tcase $el->{CASE}:\n";
1189                 }
1190                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1191                         ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1192                 }
1193                 pidl "\tbreak;\n\n";
1194         }
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";
1198         }
1199         pidl "\t}\n";
1200         pidl "\tndr_pull_struct_end(ndr);\n";
1201         pidl "done:\n";
1202         end_flags($e);
1203 }
1204
1205
1206 #####################################################################
1207 # parse a type
1208 sub ParseTypePush($)
1209 {
1210         my($data) = shift;
1211
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);
1221         }
1222 }
1223
1224 #####################################################################
1225 # generate a print function for a type
1226 sub ParseTypePrint($)
1227 {
1228         my($data) = shift;
1229
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);
1239         }
1240 }
1241
1242 #####################################################################
1243 # parse a type
1244 sub ParseTypePull($)
1245 {
1246         my($data) = shift;
1247
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);
1257         }
1258 }
1259
1260 #####################################################################
1261 # parse a typedef - push side
1262 sub ParseTypedefPush($)
1263 {
1264         my($e) = shift;
1265         my $static = fn_prefix($e);
1266
1267         if (! needed::is_needed("push_$e->{NAME}")) {
1268 #               print "push_$e->{NAME} not needed\n";
1269                 return;
1270         }
1271
1272         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1273                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1274         }
1275
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)";
1278                 pidl "\n{\n";
1279                 ParseTypePush($e->{DATA});
1280                 pidl "\treturn NT_STATUS_OK;\n";
1281                 pidl "}\n\n";
1282         }
1283
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)";
1286                 pidl "\n{\n";
1287                 ParseTypePush($e->{DATA});
1288                 pidl "\treturn NT_STATUS_OK;\n";
1289                 pidl "}\n\n";
1290         }
1291
1292         if ($e->{DATA}->{TYPE} eq "ENUM") {
1293                 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, enum $e->{NAME} r)";
1294                 pidl "\n{\n";
1295                 ParseTypePush($e->{DATA});
1296                 pidl "\treturn NT_STATUS_OK;\n";
1297                 pidl "}\n\n";
1298         }
1299
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)";
1303                 pidl "\n{\n";
1304                 ParseTypePush($e->{DATA});
1305                 pidl "\treturn NT_STATUS_OK;\n";
1306                 pidl "}\n\n";
1307         }
1308 }
1309
1310
1311 #####################################################################
1312 # parse a typedef - pull side
1313 sub ParseTypedefPull($)
1314 {
1315         my($e) = shift;
1316         my $static = fn_prefix($e);
1317
1318         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1319                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1320         }
1321
1322         if (! needed::is_needed("pull_$e->{NAME}")) {
1323 #               print "pull_$e->{NAME} not needed\n";
1324                 return;
1325         }
1326
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)";
1329                 pidl "\n{\n";
1330                 ParseTypePull($e->{DATA});
1331                 pidl "\treturn NT_STATUS_OK;\n";
1332                 pidl "}\n\n";
1333         }
1334
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)";
1337                 pidl "\n{\n";
1338                 ParseTypePull($e->{DATA});
1339                 pidl "\treturn NT_STATUS_OK;\n";
1340                 pidl "}\n\n";
1341         }
1342
1343         if ($e->{DATA}->{TYPE} eq "ENUM") {
1344                 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, enum $e->{NAME} *r)";
1345                 pidl "\n{\n";
1346                 ParseTypePull($e->{DATA});
1347                 pidl "\treturn NT_STATUS_OK;\n";
1348                 pidl "}\n\n";
1349         }
1350
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)";
1354                 pidl "\n{\n";
1355                 ParseTypePull($e->{DATA});
1356                 pidl "\treturn NT_STATUS_OK;\n";
1357                 pidl "}\n\n";
1358         }
1359 }
1360
1361
1362 #####################################################################
1363 # parse a typedef - print side
1364 sub ParseTypedefPrint($)
1365 {
1366         my($e) = shift;
1367
1368         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1369                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1370         }
1371
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)";
1374                 pidl "\n{\n";
1375                 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1376                 ParseTypePrint($e->{DATA});
1377                 pidl "}\n\n";
1378         }
1379
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)";
1382                 pidl "\n{\n";
1383                 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1384                 ParseTypePrint($e->{DATA});
1385                 pidl "}\n\n";
1386         }
1387
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)";
1390                 pidl "\n{\n";
1391                 ParseTypePrint($e->{DATA});
1392                 pidl "}\n\n";
1393         }
1394
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)";
1398                 pidl "\n{\n";
1399                 ParseTypePrint($e->{DATA});
1400                 pidl "}\n\n";
1401         }
1402 }
1403
1404 #####################################################################
1405 ## calculate the size of a structure
1406 sub ParseTypedefNdrSize($)
1407 {
1408         my($t) = shift;
1409         if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1410                 return;
1411         }
1412         
1413         ($t->{DATA}->{TYPE} eq "STRUCT") &&
1414                 ParseStructNdrSize($t);
1415 }
1416
1417 #####################################################################
1418 # parse a function - print side
1419 sub ParseFunctionPrint($)
1420 {
1421         my($fn) = shift;
1422
1423         pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1424         pidl "\n{\n";
1425         pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1426         pidl "\tndr->depth++;\n";
1427
1428         pidl "\tif (flags & NDR_SET_VALUES) {\n";
1429         pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n";
1430         pidl "\t}\n";
1431
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.");
1438                 }
1439         }
1440         pidl "\tndr->depth--;\n";
1441         pidl "\t}\n";
1442         
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.");
1449                 }
1450         }
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";
1454                 } else {
1455                         pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
1456                 }
1457         }
1458         pidl "\tndr->depth--;\n";
1459         pidl "\t}\n";
1460         
1461         pidl "\tndr->depth--;\n";
1462         pidl "}\n\n";
1463 }
1464
1465
1466 #####################################################################
1467 # parse a function element
1468 sub ParseFunctionElementPush($$)
1469
1470         my $e = shift;
1471         my $inout = shift;
1472
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");
1478                         pidl "\t}\n";
1479                 } else {
1480                         ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1481                 }
1482         } else {
1483                 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1484                 if ($e->{POINTERS}) {
1485                         ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1486                 }
1487         }
1488 }       
1489
1490 #####################################################################
1491 # parse a function
1492 sub ParseFunctionPush($)
1493
1494         my($fn) = shift;
1495         my $static = fn_prefix($fn);
1496
1497         pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1498
1499         pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1500
1501         foreach my $e (@{$fn->{DATA}}) {
1502                 if (util::has_property($e, "in")) {
1503                         ParseFunctionElementPush($e, "in");
1504                 }               
1505         }
1506
1507         pidl "\nndr_out:\n";
1508         pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1509
1510         foreach my $e (@{$fn->{DATA}}) {
1511                 if (util::has_property($e, "out")) {
1512                         ParseFunctionElementPush($e, "out");
1513                 }               
1514         }
1515
1516         if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1517                 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n";
1518         }
1519     
1520         pidl "\ndone:\n";
1521         pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1522 }
1523
1524 #####################################################################
1525 # parse a function element
1526 sub ParseFunctionElementPull($$)
1527
1528         my $e = shift;
1529         my $inout = shift;
1530
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";
1538                 } else {
1539                         pidl "\t{\n";
1540                 }
1541                 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1542                 pidl "\t}\n";
1543         } else {
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";
1547                         pidl "\t}\n";
1548                 }
1549                 if ($inout eq "in" && util::has_property($e, "ref")) {
1550                         pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1551                 }
1552
1553                 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1554                 if ($e->{POINTERS}) {
1555                         ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1556                 }
1557         }
1558 }
1559
1560
1561 ############################################################
1562 # allocate ref variables
1563 sub AllocateRefVars($)
1564 {
1565         my $e = shift;
1566         my $asize = util::array_size($e);
1567
1568         # note that if the variable is also an "in"
1569         # variable then we copy the initial value from
1570         # the in side
1571
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";
1577                 } else {
1578                         pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n";
1579                 }
1580                 return;
1581         }
1582
1583         # its an array
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";
1589         } else {
1590                 pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n";
1591         }
1592 }
1593
1594
1595 #####################################################################
1596 # parse a function
1597 sub ParseFunctionPull($)
1598
1599         my($fn) = shift;
1600         my $static = fn_prefix($fn);
1601
1602         # pull function args
1603         pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1604
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";
1609                 }
1610         }
1611
1612         pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1613
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";
1621                         last;
1622                 }
1623         }
1624
1625         foreach my $e (@{$fn->{DATA}}) {
1626                 if (util::has_property($e, "in")) {
1627                         ParseFunctionElementPull($e, "in");
1628                 }
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);
1633                 }
1634         }
1635
1636         foreach my $e (@{$fn->{DATA}}) {
1637                 if (util::has_property($e, "in")) {
1638                         CheckArraySizes($e, "r->in.");
1639                 }
1640         }
1641
1642         pidl "\nndr_out:\n";
1643         pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1644
1645         foreach my $e (@{$fn->{DATA}}) {
1646                 if (util::has_property($e, "out")) {
1647                         ParseFunctionElementPull($e, "out");
1648                 }
1649         }
1650
1651         foreach my $e (@{$fn->{DATA}}) {
1652                 if (util::has_property($e, "out")) {
1653                         CheckArraySizes($e, "r->out.");
1654                 }
1655         }
1656
1657         if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1658                 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
1659         }
1660
1661         pidl "\ndone:\n";
1662         pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1663 }
1664
1665 #####################################################################
1666 # produce a function call table
1667 sub FunctionTable($)
1668 {
1669         my($interface) = shift;
1670         my($data) = $interface->{INHERITED_DATA};
1671         my $count = 0;
1672         my $uname = uc $interface->{NAME};
1673
1674         foreach my $d (@{$data}) {
1675                 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1676         }
1677
1678         return if ($count == 0);
1679
1680         pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n";
1681         foreach my $d (@{$data}) {
1682                 if ($d->{TYPE} eq "FUNCTION") {
1683                         pidl "\t{\n";
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";
1689                         pidl "\t},\n";
1690                 }
1691         }
1692         pidl "\t{ NULL, 0, NULL, NULL }\n};\n\n";
1693
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} . "]\"";
1697         }
1698
1699         my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1700         my $endpoint_count = $#e + 1;
1701
1702         pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n";
1703         foreach my $ep (@e) {
1704                 pidl "\t$ep, \n";
1705         }
1706         pidl "};\n\n";
1707
1708         pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n";
1709         pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n";
1710         pidl "};\n\n";
1711
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";
1717         pidl "\t$count,\n";
1718         pidl "\t$interface->{NAME}\_calls,\n";
1719         pidl "\t&$interface->{NAME}\_endpoints\n";
1720         pidl "};\n\n";
1721
1722         pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)\n";
1723         pidl "{\n";
1724         pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});\n";
1725         pidl "}\n\n";
1726 }
1727
1728 #####################################################################
1729 # parse the interface definitions
1730 sub ParseInterface($)
1731 {
1732         my($interface) = shift;
1733         my($data) = $interface->{DATA};
1734
1735         foreach my $d (@{$data}) {
1736                 if ($d->{TYPE} eq "TYPEDEF") {
1737                     $structs{$d->{NAME}} = $d;
1738             }
1739         }
1740
1741         foreach my $d (@{$data}) {
1742                 ($d->{TYPE} eq "TYPEDEF") &&
1743                     ParseTypedefPush($d);
1744                 ($d->{TYPE} eq "FUNCTION") && 
1745                     ParseFunctionPush($d);
1746         }
1747         foreach my $d (@{$data}) {
1748                 ($d->{TYPE} eq "TYPEDEF") &&
1749                     ParseTypedefPull($d);
1750                 ($d->{TYPE} eq "FUNCTION") && 
1751                     ParseFunctionPull($d);
1752         }
1753         foreach my $d (@{$data}) {
1754                 if ($d->{TYPE} eq "TYPEDEF" &&
1755                     !util::has_property($d, "noprint")) {
1756                         ParseTypedefPrint($d);
1757                 }
1758                 if ($d->{TYPE} eq "FUNCTION" &&
1759                     !util::has_property($d, "noprint")) {
1760                         ParseFunctionPrint($d);
1761                 }
1762         }
1763
1764         foreach my $d (@{$data}) {
1765                 ($d->{TYPE} eq "TYPEDEF") && 
1766                         ParseTypedefNdrSize($d);
1767         }
1768
1769         FunctionTable($interface);
1770 }
1771
1772 sub RegistrationFunction($$)
1773 {
1774         my $idl = shift;
1775         my $filename = shift;
1776
1777         $filename =~ /.*\/ndr_(.*).c/;
1778         my $basename = $1;
1779         pidl "NTSTATUS dcerpc_$basename\_init(void)\n";
1780         pidl "{\n";
1781         pidl "\tNTSTATUS status = NT_STATUS_OK;\n";
1782         foreach my $interface (@{$idl}) {
1783                 next if $interface->{TYPE} ne "INTERFACE";
1784
1785                 my $data = $interface->{INHERITED_DATA};
1786                 my $count = 0;
1787                 foreach my $d (@{$data}) {
1788                         if ($d->{TYPE} eq "FUNCTION") { $count++; }
1789                 }
1790
1791                 next if ($count == 0);
1792
1793                 pidl "\tstatus = dcerpc_ndr_$interface->{NAME}_init();\n";
1794                 pidl "\tif (NT_STATUS_IS_ERR(status)) {\n";
1795                 pidl "\t\treturn status;\n";
1796                 pidl "\t}\n\n";
1797         }
1798         pidl "\treturn status;\n";
1799         pidl "}\n\n";
1800 }
1801
1802 #####################################################################
1803 # parse a parsed IDL structure back into an IDL file
1804 sub Parse($$)
1805 {
1806         my($idl) = shift;
1807         my($filename) = shift;
1808         my $h_filename = $filename;
1809
1810         if ($h_filename =~ /(.*)\.c/) {
1811                 $h_filename = "$1.h";
1812         }
1813
1814         open(OUT, ">$filename") || die "can't open $filename";    
1815
1816         pidl "/* parser auto-generated by pidl */\n\n";
1817         pidl "#include \"includes.h\"\n";
1818         pidl "#include \"$h_filename\"\n\n";
1819
1820         foreach my $x (@{$idl}) {
1821                 if ($x->{TYPE} eq "INTERFACE") { 
1822                         needed::BuildNeeded($x);
1823                         ParseInterface($x);
1824                 }
1825         }
1826
1827         RegistrationFunction($idl, $filename);
1828
1829         close(OUT);
1830 }
1831
1832 1;