summaryrefslogtreecommitdiff
path: root/tools/pidl/lib/Parse/Pidl/Samba3/Types.pm
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pidl/lib/Parse/Pidl/Samba3/Types.pm')
-rw-r--r--tools/pidl/lib/Parse/Pidl/Samba3/Types.pm395
1 files changed, 395 insertions, 0 deletions
diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/Types.pm b/tools/pidl/lib/Parse/Pidl/Samba3/Types.pm
new file mode 100644
index 0000000000..8cb09343ac
--- /dev/null
+++ b/tools/pidl/lib/Parse/Pidl/Samba3/Types.pm
@@ -0,0 +1,395 @@
+###################################################
+# Samba3 type-specific declarations / initialization / marshalling
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package Parse::Pidl::Samba3::Types;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(DeclShort DeclLong InitType DissectType AddType);
+
+use strict;
+use Parse::Pidl::Util qw(has_property ParseExpr property_matches);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+# TODO: Find external types somehow?
+
+sub warning($$) { my ($e,$s) = @_; print STDERR "$e->{FILE}:$e->{LINE}: $s\n"; }
+
+sub init_scalar($$$$)
+{
+ my ($e,$l,$n,$v) = @_;
+
+ return "$n = $v;";
+}
+
+sub dissect_scalar($$$$$)
+{
+ my ($e,$l,$n,$w,$a) = @_;
+
+ my $t = lc($e->{TYPE});
+
+ return "prs_$t(\"$e->{NAME}\", ps, depth, &$n)";
+}
+
+sub decl_string($)
+{
+ my $e = shift;
+
+ my $is_conformant = property_matches($e, "flag", ".*STR_SIZE4.*");
+ my $is_varying = property_matches($e, "flag", ".*STR_LEN4.*");
+ my $is_ascii = property_matches($e, "flag", ".*STR_ASCII.*");
+
+ return "STRING2" if ($is_conformant and $is_varying and $is_ascii);
+
+ return "UNISTR2" if ($is_conformant and $is_varying);
+ return "UNISTR3" if ($is_varying);
+ # We don't do UNISTR4, as we have lsa_String for that in Samba4's IDL
+
+ die("Don't know what string type to use");
+}
+
+sub contains_pointer($)
+{
+ my $e = shift;
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ return 1 if ($l->{TYPE} eq "POINTER");
+ }
+
+ return 0;
+}
+
+sub ext_decl_string($)
+{
+ my $e = shift;
+
+ # One pointer is sufficient..
+ return "const char" if (contains_pointer($e));
+ return "const char *";
+}
+
+sub init_string($$$$)
+{
+ my ($e,$l,$n,$v) = @_;
+
+ my $t = lc(decl_string($e));
+
+ my $flags;
+ if (property_matches($e, "flag", ".*STR_NULLTERM.*")) {
+ $flags = "UNI_STR_TERMINATE";
+ } elsif (property_matches($e, "flag", ".*STR_NOTERM.*")) {
+ $flags = "UNI_STR_NOTERM";
+ } else {
+ $flags = "UNI_FLAGS_NONE";
+ }
+
+ # One pointer is sufficient
+ if (substr($v, 0, 1) eq "*") { $v = substr($v, 1); }
+
+ return "init_$t(&$n, $v, $flags);";
+}
+
+sub dissect_string($$$$$)
+{
+ my ($e,$l,$n,$w,$a) = @_;
+
+ my $t = lc(decl_string($e));
+
+ $$a = 1;
+ return "smb_io_$t(\"$e->{NAME}\", &$n, 1, ps, depth)";
+}
+
+my $known_types =
+{
+ uint8 =>
+ {
+ DECL => "uint8",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ uint16 =>
+ {
+ DECL => "uint16",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ uint32 =>
+ {
+ DECL => "uint32",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ uint64 =>
+ {
+ DECL => "uint64",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ string =>
+ {
+ DECL => \&decl_string,
+ EXT_DECL => \&ext_decl_string,
+ INIT => \&init_string,
+ DISSECT_P => \&dissect_string,
+ },
+ NTSTATUS =>
+ {
+ DECL => "NTSTATUS",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ WERROR =>
+ {
+ DECL => "WERROR",
+ INIT => \&init_scalar,
+ DISSECT_P => \&dissect_scalar,
+ },
+ GUID =>
+ {
+ DECL => "struct uuid",
+ INIT => "",
+ DISSECT_P => sub {
+ my ($e,$l,$n) = @_;
+ return "smb_io_uuid(\"$e->{NAME}\", &$n, ps, depth)";
+ }
+ },
+ NTTIME =>
+ {
+ DECL => "NTTIME",
+ INIT => "",
+ DISSECT_P => sub {
+ my ($e,$l,$n,$w,$a) = @_;
+ return "smb_io_nttime(\"$e->{NAME}\", &n, ps, depth)";
+ }
+ },
+ dom_sid =>
+ {
+ DECL => "DOM_SID",
+ INIT => "",
+ DISSECT_P => sub {
+ my ($e,$l,$n,$w,$a) = @_;
+ return "smb_io_dom_sid(\"$e->{NAME}\", &n, ps, depth)";
+ }
+ },
+ policy_handle =>
+ {
+ DECL => "POLICY_HND",
+ INIT => "",
+ DISSECT_P => sub {
+ my ($e,$l,$n,$w,$a) = @_;
+ return "smb_io_pol_hnd(\"$e->{NAME}\", &n, ps, depth)";
+ }
+ },
+ hyper =>
+ {
+ DECL => "uint64",
+ INIT => "",
+ DISSECT_P => sub {
+ my ($e,$l,$n,$w,$a) = @_;
+ return "prs_uint64(\"$e->{NAME}\", ps, depth, &$n)";
+ }
+ },
+};
+
+sub AddType($$)
+{
+ my ($t,$d) = @_;
+
+ warn("Reregistering type $t") if (defined($known_types->{$t}));
+
+ $known_types->{$t} = $d;
+}
+
+sub GetType($)
+{
+ my $e = shift;
+
+}
+
+# Return type without special stuff, as used in
+# declarations for internal structs
+sub DeclShort($)
+{
+ my $e = shift;
+
+ my $t = $known_types->{$e->{TYPE}};
+
+ if (not $t) {
+ warning($e, "Can't declare unknown type $e->{TYPE}");
+ return undef;
+ }
+
+ my $p;
+
+ # DECL can be a function
+ if (ref($t->{DECL}) eq "CODE") {
+ $p = $t->{DECL}->($e);
+ } else {
+ $p = $t->{DECL};
+ }
+
+ my $prefixes = "";
+ my $suffixes = "";
+ foreach my $l (@{$e->{LEVELS}}) {
+ if ($l->{TYPE} eq "ARRAY" and not $l->{IS_FIXED}) {
+ $prefixes = "*$prefixes";
+ } elsif ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED}) {
+ $suffixes.="[$l->{SIZE_IS}]";
+ }
+ }
+
+ return "$p $prefixes$e->{NAME}$suffixes";
+}
+
+# Return type including special stuff (pointers, etc).
+sub DeclLong($)
+{
+ my $e = shift;
+
+ my $t = $known_types->{$e->{TYPE}};
+
+ if (not $t) {
+ warning($e, "Can't declare unknown type $e->{TYPE}");
+ return undef;
+ }
+
+ my $p;
+
+ if (defined($t->{EXT_DECL})) {
+ $p = $t->{EXT_DECL}
+ } else {
+ $p = $t->{DECL};
+ }
+
+ if (ref($p) eq "CODE") {
+ $p = $p->($e);
+ }
+
+ my $prefixes = "";
+ my $suffixes = "";
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ if ($l->{TYPE} eq "ARRAY" and not $l->{IS_FIXED}) {
+ $prefixes = "*$prefixes";
+ } elsif ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED}) {
+ $suffixes.="[$l->{SIZE_IS}]";
+ } elsif ($l->{TYPE} eq "POINTER") {
+ $prefixes = "*$prefixes";
+ }
+ }
+
+ return "$p $prefixes$e->{NAME}$suffixes";
+}
+
+sub InitType($$$$)
+{
+ my ($e, $l, $varname, $value) = @_;
+
+ my $t = $known_types->{$l->{DATA_TYPE}};
+
+ if (not $t) {
+ warning($e, "Don't know how to initialize type $l->{DATA_TYPE}");
+ return undef;
+ }
+
+ # INIT can be a function
+ if (ref($t->{INIT}) eq "CODE") {
+ return $t->{INIT}->($e, $l, $varname, $value);
+ } else {
+ return $t->{INIT};
+ }
+}
+
+sub DissectType
+{
+ my @args = @_;
+ my $e = shift @_;
+ my $l = shift @_;
+ my $varname = shift @_;
+ my $what = shift @_;
+ my $align = shift @_;
+
+ my $t = $known_types->{$l->{DATA_TYPE}};
+
+ if (not $t) {
+ warning($e, "Don't know how to dissect type $l->{DATA_TYPE}");
+ return undef;
+ }
+
+ my $dissect;
+ if ($what == 1) { #primitives
+ $dissect = $t->{DISSECT_P};
+ } elsif ($what == 2) {
+ $dissect = $t->{DISSECT_D};
+ }
+
+ return "" if not defined($dissect);
+
+ # DISSECT can be a function
+ if (ref($dissect) eq "CODE") {
+ return $dissect->(@args);
+ } else {
+ return $dissect;
+ }
+}
+
+sub LoadTypes($)
+{
+ my $ndr = shift;
+ foreach my $if (@{$ndr}) {
+ next unless ($if->{TYPE} eq "INTERFACE");
+
+ foreach my $td (@{$if->{TYPEDEFS}}) {
+ my $decl = uc("$if->{NAME}_$td->{NAME}");
+
+ my $init = sub {
+ my ($e,$l,$n,$v) = @_;
+ return "$n = $v;";
+ };
+
+ my $dissect_d;
+ my $dissect_p;
+ if ($td->{DATA}->{TYPE} eq "UNION") {
+ $decl.="_CTR";
+ $dissect_p = sub {
+ my ($e,$l,$n,$w,$a,$s) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, $s, ps, depth)";
+ };
+
+ $dissect_d = sub {
+ my ($e,$l,$n,$w,$a,$s) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, $s, ps, depth)";
+ };
+
+ } else {
+ $dissect_p = sub {
+ my ($e,$l,$n,$w,$a) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, ps, depth)";
+ };
+ $dissect_d = sub {
+ my ($e,$l,$n,$w,$a) = @_;
+
+ return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, ps, depth)";
+ };
+
+ }
+
+ AddType($td->{NAME}, {
+ DECL => $decl,
+ INIT => $init,
+ DISSECT_D => $dissect_d,
+ DISSECT_P => $dissect_p
+ });
+ }
+ }
+}
+
+1;