diff options
Diffstat (limited to 'source4/build/pidl')
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Samba/TDR.pm | 252 | ||||
-rwxr-xr-x | source4/build/pidl/pidl | 18 |
2 files changed, 270 insertions, 0 deletions
diff --git a/source4/build/pidl/Parse/Pidl/Samba/TDR.pm b/source4/build/pidl/Parse/Pidl/Samba/TDR.pm new file mode 100644 index 0000000000..fb9dd0daea --- /dev/null +++ b/source4/build/pidl/Parse/Pidl/Samba/TDR.pm @@ -0,0 +1,252 @@ +################################################### +# Trivial Parser Generator +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba::TDR; +use Parse::Pidl::Util qw(has_property ParseExpr is_constant); +use Data::Dumper; + +use strict; + +my $ret = ""; +my $tabs = ""; + +sub indent() { $tabs.="\t"; } +sub deindent() { $tabs = substr($tabs, 1); } +sub pidl($) { $ret .= $tabs.(shift)."\n"; } +sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); } +sub static($) { my $p = shift; return("static ") unless ($p); return ""; } +sub printarg($) { + my $t = shift; + return(", const char *name") if ($t eq "print"); + return(""); +} + +sub ContainsArray($) +{ + my $e = shift; + foreach (@{$e->{ELEMENTS}}) { + next if (has_property($_, "charset") and + scalar(@{$_->{ARRAY_LEN}}) == 1); + return 1 if (defined($_->{ARRAY_LEN}) and + scalar(@{$_->{ARRAY_LEN}}) > 0); + } + return 0; +} + +sub ParserElement($$$) +{ + my ($e,$t,$env) = @_; + my $switch = ""; + my $array = ""; + my $name = ""; + + fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0); + fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is")); + fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is")); + + if ($t eq "print") { + $name = ", \"$e->{NAME}\"$array"; + } + + if (has_property($e, "charset")) { + fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0); + + my $len = @{$e->{ARRAY_LEN}}[0]; + if ($len eq "*") { $len = "-1"; } + pidl "TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));"; + return; + } + + if (has_property($e, "switch_is")) { + $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env); + } + + if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) { + my $len = ParseExpr($e->{ARRAY_LEN}[0], $env); + + if ($t eq "pull" and not is_constant($len)) { + pidl "TDR_ALLOC(tdr, v->$e->{NAME}, $len);" + } + + pidl "for (i = 0; i < $len; i++) {"; + indent; + $array = "[i]"; + } + + if (has_property($e, "value") && $t eq "push") { + pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env).";"; + } + + pidl "TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));"; + + if ($array) { deindent; pidl "}"; } +} + +sub ParserStruct($$$$) +{ + my ($e,$n,$t,$p) = @_; + + pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", struct $n *v)"; + pidl "{"; indent; + pidl "int i;" if (ContainsArray($e)); + + if ($t eq "print") { + pidl "tdr->print(tdr, \"\%-25s: struct $n\", name);"; + pidl "tdr->level++;"; + } + + my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}}; + ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}}); + + if ($t eq "print") { + pidl "tdr->level--;"; + } + + pidl "return NT_STATUS_OK;"; + + deindent; pidl "}"; +} + +sub ParserUnion($$$$) +{ + my ($e,$n,$t,$p) = @_; + + pidl static($p)."NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".printarg($t).", int level, union $n *v)"; + pidl "{"; indent; + pidl "int i;" if (ContainsArray($e)); + + if ($t eq "print") { + pidl "tdr->print(tdr, \"\%-25s: union $n\", name);"; + pidl "tdr->level++;"; + } + + pidl "switch (level) {"; indent; + foreach (@{$e->{ELEMENTS}}) { + if (has_property($_, "case")) { + pidl "case " . $_->{PROPERTIES}->{case} . ":"; + } elsif (has_property($_, "default")) { + pidl "default:"; + } + indent; ParserElement($_, $t, {}); deindent; + pidl "break;"; + } + deindent; pidl "}"; + + if ($t eq "print") { + pidl "tdr->level--;"; + } + + pidl "return NT_STATUS_OK;\n"; + deindent; pidl "}"; +} + +sub ParserBitmap($$$$) +{ + my ($e,$n,$t,$p) = @_; + return if ($p); + pidl "#define tdr_$t\_$n tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e); +} + +sub ParserEnum($$$$) +{ + my ($e,$n,$t,$p) = @_; + my $bt = Parse::Pidl::Typelist::enum_type_fn($e); + + pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", enum $n *v)"; + pidl "{"; + if ($t eq "pull") { + pidl "\t$bt\_t r;"; + pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, \&r));"; + pidl "\t*v = r;"; + } elsif ($t eq "push") { + pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, ($bt\_t *)v));"; + } elsif ($t eq "print") { + pidl "\t/* FIXME */"; + } + pidl "\treturn NT_STATUS_OK;"; + pidl "}"; +} + +sub ParserTypedef($$) +{ + my ($e,$t) = @_; + + return if (has_property($e, "no$t")); + + { STRUCT => \&ParserStruct, UNION => \&ParserUnion, + ENUM => \&ParserEnum, BITMAP => \&ParserBitmap + }->{$e->{DATA}->{TYPE}}($e->{DATA}, $e->{NAME}, $t, has_property($e, "public")); + + pidl ""; +} + +sub ParserInterface($) +{ + my $x = shift; + + foreach (@{$x->{DATA}}) { + next if ($_->{TYPE} ne "TYPEDEF"); + ParserTypedef($_, "pull"); + ParserTypedef($_, "push"); + ParserTypedef($_, "print"); + } +} + +sub Parser($$) +{ + my ($idl,$hdrname) = @_; + $ret = ""; + pidl "/* autogenerated by pidl */"; + pidl "#include \"includes.h\""; + pidl "#include \"$hdrname\""; + foreach (@$idl) { ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); } + return $ret; +} + +sub HeaderInterface($$) +{ + my ($x,$outputdir) = @_; + + pidl "#ifndef __TDR_$x->{NAME}_HEADER__"; + pidl "#define __TDR_$x->{NAME}_HEADER__"; + + pidl "#include \"$outputdir/$x->{NAME}.h\""; + + foreach my $e (@{$x->{DATA}}) { + next unless ($e->{TYPE} eq "TYPEDEF"); + next unless has_property($e, "public"); + + my $switch = ""; + + $switch = ", int level" if ($e->{DATA}->{TYPE} eq "UNION"); + + if ($e->{DATA}->{TYPE} eq "BITMAP") { + # FIXME + } else { + my ($n, $d) = ($e->{NAME}, lc($e->{DATA}->{TYPE})); + pidl "NTSTATUS tdr_pull\_$n(struct tdr_pull *tdr$switch, $d $n *v);"; + pidl "NTSTATUS tdr_print\_$n(struct tdr_print *tdr, const char *name$switch, $d $n *v);"; + pidl "NTSTATUS tdr_push\_$n(struct tdr_push *tdr$switch, $d $n *v);"; + } + + pidl ""; + } + + pidl "#endif /* __TDR_$x->{NAME}_HEADER__ */"; +} + +sub Header($$) +{ + my ($idl,$outputdir) = @_; + $ret = ""; + pidl "/* Generated by pidl */"; + + foreach (@$idl) { + HeaderInterface($_, $outputdir) if ($_->{TYPE} eq "INTERFACE"); + } + return $ret; +} + +1; diff --git a/source4/build/pidl/pidl b/source4/build/pidl/pidl index 7523f03495..99e5cbc076 100755 --- a/source4/build/pidl/pidl +++ b/source4/build/pidl/pidl @@ -43,6 +43,8 @@ my($opt_template) = 0; my($opt_client); my($opt_server); my($opt_ndr_parser); +my($opt_tdr_header); +my($opt_tdr_parser); my($opt_eth_parser); my($opt_eth_header); my($opt_keep); @@ -74,6 +76,8 @@ Options: --header[=OUTFILE] create generic header file --ndr-header[=OUTFILE]create a C NDR-specific header file --ndr-parser[=OUTFILE]create a C NDR parser + --tdr-header[=OUTFILE]create a C TDR header file + --tdr-parser[=OUTFILE]create a C TDR parser --ejs[=OUTFILE] create ejs wrapper file --client[=OUTFILE] create a C NDR client --server[=OUTFILE] create server boilerplate @@ -103,6 +107,8 @@ GetOptions ( 'ndr-header:s' => \$opt_ndr_header, 'header:s' => \$opt_header, 'server:s' => \$opt_server, + 'tdr-header:s' => \$opt_tdr_header, + 'tdr-parser:s' => \$opt_tdr_parser, 'template' => \$opt_template, 'ndr-parser:s' => \$opt_ndr_parser, 'client:s' => \$opt_client, @@ -295,6 +301,18 @@ $dcom Parse::Pidl::Util::FileSave($eparser, Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser)); } + my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c"); + my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h"); + if (defined($opt_tdr_parser)) { + require Parse::Pidl::Samba::TDR; + Parse::Pidl::Util::FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header)); + } + + if (defined($opt_tdr_header)) { + require Parse::Pidl::Samba::TDR; + Parse::Pidl::Util::FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir)); + } + if ($opt_template) { require Parse::Pidl::Samba::Template; print Parse::Pidl::Samba::Template::Parse($pidl); |