diff options
author | Andrew Tridgell <tridge@samba.org> | 2003-11-06 12:29:23 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2003-11-06 12:29:23 +0000 |
commit | fa3db33a5441ed31f9d8c19dc6984d160b86e4da (patch) | |
tree | 12fd394ae4baad3eeded82953c39959a3521f362 | |
parent | 60f4bb657a5bbec766e170cb0755b1f36a33c8bc (diff) | |
download | samba-fa3db33a5441ed31f9d8c19dc6984d160b86e4da.tar.gz samba-fa3db33a5441ed31f9d8c19dc6984d160b86e4da.tar.bz2 samba-fa3db33a5441ed31f9d8c19dc6984d160b86e4da.zip |
updated pidl to auto-generate the ndr_push_*() functions for the
Samba4 rpc framework
not complete, but sufficient for a number of lsa functions
(This used to be commit 42cd6904f51bac1ff92f0aea0deffb11864dfac2)
-rw-r--r-- | source4/build/pidl/eparser.pm | 33 | ||||
-rw-r--r-- | source4/build/pidl/header.pm | 116 | ||||
-rw-r--r-- | source4/build/pidl/idl.gram | 11 | ||||
-rw-r--r-- | source4/build/pidl/parser.pm | 190 | ||||
-rwxr-xr-x | source4/build/pidl/pidl.pl | 7 | ||||
-rw-r--r-- | source4/build/pidl/util.pm | 60 |
6 files changed, 340 insertions, 77 deletions
diff --git a/source4/build/pidl/eparser.pm b/source4/build/pidl/eparser.pm index 3cb71a6c7e..bc69d831c8 100644 --- a/source4/build/pidl/eparser.pm +++ b/source4/build/pidl/eparser.pm @@ -1,5 +1,5 @@ ################################################### -# Ethereal parser generator for IDL structures +# parser generator for IDL structures # Copyright tpot@samba.org 2001 # Copyright tridge@samba.org 2000 # released under the GNU GPL @@ -10,21 +10,6 @@ use Data::Dumper; my($res); -sub is_scalar_type($) -{ - my($type) = shift; - - return 1, if ($type eq "uint32"); - return 1, if ($type eq "long"); - return 1, if ($type eq "short"); - return 1, if ($type eq "char"); - return 1, if ($type eq "uint16"); - return 1, if ($type eq "hyper"); - return 1, if ($type eq "wchar_t"); - - return 0; -} - sub has_property($$) { my($props) = shift; @@ -67,7 +52,7 @@ sub ParseArray($) my($elt) = shift; $res .= "\tfor (i = 0; i < count; i++) {\n"; - if (is_scalar_type($elt)) { + if (util::is_scalar_type($elt)) { $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, NULL, \"$elt->{NAME});\n"; $res .= "\t}\n\n"; } else { @@ -89,7 +74,7 @@ sub ParseElement($$) # Arg is a policy handle - if (has_property($elt->{PROPERTIES}, "context_handle")) { + if (util::has_property($elt->{PROPERTIES}, "context_handle")) { $res .= "\toffset = prs_policy_hnd(tvb, offset, pinfo, tree);\n"; return; } @@ -106,7 +91,7 @@ sub ParseElement($$) # Simple type are scalars too - if (is_scalar_type($elt->{TYPE})) { + if (util::is_scalar_type($elt->{TYPE})) { $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, NULL, \"$elt->{NAME}\");\n\n"; } } @@ -117,7 +102,7 @@ sub ParseElement($$) # Scalars are not buffers, except if they are pointed to - if (!is_scalar_type($elt->{TYPE}) || $elt->{POINTERS}) { + if (!util::is_scalar_type($elt->{TYPE}) || $elt->{POINTERS}) { # If we have a pointer, check it @@ -125,11 +110,11 @@ sub ParseElement($$) $res .= "\t\tif (ptr_$elt->{NAME})\n\t"; } - if (has_property($elt->{PROPERTIES}, "size_is")) { + if (util::has_property($elt->{PROPERTIES}, "size_is")) { ParseArray($elt); } else { $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, "; - if (is_scalar_type($elt->{TYPE})) { + if (util::is_scalar_type($elt->{TYPE})) { $res .= "NULL, "; } else { $res .= "flags, "; @@ -236,12 +221,12 @@ sub ParseFunctionArg($$) my($arg) = shift; my($io) = shift; # "in" or "out" - if (has_property($arg->{PROPERTIES}, $io)) { + if (util::has_property($arg->{PROPERTIES}, $io)) { # For some reason, pointers to elements in function definitions # aren't parsed. - if (defined($arg->{POINTERS}) && !is_scalar_type($arg->{TYPE})) { + if (defined($arg->{POINTERS}) && !util::is_scalar_type($arg->{TYPE})) { $arg->{POINTERS} -= 1, if ($arg->{POINTERS} > 0); delete($arg->{POINTERS}), if ($arg->{POINTERS} == 0); } diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm index 34707f8672..783fff2204 100644 --- a/source4/build/pidl/header.pm +++ b/source4/build/pidl/header.pm @@ -7,12 +7,23 @@ package IdlHeader; use Data::Dumper; my($res); +my($tab_depth); + +sub tabs() +{ + for (my($i)=0; $i < $tab_depth; $i++) { + $res .= "\t"; + } +} ##################################################################### # dump a properties list sub DumpProperties($) { my($props) = shift; + + return; + foreach my $d (@{$props}) { if (ref($d) ne "HASH") { $res .= "/* [$d] */ "; @@ -29,30 +40,48 @@ sub DumpProperties($) sub DumpElement($) { my($element) = shift; + + if (util::has_property($element->{PROPERTIES}, "struct_len")) { + # a struct_len is an internal artifact - it is put on the + # wire but not exposed via the api, which means it does + # not appear in the header file + return; + } + + (defined $element->{PROPERTIES}) && DumpProperties($element->{PROPERTIES}); - DumpType($element->{TYPE}); + $res .= tabs(); + DumpType($element->{TYPE}, ""); $res .= " "; if ($element->{POINTERS}) { - for (my($i)=0; $i < $element->{POINTERS}; $i++) { - $res .= "*"; - } + my($n) = $element->{POINTERS}; + if (util::is_scalar_type($element->{TYPE}) && + util::has_property($element->{PROPERTIES}, "ref")) { + $n--; + } + for (my($i)=$n; $i > 0; $i--) { + $res .= "*"; + } } $res .= "$element->{NAME}"; (defined $element->{ARRAY_LEN}) && ($res .= "[$element->{ARRAY_LEN}]"); + $res .= ";\n"; } ##################################################################### # dump a struct -sub DumpStruct($) +sub DumpStruct($$) { my($struct) = shift; - $res .= "struct {\n"; + my($name) = shift; + $res .= "struct $name {\n"; + $tab_depth++; if (defined $struct->{ELEMENTS}) { foreach my $e (@{$struct->{ELEMENTS}}) { DumpElement($e); - $res .= ";\n"; } } + $tab_depth--; $res .= "}"; } @@ -64,16 +93,16 @@ sub DumpUnionElement($) my($element) = shift; $res .= "/* [case($element->{CASE})] */ "; DumpElement($element->{DATA}); - $res .= ";\n"; } ##################################################################### # dump a union -sub DumpUnion($) +sub DumpUnion($$) { my($union) = shift; + my($name) = shift; (defined $union->{PROPERTIES}) && DumpProperties($union->{PROPERTIES}); - $res .= "union {\n"; + $res .= "union $name {\n"; foreach my $e (@{$union->{DATA}}) { DumpUnionElement($e); } @@ -82,16 +111,23 @@ sub DumpUnion($) ##################################################################### # dump a type -sub DumpType($) +sub DumpType($$) { my($data) = shift; + my($name) = shift; if (ref($data) eq "HASH") { ($data->{TYPE} eq "STRUCT") && - DumpStruct($data); + DumpStruct($data, $name); ($data->{TYPE} eq "UNION") && - DumpUnion($data); + DumpUnion($data, $name); + return; + } + if ($data =~ "unistr") { + $res .= "const char"; + } elsif (util::is_scalar_type($data)) { + $res .= "$data"; } else { - $res .= "$data"; + $res .= "struct $data"; } } @@ -100,9 +136,51 @@ sub DumpType($) sub DumpTypedef($) { my($typedef) = shift; - $res .= "typedef "; - DumpType($typedef->{DATA}); - $res .= " $typedef->{NAME};\n\n"; + DumpType($typedef->{DATA}, $typedef->{NAME}); + $res .= ";\n\n"; +} + +##################################################################### +# dump a function +sub DumpFunctionInOut($$) +{ + my($fn) = shift; + my($prop) = shift; + foreach my $e (@{$fn->{DATA}}) { + if (util::has_property($e->{PROPERTIES}, $prop)) { + DumpElement($e); + } + } +} + + +##################################################################### +# dump a function +sub DumpFunction($) +{ + my($fn) = shift; + $res .= "struct $fn->{NAME} {\n"; + $tab_depth++; + tabs(); + $res .= "struct {\n"; + $tab_depth++; + DumpFunctionInOut($fn, "in"); + $tab_depth--; + tabs(); + $res .= "} in;\n\n"; + tabs(); + $res .= "struct {\n"; + $tab_depth++; + DumpFunctionInOut($fn, "out"); + if ($fn->{RETURN_TYPE}) { + tabs(); + $res .= "$fn->{RETURN_TYPE} result;\n"; + } + $tab_depth--; + tabs(); + $res .= "} out;\n\n"; + $tab_depth--; + $res .= "};\n\n"; } ##################################################################### @@ -114,6 +192,8 @@ sub DumpInterface($) foreach my $d (@{$data}) { ($d->{TYPE} eq "TYPEDEF") && DumpTypedef($d); + ($d->{TYPE} eq "FUNCTION") && + DumpFunction($d); } } @@ -123,6 +203,8 @@ sub DumpInterface($) sub Dump($) { my($idl) = shift; + $tab_depth = 0; + $res = "/* header auto-generated by pidl */\n\n"; foreach my $x (@{$idl}) { ($x->{TYPE} eq "INTERFACE") && diff --git a/source4/build/pidl/idl.gram b/source4/build/pidl/idl.gram index 00b3952ba2..b700cb378e 100644 --- a/source4/build/pidl/idl.gram +++ b/source4/build/pidl/idl.gram @@ -33,14 +33,14 @@ typedef : 'typedef' <commit> type identifier array_len(?) ';' "TYPE" => "TYPEDEF", "NAME" => $item{identifier}, "DATA" => $item{type}, - "ARRAY_LEN" => $item{array_len}[0] + "ARRAY_LEN" => $item[5][0] }} | <error?> struct: 'struct' <commit> '{' element_list1(?) '}' {{ "TYPE" => "STRUCT", - "ELEMENTS" => util::FlattenArray($item{element_list1}) + "ELEMENTS" => util::FlattenArray2($item[4]) }} | <error?> @@ -48,7 +48,7 @@ union: property_list(s?) 'union' <commit> '{' union_element(s?) '}' {{ "TYPE" => "UNION", "PROPERTIES" => util::FlattenArray($item[1]), - "DATA" => $item{union_element} + "DATA" => $item[5] }} | <error?> @@ -70,8 +70,8 @@ base_element: property_list(s?) type pointer(s?) identifier array_len(?) "NAME" => $item{identifier}, "TYPE" => $item{type}, "PROPERTIES" => util::FlattenArray($item[1]), - "POINTERS" => $#{$item{pointer}}==-1?undef:$#{$item{pointer}}+1, - "ARRAY_LEN" => $item{array_len}[0] + "POINTERS" => $#{$item[3]}==-1?undef:$#{$item[3]}+1, + "ARRAY_LEN" => $item[5][0] }} | <error> @@ -97,6 +97,7 @@ property: 'unique' | 'in' | 'out' | 'ref' + | 'struct_len' | 'context_handle' | 'string' | 'byte_count_pointer' '(' expression ')' {{ "$item[1]" => "$item{expression}" }} diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm index 03bc5f3aff..695d943ee2 100644 --- a/source4/build/pidl/parser.pm +++ b/source4/build/pidl/parser.pm @@ -1,5 +1,6 @@ ################################################### -# C parser generator for IDL structures +# Ethereal parser generator for IDL structures +# Copyright tpot@samba.org 2001 # Copyright tridge@samba.org 2000 # released under the GNU GPL @@ -26,35 +27,120 @@ sub ParseProperties($) } ##################################################################### -# parse a structure element -sub ParseElement($) +# parse an array - called in buffers context +sub ParseArray($) { - my($element) = shift; - (defined $element->{PROPERTIES}) && ParseProperties($element->{PROPERTIES}); - ParseType($element->{TYPE}); - $res .= " "; - if ($element->{POINTERS}) { - for (my($i)=0; $i < $element->{POINTERS}; $i++) { - $res .= "*"; - } + my($elt) = shift; + + $res .= "\tfor (i = 0; i < count; i++) {\n"; + if (util::is_scalar_type($elt)) { + $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, NULL, \"$elt->{NAME});\n"; + $res .= "\t}\n\n"; + } else { + $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, \"PARSE_SCALARS\", \"$elt->{NAME}\");\n"; + $res .= "\t}\n\n"; + + $res .= "\tfor (i = 0; i < count; i++) {\n"; + $res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, \"PARSE_BUFFERS\", \"$elt->{NAME}\");\n"; + $res .= "\t}\n\n"; } - $res .= "$element->{NAME}"; - (defined $element->{ARRAY_LEN}) && ($res .= "[$element->{ARRAY_LEN}]"); +} + + +##################################################################### +# parse scalars in a structure element +sub ParseElementScalars($$) +{ + my($elt) = shift; + my($var_prefix) = shift; + + if (defined $elt->{VALUE}) { + $res .= "\tNDR_CHECK(ndr_push_$elt->{TYPE}(ndr, $elt->{VALUE}));\n"; + } elsif ($elt->{POINTERS} && + !util::has_property($elt->{PROPERTIES}, "ref")) { + $res .= "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$elt->{NAME}));\n"; + } else { + $res .= "\tNDR_CHECK(ndr_push_$elt->{TYPE}(ndr, $var_prefix$elt->{NAME}));\n"; + } +} + +##################################################################### +# parse buffers in a structure element +sub ParseElementBuffers($$) +{ + my($elt) = shift; + my($var_prefix) = shift; + + if (util::has_property($elt->{PROPERTIES}, "ref")) { + return; + } + + if (util::is_scalar_type($elt->{TYPE}) && !$elt->{POINTERS}) { + return; + } + + if ($elt->{POINTERS}) { + $res .= "\tif ($var_prefix$elt->{NAME}) {\n\t"; + } + + if (util::has_property($elt->{PROPERTIES}, "size_is")) { + ParseArray($elt); + } else { + if (util::is_scalar_type($elt->{TYPE})) { + $res .= "\tNDR_CHECK(ndr_push_$elt->{TYPE}(ndr, *$var_prefix$elt->{NAME}));\n"; + } else { + $res .= "\tNDR_CHECK(ndr_push_$elt->{TYPE}(ndr, $var_prefix$elt->{NAME}));\n"; + } + } + + if ($elt->{POINTERS}) { + $res .= "\t}\n"; + } } ##################################################################### # parse a struct sub ParseStruct($) { - my($struct) = shift; - $res .= "struct {\n"; - if (defined $struct->{ELEMENTS}) { + my($struct) = shift; + my($struct_len); + + if (! defined $struct->{ELEMENTS}) { + return; + } + + # see if we have a structure length foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElement($e); - $res .= ";\n"; + if (util::has_property($e->{PROPERTIES}, "struct_len")) { + $struct_len = $e; + $e->{VALUE} = "0"; + } + } + + if (defined $struct_len) { + $res .= "\tstruct ndr_push_save len_save1, len_save2, len_save3;\n"; + $res .= "\tndr_push_save(ndr, &len_save1);\n"; + } + + foreach my $e (@{$struct->{ELEMENTS}}) { + if ($e == $struct_len) { + $res .= "\tNDR_CHECK(ndr_push_align_$e->{TYPE}(ndr));\n"; + $res .= "\tndr_push_save(ndr, &len_save2);\n"; + } + ParseElementScalars($e, "r->"); + } + + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElementBuffers($e, "r->"); + } + + if (defined $struct_len) { + $res .= "\tndr_push_save(ndr, &len_save3);\n"; + $res .= "\tndr_push_restore(ndr, &len_save2);\n"; + $struct_len->{VALUE} = "len_save3.offset - len_save1.offset"; + ParseElementScalars($struct_len, "r->"); + $res .= "\tndr_push_restore(ndr, &len_save3);\n"; } - } - $res .= "}"; } @@ -63,9 +149,10 @@ sub ParseStruct($) sub ParseUnionElement($) { my($element) = shift; - $res .= "[case($element->{CASE})] "; - ParseElement($element->{DATA}); - $res .= ";\n"; + + $res .= "\tcase $element->{DATA}->{NAME}: \n"; + $res .= "\t\toffset = prs_$element->{DATA}->{TYPE}(tvb, offset, pinfo, tree, \"$element->{DATA}->{NAME}\");\n\t\tbreak;\n"; + } ##################################################################### @@ -73,12 +160,15 @@ sub ParseUnionElement($) sub ParseUnion($) { my($union) = shift; + + $res .= "\tswitch (level) {\n"; + (defined $union->{PROPERTIES}) && ParseProperties($union->{PROPERTIES}); - $res .= "union {\n"; foreach my $e (@{$union->{DATA}}) { ParseUnionElement($e); } - $res .= "}"; + + $res .= "\t}\n"; } ##################################################################### @@ -86,6 +176,7 @@ sub ParseUnion($) sub ParseType($) { my($data) = shift; + if (ref($data) eq "HASH") { ($data->{TYPE} eq "STRUCT") && ParseStruct($data); @@ -101,17 +192,58 @@ sub ParseType($) sub ParseTypedef($) { my($typedef) = shift; - $res .= "typedef "; + + $res .= "static NTSTATUS ndr_push_$typedef->{NAME}(struct ndr_push *ndr, struct $typedef->{NAME} *r)"; + $res .= "\n{\n"; ParseType($typedef->{DATA}); - $res .= " $typedef->{NAME};\n\n"; + $res .= "\treturn NT_STATUS_OK;\n"; + $res .= "}\n\n"; } ##################################################################### # parse a function -sub ParseFunction($) +sub ParseFunctionArg($$) +{ + my($arg) = shift; + my($io) = shift; # "in" or "out" + + if (!util::has_property($arg->{PROPERTIES}, $io)) { + return; + } + + ParseElementScalars($arg, "r->in."); + ParseElementBuffers($arg, "r->in."); +} + +##################################################################### +# parse a function +sub ParseFunctionPush($) { my($function) = shift; - $res .= "/* ignoring function $function->{NAME} */\n"; + + # Input function + $res .= "NTSTATUS ndr_push_$function->{NAME}(struct ndr_push *ndr, struct $function->{NAME} *r)\n{\n"; + + foreach my $arg (@{$function->{DATA}}) { + ParseFunctionArg($arg, "in"); + } + + $res .= "\n\treturn NT_STATUS_OK;\n}\n\n"; +} + +##################################################################### +# parse a function +sub ParseFunctionPull($) +{ +} + +##################################################################### +# parse a function +sub ParseFunction($) +{ + my $i = shift; + ParseFunctionPush($i); + ParseFunctionPull($i); } ##################################################################### diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index 6b32ade75a..a332671e34 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -7,6 +7,10 @@ # released under the GNU GPL use strict; + +my($PIDLBASE) = "$ENV{HOME}/pidl"; +use lib "$ENV{HOME}/pidl"; + use Getopt::Long; use Data::Dumper; use Parse::RecDescent; @@ -35,9 +39,10 @@ sub IdlParse($) $item[1] : "XX_" . $item[0] . "_XX[$#item]" }; my($filename) = shift; - my($grammer) = util::FileLoad("idl.gram"); + my($grammer) = util::FileLoad("$PIDLBASE/idl.gram"); my($parser) = Parse::RecDescent->new($grammer); my($saved_sep) = $/; + undef $/; my($idl) = $parser->idl(`cpp $filename`); $/ = $saved_sep; diff --git a/source4/build/pidl/util.pm b/source4/build/pidl/util.pm index f0e3c2a2f8..53e391eb42 100644 --- a/source4/build/pidl/util.pm +++ b/source4/build/pidl/util.pm @@ -6,6 +6,25 @@ package util; use Data::Dumper; +sub dumpit($) +{ + my $a = shift; + return Dumper $a; +} + +##################################################################### +# flatten an array of arrays into a single array +sub FlattenArray2($) +{ + my $a = shift; + my @b; + for my $d (@{$a}) { + for my $d1 (@{$d}) { + push(@b, $d1); + } + } + return \@b; +} ##################################################################### # flatten an array of arrays into a single array @@ -75,7 +94,7 @@ sub FileLoad($) { my($filename) = shift; local(*INPUTFILE); - open(INPUTFILE, $filename) || die "can't open $filename"; + open(INPUTFILE, $filename) || die "can't load $filename"; my($saved_delim) = $/; undef $/; my($data) = <INPUTFILE>; @@ -124,5 +143,44 @@ sub LoadStructure($) return eval FileLoad(shift); } +##################################################################### +# see if a pidl property list contains a give property +sub has_property($$) +{ + my($props) = shift; + my($p) = shift; + + foreach my $d (@{$props}) { + if (ref($d) ne "HASH") { + return 1, if ($d eq $p); + return 1, if ($d eq "in,out" && ($p eq "in" || $p eq "out")); + } else { + foreach my $k (keys %{$d}) { + return $d->{$k}, if ($k eq $p); + } + } + } + + return 0; +} + + +sub is_scalar_type($) +{ + my($type) = shift; + + return 1, if ($type eq "uint32"); + return 1, if ($type eq "long"); + return 1, if ($type eq "short"); + return 1, if ($type eq "char"); + return 1, if ($type eq "uint8"); + return 1, if ($type eq "uint16"); + return 1, if ($type eq "hyper"); + return 1, if ($type eq "wchar_t"); + + return 0; +} + 1; + |