summaryrefslogtreecommitdiff
path: root/source4/pidl
diff options
context:
space:
mode:
Diffstat (limited to 'source4/pidl')
-rw-r--r--source4/pidl/TODO7
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/Header.pm31
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm46
-rw-r--r--source4/pidl/lib/Parse/Pidl/Util.pm75
-rw-r--r--source4/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm48
-rw-r--r--source4/pidl/lib/Parse/Pidl/Wireshark/NDR.pm6
-rwxr-xr-xsource4/pidl/tests/header.pl36
-rwxr-xr-xsource4/pidl/tests/samba-ndr.pl23
-rwxr-xr-xsource4/pidl/tests/wireshark-conf.pl62
9 files changed, 276 insertions, 58 deletions
diff --git a/source4/pidl/TODO b/source4/pidl/TODO
index 7cf6a4209a..4e344e3c37 100644
--- a/source4/pidl/TODO
+++ b/source4/pidl/TODO
@@ -21,3 +21,10 @@
- mem_ctx in the interface rather than as struct ndr member.
- real typelibs
+
+- fix [in,out] handling and allocation for samba3:
+ - add inout
+ - make NULL to mean "allocate me"
+ - remove NDR_AUTO_REF_ALLOC flag
+
+- automatic test generator based on IDL pointer types
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm b/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm
index 96f695d1cd..2b5b9c9e01 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm
@@ -9,7 +9,6 @@ package Parse::Pidl::Samba4::Header;
use strict;
use Parse::Pidl::Typelist qw(mapType);
use Parse::Pidl::Util qw(has_property is_constant);
-use Parse::Pidl::NDR qw(GetNextLevel GetPrevLevel);
use Parse::Pidl::Samba4 qw(is_intree);
use vars qw($VERSION);
@@ -236,15 +235,25 @@ sub HeaderConst($)
}
}
+sub ElementDirection($)
+{
+ my ($e) = @_;
+
+ return "inout" if (has_property($e, "in") and has_property($e, "out"));
+ return "in" if (has_property($e, "in"));
+ return "out" if (has_property($e, "out"));
+ return "inout";
+}
+
#####################################################################
# parse a function
sub HeaderFunctionInOut($$)
{
my($fn,$prop) = @_;
- foreach (@{$fn->{ELEMENTS}}) {
- HeaderElement($_) if (has_property($_, $prop));
- }
+ foreach (@{$fn->{ELEMENTS}}) {
+ HeaderElement($_) if (ElementDirection($_) eq $prop);
+ }
}
#####################################################################
@@ -255,8 +264,8 @@ sub HeaderFunctionInOut_needed($$)
return 1 if ($prop eq "out" && $fn->{RETURN_TYPE} ne "void");
- foreach (@{$fn->{ELEMENTS}}) {
- return 1 if (has_property($_, $prop));
+ foreach (@{$fn->{ELEMENTS}}) {
+ return 1 if (ElementDirection($_) eq $prop);
}
return undef;
@@ -278,19 +287,23 @@ sub HeaderFunction($)
$tab_depth++;
my $needed = 0;
- if (HeaderFunctionInOut_needed($fn, "in")) {
+ if (HeaderFunctionInOut_needed($fn, "in") or
+ HeaderFunctionInOut_needed($fn, "inout")) {
pidl tabs()."struct {\n";
$tab_depth++;
HeaderFunctionInOut($fn, "in");
+ HeaderFunctionInOut($fn, "inout");
$tab_depth--;
pidl tabs()."} in;\n\n";
$needed++;
}
- if (HeaderFunctionInOut_needed($fn, "out")) {
+ if (HeaderFunctionInOut_needed($fn, "out") or
+ HeaderFunctionInOut_needed($fn, "inout")) {
pidl tabs()."struct {\n";
$tab_depth++;
HeaderFunctionInOut($fn, "out");
+ HeaderFunctionInOut($fn, "inout");
if ($fn->{RETURN_TYPE} ne "void") {
pidl tabs().mapType($fn->{RETURN_TYPE}) . " result;\n";
}
@@ -299,7 +312,7 @@ sub HeaderFunction($)
$needed++;
}
- if (! $needed) {
+ if (!$needed) {
# sigh - some compilers don't like empty structures
pidl tabs()."int _dummy_element;\n";
}
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
index 1e199ba62b..3b1bc726ff 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
@@ -10,7 +10,7 @@ package Parse::Pidl::Samba4::NDR::Parser;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(is_charset_array);
-@EXPORT_OK = qw(check_null_pointer);
+@EXPORT_OK = qw(check_null_pointer GenerateFunctionInEnv GenerateFunctionOutEnv);
use strict;
use Parse::Pidl::Typelist qw(hasType getType mapType);
@@ -451,7 +451,9 @@ sub ParseArrayPullHeader($$$$$)
if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) {
defer "if ($var_name) {";
defer_indent;
- my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, \&defer, "return NT_STATUS_INVALID_PARAMETER_MIX;"), check_fully_dereferenced($e, $env));
+ my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL},
+ check_null_pointer($e, $env, \&defer, "return NT_STATUS_INVALID_PARAMETER_MIX;"),
+ check_fully_dereferenced($e, $env));
defer "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));";
defer_deindent;
defer "}"
@@ -689,12 +691,12 @@ sub ParseElementPushLevel
#####################################################################
# parse scalars in a structure element
-sub ParseElementPush($$$$$$)
+sub ParseElementPush($$$$$)
{
- my ($e,$ndr,$var_prefix,$env,$primitives,$deferred) = @_;
+ my ($e,$ndr,$env,$primitives,$deferred) = @_;
my $subndr = undef;
- my $var_name = $var_prefix.$e->{NAME};
+ my $var_name = $env->{$e->{NAME}};
return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));
@@ -1096,11 +1098,11 @@ sub ParseElementPullLevel
#####################################################################
# parse scalars in a structure element - pull size
-sub ParseElementPull($$$$$$)
+sub ParseElementPull($$$$$)
{
- my($e,$ndr,$var_prefix,$env,$primitives,$deferred) = @_;
+ my($e,$ndr,$env,$primitives,$deferred) = @_;
- my $var_name = $var_prefix.$e->{NAME};
+ my $var_name = $env->{$e->{NAME}};
my $represent_name;
my $transmit_name;
@@ -1247,7 +1249,7 @@ sub ParseStructPush($$)
}
foreach my $e (@{$struct->{ELEMENTS}}) {
- ParseElementPush($e, "ndr", "r->", $env, 1, 0);
+ ParseElementPush($e, "ndr", $env, 1, 0);
}
deindent;
@@ -1261,7 +1263,7 @@ sub ParseStructPush($$)
pidl "NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, r));";
}
foreach my $e (@{$struct->{ELEMENTS}}) {
- ParseElementPush($e, "ndr", "r->", $env, 0, 1);
+ ParseElementPush($e, "ndr", $env, 0, 1);
}
deindent;
@@ -1547,7 +1549,7 @@ sub ParseStructPull($$)
}
foreach my $e (@{$struct->{ELEMENTS}}) {
- ParseElementPull($e, "ndr", "r->", $env, 1, 0);
+ ParseElementPull($e, "ndr", $env, 1, 0);
}
add_deferred();
@@ -1562,7 +1564,7 @@ sub ParseStructPull($$)
pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));";
}
foreach my $e (@{$struct->{ELEMENTS}}) {
- ParseElementPull($e, "ndr", "r->", $env, 0, 1);
+ ParseElementPull($e, "ndr", $env, 0, 1);
}
add_deferred();
@@ -1662,7 +1664,7 @@ sub ParseUnionPush($$)
pidl "NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));";
}
DeclareArrayVariables($el);
- ParseElementPush($el, "ndr", "r->", {}, 1, 0);
+ ParseElementPush($el, "ndr", {$el->{NAME} => "r->$el->{NAME}"}, 1, 0);
deindent;
}
pidl "break;";
@@ -1689,7 +1691,7 @@ sub ParseUnionPush($$)
pidl "$el->{CASE}:";
if ($el->{TYPE} ne "EMPTY") {
indent;
- ParseElementPush($el, "ndr", "r->", {}, 0, 1);
+ ParseElementPush($el, "ndr", {$el->{NAME} => "r->$el->{NAME}"}, 0, 1);
deindent;
}
pidl "break;";
@@ -1810,7 +1812,7 @@ sub ParseUnionPull($$)
# and store it based on the toplevel struct/union
pidl "NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));";
}
- ParseElementPull($el, "ndr", "r->", {}, 1, 0);
+ ParseElementPull($el, "ndr", {$el->{NAME} => "r->$el->{NAME}"}, 1, 0);
deindent;
}
pidl "break; }";
@@ -1837,7 +1839,7 @@ sub ParseUnionPull($$)
pidl "$el->{CASE}:";
if ($el->{TYPE} ne "EMPTY") {
indent;
- ParseElementPull($el, "ndr", "r->", {}, 0, 1);
+ ParseElementPull($el, "ndr", {$el->{NAME} => "r->$el->{NAME}"}, 0, 1);
deindent;
}
pidl "break;";
@@ -1993,7 +1995,7 @@ sub ParseFunctionPrint($)
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/in/,@{$e->{DIRECTION}})) {
- ParseElementPrint($e, "r->in.$e->{NAME}", $env);
+ ParseElementPrint($e, $env->{$e->{NAME}}, $env);
}
}
pidl "ndr->depth--;";
@@ -2008,7 +2010,7 @@ sub ParseFunctionPrint($)
$env = GenerateFunctionOutEnv($fn);
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/out/,@{$e->{DIRECTION}})) {
- ParseElementPrint($e, "r->out.$e->{NAME}", $env);
+ ParseElementPrint($e, $env->{$e->{NAME}}, $env);
}
}
if ($fn->{RETURN_TYPE}) {
@@ -2050,7 +2052,7 @@ sub ParseFunctionPush($)
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/in/,@{$e->{DIRECTION}})) {
- ParseElementPush($e, "ndr", "r->in.", $env, 1, 1);
+ ParseElementPush($e, "ndr", $env, 1, 1);
}
}
@@ -2063,7 +2065,7 @@ sub ParseFunctionPush($)
$env = GenerateFunctionOutEnv($fn);
foreach my $e (@{$fn->{ELEMENTS}}) {
if (grep(/out/,@{$e->{DIRECTION}})) {
- ParseElementPush($e, "ndr", "r->out.", $env, 1, 1);
+ ParseElementPush($e, "ndr", $env, 1, 1);
}
}
@@ -2147,7 +2149,7 @@ sub ParseFunctionPull($)
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless (grep(/in/, @{$e->{DIRECTION}}));
- ParseElementPull($e, "ndr", "r->in.", $env, 1, 1);
+ ParseElementPull($e, "ndr", $env, 1, 1);
}
# allocate the "simple" out ref variables. FIXME: Shouldn't this have it's
@@ -2194,7 +2196,7 @@ sub ParseFunctionPull($)
$env = GenerateFunctionOutEnv($fn);
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless grep(/out/, @{$e->{DIRECTION}});
- ParseElementPull($e, "ndr", "r->out.", $env, 1, 1);
+ ParseElementPull($e, "ndr", $env, 1, 1);
}
if ($fn->{RETURN_TYPE}) {
diff --git a/source4/pidl/lib/Parse/Pidl/Util.pm b/source4/pidl/lib/Parse/Pidl/Util.pm
index 00185fbef7..8716094abd 100644
--- a/source4/pidl/lib/Parse/Pidl/Util.pm
+++ b/source4/pidl/lib/Parse/Pidl/Util.pm
@@ -15,9 +15,31 @@ use strict;
use Parse::Pidl::Expr;
use Parse::Pidl qw(error);
-#####################################################################
-# a dumper wrapper to prevent dependence on the Data::Dumper module
-# unless we actually need it
+=head1 NAME
+
+Parse::Pidl::Util - Generic utility functions for pidl
+
+=head1 SYNOPSIS
+
+use Parse::Pidl::Util;
+
+=head1 DESCRIPTION
+
+Simple module that contains a couple of trivial helper functions
+used throughout the various pidl modules.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=cut
+
+=item B<MyDumper>
+a dumper wrapper to prevent dependence on the Data::Dumper module
+unless we actually need it
+
+=cut
+
sub MyDumper($)
{
require Data::Dumper;
@@ -25,8 +47,10 @@ sub MyDumper($)
return Data::Dumper::Dumper($s);
}
-#####################################################################
-# see if a pidl property list contains a given property
+=item B<has_property>
+see if a pidl property list contains a given property
+
+=cut
sub has_property($$)
{
my($e, $p) = @_;
@@ -36,8 +60,10 @@ sub has_property($$)
return $e->{PROPERTIES}->{$p};
}
-#####################################################################
-# see if a pidl property matches a value
+=item B<property_matches>
+see if a pidl property matches a value
+
+=cut
sub property_matches($$$)
{
my($e,$p,$v) = @_;
@@ -53,16 +79,22 @@ sub property_matches($$$)
return undef;
}
-# return 1 if the string is a C constant
+=item B<is_constant>
+return 1 if the string is a C constant
+
+=cut
sub is_constant($)
{
my $s = shift;
- return 1 if (defined $s && $s =~ /^\d+$/);
- return 1 if (defined $s && $s =~ /^0x[0-9A-Fa-f]+$/);
+ return 1 if ($s =~ /^\d+$/);
+ return 1 if ($s =~ /^0x[0-9A-Fa-f]+$/);
return 0;
}
-# return a "" quoted string, unless already quoted
+=item B<make_str>
+return a "" quoted string, unless already quoted
+
+=cut
sub make_str($)
{
my $str = shift;
@@ -72,6 +104,10 @@ sub make_str($)
return "\"$str\"";
}
+=item B<print_uuid>
+Print C representation of a UUID.
+
+=cut
sub print_uuid($)
{
my ($uuid) = @_;
@@ -87,12 +123,14 @@ sub print_uuid($)
"{".join(',', map {"0x$_"} @node)."}}";
}
+=item B<ParseExpr>
+Interpret an IDL expression, substituting particular variables.
+
+=cut
sub ParseExpr($$$)
{
my($expr, $varlist, $e) = @_;
- die("Undefined value in ParseExpr") if not defined($expr);
-
my $x = new Parse::Pidl::Expr();
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
@@ -104,12 +142,15 @@ sub ParseExpr($$$)
undef, undef);
}
+=item B<ParseExprExt>
+Interpret an IDL expression, substituting particular variables. Can call
+callbacks when pointers are being dereferenced or variables are being used.
+
+=cut
sub ParseExprExt($$$$$)
{
my($expr, $varlist, $e, $deref, $use) = @_;
- die("Undefined value in ParseExpr") if not defined($expr);
-
my $x = new Parse::Pidl::Expr();
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
@@ -121,4 +162,8 @@ sub ParseExprExt($$$$$)
$deref, $use);
}
+=back
+
+=cut
+
1;
diff --git a/source4/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm b/source4/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm
index 4ad60319a6..9798c7c552 100644
--- a/source4/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm
+++ b/source4/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm
@@ -96,7 +96,7 @@ use vars qw($VERSION);
$VERSION = '0.01';
@ISA = qw(Exporter);
-@EXPORT_OK = qw(ReadConformance);
+@EXPORT_OK = qw(ReadConformance ReadConformanceFH);
use strict;
@@ -157,7 +157,7 @@ sub handle_hf_rename($$$$)
my ($pos,$data,$old,$new) = @_;
unless(defined($new)) {
- error($pos, "incomplete HF_RENAME command");
+ warning($pos, "incomplete HF_RENAME command");
return;
}
@@ -253,6 +253,11 @@ sub handle_manual($$$)
{
my ($pos,$data,$fn) = @_;
+ unless(defined($fn)) {
+ warning($pos, "incomplete MANUAL command");
+ return;
+ }
+
$data->{manual}->{$fn} = 1;
}
@@ -271,6 +276,11 @@ sub handle_fielddescription($$$$)
{
my ($pos,$data,$field,$desc) = @_;
+ unless(defined($desc)) {
+ warning($pos, "incomplete FIELD_DESCRIPTION command");
+ return;
+ }
+
$data->{fielddescription}->{$field} = {
DESCRIPTION => $desc,
POS => $pos,
@@ -314,16 +324,26 @@ my %field_handlers = (
sub ReadConformance($$)
{
my ($f,$data) = @_;
+ my $ret;
- $data->{override} = "";
+ open(IN,"<$f") or return undef;
- my $incodeblock = 0;
+ $ret = ReadConformanceFH(*IN, $data, $f);
- open(IN,"<$f") or return undef;
+ close(IN);
+
+ return $ret;
+}
+
+sub ReadConformanceFH($$$)
+{
+ my ($fh,$data,$f) = @_;
+
+ my $incodeblock = 0;
my $ln = 0;
- foreach (<IN>) {
+ foreach (<$fh>) {
$ln++;
next if (/^#.*$/);
next if (/^$/);
@@ -337,7 +357,11 @@ sub ReadConformance($$)
$incodeblock = 0;
next;
} elsif ($incodeblock) {
- $data->{override}.="$_\n";
+ if (exists $data->{override}) {
+ $data->{override}.="$_\n";
+ } else {
+ $data->{override} = "$_\n";
+ }
next;
}
@@ -349,6 +373,8 @@ sub ReadConformance($$)
my $pos = { FILE => $f, LINE => $ln };
+ next unless(defined($cmd));
+
if (not defined($field_handlers{$cmd})) {
warning($pos, "Unknown command `$cmd'");
next;
@@ -357,7 +383,13 @@ sub ReadConformance($$)
$field_handlers{$cmd}($pos, $data, @fields);
}
- close(IN);
+ if ($incodeblock) {
+ warning({ FILE => $f, LINE => $ln },
+ "Expecting CODE END");
+ return undef;
+ }
+
+ return 1;
}
1;
diff --git a/source4/pidl/lib/Parse/Pidl/Wireshark/NDR.pm b/source4/pidl/lib/Parse/Pidl/Wireshark/NDR.pm
index 9415c16652..646f5fdabc 100644
--- a/source4/pidl/lib/Parse/Pidl/Wireshark/NDR.pm
+++ b/source4/pidl/lib/Parse/Pidl/Wireshark/NDR.pm
@@ -2,7 +2,7 @@
# Samba4 NDR parser generator for IDL structures
# Copyright tridge@samba.org 2000-2003
# Copyright tpot@samba.org 2001,2005
-# Copyright jelmer@samba.org 2004-2005
+# Copyright jelmer@samba.org 2004-2007
# Portions based on idl2eth.c by Ronnie Sahlberg
# released under the GNU GPL
@@ -918,7 +918,9 @@ sub Parse($$$$)
$parser.=$res{ett};
$parser.=$res{hf};
$parser.=$res{def};
- $parser.=$conformance->{override};
+ if (exists ($conformance->{override})) {
+ $parser.=$conformance->{override};
+ }
$parser.=$res{code};
my $header = "/* autogenerated by pidl */\n\n";
diff --git a/source4/pidl/tests/header.pl b/source4/pidl/tests/header.pl
new file mode 100755
index 0000000000..e7cd913916
--- /dev/null
+++ b/source4/pidl/tests/header.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
+# Published under the GNU General Public License
+use strict;
+use warnings;
+
+use Test::More tests => 9;
+use FindBin qw($RealBin);
+use lib "$RealBin";
+use Util;
+use Parse::Pidl::Util qw(MyDumper);
+use Parse::Pidl::Samba4::Header;
+use Parse::Pidl::IDL qw(parse_string);
+
+sub parse_idl($)
+{
+ my $text = shift;
+ my $idl = Parse::Pidl::IDL::parse_string($text, "nofile");
+ return Parse::Pidl::Samba4::Header::Parse($idl);
+}
+
+is("/* header auto-generated by pidl */\n\n#include <core.h>\n\n", parse_idl(""), "includes work");
+is("/* header auto-generated by pidl */\n\n#include <core.h>\n\n", parse_idl("interface x {}"), "simple empty interface doesn't cause overhead");
+like(parse_idl("interface p { typedef struct { int y; } x; };"),
+ qr/.*#ifndef _HEADER_p\n#define _HEADER_p\n.+\n#endif \/\* _HEADER_p \*\/.*/ms, "ifdefs are created");
+like(parse_idl("interface p { typedef struct { int y; } x; };"),
+ qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
+like(parse_idl("interface x { void foo (void); };"),
+ qr/struct foo.*{\s+int _dummy_element;\s+};/sm, "void fn contains dummy element");
+like(parse_idl("interface x { void foo ([in] uint32 x); };"),
+ qr/struct foo.*{\s+struct\s+{\s+uint32_t x;\s+} in;\s+};/sm, "fn in arg works");
+like(parse_idl("interface x { void foo ([out] uint32 x); };"),
+ qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn out arg works");
+like(parse_idl("interface x { void foo ([in,out] uint32 x); };"),
+ qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn in,out arg works");
+like(parse_idl("interface x { void foo (uint32 x); };"), qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn with no props implies in,out");
diff --git a/source4/pidl/tests/samba-ndr.pl b/source4/pidl/tests/samba-ndr.pl
index a3e94bd8b5..a6d74beea9 100755
--- a/source4/pidl/tests/samba-ndr.pl
+++ b/source4/pidl/tests/samba-ndr.pl
@@ -4,12 +4,12 @@
use strict;
use warnings;
-use Test::More tests => 10;
+use Test::More tests => 16;
use FindBin qw($RealBin);
use lib "$RealBin";
use Util;
use Parse::Pidl::Util qw(MyDumper);
-use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer);
+use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer GenerateFunctionInEnv GenerateFunctionOutEnv);
my $output;
sub print_fn($) { my $x = shift; $output.=$x; }
@@ -133,3 +133,22 @@ test_warnings("nofile:2: unknown dereferenced expression `r->in.bla'\n",
sub { $fn->("r->in.bla"); });
is($output, "if (r->in.bla == NULL) return;");
+
+# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
+$fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
+is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
+
+$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
+is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
+
+$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
+is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
+
+$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
+is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
+
+$fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
+is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv($fn));
+
+$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
+is_deeply({ }, GenerateFunctionInEnv($fn));
diff --git a/source4/pidl/tests/wireshark-conf.pl b/source4/pidl/tests/wireshark-conf.pl
new file mode 100755
index 0000000000..8601a91ed9
--- /dev/null
+++ b/source4/pidl/tests/wireshark-conf.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
+# Published under the GNU General Public License
+# test parsing wireshark conformance files
+use strict;
+use warnings;
+
+use Test::More tests => 20;
+use FindBin qw($RealBin);
+use lib "$RealBin";
+use Util;
+use Parse::Pidl::Util qw(MyDumper);
+use Parse::Pidl::Wireshark::Conformance qw(ReadConformanceFH);
+
+sub parse_conf($)
+{
+ my $str = shift;
+ open(TMP, "+>", undef) or die("unable to open temp file");
+ print TMP $str;
+ seek(TMP, 0, 0);
+ my $data = {};
+ ReadConformanceFH(*TMP, $data, "nofile") or return undef;
+ close(TMP);
+ return $data;
+}
+
+ok(parse_conf("\n"), undef);
+ok(parse_conf(" \n"), undef);
+ok(parse_conf("CODE START\nCODE END\n"));
+test_warnings("nofile:1: Expecting CODE END\n", sub { is(parse_conf("CODE START\n"), undef); });
+ok(parse_conf("#foobar\n"), undef);
+test_warnings("nofile:1: Unknown command `foobar'\n",
+ sub { ok(parse_conf("foobar\n"), undef); });
+
+test_warnings("nofile:1: incomplete HF_RENAME command\n",
+ sub { parse_conf("HF_RENAME\n"); });
+
+
+is_deeply(parse_conf("HF_RENAME foo bar\n")->{hf_renames}->{foo},
+ { OLDNAME => "foo", NEWNAME => "bar", POS => {FILE => "nofile", LINE => 1}, USED => 0});
+
+is_deeply(parse_conf("NOEMIT\n"), { "noemit_dissector" => 1 });
+is_deeply(parse_conf("NOEMIT foo\n"), { "noemit" => { "foo" => 1 } });
+
+test_warnings("nofile:1: incomplete MANUAL command\n",
+ sub { parse_conf("MANUAL\n"); } );
+
+is_deeply(parse_conf("MANUAL foo\n"), { manual => {foo => 1}});
+
+test_warnings("nofile:1: incomplete FIELD_DESCRIPTION command\n",
+ sub { parse_conf("FIELD_DESCRIPTION foo\n"); });
+
+is_deeply(parse_conf("FIELD_DESCRIPTION foo \"my description\"\n"),
+ { fielddescription => { foo => { DESCRIPTION => "\"my description\"", POS => { FILE => "nofile", LINE => 1}, USED => 0 }}});
+
+is_deeply(parse_conf("FIELD_DESCRIPTION foo my description\n"),
+ { fielddescription => { foo => { DESCRIPTION => "my", POS => { FILE => "nofile", LINE => 1}, USED => 0 }}});
+
+is_deeply(parse_conf("CODE START\ndata\nCODE END\n"), { override => "data\n" });
+is_deeply(parse_conf("CODE START\ndata\nmore data\nCODE END\n"), { override => "data\nmore data\n" });
+test_warnings("nofile:1: Unknown command `CODE'\n",
+ sub { parse_conf("CODE END\n"); } );