1 ###################################################
2 # Trivial Parser Generator
3 # Copyright jelmer@samba.org 2005-2007
4 # released under the GNU GPL
6 package Parse::Pidl::Samba4::TDR;
7 use Parse::Pidl qw(fatal);
8 use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
9 use Parse::Pidl::Samba4 qw(is_intree choose_header);
10 use Parse::Pidl::Typelist qw(mapTypeName);
12 use base Parse::Pidl::Base;
15 push @ISA, qw(Exporter);
16 @EXPORT_OK = qw(ParserType $res $res_hdr);
18 use vars qw($VERSION);
25 my $self = { res => "", res_hdr => "", tabs => "" };
31 return(", const char *name") if ($t eq "print");
32 return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
38 my ($self, $p, $d) = @_;
40 $self->pidl($d); $self->pidl_hdr("$d;");
42 $self->pidl("static $d");
49 foreach (@{$e->{ELEMENTS}}) {
50 next if (has_property($_, "charset") and
51 scalar(@{$_->{ARRAY_LEN}}) == 1);
52 return 1 if (defined($_->{ARRAY_LEN}) and
53 scalar(@{$_->{ARRAY_LEN}}) > 0);
58 sub ParserElement($$$$)
60 my ($self, $e,$t,$env) = @_;
64 my $mem_ctx = "mem_ctx";
66 fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
67 fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
68 fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is"));
71 $name = ", \"$e->{NAME}\"$array";
74 if (has_property($e, "flag")) {
77 $self->pidl("uint32_t saved_flags = tdr->flags;");
78 $self->pidl("tdr->flags |= $e->{PROPERTIES}->{flag};");
81 if (has_property($e, "charset")) {
82 fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0);
84 my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env, $e);
85 if ($len eq "*") { $len = "-1"; }
86 $name = ", mem_ctx" if ($t eq "pull");
87 $self->pidl("TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));");
91 if (has_property($e, "switch_is")) {
92 $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env, $e);
95 if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
96 my $len = ParseExpr($e->{ARRAY_LEN}[0], $env, $e);
98 if ($t eq "pull" and not is_constant($len)) {
99 $self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);");
100 $mem_ctx = "v->$e->{NAME}";
103 $self->pidl("for (i = 0; i < $len; i++) {");
109 $name = ", $mem_ctx";
112 if (has_property($e, "value") && $t eq "push") {
113 $self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";");
116 $self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));");
118 if ($array) { $self->deindent; $self->pidl("}"); }
120 if (has_property($e, "flag")) {
121 $self->pidl("tdr->flags = saved_flags;");
127 sub ParserStruct($$$$$)
129 my ($self, $e,$t,$p) = @_;
131 $self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
132 $self->pidl("{"); $self->indent;
133 $self->pidl("int i;") if (ContainsArray($e));
136 $self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);");
137 $self->pidl("tdr->level++;");
140 my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
142 $self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
145 $self->pidl("tdr->level--;");
148 $self->pidl("return NT_STATUS_OK;");
150 $self->deindent; $self->pidl("}");
153 sub ParserUnion($$$$)
155 my ($self, $e,$t,$p) = @_;
157 $self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
158 $self->pidl("{"); $self->indent;
159 $self->pidl("int i;") if (ContainsArray($e));
162 $self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);");
163 $self->pidl("tdr->level++;");
166 $self->pidl("switch (level) {"); $self->indent;
167 foreach (@{$e->{ELEMENTS}}) {
168 if (has_property($_, "case")) {
169 $self->pidl("case " . $_->{PROPERTIES}->{case} . ":");
170 } elsif (has_property($_, "default")) {
171 $self->pidl("default:");
173 $self->indent; $self->ParserElement($_, $t, {}); $self->deindent;
174 $self->pidl("break;");
176 $self->deindent; $self->pidl("}");
179 $self->pidl("tdr->level--;");
182 $self->pidl("return NT_STATUS_OK;\n");
183 $self->deindent; $self->pidl("}");
186 sub ParserBitmap($$$$)
188 my ($self,$e,$t,$p) = @_;
190 $self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e));
195 my ($self,$e,$t,$p) = @_;
196 my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
197 my $mt = mapTypeName($bt);
199 $self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
202 $self->pidl("\t$mt r;");
203 $self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));");
204 $self->pidl("\t*v = r;");
205 } elsif ($t eq "push") {
206 $self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));");
207 } elsif ($t eq "print") {
208 $self->pidl("\t/* FIXME */");
210 $self->pidl("\treturn NT_STATUS_OK;");
214 sub ParserTypedef($$$$)
216 my ($self, $e,$t,$p) = @_;
218 $self->ParserType($e->{DATA},$t);
223 my ($self, $e,$t) = @_;
225 return if (has_property($e, "no$t"));
228 STRUCT => \&ParserStruct, UNION => \&ParserUnion,
229 ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
230 TYPEDEF => \&ParserTypedef
233 $handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public"))
234 if (defined($handlers->{$e->{TYPE}}));
239 sub ParserInterface($$)
243 $self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__");
244 $self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__");
246 foreach (@{$x->{DATA}}) {
247 $self->ParserType($_, "pull");
248 $self->ParserType($_, "push");
249 $self->ParserType($_, "print");
252 $self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */");
257 my ($self,$idl,$hdrname,$baseheader) = @_;
258 $self->pidl("/* autogenerated by pidl */");
260 $self->pidl("#include \"includes.h\"");
262 $self->pidl("#include <stdio.h>");
263 $self->pidl("#include <stdbool.h>");
264 $self->pidl("#include <stdlib.h>");
265 $self->pidl("#include <stdint.h>");
266 $self->pidl("#include <stdarg.h>");
267 $self->pidl("#include <string.h>");
268 $self->pidl("#include <core/ntstatus.h>");
270 $self->pidl("#include \"$hdrname\"");
272 $self->pidl_hdr("/* autogenerated by pidl */");
273 $self->pidl_hdr("#include \"$baseheader\"");
274 $self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h"));
277 foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
278 return ($self->{res_hdr}, $self->{res});