1 ###################################################
2 # Trivial Parser Generator
3 # Copyright jelmer@samba.org 2005
4 # released under the GNU GPL
6 package Parse::Pidl::Samba::TDR;
7 use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
17 sub indent() { $tabs.="\t"; }
18 sub deindent() { $tabs = substr($tabs, 1); }
19 sub pidl($) { $ret .= $tabs.(shift)."\n"; }
20 sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
21 sub static($) { my $p = shift; return("static ") unless ($p); return ""; }
24 return(", const char *name") if ($t eq "print");
25 return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
32 foreach (@{$e->{ELEMENTS}}) {
33 next if (has_property($_, "charset") and
34 scalar(@{$_->{ARRAY_LEN}}) == 1);
35 return 1 if (defined($_->{ARRAY_LEN}) and
36 scalar(@{$_->{ARRAY_LEN}}) > 0);
41 sub ParserElement($$$)
47 my $mem_ctx = "mem_ctx";
49 fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
50 fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
51 fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is"));
54 $name = ", \"$e->{NAME}\"$array";
57 if (has_property($e, "flag")) {
60 pidl "uint32_t saved_flags = tdr->flags;";
61 pidl "tdr->flags |= $e->{PROPERTIES}->{flag};";
64 if (has_property($e, "charset")) {
65 fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0);
67 my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env);
68 if ($len eq "*") { $len = "-1"; }
69 $name = ", mem_ctx" if ($t eq "pull");
70 pidl "TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));";
74 if (has_property($e, "switch_is")) {
75 $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env);
78 if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
79 my $len = ParseExpr($e->{ARRAY_LEN}[0], $env);
81 if ($t eq "pull" and not is_constant($len)) {
82 pidl "TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);";
83 $mem_ctx = "v->$e->{NAME}";
86 pidl "for (i = 0; i < $len; i++) {";
95 if (has_property($e, "value") && $t eq "push") {
96 pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env).";";
99 pidl "TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));";
101 if ($array) { deindent; pidl "}"; }
103 if (has_property($e, "flag")) {
104 pidl "tdr->flags = saved_flags;";
110 sub ParserStruct($$$$)
112 my ($e,$n,$t,$p) = @_;
114 pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", struct $n *v)";
116 pidl "int i;" if (ContainsArray($e));
119 pidl "tdr->print(tdr, \"\%-25s: struct $n\", name);";
120 pidl "tdr->level++;";
123 my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
125 ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
128 pidl "tdr->level--;";
131 pidl "return NT_STATUS_OK;";
136 sub ParserUnion($$$$)
138 my ($e,$n,$t,$p) = @_;
140 pidl static($p)."NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".typearg($t).", int level, union $n *v)";
142 pidl "int i;" if (ContainsArray($e));
145 pidl "tdr->print(tdr, \"\%-25s: union $n\", name);";
146 pidl "tdr->level++;";
149 pidl "switch (level) {"; indent;
150 foreach (@{$e->{ELEMENTS}}) {
151 if (has_property($_, "case")) {
152 pidl "case " . $_->{PROPERTIES}->{case} . ":";
153 } elsif (has_property($_, "default")) {
156 indent; ParserElement($_, $t, {}); deindent;
162 pidl "tdr->level--;";
165 pidl "return NT_STATUS_OK;\n";
169 sub ParserBitmap($$$$)
171 my ($e,$n,$t,$p) = @_;
173 pidl "#define tdr_$t\_$n tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e);
178 my ($e,$n,$t,$p) = @_;
179 my $bt = ($e->{PROPERTIES}->{base_type} or "uint8");
181 pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", enum $n *v)";
185 pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));";
187 } elsif ($t eq "push") {
188 pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, ($bt\_t *)v));";
189 } elsif ($t eq "print") {
190 pidl "\t/* FIXME */";
192 pidl "\treturn NT_STATUS_OK;";
196 sub ParserTypedef($$)
200 return if (has_property($e, "no$t"));
202 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
204 { STRUCT => \&ParserStruct, UNION => \&ParserUnion,
205 ENUM => \&ParserEnum, BITMAP => \&ParserBitmap
206 }->{$e->{DATA}->{TYPE}}->($e->{DATA}, $e->{NAME}, $t, has_property($e, "public"));
211 sub ParserInterface($)
215 foreach (@{$x->{DATA}}) {
216 next if ($_->{TYPE} ne "TYPEDEF");
217 ParserTypedef($_, "pull");
218 ParserTypedef($_, "push");
219 ParserTypedef($_, "print");
225 my ($idl,$hdrname) = @_;
227 pidl "/* autogenerated by pidl */";
228 pidl "#include \"includes.h\"";
229 pidl "#include \"$hdrname\"";
231 foreach (@$idl) { ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
235 sub HeaderInterface($$)
237 my ($x,$outputdir) = @_;
239 pidl "#ifndef __TDR_$x->{NAME}_HEADER__";
240 pidl "#define __TDR_$x->{NAME}_HEADER__";
242 foreach my $e (@{$x->{DATA}}) {
243 next unless ($e->{TYPE} eq "TYPEDEF");
244 next unless has_property($e, "public");
248 $switch = ", int level" if ($e->{DATA}->{TYPE} eq "UNION");
250 if ($e->{DATA}->{TYPE} eq "BITMAP") {
253 my ($n, $d) = ($e->{NAME}, lc($e->{DATA}->{TYPE}));
254 pidl "NTSTATUS tdr_pull\_$n(struct tdr_pull *tdr, TALLOC_CTX *ctx$switch, $d $n *v);";
255 pidl "NTSTATUS tdr_print\_$n(struct tdr_print *tdr, const char *name$switch, $d $n *v);";
256 pidl "NTSTATUS tdr_push\_$n(struct tdr_push *tdr$switch, $d $n *v);";
262 pidl "#endif /* __TDR_$x->{NAME}_HEADER__ */";
267 my ($idl,$outputdir,$basename) = @_;
269 pidl "/* Generated by pidl */";
271 pidl "#include \"$outputdir/$basename.h\"";
275 HeaderInterface($_, $outputdir) if ($_->{TYPE} eq "INTERFACE");