mirror of
https://github.com/samba-team/samba.git
synced 2025-12-04 08:23:50 +03:00
always bring it back if we need to. This code was getting in the way while refactoring. Add some tests for TDR. Get rid of typedef in lib/registry/tdr_regf.idl and fix the TDR code to be able to deal with it.
277 lines
6.3 KiB
Perl
277 lines
6.3 KiB
Perl
###################################################
|
|
# Trivial Parser Generator
|
|
# Copyright jelmer@samba.org 2005-2007
|
|
# released under the GNU GPL
|
|
|
|
package Parse::Pidl::Samba4::TDR;
|
|
use Parse::Pidl qw(fatal);
|
|
use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
|
|
use Parse::Pidl::Samba4 qw(is_intree choose_header);
|
|
|
|
use Exporter;
|
|
@ISA = qw(Exporter);
|
|
@EXPORT_OK = qw(ParserType $ret $ret_hdr);
|
|
|
|
use vars qw($VERSION);
|
|
$VERSION = '0.01';
|
|
|
|
use strict;
|
|
|
|
our $ret;
|
|
our $ret_hdr;
|
|
my $tabs = "";
|
|
|
|
sub indent() { $tabs.="\t"; }
|
|
sub deindent() { $tabs = substr($tabs, 1); }
|
|
sub pidl($) { $ret .= $tabs.(shift)."\n"; }
|
|
sub pidl_hdr($) { $ret_hdr .= (shift)."\n"; }
|
|
sub typearg($) {
|
|
my $t = shift;
|
|
return(", const char *name") if ($t eq "print");
|
|
return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
|
|
return("");
|
|
}
|
|
|
|
sub fn_declare($$)
|
|
{
|
|
my ($p, $d) = @_;
|
|
if ($p) { pidl $d; pidl_hdr "$d;"; } else { pidl "static $d"; }
|
|
}
|
|
|
|
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 = "";
|
|
my $mem_ctx = "mem_ctx";
|
|
|
|
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, "flag")) {
|
|
pidl "{";
|
|
indent;
|
|
pidl "uint32_t saved_flags = tdr->flags;";
|
|
pidl "tdr->flags |= $e->{PROPERTIES}->{flag};";
|
|
}
|
|
|
|
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 = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env, $e);
|
|
if ($len eq "*") { $len = "-1"; }
|
|
$name = ", mem_ctx" if ($t eq "pull");
|
|
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, $e);
|
|
}
|
|
|
|
if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
|
|
my $len = ParseExpr($e->{ARRAY_LEN}[0], $env, $e);
|
|
|
|
if ($t eq "pull" and not is_constant($len)) {
|
|
pidl "TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);";
|
|
$mem_ctx = "v->$e->{NAME}";
|
|
}
|
|
|
|
pidl "for (i = 0; i < $len; i++) {";
|
|
indent;
|
|
$array = "[i]";
|
|
}
|
|
|
|
if ($t eq "pull") {
|
|
$name = ", $mem_ctx";
|
|
}
|
|
|
|
if (has_property($e, "value") && $t eq "push") {
|
|
pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";";
|
|
}
|
|
|
|
pidl "TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));";
|
|
|
|
if ($array) { deindent; pidl "}"; }
|
|
|
|
if (has_property($e, "flag")) {
|
|
pidl "tdr->flags = saved_flags;";
|
|
deindent;
|
|
pidl "}";
|
|
}
|
|
}
|
|
|
|
sub ParserStruct($$$$)
|
|
{
|
|
my ($e,$t,$p) = @_;
|
|
|
|
fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
|
|
pidl "{"; indent;
|
|
pidl "int i;" if (ContainsArray($e));
|
|
|
|
if ($t eq "print") {
|
|
pidl "tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);";
|
|
pidl "tdr->level++;";
|
|
}
|
|
|
|
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
|
$env{"this"} = "v";
|
|
ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
|
|
|
if ($t eq "print") {
|
|
pidl "tdr->level--;";
|
|
}
|
|
|
|
pidl "return NT_STATUS_OK;";
|
|
|
|
deindent; pidl "}";
|
|
}
|
|
|
|
sub ParserUnion($$$)
|
|
{
|
|
my ($e,$t,$p) = @_;
|
|
|
|
fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
|
|
pidl "{"; indent;
|
|
pidl "int i;" if (ContainsArray($e));
|
|
|
|
if ($t eq "print") {
|
|
pidl "tdr->print(tdr, \"\%-25s: union $e->{NAME}\", 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,$t,$p) = @_;
|
|
return if ($p);
|
|
pidl "#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e);
|
|
}
|
|
|
|
sub ParserEnum($$$)
|
|
{
|
|
my ($e,$t,$p) = @_;
|
|
my $bt = ($e->{PROPERTIES}->{base_type} or "uint8");
|
|
|
|
fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
|
|
pidl "{";
|
|
if ($t eq "pull") {
|
|
pidl "\t$bt\_t r;";
|
|
pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&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,$p) = @_;
|
|
|
|
ParserType($e->{DATA},$t);
|
|
}
|
|
|
|
sub ParserType($$)
|
|
{
|
|
my ($e,$t) = @_;
|
|
|
|
return if (has_property($e, "no$t"));
|
|
|
|
my $handlers = {
|
|
STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
|
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
|
|
TYPEDEF => \&ParserTypedef
|
|
};
|
|
|
|
$handlers->{$e->{TYPE}}->($e, $t, has_property($e, "public"))
|
|
if (defined($handlers->{$e->{TYPE}}));
|
|
|
|
pidl "";
|
|
}
|
|
|
|
sub ParserInterface($)
|
|
{
|
|
my $x = shift;
|
|
|
|
pidl_hdr "#ifndef __TDR_$x->{NAME}_HEADER__";
|
|
pidl_hdr "#define __TDR_$x->{NAME}_HEADER__";
|
|
|
|
foreach (@{$x->{DATA}}) {
|
|
ParserType($_, "pull");
|
|
ParserType($_, "push");
|
|
ParserType($_, "print");
|
|
}
|
|
|
|
pidl_hdr "#endif /* __TDR_$x->{NAME}_HEADER__ */";
|
|
}
|
|
|
|
sub Parser($$$)
|
|
{
|
|
my ($idl,$hdrname,$baseheader) = @_;
|
|
$ret = ""; $ret_hdr = "";
|
|
pidl "/* autogenerated by pidl */";
|
|
if (is_intree()) {
|
|
pidl "#include \"includes.h\"";
|
|
} else {
|
|
pidl "#include <stdio.h>";
|
|
pidl "#include <stdbool.h>";
|
|
pidl "#include <stdlib.h>";
|
|
pidl "#include <stdint.h>";
|
|
pidl "#include <stdarg.h>";
|
|
pidl "#include <string.h>";
|
|
pidl "#include <core/nterr.h>";
|
|
}
|
|
pidl "#include \"$hdrname\"";
|
|
pidl "";
|
|
pidl_hdr "/* autogenerated by pidl */";
|
|
pidl_hdr "#include \"$baseheader\"";
|
|
pidl_hdr choose_header("tdr/tdr.h", "tdr.h");
|
|
pidl_hdr "";
|
|
|
|
foreach (@$idl) { ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
|
return ($ret_hdr, $ret);
|
|
}
|
|
|
|
1;
|