1 ###################################################
2 # Samba3 NDR parser generator for IDL structures
3 # Copyright jelmer@samba.org 2005
4 # released under the GNU GPL
6 package Parse
::Pidl
::Samba3
::Parser
;
9 use Parse
::Pidl
::Typelist
qw(hasType getType mapType);
10 use Parse
::Pidl
::Util
qw(has_property ParseExpr);
11 use Parse
::Pidl
::NDR
qw(GetPrevLevel GetNextLevel ContainsDeferred);
12 use Parse
::Pidl
::Samba3
::Types
qw(DeclShort DeclLong InitType DissectType);
14 use vars
qw($VERSION);
17 use constant PRIMITIVES => 1;
18 use constant DEFERRED => 2;
22 sub indent() { $tabs.="\t"; }
23 sub deindent() { $tabs = substr($tabs, 1); }
24 sub pidl($) { $res .= $tabs.(shift)."\n"; }
25 sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
28 # - Add some security checks (array sizes, memory alloc == NULL, etc)
29 # - Don't add seperate _p and _d functions if there is no deferred data
38 # Only align if previous element was smaller then current one
40 pidl "if (!prs_align_custom(ps, $b))";
41 pidl "\treturn False;";
48 sub DeclareArrayVariables
55 foreach my $e (@$es) {
56 foreach my $l (@{$e->{LEVELS}}) {
58 next if ($l->{IS_DEFERRED} and $what == PRIMITIVES);
59 next if (not $l->{IS_DEFERRED} and $what == DEFERRED);
61 if ($l->{TYPE} eq "ARRAY") {
62 pidl "uint32 i_$e->{NAME}_$l->{LEVEL_INDEX};";
70 sub ParseElementLevelData($$$$$$$)
72 my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
74 my $c = DissectType($e,$l,$varname,$what,$align);
77 if (defined($e->{ALIGN})) {
78 Align($align, $e->{ALIGN});
85 pidl "\treturn False;";
88 sub ParseElementLevelArray($$$$$$$)
90 my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
92 if ($l->{IS_ZERO_TERMINATED}) {
93 fatal($e, "[string] attribute not supported for Samba3 yet");
98 my $len = ParseExpr($l->{LENGTH_IS}, $env);
99 my $size = ParseExpr($l->{SIZE_IS}, $env);
101 if ($what == PRIMITIVES) {
103 if ($l->{IS_CONFORMANT} and not $l->{IS_SURROUNDING}) {
105 pidl "if (!prs_uint32(\"size_$e->{NAME}\", ps, depth, &" . ParseExpr("size_$e->{NAME}", $env) . "))";
106 pidl "\treturn False;";
110 if ($l->{IS_VARYING}) {
112 pidl "if (!prs_uint32(\"offset_$e->{NAME}\", ps, depth, &" . ParseExpr("offset_$e->{NAME}", $env) . "))";
113 pidl "\treturn False;";
116 pidl "if (!prs_uint32(\"length_$e->{NAME}\", ps, depth, &" . ParseExpr("length_$e->{NAME}", $env) . "))";
117 pidl "\treturn False;";
122 # Everything but fixed arrays have to be allocated
123 if (!$l->{IS_FIXED} and $what == PRIMITIVES) {
124 pidl "if (UNMARSHALLING(ps)) {";
126 pidl "$varname = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*$varname)*$size);";
131 return if ($what == DEFERRED and not ContainsDeferred($e,$l));
133 my $i = "i_$e->{NAME}_$l->{LEVEL_INDEX}";
134 pidl "for ($i=0; $i<$len;$i++) {";
136 ParseElementLevel($e,$nl,$env,$varname."[$i]",$what,$align);
141 sub ParseElementLevelSwitch($$$$$$$)
143 my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
145 ParseElementLevel($e,$nl,$env,$varname,$what,$align);
148 sub ParseElementLevelPtr($$$$$$$)
150 my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
152 if ($what == PRIMITIVES) {
153 if (($l->{POINTER_TYPE} eq "ref") and ($l->{LEVEL} eq "EMBEDDED")) {
154 # Ref pointers always have to be non-NULL
155 pidl "if (MARSHALLING(ps) && !" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . ")";
156 pidl "\treturn False;";
160 unless ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") {
162 pidl "if (!prs_uint32(\"ptr$l->{POINTER_INDEX}_$e->{NAME}\", ps, depth, &" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . "))";
163 pidl "\treturn False;";
168 if ($l->{POINTER_TYPE} eq "relative") {
169 fatal($e, "relative pointers not supported for Samba 3");
173 if ($what == DEFERRED) {
174 if ($l->{POINTER_TYPE} ne "ref") {
175 pidl "if (" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . ") {";
178 ParseElementLevel($e,$nl,$env,$varname,PRIMITIVES,$align);
179 ParseElementLevel($e,$nl,$env,$varname,DEFERRED,$align);
180 if ($l->{POINTER_TYPE} ne "ref") {
188 sub ParseElementLevelSubcontext($$$$$$$)
190 my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
192 fatal($e, "subcontext() not supported for Samba 3");
196 sub ParseElementLevel($$$$$$)
198 my ($e,$l,$env,$varname,$what,$align) = @_;
201 DATA => \&ParseElementLevelData,
202 SUBCONTEXT => \&ParseElementLevelSubcontext,
203 POINTER => \&ParseElementLevelPtr,
204 SWITCH => \&ParseElementLevelSwitch,
205 ARRAY => \&ParseElementLevelArray
206 }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname,$what,$align);
209 sub ParseElement($$$$)
211 my ($e,$env,$what,$align) = @_;
213 ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env), $what, $align);
219 my ($e,$l,$varname,$env) = @_;
221 if ($l->{TYPE} eq "POINTER") {
222 if ($l->{POINTER_TYPE} eq "ref") {
223 pidl "if (!$varname)";
224 pidl "\treturn False;";
227 pidl "if ($varname) {";
231 pidl ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . " = 1;";
232 InitLevel($e, GetNextLevel($e,$l), "*$varname", $env);
234 if ($l->{POINTER_TYPE} ne "ref") {
237 pidl "\t" . ParseExpr("ptr$l->{POINTER_INDEX}_$e->{NAME}", $env) . " = 0;";
240 } elsif ($l->{TYPE} eq "ARRAY") {
241 pidl ParseExpr($e->{NAME}, $env) . " = $varname;";
242 } elsif ($l->{TYPE} eq "DATA") {
243 pidl InitType($e, $l, ParseExpr($e->{NAME}, $env), $varname);
244 } elsif ($l->{TYPE} eq "SWITCH") {
245 InitLevel($e, GetNextLevel($e,$l), $varname, $env);
246 pidl ParseExpr($e->{NAME}, $env) . ".switch_value = " . ParseExpr($l->{SWITCH_IS}, $env) . ";";
250 sub GenerateEnvElement($$)
253 foreach my $l (@{$e->{LEVELS}}) {
254 if ($l->{TYPE} eq "DATA") {
255 $env->{$e->{NAME}} = "v->$e->{NAME}";
256 } elsif ($l->{TYPE} eq "POINTER") {
257 $env->{"ptr$l->{POINTER_INDEX}_$e->{NAME}"} = "v->ptr$l->{POINTER_INDEX}_$e->{NAME}";
258 } elsif ($l->{TYPE} eq "SWITCH") {
259 } elsif ($l->{TYPE} eq "ARRAY") {
260 $env->{"length_$e->{NAME}"} = "v->length_$e->{NAME}";
261 $env->{"size_$e->{NAME}"} = "v->size_$e->{NAME}";
262 $env->{"offset_$e->{NAME}"} = "v->offset_$e->{NAME}";
271 my $fn = "$if->{NAME}_io_$n";
272 my $sn = uc("$if->{NAME}_$n");
273 my $ifn = "init_$if->{NAME}_$n";
276 foreach (@{$s->{ELEMENTS}}) {
277 $args .= ", " . DeclLong($_);
280 my $env = { "this" => "v" };
281 GenerateEnvElement($_, $env) foreach (@{$s->{ELEMENTS}});
283 pidl "BOOL $ifn($sn *v$args)";
286 pidl "DEBUG(5,(\"$ifn\\n\"));";
288 # Call init for all arguments
289 foreach (@{$s->{ELEMENTS}}) {
290 InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env);
301 pidl "BOOL $pfn(const char *desc, $sn *v, prs_struct *ps, int depth)";
304 DeclareArrayVariables($s->{ELEMENTS}, PRIMITIVES);
305 pidl "if (v == NULL)";
306 pidl "\treturn False;";
308 pidl "prs_debug(ps, depth, desc, \"$pfn\");";
312 if ($s->{SURROUNDING_ELEMENT}) {
313 pidl "if (!prs_uint32(\"size_$s->{SURROUNDING_ELEMENT}->{NAME}\", ps, depth, &" . ParseExpr("size_$s->{SURROUNDING_ELEMENT}->{NAME}", $env) . "))";
314 pidl "\treturn False;";
320 foreach (@{$s->{ELEMENTS}}) {
321 ParseElement($_, $env, PRIMITIVES, \$align);
330 pidl "BOOL $dfn(const char *desc, $sn *v, prs_struct *ps, int depth)";
333 DeclareArrayVariables($s->{ELEMENTS}, DEFERRED);
334 pidl "if (v == NULL)";
335 pidl "\treturn False;";
337 pidl "prs_debug(ps, depth, desc, \"$dfn\");";
341 foreach (@{$s->{ELEMENTS}}) {
342 ParseElement($_, $env, DEFERRED, \$align);
352 sub UnionGenerateEnvElement($)
357 foreach my $l (@{$e->{LEVELS}}) {
358 if ($l->{TYPE} eq "DATA") {
359 $env->{$e->{NAME}} = "v->u.$e->{NAME}";
360 } elsif ($l->{TYPE} eq "POINTER") {
361 $env->{"ptr$l->{POINTER_INDEX}_$e->{NAME}"} = "v->ptr$l->{POINTER_INDEX}";
362 } elsif ($l->{TYPE} eq "SWITCH") {
363 } elsif ($l->{TYPE} eq "ARRAY") {
364 $env->{"length_$e->{NAME}"} = "v->length";
365 $env->{"size_$e->{NAME}"} = "v->size";
366 $env->{"offset_$e->{NAME}"} = "v->offset";
377 my $fn = "$if->{NAME}_io_$n";
378 my $sn = uc("$if->{NAME}_$n\_ctr");
383 pidl "BOOL $pfn(const char *desc, $sn* v, prs_struct *ps, int depth)";
386 DeclareArrayVariables($u->{ELEMENTS});
388 if (defined ($u->{SWITCH_TYPE})) {
389 pidl "if (!prs_$u->{SWITCH_TYPE}(\"switch_value\", ps, depth, &v->switch_value))";
390 pidl "\treturn False;";
394 # Maybe check here that level and v->switch_value are equal?
396 pidl "switch (v->switch_value) {";
399 foreach (@{$u->{ELEMENTS}}) {
402 if ($_->{TYPE} ne "EMPTY") {
404 my $env = UnionGenerateEnvElement($_);
406 ParseElement($_, $env, PRIMITIVES, \$align);
414 unless ($u->{HAS_DEFAULT}) {
416 pidl "\treturn False;";
428 pidl "BOOL $dfn(const char *desc, $sn* v, prs_struct *ps, int depth)";
431 DeclareArrayVariables($u->{ELEMENTS});
433 if (defined($u->{SWITCH_TYPE})) {
434 pidl "switch (v->switch_value) {";
436 pidl "switch (level) {";
440 foreach (@{$u->{ELEMENTS}}) {
443 if ($_->{TYPE} ne "EMPTY") {
445 my $env = UnionGenerateEnvElement($_);
447 ParseElement($_, $env, DEFERRED, \$align);
464 sub CreateFnDirection($$$$$)
466 my ($fn,$ifn,$s,$all,$es) = @_;
469 foreach (@$all) { $args .= ", " . DeclLong($_); }
472 GenerateEnvElement($_, $env) foreach (@$es);
474 pidl "BOOL $ifn($s *v$args)";
477 pidl "DEBUG(5,(\"$ifn\\n\"));";
479 # Call init for all arguments
481 InitLevel($_, $_->{LEVELS}[0], $_->{NAME}, $env);
489 pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)";
492 DeclareArrayVariables($es);
493 pidl "if (v == NULL)";
494 pidl "\treturn False;";
496 pidl "prs_debug(ps, depth, desc, \"$fn\");";
501 ParseElement($_, $env, PRIMITIVES, \$align);
502 ParseElement($_, $env, DEFERRED, \$align);
512 sub ParseFunction($$)
518 my @all = @{$fn->{ELEMENTS}};
520 foreach (@{$fn->{ELEMENTS}}) {
521 push (@in, $_) if (grep(/in/, @{$_->{DIRECTION}}));
522 push (@out, $_) if (grep(/out/, @{$_->{DIRECTION}}));
525 if (defined($fn->{RETURN_TYPE})) {
528 TYPE => $fn->{RETURN_TYPE},
532 DATA_TYPE => $fn->{RETURN_TYPE}
537 push (@out, $status);
538 push (@all, $status);
541 CreateFnDirection("$if->{NAME}_io_q_$fn->{NAME}",
542 "init_$if->{NAME}_q_$fn->{NAME}",
543 uc("$if->{NAME}_q_$fn->{NAME}"),
545 CreateFnDirection("$if->{NAME}_io_r_$fn->{NAME}",
546 "init_$if->{NAME}_r_$fn->{NAME}",
547 uc("$if->{NAME}_r_$fn->{NAME}"),
551 sub ParseInterface($)
556 pidl "/* $if->{NAME} structures */";
557 foreach (@{$if->{TYPEDEFS}}) {
558 ParseStruct($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "STRUCT");
559 ParseUnion($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "UNION");
562 pidl "/* $if->{NAME} functions */";
563 ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}});
568 my($ndr,$filename) = @_;
574 pidl " * Unix SMB/CIFS implementation.";
575 pidl " * parser auto-generated by pidl. DO NOT MODIFY!";
578 pidl "#include \"includes.h\"";
580 pidl "#undef DBGC_CLASS";
581 pidl "#define DBGC_CLASS DBGC_RPC_PARSE";
585 ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");